-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Copy pathUserType.qll
143 lines (114 loc) · 4.47 KB
/
UserType.qll
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/**
* Provides classes for modeling user-defined types such as classes, typedefs
* and enums.
*/
import semmle.code.cpp.Declaration
import semmle.code.cpp.Type
import semmle.code.cpp.Function
private import semmle.code.cpp.internal.ResolveClass
/**
* A C/C++ user-defined type. Examples include `class`, `struct`, `union`,
* `enum` and `typedef` types.
* ```
* enum e1 { val1, val2 } b;
* enum class e2: short { val3, val4 } c;
* typedef int my_int;
* class C { int a, b; };
* ```
*/
class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @usertype {
/**
* Gets the name of this type.
*/
override string getName() { usertypes(underlyingElement(this), result, _) }
override string getAPrimaryQlClass() { result = "UserType" }
/**
* Gets the simple name of this type, without any template parameters. For example
* if the name of the type is `"myType<int>"`, the simple name is just `"myType"`.
*/
string getSimpleName() { result = this.getName().regexpReplaceAll("<.*", "") }
override predicate hasName(string name) { usertypes(underlyingElement(this), name, _) }
/** Holds if this type is anonymous. */
predicate isAnonymous() { this.getName().matches("(unnamed%") }
override predicate hasSpecifier(string s) { Type.super.hasSpecifier(s) }
override Specifier getASpecifier() { result = Type.super.getASpecifier() }
override Location getLocation() {
if this.hasDefinition()
then result = this.getDefinitionLocation()
else result = this.getADeclarationLocation()
}
pragma[nomagic]
private TypeDeclarationEntry getADeclarationEntryBase() {
type_decls(underlyingElement(result), unresolveElement(this), _)
}
override TypeDeclarationEntry getADeclarationEntry() {
pragma[only_bind_into](result) = pragma[only_bind_into](this).getADeclarationEntryBase()
or
not exists(this.getADeclarationEntryBase()) and
exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry())
}
override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() }
override TypeDeclarationEntry getDefinition() {
result = this.getADeclarationEntry() and
result.isDefinition()
}
override Location getDefinitionLocation() {
if exists(this.getDefinition())
then result = this.getDefinition().getLocation()
else
exists(Class t |
this.(Class).isConstructedFrom(t) and result = t.getDefinition().getLocation()
)
}
/**
* Gets the function that directly encloses this type (if any).
*/
Function getEnclosingFunction() {
enclosingfunction(underlyingElement(this), unresolveElement(result))
}
/**
* Holds if this is a local type (that is, a type that has a directly-enclosing
* function).
*/
predicate isLocal() { exists(this.getEnclosingFunction()) }
/*
* Dummy implementations of inherited methods. This class must not be
* made abstract, because it is important that it captures the @usertype
* type exactly - but this is not apparent from its subclasses
*/
/**
* Gets a child declaration within this user-defined type.
*/
Declaration getADeclaration() { none() }
override string explain() { result = this.getName() }
// further overridden in LocalClass
override AccessHolder getEnclosingAccessHolder() { result = this.getDeclaringType() }
}
/**
* A particular definition or forward declaration of a C/C++ user-defined type.
* ```
* class C;
* typedef int ti;
* ```
*/
class TypeDeclarationEntry extends DeclarationEntry, @type_decl {
override UserType getDeclaration() { result = this.getType() }
override string getName() { result = this.getType().getName() }
override string getAPrimaryQlClass() { result = "TypeDeclarationEntry" }
/**
* The type which is being declared or defined.
*/
override Type getType() { type_decls(underlyingElement(this), unresolveElement(result), _) }
override Location getLocation() { type_decls(underlyingElement(this), _, result) }
override predicate isDefinition() { type_def(underlyingElement(this)) }
override string getASpecifier() { none() }
/**
* A top level type declaration entry is not declared within a function, function declaration,
* class or typedef.
*/
predicate isTopLevel() { type_decl_top(underlyingElement(this)) }
/**
* Gets the requires clause if this declaration is a template with such a clause.
*/
Expr getRequiresClause() { type_requires(underlyingElement(this), unresolveElement(result)) }
}