@@ -153,11 +153,110 @@ class NestedRequirementExpr extends Expr, @nested_requirement {
153153
154154/**
155155 * 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`.
156165 */
157166class 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+ }
159179
160180 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+ }
161260}
162261
163262/**
@@ -187,4 +286,9 @@ class Concept extends Declaration, @concept_template {
187286 * the constraint expression is `std::is_same<T, int>::value`.
188287 */
189288 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 ( ) }
190294}
0 commit comments