@@ -153,11 +153,104 @@ 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+ }
159173
160174 override string getAPrimaryQlClass ( ) { result = "ConceptIdExpr" }
175+
176+ /**
177+ * Holds if the concept id is used as a type constraint.
178+ *
179+ * In this case, the first template argument is implicit.
180+ */
181+ predicate isTypeConstraint ( ) { is_type_constraint ( underlyingElement ( this ) ) }
182+
183+ /**
184+ * Gets the concept this concept id refers to.
185+ */
186+ Concept getConcept ( ) { concept_instantiation ( underlyingElement ( this ) , unresolveElement ( result ) ) }
187+
188+ /**
189+ * Gets a template argument passed to the concept.
190+ */
191+ final Locatable getATemplateArgument ( ) { result = this .getTemplateArgument ( _) }
192+
193+ /**
194+ * Gets the kind of a non-type template argument passed to the concept.
195+ */
196+ final Locatable getATemplateArgumentKind ( ) { result = this .getTemplateArgumentKind ( _) }
197+
198+ /**
199+ * Gets the `i`th template argument passed to the concept.
200+ *
201+ * For example, if:
202+ * ```cpp
203+ * template<typename T, T X> concept C = ...;
204+ * ...
205+ * requires { C<int, 1>; };
206+ * ```
207+ * then `getTemplateArgument(0)` yields `int`, and `getTemplateArgument(1)`
208+ * yields `1`.
209+ *
210+ * If the concept id is a type constraint, then `getTemplateArgument(0)`
211+ * will not yield a result.
212+ */
213+ final Locatable getTemplateArgument ( int index ) {
214+ if exists ( this .getTemplateArgumentValue ( index ) )
215+ then result = this .getTemplateArgumentValue ( index )
216+ else result = this .getTemplateArgumentType ( index )
217+ }
218+
219+ /**
220+ * Gets the kind of the `i`th template argument value passed to the concept.
221+ *
222+ * For example, if:
223+ * ```cpp
224+ * template<typename T, T X> concept C = ...;
225+ * ...
226+ * requires { C<int, 1>; };
227+ * ```
228+ * then `getTemplateArgumentKind(1)` yields `int`, and there is no result for
229+ * `getTemplateArgumentKind(0)`.
230+ */
231+ final Locatable getTemplateArgumentKind ( int index ) {
232+ exists ( this .getTemplateArgumentValue ( index ) ) and
233+ result = this .getTemplateArgumentType ( index )
234+ }
235+
236+ /**
237+ * Gets the number of template arguments passed to the concept.
238+ */
239+ final int getNumberOfTemplateArguments ( ) {
240+ result = count ( int i | exists ( this .getTemplateArgument ( i ) ) )
241+ }
242+
243+ private Type getTemplateArgumentType ( int index ) {
244+ exists ( int i | if this .isTypeConstraint ( ) then i = index - 1 else i = index |
245+ concept_template_argument ( underlyingElement ( this ) , i , unresolveElement ( result ) )
246+ )
247+ }
248+
249+ private Expr getTemplateArgumentValue ( int index ) {
250+ exists ( int i | if this .isTypeConstraint ( ) then i = index - 1 else i = index |
251+ concept_template_argument_value ( underlyingElement ( this ) , i , unresolveElement ( result ) )
252+ )
253+ }
161254}
162255
163256/**
@@ -177,7 +270,7 @@ class Concept extends Declaration, @concept_template {
177270 override string getName ( ) { concept_templates ( underlyingElement ( this ) , result , _) }
178271
179272 /**
180- * Get the constraint expression of the concept.
273+ * Gets the constraint expression of the concept.
181274 *
182275 * For example, in
183276 * ```cpp
@@ -187,4 +280,12 @@ class Concept extends Declaration, @concept_template {
187280 * the constraint expression is `true`.
188281 */
189282 Expr getExpr ( ) { result .getParent ( ) = this }
283+
284+ /**
285+ * Gets a concept id expression that refers to this concept
286+ */
287+ ConceptIdExpr getAReferringConceptIdExpr ( ) {
288+ this = result .getConcept ( ) and
289+ exists ( result .getATemplateArgument ( ) )
290+ }
190291}
0 commit comments