@@ -153,11 +153,110 @@ class NestedRequirementExpr extends Expr, @nested_requirement {
153
153
154
154
/**
155
155
* A C++ concept id expression.
156
+ *
157
+ * For example, if:
158
+ * ```cpp
159
+ * template<typename T, T X> concept C = ...;
160
+ * ...
161
+ * requires { C<int, 1>; };
162
+ * ```
163
+ * then `C<int, 1>` is a concept id expression that refers to
164
+ * the concept `C`.
156
165
*/
157
166
class ConceptIdExpr extends RequirementExpr , @concept_id {
158
- override string toString ( ) { result = "concept<...>" }
167
+ override string toString ( ) {
168
+ exists ( string name |
169
+ concept_templates ( this .getConcept ( ) , name , _) and
170
+ result = name + "<...>"
171
+ )
172
+ or
173
+ // The following is for backward compatibility with databases created with
174
+ // CodeQL 2.19.3, 2.19.4, and 2.20.0. Those databases include concept id
175
+ // expressions, but do not include concept template information.
176
+ not exists ( this .getConcept ( ) ) and
177
+ result = "concept<...>"
178
+ }
159
179
160
180
override string getAPrimaryQlClass ( ) { result = "ConceptIdExpr" }
181
+
182
+ /**
183
+ * Holds if the concept id is used as a type constraint.
184
+ *
185
+ * In this case, the first template argument is implicit.
186
+ */
187
+ predicate isTypeConstraint ( ) { is_type_constraint ( underlyingElement ( this ) ) }
188
+
189
+ /**
190
+ * Gets the concept this concept id refers to.
191
+ */
192
+ Concept getConcept ( ) { concept_instantiation ( underlyingElement ( this ) , unresolveElement ( result ) ) }
193
+
194
+ /**
195
+ * Gets a template argument passed to the concept.
196
+ */
197
+ final Locatable getATemplateArgument ( ) { result = this .getTemplateArgument ( _) }
198
+
199
+ /**
200
+ * Gets the kind of a non-type template argument passed to the concept.
201
+ */
202
+ final Locatable getATemplateArgumentKind ( ) { result = this .getTemplateArgumentKind ( _) }
203
+
204
+ /**
205
+ * Gets the `i`th template argument passed to the concept.
206
+ *
207
+ * For example, if:
208
+ * ```cpp
209
+ * template<typename T, T X> concept C = ...;
210
+ * ...
211
+ * requires { C<int, 1>; };
212
+ * ```
213
+ * then `getTemplateArgument(0)` yields `int`, and `getTemplateArgument(1)`
214
+ * yields `1`.
215
+ *
216
+ * If the concept id is a type constraint, then `getTemplateArgument(0)`
217
+ * will not yield a result.
218
+ */
219
+ final Locatable getTemplateArgument ( int index ) {
220
+ if exists ( this .getTemplateArgumentValue ( index ) )
221
+ then result = this .getTemplateArgumentValue ( index )
222
+ else result = this .getTemplateArgumentType ( index )
223
+ }
224
+
225
+ /**
226
+ * Gets the kind of the `i`th template argument value passed to the concept.
227
+ *
228
+ * For example, if:
229
+ * ```cpp
230
+ * template<typename T, T X> concept C = ...;
231
+ * ...
232
+ * requires { C<int, 1>; };
233
+ * ```
234
+ * then `getTemplateArgumentKind(1)` yields `int`, and there is no result for
235
+ * `getTemplateArgumentKind(0)`.
236
+ */
237
+ final Locatable getTemplateArgumentKind ( int index ) {
238
+ exists ( this .getTemplateArgumentValue ( index ) ) and
239
+ result = this .getTemplateArgumentType ( index )
240
+ }
241
+
242
+ /**
243
+ * Gets the number of template arguments passed to the concept.
244
+ */
245
+ final int getNumberOfTemplateArguments ( ) {
246
+ result = count ( int i | exists ( this .getTemplateArgument ( i ) ) )
247
+ }
248
+
249
+ private Type getTemplateArgumentType ( int index ) {
250
+ exists ( int i | if this .isTypeConstraint ( ) then i = index - 1 else i = index |
251
+ concept_template_argument ( underlyingElement ( this ) , i , unresolveElement ( result ) )
252
+ )
253
+ }
254
+
255
+ private Expr getTemplateArgumentValue ( int index ) {
256
+ exists ( int i | if this .isTypeConstraint ( ) then i = index - 1 else i = index |
257
+ concept_template_argument_value ( underlyingElement ( this ) , i , unresolveElement ( result ) )
258
+ )
259
+ }
161
260
}
162
261
163
262
/**
@@ -187,4 +286,9 @@ class Concept extends Declaration, @concept_template {
187
286
* the constraint expression is `std::is_same<T, int>::value`.
188
287
*/
189
288
Expr getExpr ( ) { result .getParent ( ) = this }
289
+
290
+ /**
291
+ * Gets a concept id expression that refers to this concept
292
+ */
293
+ ConceptIdExpr getAReferringConceptIdExpr ( ) { this = result .getConcept ( ) }
190
294
}
0 commit comments