1+ /**
2+ * A library for handling "predicate" types, which are function parameters in the standard library.
3+ *
4+ * For example, `std::sort` takes a predicate as its third argument, and `std::set` takes a
5+ * predicate as its second template parameter. Predicates are always template parameters, and we
6+ * can identify them by their name -- this is what MISRA expects us to do.
7+ */
8+
19import cpp
210private import codingstandards.cpp.StdNamespace
11+ private import codingstandards.cpp.ast.Templates
312private import codingstandards.cpp.types.Templates
413private import semmle.code.cpp.dataflow.new.DataFlow
514
6- Namespace getTemplateParameterNamespace ( TypeTemplateParameter param ) {
7- exists ( Declaration decl |
8- param = decl .( TemplateClass ) .getATemplateArgument ( ) or
9- param = decl .( TemplateVariable ) .getATemplateArgument ( ) or
10- param = decl .( TemplateFunction ) .getATemplateArgument ( )
11- |
12- result = decl .getNamespace ( )
13- )
14- }
15-
15+ /**
16+ * A "predicate" type parameter as defined by MISRA, which is a standard library function named
17+ * "Compare" or "Predicate" or "BinaryPredicate" in the standard library.
18+ *
19+ * To be more widely useful, we match more flexibly on the name, as `_Compare` is also common, etc.
20+ *
21+ * To get a particular `Type` that is _used_ as a predicate type, see `getASubstitutedType()`,
22+ * rather than the type parameter itself, see `getASubstitutedType()`.
23+ */
1624class PredicateType extends TypeTemplateParameter {
1725 PredicateType ( ) {
1826 this .getName ( ) .matches ( [ "%Compare%" , "%Predicate%" ] ) and
1927 getTemplateParameterNamespace ( this ) instanceof StdNS
2028 }
2129
30+ /**
31+ * Get a type that is used (anywhere, via some substitution) as this predicate type parameter.
32+ *
33+ * For example, `std::sort(..., ..., [](int a, int b) { return a < b; })` creates a `Closure`
34+ * type, and substitutes that closure type for the predicate type parameter of `std::sort`.
35+ */
2236 Type getASubstitutedType ( Substitution sub ) { result = sub .getSubstitutedTypeForParameter ( this ) }
2337}
2438
39+ /**
40+ * A class type that has been substituted for a predicate type parameter, and has an `operator()`
41+ * member function.
42+ *
43+ * For example, the closure type in `std::sort(..., ..., [](int a, int b) { return a < b; })` is a
44+ * `PredicateFunctionObject`, and so is any `std::less<int>` that is used as a predicate type
45+ * parameter, etc.
46+ *
47+ * This does not cover function pointer types, as these are not class types.
48+ */
2549class PredicateFunctionObject extends Class {
2650 PredicateType pred ;
2751 Function operator ;
@@ -33,13 +57,38 @@ class PredicateFunctionObject extends Class {
3357 operator .getName ( ) = "operator()"
3458 }
3559
60+ /**
61+ * Get the predicate type parameter that this function object is being substituted for.
62+ */
3663 PredicateType getPredicateType ( ) { result = pred }
3764
65+ /**
66+ * Get the `operator()` function that this function object defines. This is the function that will
67+ * be invoked and essentially defines the predicate behavior.
68+ */
3869 Function getCallOperator ( ) { result = operator }
3970
71+ /**
72+ * Get the `Substitution` object that makes this type a `PredicateFunctionObject`.
73+ *
74+ * This is a particular instantiation of some template that contains a predicate type parameter,
75+ * which is substituted by this type in that instantiation. The `Substitution` object may refer
76+ * to a `TemplateClass`, `TemplateVariable`, or `TemplateFunction`.
77+ */
4078 Substitution getSubstitution ( ) { result = sub }
4179}
4280
81+ /**
82+ * Gets a function access where the purpose of that access is to pass the accessed function as a
83+ * predicate argument to a standard library template.
84+ *
85+ * For example, in `std::sort(..., ..., myCompare)`, where `myCompare` is a function, then
86+ * `myCompare` will be converted into a function pointer and that function pointer will be used as
87+ * a predicate in that `std::sort` call.
88+ *
89+ * This is more complex to identify than `PredicateFunctionObject` because the addressee of the
90+ * function pointer is not necessarily statically known.
91+ */
4392class PredicateFunctionPointerUse extends FunctionAccess {
4493 Expr functionPointerArgument ;
4594 FunctionCall templateFunctionCall ;
@@ -62,5 +111,8 @@ class PredicateFunctionPointerUse extends FunctionAccess {
62111 )
63112 }
64113
114+ /**
115+ * Get the predicate type parameter that this function pointer is being substituted for.
116+ */
65117 PredicateType getPredicateType ( ) { result = pred }
66118}
0 commit comments