1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 /* This file respects the LLVM coding standard described at
6  * http://llvm.org/docs/CodingStandards.html */
7 
8 #include "clang/AST/ASTConsumer.h"
9 #include "clang/AST/ASTContext.h"
10 #include "clang/AST/RecursiveASTVisitor.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/ASTMatchers/ASTMatchers.h"
13 #include "clang/Basic/Version.h"
14 #include "clang/Frontend/CompilerInstance.h"
15 #include "clang/Frontend/FrontendPluginRegistry.h"
16 #include "clang/Frontend/MultiplexConsumer.h"
17 #include "clang/Sema/Sema.h"
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/Support/FileSystem.h"
20 #include "llvm/Support/Path.h"
21 #include <memory>
22 #include <iterator>
23 
24 #define CLANG_VERSION_FULL (CLANG_VERSION_MAJOR * 100 + CLANG_VERSION_MINOR)
25 
26 using namespace llvm;
27 using namespace clang;
28 
29 #if CLANG_VERSION_FULL >= 306
30 typedef std::unique_ptr<ASTConsumer> ASTConsumerPtr;
31 #else
32 typedef ASTConsumer *ASTConsumerPtr;
33 #endif
34 
35 #ifndef HAVE_NEW_ASTMATCHER_NAMES
36 // In clang 3.8, a number of AST matchers were renamed to better match the
37 // respective AST node.  We use the new names, and #define them to the old
38 // ones for compatibility with older versions.
39 #define cxxConstructExpr constructExpr
40 #define cxxConstructorDecl constructorDecl
41 #define cxxMethodDecl methodDecl
42 #define cxxNewExpr newExpr
43 #define cxxRecordDecl recordDecl
44 #endif
45 
46 #ifndef HAS_ACCEPTS_IGNORINGPARENIMPCASTS
47 #define hasIgnoringParenImpCasts(x) has(x)
48 #else
49 // Before clang 3.9 "has" would behave like has(ignoringParenImpCasts(x)),
50 // however doing that explicitly would not compile.
51 #define hasIgnoringParenImpCasts(x) has(ignoringParenImpCasts(x))
52 #endif
53 
54 // Check if the given expression contains an assignment expression.
55 // This can either take the form of a Binary Operator or a
56 // Overloaded Operator Call.
hasSideEffectAssignment(const Expr * Expression)57 bool hasSideEffectAssignment(const Expr *Expression) {
58   if (auto OpCallExpr = dyn_cast_or_null<CXXOperatorCallExpr>(Expression)) {
59     auto BinOp = OpCallExpr->getOperator();
60     if (BinOp == OO_Equal || (BinOp >= OO_PlusEqual && BinOp <= OO_PipeEqual)) {
61       return true;
62     }
63   } else if (auto BinOpExpr = dyn_cast_or_null<BinaryOperator>(Expression)) {
64     if (BinOpExpr->isAssignmentOp()) {
65       return true;
66     }
67   }
68 
69   // Recurse to children.
70   for (const Stmt *SubStmt : Expression->children()) {
71     auto ChildExpr = dyn_cast_or_null<Expr>(SubStmt);
72     if (ChildExpr && hasSideEffectAssignment(ChildExpr)) {
73       return true;
74     }
75   }
76 
77   return false;
78 }
79 
80 namespace {
81 
82 using namespace clang::ast_matchers;
83 class DiagnosticsMatcher {
84 public:
85   DiagnosticsMatcher();
86 
makeASTConsumer()87   ASTConsumerPtr makeASTConsumer() { return AstMatcher.newASTConsumer(); }
88 
89 private:
90   class ScopeChecker : public MatchFinder::MatchCallback {
91   public:
92     virtual void run(const MatchFinder::MatchResult &Result);
93   };
94 
95   class ArithmeticArgChecker : public MatchFinder::MatchCallback {
96   public:
97     virtual void run(const MatchFinder::MatchResult &Result);
98   };
99 
100   class TrivialCtorDtorChecker : public MatchFinder::MatchCallback {
101   public:
102     virtual void run(const MatchFinder::MatchResult &Result);
103   };
104 
105   class NaNExprChecker : public MatchFinder::MatchCallback {
106   public:
107     virtual void run(const MatchFinder::MatchResult &Result);
108   };
109 
110   class NoAddRefReleaseOnReturnChecker : public MatchFinder::MatchCallback {
111   public:
112     virtual void run(const MatchFinder::MatchResult &Result);
113   };
114 
115   class RefCountedInsideLambdaChecker : public MatchFinder::MatchCallback {
116   public:
117     virtual void run(const MatchFinder::MatchResult &Result);
118     void emitDiagnostics(SourceLocation Loc, StringRef Name, QualType Type);
119 
120   private:
121     class ThisVisitor : public RecursiveASTVisitor<ThisVisitor> {
122     public:
ThisVisitor(RefCountedInsideLambdaChecker & Checker)123       explicit ThisVisitor(RefCountedInsideLambdaChecker& Checker)
124         : Checker(Checker) {}
125 
126       bool VisitCXXThisExpr(CXXThisExpr *This);
127     private:
128       RefCountedInsideLambdaChecker& Checker;
129     };
130 
131     ASTContext *Context;
132   };
133 
134   class ExplicitOperatorBoolChecker : public MatchFinder::MatchCallback {
135   public:
136     virtual void run(const MatchFinder::MatchResult &Result);
137   };
138 
139   class NoDuplicateRefCntMemberChecker : public MatchFinder::MatchCallback {
140   public:
141     virtual void run(const MatchFinder::MatchResult &Result);
142   };
143 
144   class NeedsNoVTableTypeChecker : public MatchFinder::MatchCallback {
145   public:
146     virtual void run(const MatchFinder::MatchResult &Result);
147   };
148 
149   class NonMemMovableTemplateArgChecker : public MatchFinder::MatchCallback {
150   public:
151     virtual void run(const MatchFinder::MatchResult &Result);
152   };
153 
154   class NonMemMovableMemberChecker : public MatchFinder::MatchCallback {
155   public:
156     virtual void run(const MatchFinder::MatchResult &Result);
157   };
158 
159   class ExplicitImplicitChecker : public MatchFinder::MatchCallback {
160   public:
161     virtual void run(const MatchFinder::MatchResult &Result);
162   };
163 
164   class NoAutoTypeChecker : public MatchFinder::MatchCallback {
165   public:
166     virtual void run(const MatchFinder::MatchResult &Result);
167   };
168 
169   class NoExplicitMoveConstructorChecker : public MatchFinder::MatchCallback {
170   public:
171     virtual void run(const MatchFinder::MatchResult &Result);
172   };
173 
174   class RefCountedCopyConstructorChecker : public MatchFinder::MatchCallback {
175   public:
176     virtual void run(const MatchFinder::MatchResult &Result);
177   };
178 
179   class AssertAssignmentChecker : public MatchFinder::MatchCallback {
180   public:
181     virtual void run(const MatchFinder::MatchResult &Result);
182   };
183 
184   class KungFuDeathGripChecker : public MatchFinder::MatchCallback {
185   public:
186     virtual void run(const MatchFinder::MatchResult &Result);
187   };
188 
189   class SprintfLiteralChecker : public MatchFinder::MatchCallback {
190   public:
191     virtual void run(const MatchFinder::MatchResult &Result);
192   };
193 
194   class OverrideBaseCallChecker : public MatchFinder::MatchCallback {
195   public:
196     virtual void run(const MatchFinder::MatchResult &Result);
197   private:
198     void evaluateExpression(const Stmt *StmtExpr,
199         std::list<const CXXMethodDecl*> &MethodList);
200     void getRequiredBaseMethod(const CXXMethodDecl* Method,
201         std::list<const CXXMethodDecl*>& MethodsList);
202     void findBaseMethodCall(const CXXMethodDecl* Method,
203         std::list<const CXXMethodDecl*>& MethodsList);
204     bool isRequiredBaseMethod(const CXXMethodDecl *Method);
205   };
206 
207 /*
208  *  This is a companion checker for OverrideBaseCallChecker that rejects
209  *  the usage of MOZ_REQUIRED_BASE_METHOD on non-virtual base methods.
210  */
211   class OverrideBaseCallUsageChecker : public MatchFinder::MatchCallback {
212   public:
213     virtual void run(const MatchFinder::MatchResult &Result);
214   };
215 
216   class NonParamInsideFunctionDeclChecker : public MatchFinder::MatchCallback {
217   public:
218     virtual void run(const MatchFinder::MatchResult &Result);
219   };
220 
221   ScopeChecker Scope;
222   ArithmeticArgChecker ArithmeticArg;
223   TrivialCtorDtorChecker TrivialCtorDtor;
224   NaNExprChecker NaNExpr;
225   NoAddRefReleaseOnReturnChecker NoAddRefReleaseOnReturn;
226   RefCountedInsideLambdaChecker RefCountedInsideLambda;
227   ExplicitOperatorBoolChecker ExplicitOperatorBool;
228   NoDuplicateRefCntMemberChecker NoDuplicateRefCntMember;
229   NeedsNoVTableTypeChecker NeedsNoVTableType;
230   NonMemMovableTemplateArgChecker NonMemMovableTemplateArg;
231   NonMemMovableMemberChecker NonMemMovableMember;
232   ExplicitImplicitChecker ExplicitImplicit;
233   NoAutoTypeChecker NoAutoType;
234   NoExplicitMoveConstructorChecker NoExplicitMoveConstructor;
235   RefCountedCopyConstructorChecker RefCountedCopyConstructor;
236   AssertAssignmentChecker AssertAttribution;
237   KungFuDeathGripChecker KungFuDeathGrip;
238   SprintfLiteralChecker SprintfLiteral;
239   OverrideBaseCallChecker OverrideBaseCall;
240   OverrideBaseCallUsageChecker OverrideBaseCallUsage;
241   NonParamInsideFunctionDeclChecker NonParamInsideFunctionDecl;
242   MatchFinder AstMatcher;
243 };
244 
245 namespace {
246 
getDeclarationNamespace(const Decl * Declaration)247 std::string getDeclarationNamespace(const Decl *Declaration) {
248   const DeclContext *DC =
249       Declaration->getDeclContext()->getEnclosingNamespaceContext();
250   const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
251   if (!ND) {
252     return "";
253   }
254 
255   while (const DeclContext *ParentDC = ND->getParent()) {
256     if (!isa<NamespaceDecl>(ParentDC)) {
257       break;
258     }
259     ND = cast<NamespaceDecl>(ParentDC);
260   }
261 
262   const auto &Name = ND->getName();
263   return Name;
264 }
265 
isInIgnoredNamespaceForImplicitCtor(const Decl * Declaration)266 bool isInIgnoredNamespaceForImplicitCtor(const Decl *Declaration) {
267   std::string Name = getDeclarationNamespace(Declaration);
268   if (Name == "") {
269     return false;
270   }
271 
272   return Name == "std" ||               // standard C++ lib
273          Name == "__gnu_cxx" ||         // gnu C++ lib
274          Name == "boost" ||             // boost
275          Name == "webrtc" ||            // upstream webrtc
276          Name == "rtc" ||               // upstream webrtc 'base' package
277          Name.substr(0, 4) == "icu_" || // icu
278          Name == "google" ||            // protobuf
279          Name == "google_breakpad" ||   // breakpad
280          Name == "soundtouch" ||        // libsoundtouch
281          Name == "stagefright" ||       // libstagefright
282          Name == "MacFileUtilities" ||  // MacFileUtilities
283          Name == "dwarf2reader" ||      // dwarf2reader
284          Name == "arm_ex_to_module" ||  // arm_ex_to_module
285          Name == "testing" ||           // gtest
286          Name == "Json";                // jsoncpp
287 }
288 
isInIgnoredNamespaceForImplicitConversion(const Decl * Declaration)289 bool isInIgnoredNamespaceForImplicitConversion(const Decl *Declaration) {
290   std::string Name = getDeclarationNamespace(Declaration);
291   if (Name == "") {
292     return false;
293   }
294 
295   return Name == "std" ||             // standard C++ lib
296          Name == "__gnu_cxx" ||       // gnu C++ lib
297          Name == "google_breakpad" || // breakpad
298          Name == "testing";           // gtest
299 }
300 
isIgnoredPathForImplicitCtor(const Decl * Declaration)301 bool isIgnoredPathForImplicitCtor(const Decl *Declaration) {
302   SourceLocation Loc = Declaration->getLocation();
303   const SourceManager &SM = Declaration->getASTContext().getSourceManager();
304   SmallString<1024> FileName = SM.getFilename(Loc);
305   llvm::sys::fs::make_absolute(FileName);
306   llvm::sys::path::reverse_iterator Begin = llvm::sys::path::rbegin(FileName),
307                                     End = llvm::sys::path::rend(FileName);
308   for (; Begin != End; ++Begin) {
309     if (Begin->compare_lower(StringRef("skia")) == 0 ||
310         Begin->compare_lower(StringRef("angle")) == 0 ||
311         Begin->compare_lower(StringRef("harfbuzz")) == 0 ||
312         Begin->compare_lower(StringRef("hunspell")) == 0 ||
313         Begin->compare_lower(StringRef("scoped_ptr.h")) == 0 ||
314         Begin->compare_lower(StringRef("graphite2")) == 0 ||
315         Begin->compare_lower(StringRef("icu")) == 0) {
316       return true;
317     }
318     if (Begin->compare_lower(StringRef("chromium")) == 0) {
319       // Ignore security/sandbox/chromium but not ipc/chromium.
320       ++Begin;
321       return Begin != End && Begin->compare_lower(StringRef("sandbox")) == 0;
322     }
323   }
324   return false;
325 }
326 
isIgnoredPathForImplicitConversion(const Decl * Declaration)327 bool isIgnoredPathForImplicitConversion(const Decl *Declaration) {
328   Declaration = Declaration->getCanonicalDecl();
329   SourceLocation Loc = Declaration->getLocation();
330   const SourceManager &SM = Declaration->getASTContext().getSourceManager();
331   SmallString<1024> FileName = SM.getFilename(Loc);
332   llvm::sys::fs::make_absolute(FileName);
333   llvm::sys::path::reverse_iterator Begin = llvm::sys::path::rbegin(FileName),
334                                     End = llvm::sys::path::rend(FileName);
335   for (; Begin != End; ++Begin) {
336     if (Begin->compare_lower(StringRef("graphite2")) == 0) {
337       return true;
338     }
339     if (Begin->compare_lower(StringRef("chromium")) == 0) {
340       // Ignore security/sandbox/chromium but not ipc/chromium.
341       ++Begin;
342       return Begin != End && Begin->compare_lower(StringRef("sandbox")) == 0;
343     }
344   }
345   return false;
346 }
347 
isIgnoredPathForSprintfLiteral(const CallExpr * Call,const SourceManager & SM)348 bool isIgnoredPathForSprintfLiteral(const CallExpr *Call, const SourceManager &SM) {
349   SourceLocation Loc = Call->getLocStart();
350   SmallString<1024> FileName = SM.getFilename(Loc);
351   llvm::sys::fs::make_absolute(FileName);
352   llvm::sys::path::reverse_iterator Begin = llvm::sys::path::rbegin(FileName),
353                                     End = llvm::sys::path::rend(FileName);
354   for (; Begin != End; ++Begin) {
355     if (Begin->compare_lower(StringRef("angle")) == 0 ||
356         Begin->compare_lower(StringRef("chromium")) == 0 ||
357         Begin->compare_lower(StringRef("crashreporter")) == 0 ||
358         Begin->compare_lower(StringRef("google-breakpad")) == 0 ||
359         Begin->compare_lower(StringRef("harfbuzz")) == 0 ||
360         Begin->compare_lower(StringRef("libstagefright")) == 0 ||
361         Begin->compare_lower(StringRef("mtransport")) == 0 ||
362         Begin->compare_lower(StringRef("protobuf")) == 0 ||
363         Begin->compare_lower(StringRef("skia")) == 0 ||
364         // Gtest uses snprintf as GTEST_SNPRINTF_ with sizeof
365         Begin->compare_lower(StringRef("testing")) == 0) {
366       return true;
367     }
368     if (Begin->compare_lower(StringRef("webrtc")) == 0) {
369       // Ignore trunk/webrtc, but not media/webrtc
370       ++Begin;
371       return Begin != End && Begin->compare_lower(StringRef("trunk")) == 0;
372     }
373   }
374   return false;
375 }
376 
isInterestingDeclForImplicitConversion(const Decl * Declaration)377 bool isInterestingDeclForImplicitConversion(const Decl *Declaration) {
378   return !isInIgnoredNamespaceForImplicitConversion(Declaration) &&
379          !isIgnoredPathForImplicitConversion(Declaration);
380 }
381 
isIgnoredExprForMustUse(const Expr * E)382 bool isIgnoredExprForMustUse(const Expr *E) {
383   if (const CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(E)) {
384     switch (OpCall->getOperator()) {
385     case OO_Equal:
386     case OO_PlusEqual:
387     case OO_MinusEqual:
388     case OO_StarEqual:
389     case OO_SlashEqual:
390     case OO_PercentEqual:
391     case OO_CaretEqual:
392     case OO_AmpEqual:
393     case OO_PipeEqual:
394     case OO_LessLessEqual:
395     case OO_GreaterGreaterEqual:
396       return true;
397     default:
398       return false;
399     }
400   }
401 
402   if (const BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) {
403     return Op->isAssignmentOp();
404   }
405 
406   return false;
407 }
408 
409 template<typename T>
getNameChecked(const T & D)410 StringRef getNameChecked(const T& D) {
411   return D->getIdentifier() ? D->getName() : "";
412 }
413 
typeIsRefPtr(QualType Q)414 bool typeIsRefPtr(QualType Q) {
415   CXXRecordDecl *D = Q->getAsCXXRecordDecl();
416   if (!D || !D->getIdentifier()) {
417     return false;
418   }
419 
420   StringRef name = D->getName();
421   if (name == "RefPtr" || name == "nsCOMPtr") {
422     return true;
423   }
424   return false;
425 }
426 
427 // The method defined in clang for ignoring implicit nodes doesn't work with
428 // some AST trees. To get around this, we define our own implementation of
429 // IgnoreImplicit.
IgnoreImplicit(const Stmt * s)430 const Stmt *IgnoreImplicit(const Stmt *s) {
431   while (true) {
432     if (auto *ewc = dyn_cast<ExprWithCleanups>(s)) {
433       s = ewc->getSubExpr();
434     } else if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s)) {
435       s = mte->GetTemporaryExpr();
436     } else if (auto *bte = dyn_cast<CXXBindTemporaryExpr>(s)) {
437       s = bte->getSubExpr();
438     } else if (auto *ice = dyn_cast<ImplicitCastExpr>(s)) {
439       s = ice->getSubExpr();
440     } else {
441       break;
442     }
443   }
444 
445   return s;
446 }
447 
IgnoreImplicit(const Expr * e)448 const Expr *IgnoreImplicit(const Expr *e) {
449   return cast<Expr>(IgnoreImplicit(static_cast<const Stmt *>(e)));
450 }
451 }
452 
453 class CustomTypeAnnotation {
454   enum ReasonKind {
455     RK_None,
456     RK_Direct,
457     RK_ArrayElement,
458     RK_BaseClass,
459     RK_Field,
460     RK_TemplateInherited,
461   };
462   struct AnnotationReason {
463     QualType Type;
464     ReasonKind Kind;
465     const FieldDecl *Field;
466 
valid__anon640086c70111::CustomTypeAnnotation::AnnotationReason467     bool valid() const { return Kind != RK_None; }
468   };
469   typedef DenseMap<void *, AnnotationReason> ReasonCache;
470 
471   const char *Spelling;
472   const char *Pretty;
473   ReasonCache Cache;
474 
475 public:
CustomTypeAnnotation(const char * Spelling,const char * Pretty)476   CustomTypeAnnotation(const char *Spelling, const char *Pretty)
477       : Spelling(Spelling), Pretty(Pretty){};
478 
~CustomTypeAnnotation()479   virtual ~CustomTypeAnnotation() {}
480 
481   // Checks if this custom annotation "effectively affects" the given type.
hasEffectiveAnnotation(QualType T)482   bool hasEffectiveAnnotation(QualType T) {
483     return directAnnotationReason(T).valid();
484   }
485   void dumpAnnotationReason(DiagnosticsEngine &Diag, QualType T,
486                             SourceLocation Loc);
487 
reportErrorIfPresent(DiagnosticsEngine & Diag,QualType T,SourceLocation Loc,unsigned ErrorID,unsigned NoteID)488   void reportErrorIfPresent(DiagnosticsEngine &Diag, QualType T,
489                             SourceLocation Loc, unsigned ErrorID,
490                             unsigned NoteID) {
491     if (hasEffectiveAnnotation(T)) {
492       Diag.Report(Loc, ErrorID) << T;
493       Diag.Report(Loc, NoteID);
494       dumpAnnotationReason(Diag, T, Loc);
495     }
496   }
497 
498 private:
499   bool hasLiteralAnnotation(QualType T) const;
500   AnnotationReason directAnnotationReason(QualType T);
501   AnnotationReason tmplArgAnnotationReason(ArrayRef<TemplateArgument> Args);
502 
503 protected:
504   // Allow subclasses to apply annotations to external code:
hasFakeAnnotation(const TagDecl * D) const505   virtual bool hasFakeAnnotation(const TagDecl *D) const { return false; }
506 };
507 
508 static CustomTypeAnnotation StackClass =
509     CustomTypeAnnotation("moz_stack_class", "stack");
510 static CustomTypeAnnotation GlobalClass =
511     CustomTypeAnnotation("moz_global_class", "global");
512 static CustomTypeAnnotation NonHeapClass =
513     CustomTypeAnnotation("moz_nonheap_class", "non-heap");
514 static CustomTypeAnnotation HeapClass =
515     CustomTypeAnnotation("moz_heap_class", "heap");
516 static CustomTypeAnnotation NonTemporaryClass =
517     CustomTypeAnnotation("moz_non_temporary_class", "non-temporary");
518 static CustomTypeAnnotation MustUse =
519     CustomTypeAnnotation("moz_must_use_type", "must-use");
520 static CustomTypeAnnotation NonParam =
521     CustomTypeAnnotation("moz_non_param", "non-param");
522 
523 class MemMoveAnnotation final : public CustomTypeAnnotation {
524 public:
MemMoveAnnotation()525   MemMoveAnnotation()
526       : CustomTypeAnnotation("moz_non_memmovable", "non-memmove()able") {}
527 
~MemMoveAnnotation()528   virtual ~MemMoveAnnotation() {}
529 
530 protected:
hasFakeAnnotation(const TagDecl * D) const531   bool hasFakeAnnotation(const TagDecl *D) const override {
532     // Annotate everything in ::std, with a few exceptions; see bug
533     // 1201314 for discussion.
534     if (getDeclarationNamespace(D) == "std") {
535       // This doesn't check that it's really ::std::pair and not
536       // ::std::something_else::pair, but should be good enough.
537       StringRef Name = getNameChecked(D);
538       if (Name == "pair" || Name == "atomic" || Name == "__atomic_base") {
539         return false;
540       }
541       return true;
542     }
543     return false;
544   }
545 };
546 
547 static MemMoveAnnotation NonMemMovable = MemMoveAnnotation();
548 
549 class MozChecker : public ASTConsumer, public RecursiveASTVisitor<MozChecker> {
550   DiagnosticsEngine &Diag;
551   const CompilerInstance &CI;
552   DiagnosticsMatcher Matcher;
553 
554 public:
MozChecker(const CompilerInstance & CI)555   MozChecker(const CompilerInstance &CI) : Diag(CI.getDiagnostics()), CI(CI) {}
556 
getOtherConsumer()557   ASTConsumerPtr getOtherConsumer() { return Matcher.makeASTConsumer(); }
558 
HandleTranslationUnit(ASTContext & Ctx)559   virtual void HandleTranslationUnit(ASTContext &Ctx) override {
560     TraverseDecl(Ctx.getTranslationUnitDecl());
561   }
562 
hasCustomAnnotation(const Decl * D,const char * Spelling)563   static bool hasCustomAnnotation(const Decl *D, const char *Spelling) {
564     iterator_range<specific_attr_iterator<AnnotateAttr>> Attrs =
565         D->specific_attrs<AnnotateAttr>();
566 
567     for (AnnotateAttr *Attr : Attrs) {
568       if (Attr->getAnnotation() == Spelling) {
569         return true;
570       }
571     }
572 
573     return false;
574   }
575 
handleUnusedExprResult(const Stmt * Statement)576   void handleUnusedExprResult(const Stmt *Statement) {
577     const Expr *E = dyn_cast_or_null<Expr>(Statement);
578     if (E) {
579       E = E->IgnoreImplicit(); // Ignore ExprWithCleanup etc. implicit wrappers
580       QualType T = E->getType();
581       if (MustUse.hasEffectiveAnnotation(T) && !isIgnoredExprForMustUse(E)) {
582         unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
583             DiagnosticIDs::Error, "Unused value of must-use type %0");
584 
585         Diag.Report(E->getLocStart(), ErrorID) << T;
586         MustUse.dumpAnnotationReason(Diag, T, E->getLocStart());
587       }
588     }
589   }
590 
VisitCXXRecordDecl(CXXRecordDecl * D)591   bool VisitCXXRecordDecl(CXXRecordDecl *D) {
592     // We need definitions, not declarations
593     if (!D->isThisDeclarationADefinition())
594       return true;
595 
596     // Look through all of our immediate bases to find methods that need to be
597     // overridden
598     typedef std::vector<CXXMethodDecl *> OverridesVector;
599     OverridesVector MustOverrides;
600     for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(),
601                                             E = D->bases_end();
602          Base != E; ++Base) {
603       // The base is either a class (CXXRecordDecl) or it's a templated class...
604       CXXRecordDecl *Parent = Base->getType()
605                                   .getDesugaredType(D->getASTContext())
606                                   ->getAsCXXRecordDecl();
607       // The parent might not be resolved to a type yet. In this case, we can't
608       // do any checking here. For complete correctness, we should visit
609       // template instantiations, but this case is likely to be rare, so we will
610       // ignore it until it becomes important.
611       if (!Parent) {
612         continue;
613       }
614       Parent = Parent->getDefinition();
615       for (CXXRecordDecl::method_iterator M = Parent->method_begin();
616            M != Parent->method_end(); ++M) {
617         if (hasCustomAnnotation(*M, "moz_must_override"))
618           MustOverrides.push_back(*M);
619       }
620     }
621 
622     for (OverridesVector::iterator It = MustOverrides.begin();
623          It != MustOverrides.end(); ++It) {
624       bool Overridden = false;
625       for (CXXRecordDecl::method_iterator M = D->method_begin();
626            !Overridden && M != D->method_end(); ++M) {
627         // The way that Clang checks if a method M overrides its parent method
628         // is if the method has the same name but would not overload.
629         if (getNameChecked(M) == getNameChecked(*It) &&
630             !CI.getSema().IsOverload(*M, (*It), false)) {
631           Overridden = true;
632           break;
633         }
634       }
635       if (!Overridden) {
636         unsigned OverrideID = Diag.getDiagnosticIDs()->getCustomDiagID(
637             DiagnosticIDs::Error, "%0 must override %1");
638         unsigned OverrideNote = Diag.getDiagnosticIDs()->getCustomDiagID(
639             DiagnosticIDs::Note, "function to override is here");
640         Diag.Report(D->getLocation(), OverrideID) << D->getDeclName()
641                                                   << (*It)->getDeclName();
642         Diag.Report((*It)->getLocation(), OverrideNote);
643       }
644     }
645 
646     return true;
647   }
648 
VisitSwitchCase(SwitchCase * Statement)649   bool VisitSwitchCase(SwitchCase *Statement) {
650     handleUnusedExprResult(Statement->getSubStmt());
651     return true;
652   }
VisitCompoundStmt(CompoundStmt * Statement)653   bool VisitCompoundStmt(CompoundStmt *Statement) {
654     for (CompoundStmt::body_iterator It = Statement->body_begin(),
655                                      E = Statement->body_end();
656          It != E; ++It) {
657       handleUnusedExprResult(*It);
658     }
659     return true;
660   }
VisitIfStmt(IfStmt * Statement)661   bool VisitIfStmt(IfStmt *Statement) {
662     handleUnusedExprResult(Statement->getThen());
663     handleUnusedExprResult(Statement->getElse());
664     return true;
665   }
VisitWhileStmt(WhileStmt * Statement)666   bool VisitWhileStmt(WhileStmt *Statement) {
667     handleUnusedExprResult(Statement->getBody());
668     return true;
669   }
VisitDoStmt(DoStmt * Statement)670   bool VisitDoStmt(DoStmt *Statement) {
671     handleUnusedExprResult(Statement->getBody());
672     return true;
673   }
VisitForStmt(ForStmt * Statement)674   bool VisitForStmt(ForStmt *Statement) {
675     handleUnusedExprResult(Statement->getBody());
676     handleUnusedExprResult(Statement->getInit());
677     handleUnusedExprResult(Statement->getInc());
678     return true;
679   }
VisitBinComma(BinaryOperator * Op)680   bool VisitBinComma(BinaryOperator *Op) {
681     handleUnusedExprResult(Op->getLHS());
682     return true;
683   }
684 };
685 
686 /// A cached data of whether classes are refcounted or not.
687 typedef DenseMap<const CXXRecordDecl *, std::pair<const Decl *, bool>>
688     RefCountedMap;
689 RefCountedMap RefCountedClasses;
690 
classHasAddRefRelease(const CXXRecordDecl * D)691 bool classHasAddRefRelease(const CXXRecordDecl *D) {
692   const RefCountedMap::iterator &It = RefCountedClasses.find(D);
693   if (It != RefCountedClasses.end()) {
694     return It->second.second;
695   }
696 
697   bool SeenAddRef = false;
698   bool SeenRelease = false;
699   for (CXXRecordDecl::method_iterator Method = D->method_begin();
700        Method != D->method_end(); ++Method) {
701     const auto &Name = getNameChecked(Method);
702     if (Name == "AddRef") {
703       SeenAddRef = true;
704     } else if (Name == "Release") {
705       SeenRelease = true;
706     }
707   }
708   RefCountedClasses[D] = std::make_pair(D, SeenAddRef && SeenRelease);
709   return SeenAddRef && SeenRelease;
710 }
711 
712 bool isClassRefCounted(QualType T);
713 
isClassRefCounted(const CXXRecordDecl * D)714 bool isClassRefCounted(const CXXRecordDecl *D) {
715   // Normalize so that D points to the definition if it exists.
716   if (!D->hasDefinition())
717     return false;
718   D = D->getDefinition();
719   // Base class: anyone with AddRef/Release is obviously a refcounted class.
720   if (classHasAddRefRelease(D))
721     return true;
722 
723   // Look through all base cases to figure out if the parent is a refcounted
724   // class.
725   for (CXXRecordDecl::base_class_const_iterator Base = D->bases_begin();
726        Base != D->bases_end(); ++Base) {
727     bool Super = isClassRefCounted(Base->getType());
728     if (Super) {
729       return true;
730     }
731   }
732 
733   return false;
734 }
735 
isClassRefCounted(QualType T)736 bool isClassRefCounted(QualType T) {
737   while (const clang::ArrayType *ArrTy = T->getAsArrayTypeUnsafe())
738     T = ArrTy->getElementType();
739   CXXRecordDecl *Clazz = T->getAsCXXRecordDecl();
740   return Clazz ? isClassRefCounted(Clazz) : false;
741 }
742 
ASTIsInSystemHeader(const ASTContext & AC,const T & D)743 template <class T> bool ASTIsInSystemHeader(const ASTContext &AC, const T &D) {
744   auto &SourceManager = AC.getSourceManager();
745   auto ExpansionLoc = SourceManager.getExpansionLoc(D.getLocStart());
746   if (ExpansionLoc.isInvalid()) {
747     return false;
748   }
749   return SourceManager.isInSystemHeader(ExpansionLoc);
750 }
751 
getClassRefCntMember(const CXXRecordDecl * D)752 const FieldDecl *getClassRefCntMember(const CXXRecordDecl *D) {
753   for (RecordDecl::field_iterator Field = D->field_begin(), E = D->field_end();
754        Field != E; ++Field) {
755     if (getNameChecked(Field) == "mRefCnt") {
756       return *Field;
757     }
758   }
759   return 0;
760 }
761 
762 const FieldDecl *getBaseRefCntMember(QualType T);
763 
getBaseRefCntMember(const CXXRecordDecl * D)764 const FieldDecl *getBaseRefCntMember(const CXXRecordDecl *D) {
765   const FieldDecl *RefCntMember = getClassRefCntMember(D);
766   if (RefCntMember && isClassRefCounted(D)) {
767     return RefCntMember;
768   }
769 
770   for (CXXRecordDecl::base_class_const_iterator Base = D->bases_begin(),
771                                                 E = D->bases_end();
772        Base != E; ++Base) {
773     RefCntMember = getBaseRefCntMember(Base->getType());
774     if (RefCntMember) {
775       return RefCntMember;
776     }
777   }
778   return 0;
779 }
780 
getBaseRefCntMember(QualType T)781 const FieldDecl *getBaseRefCntMember(QualType T) {
782   while (const clang::ArrayType *ArrTy = T->getAsArrayTypeUnsafe())
783     T = ArrTy->getElementType();
784   CXXRecordDecl *Clazz = T->getAsCXXRecordDecl();
785   return Clazz ? getBaseRefCntMember(Clazz) : 0;
786 }
787 
typeHasVTable(QualType T)788 bool typeHasVTable(QualType T) {
789   while (const clang::ArrayType *ArrTy = T->getAsArrayTypeUnsafe())
790     T = ArrTy->getElementType();
791   CXXRecordDecl *Offender = T->getAsCXXRecordDecl();
792   return Offender && Offender->hasDefinition() && Offender->isDynamicClass();
793 }
794 }
795 
796 namespace clang {
797 namespace ast_matchers {
798 
799 /// This matcher will match any function declaration that is declared as a heap
800 /// allocator.
AST_MATCHER(FunctionDecl,heapAllocator)801 AST_MATCHER(FunctionDecl, heapAllocator) {
802   return MozChecker::hasCustomAnnotation(&Node, "moz_heap_allocator");
803 }
804 
805 /// This matcher will match any declaration that is marked as not accepting
806 /// arithmetic expressions in its arguments.
AST_MATCHER(Decl,noArithmeticExprInArgs)807 AST_MATCHER(Decl, noArithmeticExprInArgs) {
808   return MozChecker::hasCustomAnnotation(&Node, "moz_no_arith_expr_in_arg");
809 }
810 
811 /// This matcher will match any C++ class that is marked as having a trivial
812 /// constructor and destructor.
AST_MATCHER(CXXRecordDecl,hasTrivialCtorDtor)813 AST_MATCHER(CXXRecordDecl, hasTrivialCtorDtor) {
814   return MozChecker::hasCustomAnnotation(&Node, "moz_trivial_ctor_dtor");
815 }
816 
817 /// This matcher will match any function declaration that is marked to prohibit
818 /// calling AddRef or Release on its return value.
AST_MATCHER(FunctionDecl,hasNoAddRefReleaseOnReturnAttr)819 AST_MATCHER(FunctionDecl, hasNoAddRefReleaseOnReturnAttr) {
820   return MozChecker::hasCustomAnnotation(&Node,
821                                          "moz_no_addref_release_on_return");
822 }
823 
824 /// This matcher will match all arithmetic binary operators.
AST_MATCHER(BinaryOperator,binaryArithmeticOperator)825 AST_MATCHER(BinaryOperator, binaryArithmeticOperator) {
826   BinaryOperatorKind OpCode = Node.getOpcode();
827   return OpCode == BO_Mul || OpCode == BO_Div || OpCode == BO_Rem ||
828          OpCode == BO_Add || OpCode == BO_Sub || OpCode == BO_Shl ||
829          OpCode == BO_Shr || OpCode == BO_And || OpCode == BO_Xor ||
830          OpCode == BO_Or || OpCode == BO_MulAssign || OpCode == BO_DivAssign ||
831          OpCode == BO_RemAssign || OpCode == BO_AddAssign ||
832          OpCode == BO_SubAssign || OpCode == BO_ShlAssign ||
833          OpCode == BO_ShrAssign || OpCode == BO_AndAssign ||
834          OpCode == BO_XorAssign || OpCode == BO_OrAssign;
835 }
836 
837 /// This matcher will match all arithmetic unary operators.
AST_MATCHER(UnaryOperator,unaryArithmeticOperator)838 AST_MATCHER(UnaryOperator, unaryArithmeticOperator) {
839   UnaryOperatorKind OpCode = Node.getOpcode();
840   return OpCode == UO_PostInc || OpCode == UO_PostDec || OpCode == UO_PreInc ||
841          OpCode == UO_PreDec || OpCode == UO_Plus || OpCode == UO_Minus ||
842          OpCode == UO_Not;
843 }
844 
845 /// This matcher will match == and != binary operators.
AST_MATCHER(BinaryOperator,binaryEqualityOperator)846 AST_MATCHER(BinaryOperator, binaryEqualityOperator) {
847   BinaryOperatorKind OpCode = Node.getOpcode();
848   return OpCode == BO_EQ || OpCode == BO_NE;
849 }
850 
851 /// This matcher will match floating point types.
AST_MATCHER(QualType,isFloat)852 AST_MATCHER(QualType, isFloat) { return Node->isRealFloatingType(); }
853 
854 /// This matcher will match locations in system headers.  This is adopted from
855 /// isExpansionInSystemHeader in newer clangs, but modified in order to work
856 /// with old clangs that we use on infra.
AST_MATCHER(BinaryOperator,isInSystemHeader)857 AST_MATCHER(BinaryOperator, isInSystemHeader) {
858   return ASTIsInSystemHeader(Finder->getASTContext(), Node);
859 }
860 
861 /// This matcher will match a list of files.  These files contain
862 /// known NaN-testing expressions which we would like to whitelist.
AST_MATCHER(BinaryOperator,isInWhitelistForNaNExpr)863 AST_MATCHER(BinaryOperator, isInWhitelistForNaNExpr) {
864   const char* whitelist[] = {
865     "SkScalar.h",
866     "json_writer.cpp"
867   };
868 
869   SourceLocation Loc = Node.getOperatorLoc();
870   auto &SourceManager = Finder->getASTContext().getSourceManager();
871   SmallString<1024> FileName = SourceManager.getFilename(Loc);
872 
873   for (auto itr = std::begin(whitelist); itr != std::end(whitelist); itr++) {
874     if (llvm::sys::path::rbegin(FileName)->equals(*itr)) {
875       return true;
876     }
877   }
878 
879   return false;
880 }
881 
882 /// This matcher will match all accesses to AddRef or Release methods.
AST_MATCHER(MemberExpr,isAddRefOrRelease)883 AST_MATCHER(MemberExpr, isAddRefOrRelease) {
884   ValueDecl *Member = Node.getMemberDecl();
885   CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member);
886   if (Method) {
887     const auto &Name = getNameChecked(Method);
888     return Name == "AddRef" || Name == "Release";
889   }
890   return false;
891 }
892 
893 /// This matcher will select classes which are refcounted.
AST_MATCHER(CXXRecordDecl,hasRefCntMember)894 AST_MATCHER(CXXRecordDecl, hasRefCntMember) {
895   return isClassRefCounted(&Node) && getClassRefCntMember(&Node);
896 }
897 
AST_MATCHER(QualType,hasVTable)898 AST_MATCHER(QualType, hasVTable) { return typeHasVTable(Node); }
899 
AST_MATCHER(CXXRecordDecl,hasNeedsNoVTableTypeAttr)900 AST_MATCHER(CXXRecordDecl, hasNeedsNoVTableTypeAttr) {
901   return MozChecker::hasCustomAnnotation(&Node, "moz_needs_no_vtable_type");
902 }
903 
904 /// This matcher will select classes which are non-memmovable
AST_MATCHER(QualType,isNonMemMovable)905 AST_MATCHER(QualType, isNonMemMovable) {
906   return NonMemMovable.hasEffectiveAnnotation(Node);
907 }
908 
909 /// This matcher will select classes which require a memmovable template arg
AST_MATCHER(CXXRecordDecl,needsMemMovableTemplateArg)910 AST_MATCHER(CXXRecordDecl, needsMemMovableTemplateArg) {
911   return MozChecker::hasCustomAnnotation(&Node, "moz_needs_memmovable_type");
912 }
913 
914 /// This matcher will select classes which require all members to be memmovable
AST_MATCHER(CXXRecordDecl,needsMemMovableMembers)915 AST_MATCHER(CXXRecordDecl, needsMemMovableMembers) {
916   return MozChecker::hasCustomAnnotation(&Node, "moz_needs_memmovable_members");
917 }
918 
AST_MATCHER(CXXConstructorDecl,isInterestingImplicitCtor)919 AST_MATCHER(CXXConstructorDecl, isInterestingImplicitCtor) {
920   const CXXConstructorDecl *Declaration = Node.getCanonicalDecl();
921   return
922       // Skip ignored namespaces and paths
923       !isInIgnoredNamespaceForImplicitCtor(Declaration) &&
924       !isIgnoredPathForImplicitCtor(Declaration) &&
925       // We only want Converting constructors
926       Declaration->isConvertingConstructor(false) &&
927       // We don't want copy of move constructors, as those are allowed to be
928       // implicit
929       !Declaration->isCopyOrMoveConstructor() &&
930       // We don't want deleted constructors.
931       !Declaration->isDeleted();
932 }
933 
934 // We can't call this "isImplicit" since it clashes with an existing matcher in
935 // clang.
AST_MATCHER(CXXConstructorDecl,isMarkedImplicit)936 AST_MATCHER(CXXConstructorDecl, isMarkedImplicit) {
937   return MozChecker::hasCustomAnnotation(&Node, "moz_implicit");
938 }
939 
AST_MATCHER(CXXRecordDecl,isConcreteClass)940 AST_MATCHER(CXXRecordDecl, isConcreteClass) { return !Node.isAbstract(); }
941 
AST_MATCHER(QualType,autoNonAutoableType)942 AST_MATCHER(QualType, autoNonAutoableType) {
943   if (const AutoType *T = Node->getContainedAutoType()) {
944     if (const CXXRecordDecl *Rec = T->getAsCXXRecordDecl()) {
945       return MozChecker::hasCustomAnnotation(Rec, "moz_non_autoable");
946     }
947   }
948   return false;
949 }
950 
AST_MATCHER(CXXConstructorDecl,isExplicitMoveConstructor)951 AST_MATCHER(CXXConstructorDecl, isExplicitMoveConstructor) {
952   return Node.isExplicit() && Node.isMoveConstructor();
953 }
954 
AST_MATCHER(CXXConstructorDecl,isCompilerProvidedCopyConstructor)955 AST_MATCHER(CXXConstructorDecl, isCompilerProvidedCopyConstructor) {
956   return !Node.isUserProvided() && Node.isCopyConstructor();
957 }
958 
AST_MATCHER(CallExpr,isAssertAssignmentTestFunc)959 AST_MATCHER(CallExpr, isAssertAssignmentTestFunc) {
960   static const std::string AssertName = "MOZ_AssertAssignmentTest";
961   const FunctionDecl *Method = Node.getDirectCallee();
962 
963   return Method
964       && Method->getDeclName().isIdentifier()
965       && Method->getName() == AssertName;
966 }
967 
AST_MATCHER(CallExpr,isSnprintfLikeFunc)968 AST_MATCHER(CallExpr, isSnprintfLikeFunc) {
969   static const std::string Snprintf = "snprintf";
970   static const std::string Vsnprintf = "vsnprintf";
971   const FunctionDecl *Func = Node.getDirectCallee();
972 
973   if (!Func || isa<CXXMethodDecl>(Func)) {
974     return false;
975   }
976 
977   StringRef Name = getNameChecked(Func);
978   if (Name != Snprintf && Name != Vsnprintf) {
979     return false;
980   }
981 
982   return !isIgnoredPathForSprintfLiteral(&Node, Finder->getASTContext().getSourceManager());
983 }
984 
AST_MATCHER(CXXRecordDecl,isLambdaDecl)985 AST_MATCHER(CXXRecordDecl, isLambdaDecl) {
986   return Node.isLambda();
987 }
988 
AST_MATCHER(QualType,isRefPtr)989 AST_MATCHER(QualType, isRefPtr) {
990   return typeIsRefPtr(Node);
991 }
992 
AST_MATCHER(CXXRecordDecl,hasBaseClasses)993 AST_MATCHER(CXXRecordDecl, hasBaseClasses) {
994   const CXXRecordDecl *Decl = Node.getCanonicalDecl();
995 
996   // Must have definition and should inherit other classes
997   return Decl && Decl->hasDefinition() && Decl->getNumBases();
998 }
999 
AST_MATCHER(CXXMethodDecl,isRequiredBaseMethod)1000 AST_MATCHER(CXXMethodDecl, isRequiredBaseMethod) {
1001   const CXXMethodDecl *Decl = Node.getCanonicalDecl();
1002   return Decl
1003       && MozChecker::hasCustomAnnotation(Decl, "moz_required_base_method");
1004 }
1005 
AST_MATCHER(CXXMethodDecl,isNonVirtual)1006 AST_MATCHER(CXXMethodDecl, isNonVirtual) {
1007   const CXXMethodDecl *Decl = Node.getCanonicalDecl();
1008   return Decl && !Decl->isVirtual();
1009 }
1010 }
1011 }
1012 
1013 namespace {
1014 
dumpAnnotationReason(DiagnosticsEngine & Diag,QualType T,SourceLocation Loc)1015 void CustomTypeAnnotation::dumpAnnotationReason(DiagnosticsEngine &Diag,
1016                                                 QualType T,
1017                                                 SourceLocation Loc) {
1018   unsigned InheritsID = Diag.getDiagnosticIDs()->getCustomDiagID(
1019       DiagnosticIDs::Note,
1020       "%1 is a %0 type because it inherits from a %0 type %2");
1021   unsigned MemberID = Diag.getDiagnosticIDs()->getCustomDiagID(
1022       DiagnosticIDs::Note, "%1 is a %0 type because member %2 is a %0 type %3");
1023   unsigned ArrayID = Diag.getDiagnosticIDs()->getCustomDiagID(
1024       DiagnosticIDs::Note,
1025       "%1 is a %0 type because it is an array of %0 type %2");
1026   unsigned TemplID = Diag.getDiagnosticIDs()->getCustomDiagID(
1027       DiagnosticIDs::Note,
1028       "%1 is a %0 type because it has a template argument %0 type %2");
1029 
1030   AnnotationReason Reason = directAnnotationReason(T);
1031   for (;;) {
1032     switch (Reason.Kind) {
1033     case RK_ArrayElement:
1034       Diag.Report(Loc, ArrayID) << Pretty << T << Reason.Type;
1035       break;
1036     case RK_BaseClass: {
1037       const CXXRecordDecl *Declaration = T->getAsCXXRecordDecl();
1038       assert(Declaration && "This type should be a C++ class");
1039 
1040       Diag.Report(Declaration->getLocation(), InheritsID) << Pretty << T
1041                                                    << Reason.Type;
1042       break;
1043     }
1044     case RK_Field:
1045       Diag.Report(Reason.Field->getLocation(), MemberID)
1046           << Pretty << T << Reason.Field << Reason.Type;
1047       break;
1048     case RK_TemplateInherited: {
1049       const CXXRecordDecl *Declaration = T->getAsCXXRecordDecl();
1050       assert(Declaration && "This type should be a C++ class");
1051 
1052       Diag.Report(Declaration->getLocation(), TemplID) << Pretty << T
1053                                                    << Reason.Type;
1054       break;
1055     }
1056     default:
1057       // FIXME (bug 1203263): note the original annotation.
1058       return;
1059     }
1060 
1061     T = Reason.Type;
1062     Reason = directAnnotationReason(T);
1063   }
1064 }
1065 
hasLiteralAnnotation(QualType T) const1066 bool CustomTypeAnnotation::hasLiteralAnnotation(QualType T) const {
1067 #if CLANG_VERSION_FULL >= 306
1068   if (const TagDecl *D = T->getAsTagDecl()) {
1069 #else
1070   if (const CXXRecordDecl *D = T->getAsCXXRecordDecl()) {
1071 #endif
1072     return hasFakeAnnotation(D) || MozChecker::hasCustomAnnotation(D, Spelling);
1073   }
1074   return false;
1075 }
1076 
1077 CustomTypeAnnotation::AnnotationReason
1078 CustomTypeAnnotation::directAnnotationReason(QualType T) {
1079   if (hasLiteralAnnotation(T)) {
1080     AnnotationReason Reason = {T, RK_Direct, nullptr};
1081     return Reason;
1082   }
1083 
1084   // Check if we have a cached answer
1085   void *Key = T.getAsOpaquePtr();
1086   ReasonCache::iterator Cached = Cache.find(T.getAsOpaquePtr());
1087   if (Cached != Cache.end()) {
1088     return Cached->second;
1089   }
1090 
1091   // Check if we have a type which we can recurse into
1092   if (const clang::ArrayType *Array = T->getAsArrayTypeUnsafe()) {
1093     if (hasEffectiveAnnotation(Array->getElementType())) {
1094       AnnotationReason Reason = {Array->getElementType(), RK_ArrayElement,
1095                                  nullptr};
1096       Cache[Key] = Reason;
1097       return Reason;
1098     }
1099   }
1100 
1101   // Recurse into Base classes
1102   if (const CXXRecordDecl *Declaration = T->getAsCXXRecordDecl()) {
1103     if (Declaration->hasDefinition()) {
1104       Declaration = Declaration->getDefinition();
1105 
1106       for (const CXXBaseSpecifier &Base : Declaration->bases()) {
1107         if (hasEffectiveAnnotation(Base.getType())) {
1108           AnnotationReason Reason = {Base.getType(), RK_BaseClass, nullptr};
1109           Cache[Key] = Reason;
1110           return Reason;
1111         }
1112       }
1113 
1114       // Recurse into members
1115       for (const FieldDecl *Field : Declaration->fields()) {
1116         if (hasEffectiveAnnotation(Field->getType())) {
1117           AnnotationReason Reason = {Field->getType(), RK_Field, Field};
1118           Cache[Key] = Reason;
1119           return Reason;
1120         }
1121       }
1122 
1123       // Recurse into template arguments if the annotation
1124       // MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS is present
1125       if (MozChecker::hasCustomAnnotation(
1126               Declaration, "moz_inherit_type_annotations_from_template_args")) {
1127         const ClassTemplateSpecializationDecl *Spec =
1128             dyn_cast<ClassTemplateSpecializationDecl>(Declaration);
1129         if (Spec) {
1130           const TemplateArgumentList &Args = Spec->getTemplateArgs();
1131 
1132           AnnotationReason Reason = tmplArgAnnotationReason(Args.asArray());
1133           if (Reason.Kind != RK_None) {
1134             Cache[Key] = Reason;
1135             return Reason;
1136           }
1137         }
1138       }
1139     }
1140   }
1141 
1142   AnnotationReason Reason = {QualType(), RK_None, nullptr};
1143   Cache[Key] = Reason;
1144   return Reason;
1145 }
1146 
1147 CustomTypeAnnotation::AnnotationReason
1148 CustomTypeAnnotation::tmplArgAnnotationReason(ArrayRef<TemplateArgument> Args) {
1149   for (const TemplateArgument &Arg : Args) {
1150     if (Arg.getKind() == TemplateArgument::Type) {
1151       QualType Type = Arg.getAsType();
1152       if (hasEffectiveAnnotation(Type)) {
1153         AnnotationReason Reason = {Type, RK_TemplateInherited, nullptr};
1154         return Reason;
1155       }
1156     } else if (Arg.getKind() == TemplateArgument::Pack) {
1157       AnnotationReason Reason = tmplArgAnnotationReason(Arg.getPackAsArray());
1158       if (Reason.Kind != RK_None) {
1159         return Reason;
1160       }
1161     }
1162   }
1163 
1164   AnnotationReason Reason = {QualType(), RK_None, nullptr};
1165   return Reason;
1166 }
1167 
1168 bool isPlacementNew(const CXXNewExpr *Expression) {
1169   // Regular new expressions aren't placement new
1170   if (Expression->getNumPlacementArgs() == 0)
1171     return false;
1172   const FunctionDecl *Declaration = Expression->getOperatorNew();
1173   if (Declaration && MozChecker::hasCustomAnnotation(Declaration,
1174                  "moz_heap_allocator")) {
1175     return false;
1176   }
1177   return true;
1178 }
1179 
1180 DiagnosticsMatcher::DiagnosticsMatcher() {
1181   AstMatcher.addMatcher(varDecl().bind("node"), &Scope);
1182   AstMatcher.addMatcher(cxxNewExpr().bind("node"), &Scope);
1183   AstMatcher.addMatcher(materializeTemporaryExpr().bind("node"), &Scope);
1184   AstMatcher.addMatcher(
1185       callExpr(callee(functionDecl(heapAllocator()))).bind("node"),
1186       &Scope);
1187   AstMatcher.addMatcher(parmVarDecl().bind("parm_vardecl"), &Scope);
1188 
1189   AstMatcher.addMatcher(
1190       callExpr(allOf(hasDeclaration(noArithmeticExprInArgs()),
1191                      anyOf(hasDescendant(
1192                                binaryOperator(
1193                                    allOf(binaryArithmeticOperator(),
1194                                          hasLHS(hasDescendant(declRefExpr())),
1195                                          hasRHS(hasDescendant(declRefExpr()))))
1196                                    .bind("node")),
1197                            hasDescendant(
1198                                unaryOperator(
1199                                    allOf(unaryArithmeticOperator(),
1200                                          hasUnaryOperand(allOf(
1201                                              hasType(builtinType()),
1202                                              anyOf(hasDescendant(declRefExpr()),
1203                                                    declRefExpr())))))
1204                                    .bind("node")))))
1205           .bind("call"),
1206       &ArithmeticArg);
1207   AstMatcher.addMatcher(
1208       cxxConstructExpr(
1209           allOf(hasDeclaration(noArithmeticExprInArgs()),
1210                 anyOf(hasDescendant(
1211                           binaryOperator(
1212                               allOf(binaryArithmeticOperator(),
1213                                     hasLHS(hasDescendant(declRefExpr())),
1214                                     hasRHS(hasDescendant(declRefExpr()))))
1215                               .bind("node")),
1216                       hasDescendant(
1217                           unaryOperator(
1218                               allOf(unaryArithmeticOperator(),
1219                                     hasUnaryOperand(allOf(
1220                                         hasType(builtinType()),
1221                                         anyOf(hasDescendant(declRefExpr()),
1222                                               declRefExpr())))))
1223                               .bind("node")))))
1224           .bind("call"),
1225       &ArithmeticArg);
1226 
1227   AstMatcher.addMatcher(cxxRecordDecl(hasTrivialCtorDtor()).bind("node"),
1228                         &TrivialCtorDtor);
1229 
1230   AstMatcher.addMatcher(
1231       binaryOperator(
1232           allOf(binaryEqualityOperator(),
1233                 hasLHS(hasIgnoringParenImpCasts(
1234                     declRefExpr(hasType(qualType((isFloat())))).bind("lhs"))),
1235                 hasRHS(hasIgnoringParenImpCasts(
1236                     declRefExpr(hasType(qualType((isFloat())))).bind("rhs"))),
1237                 unless(anyOf(isInSystemHeader(), isInWhitelistForNaNExpr()))))
1238           .bind("node"),
1239       &NaNExpr);
1240 
1241   // First, look for direct parents of the MemberExpr.
1242   AstMatcher.addMatcher(
1243       callExpr(
1244           callee(functionDecl(hasNoAddRefReleaseOnReturnAttr()).bind("func")),
1245           hasParent(memberExpr(isAddRefOrRelease(), hasParent(callExpr()))
1246                         .bind("member")))
1247           .bind("node"),
1248       &NoAddRefReleaseOnReturn);
1249   // Then, look for MemberExpr that need to be casted to the right type using
1250   // an intermediary CastExpr before we get to the CallExpr.
1251   AstMatcher.addMatcher(
1252       callExpr(
1253           callee(functionDecl(hasNoAddRefReleaseOnReturnAttr()).bind("func")),
1254           hasParent(castExpr(
1255               hasParent(memberExpr(isAddRefOrRelease(), hasParent(callExpr()))
1256                             .bind("member")))))
1257           .bind("node"),
1258       &NoAddRefReleaseOnReturn);
1259 
1260   // We want to reject any code which captures a pointer to an object of a
1261   // refcounted type, and then lets that value escape. As a primitive analysis,
1262   // we reject any occurances of the lambda as a template parameter to a class
1263   // (which could allow it to escape), as well as any presence of such a lambda
1264   // in a return value (either from lambdas, or in c++14, auto functions).
1265   //
1266   // We check these lambdas' capture lists for raw pointers to refcounted types.
1267   AstMatcher.addMatcher(
1268       functionDecl(returns(recordType(hasDeclaration(cxxRecordDecl(
1269         isLambdaDecl()).bind("decl"))))),
1270       &RefCountedInsideLambda);
1271   AstMatcher.addMatcher(lambdaExpr().bind("lambdaExpr"),
1272       &RefCountedInsideLambda);
1273   AstMatcher.addMatcher(
1274       classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(
1275         recordType(hasDeclaration(cxxRecordDecl(
1276           isLambdaDecl()).bind("decl")))))),
1277       &RefCountedInsideLambda);
1278 
1279   // Older clang versions such as the ones used on the infra recognize these
1280   // conversions as 'operator _Bool', but newer clang versions recognize these
1281   // as 'operator bool'.
1282   AstMatcher.addMatcher(
1283       cxxMethodDecl(anyOf(hasName("operator bool"), hasName("operator _Bool")))
1284           .bind("node"),
1285       &ExplicitOperatorBool);
1286 
1287   AstMatcher.addMatcher(cxxRecordDecl().bind("decl"), &NoDuplicateRefCntMember);
1288 
1289   AstMatcher.addMatcher(
1290       classTemplateSpecializationDecl(
1291           allOf(hasAnyTemplateArgument(refersToType(hasVTable())),
1292                 hasNeedsNoVTableTypeAttr()))
1293           .bind("node"),
1294       &NeedsNoVTableType);
1295 
1296   // Handle non-mem-movable template specializations
1297   AstMatcher.addMatcher(
1298       classTemplateSpecializationDecl(
1299           allOf(needsMemMovableTemplateArg(),
1300                 hasAnyTemplateArgument(refersToType(isNonMemMovable()))))
1301           .bind("specialization"),
1302       &NonMemMovableTemplateArg);
1303 
1304   // Handle non-mem-movable members
1305   AstMatcher.addMatcher(
1306       cxxRecordDecl(needsMemMovableMembers())
1307           .bind("decl"),
1308       &NonMemMovableMember);
1309 
1310   AstMatcher.addMatcher(cxxConstructorDecl(isInterestingImplicitCtor(),
1311                                            ofClass(allOf(isConcreteClass(),
1312                                                          decl().bind("class"))),
1313                                            unless(isMarkedImplicit()))
1314                             .bind("ctor"),
1315                         &ExplicitImplicit);
1316 
1317   AstMatcher.addMatcher(varDecl(hasType(autoNonAutoableType())).bind("node"),
1318                         &NoAutoType);
1319 
1320   AstMatcher.addMatcher(
1321       cxxConstructorDecl(isExplicitMoveConstructor()).bind("node"),
1322       &NoExplicitMoveConstructor);
1323 
1324   AstMatcher.addMatcher(
1325       cxxConstructExpr(
1326           hasDeclaration(cxxConstructorDecl(isCompilerProvidedCopyConstructor(),
1327                                             ofClass(hasRefCntMember()))))
1328           .bind("node"),
1329       &RefCountedCopyConstructor);
1330 
1331   AstMatcher.addMatcher(
1332       callExpr(isAssertAssignmentTestFunc()).bind("funcCall"),
1333       &AssertAttribution);
1334 
1335   AstMatcher.addMatcher(varDecl(hasType(isRefPtr())).bind("decl"),
1336                         &KungFuDeathGrip);
1337 
1338   AstMatcher.addMatcher(
1339       callExpr(isSnprintfLikeFunc(),
1340         allOf(hasArgument(0, ignoringParenImpCasts(declRefExpr().bind("buffer"))),
1341                              anyOf(hasArgument(1, sizeOfExpr(hasIgnoringParenImpCasts(declRefExpr().bind("size")))),
1342                                    hasArgument(1, integerLiteral().bind("immediate")),
1343                                    hasArgument(1, declRefExpr(to(varDecl(hasType(isConstQualified()),
1344                                                                          hasInitializer(integerLiteral().bind("constant")))))))))
1345         .bind("funcCall"),
1346       &SprintfLiteral
1347   );
1348 
1349   AstMatcher.addMatcher(cxxRecordDecl(hasBaseClasses()).bind("class"),
1350       &OverrideBaseCall);
1351 
1352   AstMatcher.addMatcher(
1353       cxxMethodDecl(isNonVirtual(), isRequiredBaseMethod()).bind("method"),
1354       &OverrideBaseCallUsage);
1355 
1356   AstMatcher.addMatcher(
1357       functionDecl(anyOf(allOf(isDefinition(),
1358                                hasAncestor(classTemplateSpecializationDecl()
1359                                                .bind("spec"))),
1360                          isDefinition()))
1361           .bind("func"),
1362       &NonParamInsideFunctionDecl);
1363   AstMatcher.addMatcher(
1364       lambdaExpr().bind("lambda"),
1365       &NonParamInsideFunctionDecl);
1366 }
1367 
1368 // These enum variants determine whether an allocation has occured in the code.
1369 enum AllocationVariety {
1370   AV_None,
1371   AV_Global,
1372   AV_Automatic,
1373   AV_Temporary,
1374   AV_Heap,
1375 };
1376 
1377 // XXX Currently the Decl* in the AutomaticTemporaryMap is unused, but it
1378 // probably will be used at some point in the future, in order to produce better
1379 // error messages.
1380 typedef DenseMap<const MaterializeTemporaryExpr *, const Decl *>
1381     AutomaticTemporaryMap;
1382 AutomaticTemporaryMap AutomaticTemporaries;
1383 
1384 void DiagnosticsMatcher::ScopeChecker::run(
1385     const MatchFinder::MatchResult &Result) {
1386   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1387 
1388   // There are a variety of different reasons why something could be allocated
1389   AllocationVariety Variety = AV_None;
1390   SourceLocation Loc;
1391   QualType T;
1392 
1393   if (const ParmVarDecl *D =
1394           Result.Nodes.getNodeAs<ParmVarDecl>("parm_vardecl")) {
1395     if (D->hasUnparsedDefaultArg() || D->hasUninstantiatedDefaultArg()) {
1396       return;
1397     }
1398     if (const Expr *Default = D->getDefaultArg()) {
1399       if (const MaterializeTemporaryExpr *E =
1400               dyn_cast<MaterializeTemporaryExpr>(Default)) {
1401         // We have just found a ParmVarDecl which has, as its default argument,
1402         // a MaterializeTemporaryExpr. We mark that MaterializeTemporaryExpr as
1403         // automatic, by adding it to the AutomaticTemporaryMap.
1404         // Reporting on this type will occur when the MaterializeTemporaryExpr
1405         // is matched against.
1406         AutomaticTemporaries[E] = D;
1407       }
1408     }
1409     return;
1410   }
1411 
1412   // Determine the type of allocation which we detected
1413   if (const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>("node")) {
1414     if (D->hasGlobalStorage()) {
1415       Variety = AV_Global;
1416     } else {
1417       Variety = AV_Automatic;
1418     }
1419     T = D->getType();
1420     Loc = D->getLocStart();
1421   } else if (const CXXNewExpr *E = Result.Nodes.getNodeAs<CXXNewExpr>("node")) {
1422     // New allocates things on the heap.
1423     // We don't consider placement new to do anything, as it doesn't actually
1424     // allocate the storage, and thus gives us no useful information.
1425     if (!isPlacementNew(E)) {
1426       Variety = AV_Heap;
1427       T = E->getAllocatedType();
1428       Loc = E->getLocStart();
1429     }
1430   } else if (const MaterializeTemporaryExpr *E =
1431                  Result.Nodes.getNodeAs<MaterializeTemporaryExpr>("node")) {
1432     // Temporaries can actually have varying storage durations, due to temporary
1433     // lifetime extension. We consider the allocation variety of this temporary
1434     // to be the same as the allocation variety of its lifetime.
1435 
1436     // XXX We maybe should mark these lifetimes as being due to a temporary
1437     // which has had its lifetime extended, to improve the error messages.
1438     switch (E->getStorageDuration()) {
1439     case SD_FullExpression: {
1440       // Check if this temporary is allocated as a default argument!
1441       // if it is, we want to pretend that it is automatic.
1442       AutomaticTemporaryMap::iterator AutomaticTemporary =
1443           AutomaticTemporaries.find(E);
1444       if (AutomaticTemporary != AutomaticTemporaries.end()) {
1445         Variety = AV_Automatic;
1446       } else {
1447         Variety = AV_Temporary;
1448       }
1449     } break;
1450     case SD_Automatic:
1451       Variety = AV_Automatic;
1452       break;
1453     case SD_Thread:
1454     case SD_Static:
1455       Variety = AV_Global;
1456       break;
1457     case SD_Dynamic:
1458       assert(false && "I don't think that this ever should occur...");
1459       Variety = AV_Heap;
1460       break;
1461     }
1462     T = E->getType().getUnqualifiedType();
1463     Loc = E->getLocStart();
1464   } else if (const CallExpr *E = Result.Nodes.getNodeAs<CallExpr>("node")) {
1465     T = E->getType()->getPointeeType();
1466     if (!T.isNull()) {
1467       // This will always allocate on the heap, as the heapAllocator() check
1468       // was made in the matcher
1469       Variety = AV_Heap;
1470       Loc = E->getLocStart();
1471     }
1472   }
1473 
1474   // Error messages for incorrect allocations.
1475   unsigned StackID = Diag.getDiagnosticIDs()->getCustomDiagID(
1476       DiagnosticIDs::Error, "variable of type %0 only valid on the stack");
1477   unsigned GlobalID = Diag.getDiagnosticIDs()->getCustomDiagID(
1478       DiagnosticIDs::Error, "variable of type %0 only valid as global");
1479   unsigned HeapID = Diag.getDiagnosticIDs()->getCustomDiagID(
1480       DiagnosticIDs::Error, "variable of type %0 only valid on the heap");
1481   unsigned NonHeapID = Diag.getDiagnosticIDs()->getCustomDiagID(
1482       DiagnosticIDs::Error, "variable of type %0 is not valid on the heap");
1483   unsigned NonTemporaryID = Diag.getDiagnosticIDs()->getCustomDiagID(
1484       DiagnosticIDs::Error, "variable of type %0 is not valid in a temporary");
1485 
1486   unsigned StackNoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
1487       DiagnosticIDs::Note,
1488       "value incorrectly allocated in an automatic variable");
1489   unsigned GlobalNoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
1490       DiagnosticIDs::Note, "value incorrectly allocated in a global variable");
1491   unsigned HeapNoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
1492       DiagnosticIDs::Note, "value incorrectly allocated on the heap");
1493   unsigned TemporaryNoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
1494       DiagnosticIDs::Note, "value incorrectly allocated in a temporary");
1495 
1496   // Report errors depending on the annotations on the input types.
1497   switch (Variety) {
1498   case AV_None:
1499     return;
1500 
1501   case AV_Global:
1502     StackClass.reportErrorIfPresent(Diag, T, Loc, StackID, GlobalNoteID);
1503     HeapClass.reportErrorIfPresent(Diag, T, Loc, HeapID, GlobalNoteID);
1504     break;
1505 
1506   case AV_Automatic:
1507     GlobalClass.reportErrorIfPresent(Diag, T, Loc, GlobalID, StackNoteID);
1508     HeapClass.reportErrorIfPresent(Diag, T, Loc, HeapID, StackNoteID);
1509     break;
1510 
1511   case AV_Temporary:
1512     GlobalClass.reportErrorIfPresent(Diag, T, Loc, GlobalID, TemporaryNoteID);
1513     HeapClass.reportErrorIfPresent(Diag, T, Loc, HeapID, TemporaryNoteID);
1514     NonTemporaryClass.reportErrorIfPresent(Diag, T, Loc, NonTemporaryID,
1515                                            TemporaryNoteID);
1516     break;
1517 
1518   case AV_Heap:
1519     GlobalClass.reportErrorIfPresent(Diag, T, Loc, GlobalID, HeapNoteID);
1520     StackClass.reportErrorIfPresent(Diag, T, Loc, StackID, HeapNoteID);
1521     NonHeapClass.reportErrorIfPresent(Diag, T, Loc, NonHeapID, HeapNoteID);
1522     break;
1523   }
1524 }
1525 
1526 void DiagnosticsMatcher::ArithmeticArgChecker::run(
1527     const MatchFinder::MatchResult &Result) {
1528   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1529   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
1530       DiagnosticIDs::Error,
1531       "cannot pass an arithmetic expression of built-in types to %0");
1532   const Expr *Expression = Result.Nodes.getNodeAs<Expr>("node");
1533   if (const CallExpr *Call = Result.Nodes.getNodeAs<CallExpr>("call")) {
1534     Diag.Report(Expression->getLocStart(), ErrorID) << Call->getDirectCallee();
1535   } else if (const CXXConstructExpr *Ctr =
1536                  Result.Nodes.getNodeAs<CXXConstructExpr>("call")) {
1537     Diag.Report(Expression->getLocStart(), ErrorID) << Ctr->getConstructor();
1538   }
1539 }
1540 
1541 void DiagnosticsMatcher::TrivialCtorDtorChecker::run(
1542     const MatchFinder::MatchResult &Result) {
1543   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1544   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
1545       DiagnosticIDs::Error,
1546       "class %0 must have trivial constructors and destructors");
1547   const CXXRecordDecl *Node = Result.Nodes.getNodeAs<CXXRecordDecl>("node");
1548 
1549   // We need to accept non-constexpr trivial constructors as well. This occurs
1550   // when a struct contains pod members, which will not be initialized. As
1551   // constexpr values are initialized, the constructor is non-constexpr.
1552   bool BadCtor = !(Node->hasConstexprDefaultConstructor() ||
1553                    Node->hasTrivialDefaultConstructor());
1554   bool BadDtor = !Node->hasTrivialDestructor();
1555   if (BadCtor || BadDtor)
1556     Diag.Report(Node->getLocStart(), ErrorID) << Node;
1557 }
1558 
1559 void DiagnosticsMatcher::NaNExprChecker::run(
1560     const MatchFinder::MatchResult &Result) {
1561   if (!Result.Context->getLangOpts().CPlusPlus) {
1562     // mozilla::IsNaN is not usable in C, so there is no point in issuing these
1563     // warnings.
1564     return;
1565   }
1566 
1567   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1568   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
1569       DiagnosticIDs::Error, "comparing a floating point value to itself for "
1570                             "NaN checking can lead to incorrect results");
1571   unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
1572       DiagnosticIDs::Note, "consider using mozilla::IsNaN instead");
1573   const BinaryOperator *Expression = Result.Nodes.getNodeAs<BinaryOperator>(
1574     "node");
1575   const DeclRefExpr *LHS = Result.Nodes.getNodeAs<DeclRefExpr>("lhs");
1576   const DeclRefExpr *RHS = Result.Nodes.getNodeAs<DeclRefExpr>("rhs");
1577   const ImplicitCastExpr *LHSExpr = dyn_cast<ImplicitCastExpr>(
1578     Expression->getLHS());
1579   const ImplicitCastExpr *RHSExpr = dyn_cast<ImplicitCastExpr>(
1580     Expression->getRHS());
1581   // The AST subtree that we are looking for will look like this:
1582   // -BinaryOperator ==/!=
1583   //  |-ImplicitCastExpr LValueToRValue
1584   //  | |-DeclRefExpr
1585   //  |-ImplicitCastExpr LValueToRValue
1586   //    |-DeclRefExpr
1587   // The check below ensures that we are dealing with the correct AST subtree
1588   // shape, and
1589   // also that both of the found DeclRefExpr's point to the same declaration.
1590   if (LHS->getFoundDecl() == RHS->getFoundDecl() && LHSExpr && RHSExpr &&
1591       std::distance(LHSExpr->child_begin(), LHSExpr->child_end()) == 1 &&
1592       std::distance(RHSExpr->child_begin(), RHSExpr->child_end()) == 1 &&
1593       *LHSExpr->child_begin() == LHS && *RHSExpr->child_begin() == RHS) {
1594     Diag.Report(Expression->getLocStart(), ErrorID);
1595     Diag.Report(Expression->getLocStart(), NoteID);
1596   }
1597 }
1598 
1599 void DiagnosticsMatcher::NoAddRefReleaseOnReturnChecker::run(
1600     const MatchFinder::MatchResult &Result) {
1601   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1602   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
1603       DiagnosticIDs::Error, "%1 cannot be called on the return value of %0");
1604   const Stmt *Node = Result.Nodes.getNodeAs<Stmt>("node");
1605   const FunctionDecl *Func = Result.Nodes.getNodeAs<FunctionDecl>("func");
1606   const MemberExpr *Member = Result.Nodes.getNodeAs<MemberExpr>("member");
1607   const CXXMethodDecl *Method =
1608       dyn_cast<CXXMethodDecl>(Member->getMemberDecl());
1609 
1610   Diag.Report(Node->getLocStart(), ErrorID) << Func << Method;
1611 }
1612 
1613 void DiagnosticsMatcher::RefCountedInsideLambdaChecker::run(
1614     const MatchFinder::MatchResult &Result) {
1615   Context = Result.Context;
1616   static DenseSet<const CXXRecordDecl*> CheckedDecls;
1617 
1618   const CXXRecordDecl *Lambda = Result.Nodes.getNodeAs<CXXRecordDecl>("decl");
1619 
1620   if (const LambdaExpr *OuterLambda =
1621     Result.Nodes.getNodeAs<LambdaExpr>("lambdaExpr")) {
1622     const CXXMethodDecl *OpCall = OuterLambda->getCallOperator();
1623     QualType ReturnTy = OpCall->getReturnType();
1624     if (const CXXRecordDecl *Record = ReturnTy->getAsCXXRecordDecl()) {
1625       Lambda = Record;
1626     }
1627   }
1628 
1629   if (!Lambda || !Lambda->isLambda()) {
1630     return;
1631   }
1632 
1633   // Don't report errors on the same declarations more than once.
1634   if (CheckedDecls.count(Lambda)) {
1635     return;
1636   }
1637   CheckedDecls.insert(Lambda);
1638 
1639   bool StrongRefToThisCaptured = false;
1640 
1641   for (const LambdaCapture& Capture : Lambda->captures()) {
1642     // Check if any of the captures are ByRef. If they are, we have nothing to
1643     // report, as it's OK to capture raw pointers to refcounted objects so long as
1644     // the Lambda doesn't escape the current scope, which is required by ByRef
1645     // captures already.
1646     if (Capture.getCaptureKind() == LCK_ByRef) {
1647       return;
1648     }
1649 
1650     // Check if this capture is byvalue, and captures a strong reference to this.
1651     // XXX: Do we want to make sure that this type which we are capturing is a "Smart Pointer" somehow?
1652     if (!StrongRefToThisCaptured &&
1653         Capture.capturesVariable() &&
1654         Capture.getCaptureKind() == LCK_ByCopy) {
1655       const VarDecl *Var = Capture.getCapturedVar();
1656       if (Var->hasInit()) {
1657         const Stmt *Init = Var->getInit();
1658 
1659         // Ignore single argument constructors, and trivial nodes.
1660         while (true) {
1661           auto NewInit = IgnoreImplicit(Init);
1662           if (auto ConstructExpr = dyn_cast<CXXConstructExpr>(NewInit)) {
1663             if (ConstructExpr->getNumArgs() == 1) {
1664               NewInit = ConstructExpr->getArg(0);
1665             }
1666           }
1667           if (Init == NewInit) {
1668             break;
1669           }
1670           Init = NewInit;
1671         }
1672 
1673         if (isa<CXXThisExpr>(Init)) {
1674           StrongRefToThisCaptured = true;
1675         }
1676       }
1677     }
1678   }
1679 
1680   // Now we can go through and produce errors for any captured variables or this pointers.
1681   for (const LambdaCapture& Capture : Lambda->captures()) {
1682     if (Capture.capturesVariable()) {
1683       QualType Pointee = Capture.getCapturedVar()->getType()->getPointeeType();
1684 
1685       if (!Pointee.isNull() && isClassRefCounted(Pointee)) {
1686         emitDiagnostics(Capture.getLocation(), Capture.getCapturedVar()->getName(), Pointee);
1687         return;
1688       }
1689     }
1690 
1691     // The situation with captures of `this` is more complex. All captures of
1692     // `this` look the same-ish (they are LCK_This). We want to complain about
1693     // captures of `this` where `this` is a refcounted type, and the capture is
1694     // actually used in the body of the lambda (if the capture isn't used, then
1695     // we don't care, because it's only being captured in order to give access
1696     // to private methods).
1697     //
1698     // In addition, we don't complain about this, even if it is used, if it was
1699     // captured implicitly when the LambdaCaptureDefault was LCD_ByRef, as that
1700     // expresses the intent that the lambda won't leave the enclosing scope.
1701     bool ImplicitByRefDefaultedCapture =
1702       Capture.isImplicit() && Lambda->getLambdaCaptureDefault() == LCD_ByRef;
1703     if (Capture.capturesThis() &&
1704         !ImplicitByRefDefaultedCapture &&
1705         !StrongRefToThisCaptured) {
1706       ThisVisitor V(*this);
1707       bool NotAborted = V.TraverseDecl(const_cast<CXXMethodDecl *>(Lambda->getLambdaCallOperator()));
1708       if (!NotAborted) {
1709         return;
1710       }
1711     }
1712   }
1713 }
1714 
1715 void DiagnosticsMatcher::RefCountedInsideLambdaChecker::emitDiagnostics(
1716     SourceLocation Loc, StringRef Name, QualType Type) {
1717   DiagnosticsEngine& Diag = Context->getDiagnostics();
1718   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
1719       DiagnosticIDs::Error, "Refcounted variable '%0' of type %1 cannot be captured by a lambda");
1720   unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
1721       DiagnosticIDs::Note, "Please consider using a smart pointer");
1722 
1723   Diag.Report(Loc, ErrorID) << Name << Type;
1724   Diag.Report(Loc, NoteID);
1725 }
1726 
1727 bool DiagnosticsMatcher::RefCountedInsideLambdaChecker::ThisVisitor::VisitCXXThisExpr(CXXThisExpr *This) {
1728   QualType Pointee = This->getType()->getPointeeType();
1729   if (!Pointee.isNull() && isClassRefCounted(Pointee)) {
1730     Checker.emitDiagnostics(This->getLocStart(), "this", Pointee);
1731     return false;
1732   }
1733 
1734   return true;
1735 }
1736 
1737 void DiagnosticsMatcher::ExplicitOperatorBoolChecker::run(
1738     const MatchFinder::MatchResult &Result) {
1739   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1740   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
1741       DiagnosticIDs::Error, "bad implicit conversion operator for %0");
1742   unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
1743       DiagnosticIDs::Note, "consider adding the explicit keyword to %0");
1744   const CXXConversionDecl *Method =
1745       Result.Nodes.getNodeAs<CXXConversionDecl>("node");
1746   const CXXRecordDecl *Clazz = Method->getParent();
1747 
1748   if (!Method->isExplicitSpecified() &&
1749       !MozChecker::hasCustomAnnotation(Method, "moz_implicit") &&
1750       !ASTIsInSystemHeader(Method->getASTContext(), *Method) &&
1751       isInterestingDeclForImplicitConversion(Method)) {
1752     Diag.Report(Method->getLocStart(), ErrorID) << Clazz;
1753     Diag.Report(Method->getLocStart(), NoteID) << "'operator bool'";
1754   }
1755 }
1756 
1757 void DiagnosticsMatcher::NoDuplicateRefCntMemberChecker::run(
1758     const MatchFinder::MatchResult &Result) {
1759   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1760   const CXXRecordDecl *D = Result.Nodes.getNodeAs<CXXRecordDecl>("decl");
1761   const FieldDecl *RefCntMember = getClassRefCntMember(D);
1762   const FieldDecl *FoundRefCntBase = nullptr;
1763 
1764   if (!D->hasDefinition())
1765     return;
1766   D = D->getDefinition();
1767 
1768   // If we don't have an mRefCnt member, and we have less than 2 superclasses,
1769   // we don't have to run this loop, as neither case will ever apply.
1770   if (!RefCntMember && D->getNumBases() < 2) {
1771     return;
1772   }
1773 
1774   // Check every superclass for whether it has a base with a refcnt member, and
1775   // warn for those which do
1776   for (auto &Base : D->bases()) {
1777     // Determine if this base class has an mRefCnt member
1778     const FieldDecl *BaseRefCntMember = getBaseRefCntMember(Base.getType());
1779 
1780     if (BaseRefCntMember) {
1781       if (RefCntMember) {
1782         // We have an mRefCnt, and superclass has an mRefCnt
1783         unsigned Error = Diag.getDiagnosticIDs()->getCustomDiagID(
1784             DiagnosticIDs::Error,
1785             "Refcounted record %0 has multiple mRefCnt members");
1786         unsigned Note1 = Diag.getDiagnosticIDs()->getCustomDiagID(
1787             DiagnosticIDs::Note, "Superclass %0 also has an mRefCnt member");
1788         unsigned Note2 = Diag.getDiagnosticIDs()->getCustomDiagID(
1789             DiagnosticIDs::Note,
1790             "Consider using the _INHERITED macros for AddRef and Release here");
1791 
1792         Diag.Report(D->getLocStart(), Error) << D;
1793         Diag.Report(BaseRefCntMember->getLocStart(), Note1)
1794           << BaseRefCntMember->getParent();
1795         Diag.Report(RefCntMember->getLocStart(), Note2);
1796       }
1797 
1798       if (FoundRefCntBase) {
1799         unsigned Error = Diag.getDiagnosticIDs()->getCustomDiagID(
1800             DiagnosticIDs::Error,
1801             "Refcounted record %0 has multiple superclasses with mRefCnt members");
1802         unsigned Note = Diag.getDiagnosticIDs()->getCustomDiagID(
1803             DiagnosticIDs::Note,
1804             "Superclass %0 has an mRefCnt member");
1805 
1806         // superclass has mRefCnt, and another superclass also has an mRefCnt
1807         Diag.Report(D->getLocStart(), Error) << D;
1808         Diag.Report(BaseRefCntMember->getLocStart(), Note)
1809           << BaseRefCntMember->getParent();
1810         Diag.Report(FoundRefCntBase->getLocStart(), Note)
1811           << FoundRefCntBase->getParent();
1812       }
1813 
1814       // Record that we've found a base with a mRefCnt member
1815       FoundRefCntBase = BaseRefCntMember;
1816     }
1817   }
1818 }
1819 
1820 void DiagnosticsMatcher::NeedsNoVTableTypeChecker::run(
1821     const MatchFinder::MatchResult &Result) {
1822   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1823   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
1824       DiagnosticIDs::Error,
1825       "%0 cannot be instantiated because %1 has a VTable");
1826   unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
1827       DiagnosticIDs::Note, "bad instantiation of %0 requested here");
1828 
1829   const ClassTemplateSpecializationDecl *Specialization =
1830       Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("node");
1831 
1832   // Get the offending template argument
1833   QualType Offender;
1834   const TemplateArgumentList &Args =
1835       Specialization->getTemplateInstantiationArgs();
1836   for (unsigned i = 0; i < Args.size(); ++i) {
1837     Offender = Args[i].getAsType();
1838     if (typeHasVTable(Offender)) {
1839       break;
1840     }
1841   }
1842 
1843   Diag.Report(Specialization->getLocStart(), ErrorID) << Specialization
1844                                                       << Offender;
1845   Diag.Report(Specialization->getPointOfInstantiation(), NoteID)
1846       << Specialization;
1847 }
1848 
1849 void DiagnosticsMatcher::NonMemMovableTemplateArgChecker::run(
1850     const MatchFinder::MatchResult &Result) {
1851   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1852   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
1853       DiagnosticIDs::Error,
1854       "Cannot instantiate %0 with non-memmovable template argument %1");
1855   unsigned Note1ID = Diag.getDiagnosticIDs()->getCustomDiagID(
1856       DiagnosticIDs::Note, "instantiation of %0 requested here");
1857 
1858   // Get the specialization
1859   const ClassTemplateSpecializationDecl *Specialization =
1860       Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("specialization");
1861   SourceLocation RequestLoc = Specialization->getPointOfInstantiation();
1862 
1863   // Report an error for every template argument which is non-memmovable
1864   const TemplateArgumentList &Args =
1865       Specialization->getTemplateInstantiationArgs();
1866   for (unsigned i = 0; i < Args.size(); ++i) {
1867     QualType ArgType = Args[i].getAsType();
1868     if (NonMemMovable.hasEffectiveAnnotation(ArgType)) {
1869       Diag.Report(Specialization->getLocation(), ErrorID) << Specialization
1870                                                           << ArgType;
1871       // XXX It would be really nice if we could get the instantiation stack
1872       // information
1873       // from Sema such that we could print a full template instantiation stack,
1874       // however,
1875       // it seems as though that information is thrown out by the time we get
1876       // here so we
1877       // can only report one level of template specialization (which in many
1878       // cases won't
1879       // be useful)
1880       Diag.Report(RequestLoc, Note1ID) << Specialization;
1881       NonMemMovable.dumpAnnotationReason(Diag, ArgType, RequestLoc);
1882     }
1883   }
1884 }
1885 
1886 void DiagnosticsMatcher::NonMemMovableMemberChecker::run(
1887     const MatchFinder::MatchResult &Result) {
1888   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1889   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
1890       DiagnosticIDs::Error,
1891       "class %0 cannot have non-memmovable member %1 of type %2");
1892 
1893   // Get the specialization
1894   const CXXRecordDecl* Declaration =
1895       Result.Nodes.getNodeAs<CXXRecordDecl>("decl");
1896 
1897   // Report an error for every member which is non-memmovable
1898   for (const FieldDecl *Field : Declaration->fields()) {
1899     QualType Type = Field->getType();
1900     if (NonMemMovable.hasEffectiveAnnotation(Type)) {
1901       Diag.Report(Field->getLocation(), ErrorID) << Declaration
1902                                                  << Field
1903                                                  << Type;
1904       NonMemMovable.dumpAnnotationReason(Diag, Type, Declaration->getLocation());
1905     }
1906   }
1907 }
1908 
1909 void DiagnosticsMatcher::ExplicitImplicitChecker::run(
1910     const MatchFinder::MatchResult &Result) {
1911   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1912   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
1913       DiagnosticIDs::Error, "bad implicit conversion constructor for %0");
1914   unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
1915       DiagnosticIDs::Note,
1916       "consider adding the explicit keyword to the constructor");
1917 
1918   // We've already checked everything in the matcher, so we just have to report
1919   // the error.
1920 
1921   const CXXConstructorDecl *Ctor =
1922       Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
1923   const CXXRecordDecl *Declaration =
1924       Result.Nodes.getNodeAs<CXXRecordDecl>("class");
1925 
1926   Diag.Report(Ctor->getLocation(), ErrorID) << Declaration->getDeclName();
1927   Diag.Report(Ctor->getLocation(), NoteID);
1928 }
1929 
1930 void DiagnosticsMatcher::NoAutoTypeChecker::run(
1931     const MatchFinder::MatchResult &Result) {
1932   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1933   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
1934       DiagnosticIDs::Error, "Cannot use auto to declare a variable of type %0");
1935   unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
1936       DiagnosticIDs::Note, "Please write out this type explicitly");
1937 
1938   const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>("node");
1939 
1940   Diag.Report(D->getLocation(), ErrorID) << D->getType();
1941   Diag.Report(D->getLocation(), NoteID);
1942 }
1943 
1944 void DiagnosticsMatcher::NoExplicitMoveConstructorChecker::run(
1945     const MatchFinder::MatchResult &Result) {
1946   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1947   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
1948       DiagnosticIDs::Error, "Move constructors may not be marked explicit");
1949 
1950   // Everything we needed to know was checked in the matcher - we just report
1951   // the error here
1952   const CXXConstructorDecl *D =
1953       Result.Nodes.getNodeAs<CXXConstructorDecl>("node");
1954 
1955   Diag.Report(D->getLocation(), ErrorID);
1956 }
1957 
1958 void DiagnosticsMatcher::RefCountedCopyConstructorChecker::run(
1959     const MatchFinder::MatchResult &Result) {
1960   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1961   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
1962       DiagnosticIDs::Error, "Invalid use of compiler-provided copy constructor "
1963                             "on refcounted type");
1964   unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
1965       DiagnosticIDs::Note,
1966       "The default copy constructor also copies the "
1967       "default mRefCnt property, leading to reference "
1968       "count imbalance issues. Please provide your own "
1969       "copy constructor which only copies the fields which "
1970       "need to be copied");
1971 
1972   // Everything we needed to know was checked in the matcher - we just report
1973   // the error here
1974   const CXXConstructExpr *E = Result.Nodes.getNodeAs<CXXConstructExpr>("node");
1975 
1976   Diag.Report(E->getLocation(), ErrorID);
1977   Diag.Report(E->getLocation(), NoteID);
1978 }
1979 
1980 void DiagnosticsMatcher::AssertAssignmentChecker::run(
1981     const MatchFinder::MatchResult &Result) {
1982   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1983   unsigned AssignInsteadOfComp = Diag.getDiagnosticIDs()->getCustomDiagID(
1984       DiagnosticIDs::Error, "Forbidden assignment in assert expression");
1985   const CallExpr *FuncCall = Result.Nodes.getNodeAs<CallExpr>("funcCall");
1986 
1987   if (FuncCall && hasSideEffectAssignment(FuncCall)) {
1988     Diag.Report(FuncCall->getLocStart(), AssignInsteadOfComp);
1989   }
1990 }
1991 
1992 void DiagnosticsMatcher::KungFuDeathGripChecker::run(
1993     const MatchFinder::MatchResult &Result) {
1994   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
1995   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
1996       DiagnosticIDs::Error,
1997       "Unused \"kungFuDeathGrip\" %0 objects constructed from %1 are prohibited");
1998 
1999   unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
2000       DiagnosticIDs::Note,
2001       "Please switch all accesses to this %0 to go through '%1', or explicitly pass '%1' to `mozilla::Unused`");
2002 
2003   const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>("decl");
2004   if (D->isReferenced() || !D->hasLocalStorage() || !D->hasInit()) {
2005     return;
2006   }
2007 
2008   // Not interested in parameters.
2009   if (isa<ImplicitParamDecl>(D) || isa<ParmVarDecl>(D)) {
2010     return;
2011   }
2012 
2013   const Expr *E = IgnoreImplicit(D->getInit());
2014   const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E);
2015   if (CE && CE->getNumArgs() == 0) {
2016     // We don't report an error when we construct and don't use a nsCOMPtr /
2017     // nsRefPtr with no arguments. We don't report it because the error is not
2018     // related to the current check. In the future it may be reported through a
2019     // more generic mechanism.
2020     return;
2021   }
2022 
2023   // We don't want to look at the single argument conversion constructors
2024   // which are inbetween the declaration and the actual object which we are
2025   // assigning into the nsCOMPtr/RefPtr. To do this, we repeatedly
2026   // IgnoreImplicit, then look at the expression. If it is one of these
2027   // conversion constructors, we ignore it and continue to dig.
2028   while ((CE = dyn_cast<CXXConstructExpr>(E)) && CE->getNumArgs() == 1) {
2029     E = IgnoreImplicit(CE->getArg(0));
2030   }
2031 
2032   // We allow taking a kungFuDeathGrip of `this` because it cannot change
2033   // beneath us, so calling directly through `this` is OK. This is the same
2034   // for local variable declarations.
2035   //
2036   // We also don't complain about unused RefPtrs which are constructed from
2037   // the return value of a new expression, as these are required in order to
2038   // immediately destroy the value created (which was presumably created for
2039   // its side effects), and are not used as a death grip.
2040   if (isa<CXXThisExpr>(E) || isa<DeclRefExpr>(E) || isa<CXXNewExpr>(E)) {
2041     return;
2042   }
2043 
2044   // These types are assigned into nsCOMPtr and RefPtr for their side effects,
2045   // and not as a kungFuDeathGrip. We don't want to consider RefPtr and nsCOMPtr
2046   // types which are initialized with these types as errors.
2047   const TagDecl *TD = E->getType()->getAsTagDecl();
2048   if (TD && TD->getIdentifier()) {
2049     static const char *IgnoreTypes[] = {
2050       "already_AddRefed",
2051       "nsGetServiceByCID",
2052       "nsGetServiceByCIDWithError",
2053       "nsGetServiceByContractID",
2054       "nsGetServiceByContractIDWithError",
2055       "nsCreateInstanceByCID",
2056       "nsCreateInstanceByContractID",
2057       "nsCreateInstanceFromFactory",
2058     };
2059 
2060     for (uint32_t i = 0; i < sizeof(IgnoreTypes) / sizeof(IgnoreTypes[0]); ++i) {
2061       if (TD->getName() == IgnoreTypes[i]) {
2062         return;
2063       }
2064     }
2065   }
2066 
2067   // Report the error
2068   const char *ErrThing;
2069   const char *NoteThing;
2070   if (isa<MemberExpr>(E)) {
2071     ErrThing  = "members";
2072     NoteThing = "member";
2073   } else {
2074     ErrThing = "temporary values";
2075     NoteThing = "value";
2076   }
2077 
2078   // We cannot provide the note if we don't have an initializer
2079   Diag.Report(D->getLocStart(), ErrorID) << D->getType() << ErrThing;
2080   Diag.Report(E->getLocStart(), NoteID) << NoteThing << getNameChecked(D);
2081 }
2082 
2083 void DiagnosticsMatcher::SprintfLiteralChecker::run(
2084     const MatchFinder::MatchResult &Result) {
2085   if (!Result.Context->getLangOpts().CPlusPlus) {
2086     // SprintfLiteral is not usable in C, so there is no point in issuing these
2087     // warnings.
2088     return;
2089   }
2090 
2091   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
2092   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
2093     DiagnosticIDs::Error, "Use %1 instead of %0 when writing into a character array.");
2094   unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
2095     DiagnosticIDs::Note, "This will prevent passing in the wrong size to %0 accidentally.");
2096 
2097   const CallExpr *D = Result.Nodes.getNodeAs<CallExpr>("funcCall");
2098 
2099   StringRef Name = D->getDirectCallee()->getName();
2100   const char *Replacement;
2101   if (Name == "snprintf") {
2102     Replacement = "SprintfLiteral";
2103   } else {
2104     assert(Name == "vsnprintf");
2105     Replacement = "VsprintfLiteral";
2106   }
2107 
2108   const DeclRefExpr *Buffer = Result.Nodes.getNodeAs<DeclRefExpr>("buffer");
2109   const DeclRefExpr *Size = Result.Nodes.getNodeAs<DeclRefExpr>("size");
2110   if (Size) {
2111     // Match calls like snprintf(x, sizeof(x), ...).
2112     if (Buffer->getFoundDecl() != Size->getFoundDecl()) {
2113       return;
2114     }
2115 
2116     Diag.Report(D->getLocStart(), ErrorID) << Name << Replacement;
2117     Diag.Report(D->getLocStart(), NoteID) << Name;
2118     return;
2119   }
2120 
2121   const QualType QType = Buffer->getType();
2122   const ConstantArrayType *Type = dyn_cast<ConstantArrayType>(QType.getTypePtrOrNull());
2123   if (Type) {
2124     // Match calls like snprintf(x, 100, ...), where x is int[100];
2125     const IntegerLiteral *Literal = Result.Nodes.getNodeAs<IntegerLiteral>("immediate");
2126     if (!Literal) {
2127       // Match calls like: const int y = 100; snprintf(x, y, ...);
2128       Literal = Result.Nodes.getNodeAs<IntegerLiteral>("constant");
2129     }
2130 
2131     if (Type->getSize().ule(Literal->getValue())) {
2132       Diag.Report(D->getLocStart(), ErrorID) << Name << Replacement;
2133       Diag.Report(D->getLocStart(), NoteID) << Name;
2134     }
2135   }
2136 }
2137 
2138 bool DiagnosticsMatcher::OverrideBaseCallChecker::isRequiredBaseMethod(
2139     const CXXMethodDecl *Method) {
2140   return MozChecker::hasCustomAnnotation(Method, "moz_required_base_method");
2141 }
2142 
2143 void DiagnosticsMatcher::OverrideBaseCallChecker::evaluateExpression(
2144     const Stmt *StmtExpr, std::list<const CXXMethodDecl*> &MethodList) {
2145   // Continue while we have methods in our list
2146   if (!MethodList.size()) {
2147     return;
2148   }
2149 
2150   if (auto MemberFuncCall = dyn_cast<CXXMemberCallExpr>(StmtExpr)) {
2151     if (auto Method = dyn_cast<CXXMethodDecl>(
2152         MemberFuncCall->getDirectCallee())) {
2153       findBaseMethodCall(Method, MethodList);
2154     }
2155   }
2156 
2157   for (auto S : StmtExpr->children()) {
2158     if (S) {
2159       evaluateExpression(S, MethodList);
2160     }
2161   }
2162 }
2163 
2164 void DiagnosticsMatcher::OverrideBaseCallChecker::getRequiredBaseMethod(
2165     const CXXMethodDecl *Method,
2166     std::list<const CXXMethodDecl*>& MethodsList) {
2167 
2168   if (isRequiredBaseMethod(Method)) {
2169     MethodsList.push_back(Method);
2170   } else {
2171     // Loop through all it's base methods.
2172     for (auto BaseMethod = Method->begin_overridden_methods();
2173         BaseMethod != Method->end_overridden_methods(); BaseMethod++) {
2174       getRequiredBaseMethod(*BaseMethod, MethodsList);
2175     }
2176   }
2177 }
2178 
2179 void DiagnosticsMatcher::OverrideBaseCallChecker::findBaseMethodCall(
2180     const CXXMethodDecl* Method,
2181     std::list<const CXXMethodDecl*>& MethodsList) {
2182 
2183   MethodsList.remove(Method);
2184   // Loop also through all it's base methods;
2185   for (auto BaseMethod = Method->begin_overridden_methods();
2186       BaseMethod != Method->end_overridden_methods(); BaseMethod++) {
2187     findBaseMethodCall(*BaseMethod, MethodsList);
2188   }
2189 }
2190 
2191 void DiagnosticsMatcher::OverrideBaseCallChecker::run(
2192     const MatchFinder::MatchResult &Result) {
2193   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
2194   unsigned OverrideBaseCallCheckID = Diag.getDiagnosticIDs()->getCustomDiagID(
2195       DiagnosticIDs::Error,
2196       "Method %0 must be called in all overrides, but is not called in "
2197       "this override defined for class %1");
2198   const CXXRecordDecl *Decl = Result.Nodes.getNodeAs<CXXRecordDecl>("class");
2199 
2200   // Loop through the methods and look for the ones that are overridden.
2201   for (auto Method : Decl->methods()) {
2202     // If this method doesn't override other methods or it doesn't have a body,
2203     // continue to the next declaration.
2204     if (!Method->size_overridden_methods() || !Method->hasBody()) {
2205       continue;
2206     }
2207 
2208     // Preferred the usage of list instead of vector in order to avoid
2209     // calling erase-remove when deleting items
2210     std::list<const CXXMethodDecl*> MethodsList;
2211     // For each overridden method push it to a list if it meets our
2212     // criteria
2213     for (auto BaseMethod = Method->begin_overridden_methods();
2214         BaseMethod != Method->end_overridden_methods(); BaseMethod++) {
2215       getRequiredBaseMethod(*BaseMethod, MethodsList);
2216     }
2217 
2218     // If no method has been found then no annotation was used
2219     // so checking is not needed
2220     if (!MethodsList.size()) {
2221       continue;
2222     }
2223 
2224     // Loop through the body of our method and search for calls to
2225     // base methods
2226     evaluateExpression(Method->getBody(), MethodsList);
2227 
2228     // If list is not empty pop up errors
2229     for (auto BaseMethod : MethodsList) {
2230       Diag.Report(Method->getLocation(), OverrideBaseCallCheckID)
2231           << BaseMethod->getQualifiedNameAsString()
2232           << Decl->getName();
2233     }
2234   }
2235 }
2236 
2237 void DiagnosticsMatcher::OverrideBaseCallUsageChecker::run(
2238     const MatchFinder::MatchResult &Result) {
2239   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
2240   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
2241       DiagnosticIDs::Error,
2242       "MOZ_REQUIRED_BASE_METHOD can be used only on virtual methods");
2243   const CXXMethodDecl *Method = Result.Nodes.getNodeAs<CXXMethodDecl>("method");
2244 
2245   Diag.Report(Method->getLocation(), ErrorID);
2246 }
2247 
2248 void DiagnosticsMatcher::NonParamInsideFunctionDeclChecker::run(
2249     const MatchFinder::MatchResult &Result) {
2250   static DenseSet<const FunctionDecl*> CheckedFunctionDecls;
2251 
2252   const FunctionDecl *func = Result.Nodes.getNodeAs<FunctionDecl>("func");
2253   if (!func) {
2254     const LambdaExpr *lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda");
2255     if (lambda) {
2256       func = lambda->getCallOperator();
2257     }
2258   }
2259 
2260   if (!func) {
2261     return;
2262   }
2263 
2264   if (func->isDeleted()) {
2265     return;
2266   }
2267 
2268   // Don't report errors on the same declarations more than once.
2269   if (CheckedFunctionDecls.count(func)) {
2270     return;
2271   }
2272   CheckedFunctionDecls.insert(func);
2273 
2274   const ClassTemplateSpecializationDecl *Spec =
2275       Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("spec");
2276 
2277   DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
2278   unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
2279       DiagnosticIDs::Error, "Type %0 must not be used as parameter");
2280   unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
2281       DiagnosticIDs::Note, "Please consider passing a const reference instead");
2282   unsigned SpecNoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
2283       DiagnosticIDs::Note, "The bad argument was passed to %0 here");
2284 
2285   for (ParmVarDecl *p : func->parameters()) {
2286     QualType T = p->getType().withoutLocalFastQualifiers();
2287     if (NonParam.hasEffectiveAnnotation(T)) {
2288       Diag.Report(p->getLocation(), ErrorID) << T;
2289       Diag.Report(p->getLocation(), NoteID);
2290 
2291       if (Spec) {
2292         Diag.Report(Spec->getPointOfInstantiation(), SpecNoteID)
2293           << Spec->getSpecializedTemplate();
2294       }
2295     }
2296   }
2297 }
2298 
2299 class MozCheckAction : public PluginASTAction {
2300 public:
2301   ASTConsumerPtr CreateASTConsumer(CompilerInstance &CI,
2302                                    StringRef FileName) override {
2303 #if CLANG_VERSION_FULL >= 306
2304     std::unique_ptr<MozChecker> Checker(llvm::make_unique<MozChecker>(CI));
2305     ASTConsumerPtr Other(Checker->getOtherConsumer());
2306 
2307     std::vector<ASTConsumerPtr> Consumers;
2308     Consumers.push_back(std::move(Checker));
2309     Consumers.push_back(std::move(Other));
2310     return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
2311 #else
2312     MozChecker *Checker = new MozChecker(CI);
2313 
2314     ASTConsumer *Consumers[] = {Checker, Checker->getOtherConsumer()};
2315     return new MultiplexConsumer(Consumers);
2316 #endif
2317   }
2318 
2319   bool ParseArgs(const CompilerInstance &CI,
2320                  const std::vector<std::string> &Args) override {
2321     return true;
2322   }
2323 };
2324 }
2325 
2326 static FrontendPluginRegistry::Add<MozCheckAction> X("moz-check",
2327                                                      "check moz action");
2328 // Export the registry on Windows.
2329 #ifdef LLVM_EXPORT_REGISTRY
2330 LLVM_EXPORT_REGISTRY(FrontendPluginRegistry)
2331 #endif
2332