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 #ifndef CustomTypeAnnotation_h__
6 #define CustomTypeAnnotation_h__
7 
8 #include "CustomAttributes.h"
9 #include "plugin.h"
10 #include "llvm/ADT/BitmaskEnum.h"
11 
12 class CustomTypeAnnotation {
13   enum ReasonKind {
14     RK_None,
15     RK_Direct,
16     RK_ArrayElement,
17     RK_BaseClass,
18     RK_Field,
19     RK_TemplateInherited,
20     RK_Implicit,
21   };
22   struct AnnotationReason {
23     QualType Type;
24     ReasonKind Kind;
25     const FieldDecl *Field;
26     std::string ImplicitReason;
27 
validAnnotationReason28     bool valid() const { return Kind != RK_None; }
29   };
30   typedef DenseMap<void *, AnnotationReason> ReasonCache;
31 
32   CustomAttributes Attribute;
33   const char *Pretty;
34   ReasonCache Cache;
35 
36 public:
CustomTypeAnnotation(CustomAttributes Attribute,const char * Pretty)37   CustomTypeAnnotation(CustomAttributes Attribute, const char *Pretty)
38       : Attribute(Attribute), Pretty(Pretty){};
39 
~CustomTypeAnnotation()40   virtual ~CustomTypeAnnotation() {}
41 
42   // Checks if this custom annotation "effectively affects" the given type.
hasEffectiveAnnotation(QualType T)43   bool hasEffectiveAnnotation(QualType T) {
44     return directAnnotationReason(T).valid();
45   }
46   void dumpAnnotationReason(BaseCheck &Check, QualType T, SourceLocation Loc);
47 
reportErrorIfPresent(BaseCheck & Check,QualType T,SourceLocation Loc,const char * Error,const char * Note)48   void reportErrorIfPresent(BaseCheck &Check, QualType T, SourceLocation Loc,
49                             const char *Error, const char *Note) {
50     if (hasEffectiveAnnotation(T)) {
51       Check.diag(Loc, Error, DiagnosticIDs::Error) << T;
52       Check.diag(Loc, Note, DiagnosticIDs::Note);
53       dumpAnnotationReason(Check, T, Loc);
54     }
55   }
56 
57 private:
58   AnnotationReason directAnnotationReason(QualType T);
59   AnnotationReason tmplArgAnnotationReason(ArrayRef<TemplateArgument> Args);
60 
61 protected:
62   // Flags specifying which properties of the underlying type we want to visit.
63   enum VisitFlags {
64     VISIT_NONE = 0,
65     VISIT_FIELDS = 1,
66     VISIT_TMPL_ARGS = 2,
67     VISIT_BASES = 4,
68     LLVM_MARK_AS_BITMASK_ENUM(VISIT_BASES)
69   };
70 
71   // Allow subclasses to apply annotations for reasons other than a direct
72   // annotation. A non-empty string return value means that the object D is
73   // annotated, and should contain the reason why.
74   //
75   // The subclass may also modify `VisitFlags` to change what properties of the
76   // type will be inspected to skip inspecting fields, force template arguments
77   // to be inspected, etc.
getImplicitReason(const TagDecl * D,VisitFlags & Flags)78   virtual std::string getImplicitReason(const TagDecl *D,
79                                         VisitFlags &Flags) const {
80     return "";
81   }
82 };
83 
84 extern CustomTypeAnnotation StackClass;
85 extern CustomTypeAnnotation GlobalClass;
86 extern CustomTypeAnnotation NonHeapClass;
87 extern CustomTypeAnnotation HeapClass;
88 extern CustomTypeAnnotation NonTemporaryClass;
89 extern CustomTypeAnnotation TemporaryClass;
90 extern CustomTypeAnnotation StaticLocalClass;
91 
92 #endif
93