/** * Provides classes for working with functions, including template functions. */ import semmle.code.cpp.Location import semmle.code.cpp.Class import semmle.code.cpp.Parameter import semmle.code.cpp.exprs.Call import semmle.code.cpp.metrics.MetricFunction import semmle.code.cpp.Linkage private import semmle.code.cpp.internal.ResolveClass private import semmle.code.cpp.internal.ResolveFunction /** * A C/C++ function [N4140 8.3.5]. Both member functions and non-member * functions are included. For example the function `MyFunction` in: * ``` * void MyFunction() { * DoSomething(); * } * ``` * * Function has a one-to-many relationship with FunctionDeclarationEntry, * because the same function can be declared in multiple locations. This * relationship between `Declaration` and `DeclarationEntry` is explained * in more detail in `Declaration.qll`. */ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { Function() { isFunction(underlyingElement(this)) } override string getName() { functions(underlyingElement(this), result, _) } /** Gets a specifier of this function. */ override Specifier getASpecifier() { funspecifiers(underlyingElement(this), unresolveElement(result)) or result.hasName(this.getADeclarationEntry().getASpecifier()) } /** Gets an attribute of this function. */ Attribute getAnAttribute() { funcattributes(underlyingElement(this), unresolveElement(result)) } /** Holds if this function is generated by the compiler. */ predicate isCompilerGenerated() { compgenerated(underlyingElement(this)) } /** Holds if this function is inline. */ predicate isInline() { this.hasSpecifier("inline") } /** * Holds if this function is virtual. * * Unlike `isDeclaredVirtual()`, `isVirtual()` holds even if the function * is not explicitly declared with the `virtual` specifier. */ predicate isVirtual() { this.hasSpecifier("virtual") } /** Holds if this function is declared with the `virtual` specifier. */ predicate isDeclaredVirtual() { this.hasSpecifier("declared_virtual") } /** Holds if this function is declared with the `override` specifier. */ predicate isOverride() { this.hasSpecifier("override") } /** Holds if this function is declared with the `final` specifier. */ predicate isFinal() { this.hasSpecifier("final") } /** * Holds if this function is deleted. * This may be because it was explicitly deleted with an `= delete` * definition, or because the compiler was unable to auto-generate a * definition for it. * * Most implicitly deleted functions are omitted from the database. * `Class.implicitCopyConstructorDeleted` and * `Class.implicitCopyAssignmentOperatorDeleted` can be used to find * whether a class would have had those members implicitly deleted. */ predicate isDeleted() { function_deleted(underlyingElement(this)) } /** * Holds if this function has a prototyped interface. * * Functions generally have a prototyped interface, unless they are * K&R-style functions either without any forward function declaration, * or with all the forward declarations omitting the parameters of the * function. */ predicate isPrototyped() { function_prototyped(underlyingElement(this)) } /** * Holds if this function is explicitly defaulted with the `= default` * specifier. */ predicate isDefaulted() { function_defaulted(underlyingElement(this)) } /** * Holds if this function is declared to be `constexpr`. * * Note that this does not hold if the function has been declared * `consteval`. */ predicate isDeclaredConstexpr() { this.hasSpecifier("declared_constexpr") } /** * Holds if this function is `constexpr`. Normally, this holds if and * only if `isDeclaredConstexpr()` holds, but in some circumstances * they differ. For example, with * ``` * int f(int i) { return 6; } * template constexpr int g(T x) { return f(x); } * ``` * `g` is declared constexpr, but is not constexpr. * * Will also hold if this function is `consteval`. */ predicate isConstexpr() { this.hasSpecifier("is_constexpr") } /** * Holds if this function is declared to be `consteval`. */ predicate isConsteval() { this.hasSpecifier("is_consteval") } /** * Holds if this function is declared to be `explicit`. */ predicate isExplicit() { this.hasSpecifier("explicit") } /** * Gets the constant expression that determines whether the function is explicit. * * For example, for the following code the result is the expression `sizeof(T) == 1`: * ``` * template struct C { * explicit(sizeof(T) == 1) * C(const T); * }; * ``` */ Expr getExplicitExpr() { explicit_specifier_exprs(underlyingElement(this), unresolveElement(result)) } /** * Holds if this function is declared with `__attribute__((naked))` or * `__declspec(naked)`. */ predicate isNaked() { this.getAnAttribute().hasName("naked") } /** * Holds if this function has a trailing return type. * * Note that this is true whether or not deduction took place. For example, * this holds for both `e` and `f`, but not `g` or `h`: * ``` * auto e() -> int { return 0; } * auto f() -> auto { return 0; } * auto g() { return 0; } * int h() { return 0; } * ``` */ predicate hasTrailingReturnType() { this.hasSpecifier("has_trailing_return_type") } /** Gets the return type of this function. */ Type getType() { function_return_type(underlyingElement(this), unresolveElement(result)) } /** * Gets the return type of this function after specifiers have been deeply * stripped and typedefs have been resolved. */ Type getUnspecifiedType() { result = this.getType().getUnspecifiedType() } /** * Gets the nth parameter of this function. There is no result for the * implicit `this` parameter, and there is no `...` varargs pseudo-parameter. */ Parameter getParameter(int n) { params(unresolveElement(result), underlyingElement(this), n, _) } /** * Gets a parameter of this function. There is no result for the implicit * `this` parameter, and there is no `...` varargs pseudo-parameter. */ Parameter getAParameter() { params(unresolveElement(result), underlyingElement(this), _, _) } /** * Gets an access of this function. * * To get calls to this function, use `getACallToThisFunction` instead. */ FunctionAccess getAnAccess() { result.getTarget() = this } /** * Gets the number of parameters of this function, _not_ including any * implicit `this` parameter or any `...` varargs pseudo-parameter. */ int getNumberOfParameters() { result = count(this.getAParameter()) } /** * Gets the number of parameters of this function, _including_ any implicit * `this` parameter but _not_ including any `...` varargs pseudo-parameter. */ int getEffectiveNumberOfParameters() { // This method is overridden in `MemberFunction`, where the result is // adjusted to account for the implicit `this` parameter. result = this.getNumberOfParameters() } /** * Gets a string representing the parameters of this function. * * For example: for a function `int Foo(int p1, int p2)` this would * return `int p1, int p2`. */ string getParameterString() { result = concat(int i | | min(this.getParameter(i).getTypedName()), ", " order by i) } /** Gets a call to this function. */ FunctionCall getACallToThisFunction() { result.getTarget() = this } /** * Gets a declaration entry corresponding to this declaration. The * relationship between `Declaration` and `DeclarationEntry` is explained * in `Declaration.qll`. */ override FunctionDeclarationEntry getADeclarationEntry() { if fun_decls(_, underlyingElement(this), _, _, _) then this.declEntry(result) else exists(Function f | this.isConstructedFrom(f) and fun_decls(unresolveElement(result), unresolveElement(f), _, _, _) ) } /** * Gets a non-implicit function declaration entry. */ FunctionDeclarationEntry getAnExplicitDeclarationEntry() { result = this.getADeclarationEntry() and not result.isImplicit() } private predicate declEntry(FunctionDeclarationEntry fde) { fun_decls(unresolveElement(fde), underlyingElement(this), _, _, _) and // If one .cpp file specializes a function, and another calls the // specialized function, then when extracting the second we only see an // instantiation, not the specialization. We Therefore need to ignore // any non-specialized declarations if there are any specialized ones. (this.isSpecialization() implies fde.isSpecialization()) } /** * Gets the location of a `FunctionDeclarationEntry` corresponding to this * declaration. */ override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() } /** Holds if this function is a template specialization. */ predicate isSpecialization() { exists(FunctionDeclarationEntry fde | fun_decls(unresolveElement(fde), underlyingElement(this), _, _, _) and fde.isSpecialization() ) } /** * Gets the declaration entry corresponding to this declaration that is a * definition, if any. */ override FunctionDeclarationEntry getDefinition() { result = this.getADeclarationEntry() and result.isDefinition() } /** Gets the location of the definition, if any. */ override Location getDefinitionLocation() { if exists(this.getDefinition()) then result = this.getDefinition().getLocation() else exists(Function f | this.isConstructedFrom(f) and result = f.getDefinition().getLocation()) } /** * Gets the preferred location of this declaration. (The location of the * definition, if possible.) */ override Location getLocation() { if exists(this.getDefinition()) then result = this.getDefinitionLocation() else result = this.getADeclarationLocation() } /** Gets a child declaration of this function. */ Declaration getADeclaration() { result = this.getAParameter() } /** * Gets the block that is the function body. * * For C++ functions whose body is a function try statement rather than a * block, this gives the block guarded by the try statement. See * `FunctionTryStmt` for further information. */ BlockStmt getBlock() { result.getParentScope() = this } /** Holds if this function has an entry point. */ predicate hasEntryPoint() { exists(this.getEntryPoint()) } /** * Gets the first node in this function's control flow graph. * * For most functions, this first node will be the `BlockStmt` returned by * `getBlock`. However in C++, the first node can also be a * `FunctionTryStmt`. */ Stmt getEntryPoint() { function_entry_point(underlyingElement(this), unresolveElement(result)) } /** * Gets the metric class. `MetricFunction` has methods for computing * various metrics, such as "number of lines of code" and "number of * function calls". */ MetricFunction getMetrics() { result = this } /** Holds if this function calls the function `f`. */ pragma[nomagic] predicate calls(Function f) { this.calls(f, _) } /** * Holds if this function calls the function `f` in the `FunctionCall` * expression `l`. */ predicate calls(Function f, Locatable l) { exists(FunctionCall call | call.getEnclosingFunction() = this and call.getTarget() = f and call = l ) } /** Holds if this function accesses a function or variable or enumerator `a`. */ predicate accesses(Declaration a) { this.accesses(a, _) } /** * Holds if this function accesses a function or variable or enumerator `a` * in the `Access` expression `l`. */ predicate accesses(Declaration a, Locatable l) { exists(Access access | access.getEnclosingFunction() = this and a = access.getTarget() and access = l ) } /** Gets a variable that is written-to in this function. */ Variable getAWrittenVariable() { exists(ConstructorFieldInit cfi | cfi.getEnclosingFunction() = this and result = cfi.getTarget() ) or exists(VariableAccess va | va = result.getAnAccess() and va.isUsedAsLValue() and va.getEnclosingFunction() = this ) } /** * Gets the class of which this function, called `memberName`, is a member. * * Prefer to use `getDeclaringType()` or `getName()` directly if you do not * need to reason about both. */ pragma[nomagic] Class getClassAndName(string memberName) { this.hasName(memberName) and this.getDeclaringType() = result } /** * Implements `ControlFlowNode.getControlFlowScope`. The `Function` is * used to represent the exit node of the control flow graph, so it is * its own scope. */ override Function getControlFlowScope() { result = this } /** * Implements `ControlFlowNode.getEnclosingStmt`. The `Function` is * used to represent the exit node of the control flow graph, so it * has no enclosing statement. */ override Stmt getEnclosingStmt() { none() } /** * Holds if this function has C linkage, as specified by one of its * declaration entries. For example: `extern "C" void foo();`. */ predicate hasCLinkage() { this.getADeclarationEntry().hasCLinkage() } /** * Holds if this function is constructed from `f` as a result * of template instantiation. If so, it originates either from a template * function or from a function nested in a template class. */ predicate isConstructedFrom(Function f) { function_instantiation(underlyingElement(this), unresolveElement(f)) } /** * Holds if this function is defined in several files. This is illegal in * C (though possible in some C++ compilers), and likely indicates that * several functions that are not linked together have been compiled. An * example would be a project with many 'main' functions. */ predicate isMultiplyDefined() { strictcount(this.getFile()) > 1 } /** Holds if this function is a varargs function. */ predicate isVarargs() { this.hasSpecifier("varargs") } /** Gets a type that is specified to be thrown by the function. */ Type getAThrownType() { result = this.getADeclarationEntry().getAThrownType() } /** * Gets the `i`th type specified to be thrown by the function. */ Type getThrownType(int i) { result = this.getADeclarationEntry().getThrownType(i) } /** Holds if the function has an exception specification. */ predicate hasExceptionSpecification() { this.getADeclarationEntry().hasExceptionSpecification() } /** Holds if this function has a `throw()` exception specification. */ predicate isNoThrow() { this.getADeclarationEntry().isNoThrow() } /** Holds if this function has a `noexcept` exception specification. */ predicate isNoExcept() { this.getADeclarationEntry().isNoExcept() } /** * Gets a function that overloads this one. * * Note: if _overrides_ are wanted rather than _overloads_ then * `MemberFunction::getAnOverridingFunction` should be used instead. */ Function getAnOverload() { ( // If this function is declared in a class, only consider other // functions from the same class. exists(string name, Class declaringType | candGetAnOverloadMember(name, declaringType, this) and candGetAnOverloadMember(name, declaringType, result) ) or // Conversely, if this function is not // declared in a class, only consider other functions not declared in a // class. exists(string name, Namespace namespace | candGetAnOverloadNonMember(name, namespace, this) and candGetAnOverloadNonMember(name, namespace, result) ) ) and result != this and // Instantiations and specializations don't participate in overload // resolution. not ( this instanceof FunctionTemplateInstantiation or result instanceof FunctionTemplateInstantiation ) and not ( this instanceof FunctionTemplateSpecialization or result instanceof FunctionTemplateSpecialization ) } /** Gets a link target which compiled or referenced this function. */ LinkTarget getALinkTarget() { this = result.getAFunction() } /** * Holds if this function is side-effect free (conservative * approximation). */ predicate isSideEffectFree() { not this.mayHaveSideEffects() } /** * Holds if this function may have side-effects; if in doubt, we assume it * may. */ predicate mayHaveSideEffects() { // If we cannot see the definition then we assume that it may have // side-effects. if exists(this.getEntryPoint()) then // If it might be globally impure (we don't care about it modifying // temporaries) then it may have side-effects. this.getEntryPoint().mayBeGloballyImpure() or // Constructor initializers are separate from the entry point ... this.(Constructor).getAnInitializer().mayBeGloballyImpure() or // ... and likewise for destructors. this.(Destructor).getADestruction().mayBeGloballyImpure() else // Unless it's a function that we know is side-effect free, it may // have side-effects. not this.hasGlobalOrStdName([ "strcmp", "wcscmp", "_mbscmp", "strlen", "wcslen", "_mbslen", "_mbslen_l", "_mbstrlen", "_mbstrlen_l", "strnlen", "strnlen_s", "wcsnlen", "wcsnlen_s", "_mbsnlen", "_mbsnlen_l", "_mbstrnlen", "_mbstrnlen_l", "strncmp", "wcsncmp", "_mbsncmp", "_mbsncmp_l", "strchr", "memchr", "wmemchr", "memcmp", "wmemcmp", "_memicmp", "_memicmp_l", "feof", "isdigit", "isxdigit", "abs", "fabs", "labs", "floor", "ceil", "atoi", "atol", "atoll", "atof" ]) } /** * Gets the nearest enclosing AccessHolder. */ override AccessHolder getEnclosingAccessHolder() { result = this.getDeclaringType() } /** * Holds if this function has extraction errors that create an `ErrorExpr`. */ predicate hasErrors() { exists(ErrorExpr e | e.getEnclosingFunction() = this and // Exclude the first allocator call argument because it is always extracted as `ErrorExpr`. not exists(NewOrNewArrayExpr new | e = new.getAllocatorCall().getArgument(0)) ) } } pragma[noinline] private predicate candGetAnOverloadMember(string name, Class declaringType, Function f) { f.getName() = name and f.getDeclaringType() = declaringType } pragma[noinline] private predicate candGetAnOverloadNonMember(string name, Namespace namespace, Function f) { f.getName() = name and f.getNamespace() = namespace and not exists(f.getDeclaringType()) } /** * A particular declaration or definition of a C/C++ function. For example the * declaration and definition of `MyFunction` in the following code are each a * `FunctionDeclarationEntry`: * ``` * void MyFunction(); * * void MyFunction() { * DoSomething(); * } * ``` */ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { /** Gets the function which is being declared or defined. */ override Function getDeclaration() { result = this.getFunction() } override string getAPrimaryQlClass() { result = "FunctionDeclarationEntry" } /** Gets the function which is being declared or defined. */ Function getFunction() { fun_decls(underlyingElement(this), unresolveElement(result), _, _, _) } /** Gets the name of the function. */ override string getName() { fun_decls(underlyingElement(this), _, _, result, _) } /** * Gets the return type of the function which is being declared or * defined. */ override Type getType() { fun_decls(underlyingElement(this), _, unresolveElement(result), _, _) } /** Gets the location of this declaration entry. */ override Location getLocation() { fun_decls(underlyingElement(this), _, _, _, result) } /** Gets a specifier associated with this declaration entry. */ override string getASpecifier() { fun_decl_specifiers(underlyingElement(this), result) } /** * Implements `Element.getEnclosingElement`. A function declaration does * not have an enclosing element. */ override Element getEnclosingElement() { none() } /** * Gets the typedef type (if any) used for this function declaration. As * an example, the typedef type in the declaration of function foo in the * following is Foo: * * typedef int Foo(); * static Foo foo; */ TypedefType getTypedefType() { fun_decl_typedef_type(underlyingElement(this), unresolveElement(result)) } /** * Gets the cyclomatic complexity of this function: * * The number of branching statements (if, while, do, for, switch, * case, catch) plus the number of branching expressions (`?`, `&&`, * `||`) plus one. */ int getCyclomaticComplexity() { result = 1 + cyclomaticComplexityBranches(this.getBlock()) } /** * If this is a function definition, get the block containing the * function body. */ BlockStmt getBlock() { this.isDefinition() and result = this.getFunction().getBlock() and result.getFile() = this.getFile() } /** * If this is a function definition, get the number of lines of code * associated with it. */ pragma[noopt] int getNumberOfLines() { exists(BlockStmt b, Location l, int start, int end, int diff | b = this.getBlock() | l = b.getLocation() and start = l.getStartLine() and end = l.getEndLine() and diff = end - start and result = diff + 1 ) } /** * Gets the declaration entry for a parameter of this function * declaration. */ ParameterDeclarationEntry getAParameterDeclarationEntry() { result = this.getParameterDeclarationEntry(_) } /** * Gets the declaration entry for the nth parameter of this function * declaration. */ ParameterDeclarationEntry getParameterDeclarationEntry(int n) { param_decl_bind(unresolveElement(result), n, underlyingElement(this)) } /** Gets the number of parameters of this function declaration. */ int getNumberOfParameters() { result = count(this.getAParameterDeclarationEntry()) } /** * Gets a string representing the parameters of this function declaration. * * For example: for a function 'int Foo(int p1, int p2)' this would * return 'int p1, int p2'. */ string getParameterString() { result = concat(int i | | min(this.getParameterDeclarationEntry(i).getTypedName()), ", " order by i) } /** * Holds if this declaration entry specifies C linkage: * * `extern "C" void foo();` */ predicate hasCLinkage() { this.getASpecifier() = "c_linkage" } /** Holds if this declaration entry has a void parameter list. */ predicate hasVoidParamList() { this.getASpecifier() = "void_param_list" } /** Holds if this declaration is also a definition of its function. */ override predicate isDefinition() { fun_def(underlyingElement(this)) } /** Holds if this declaration is a template specialization. */ predicate isSpecialization() { fun_specialized(underlyingElement(this)) } /** * Holds if this declaration is an implicit function declaration, that is, * where a function is used before it is declared (under older C standards, * or when there were parse errors). */ predicate isImplicit() { fun_implicit(underlyingElement(this)) } /** Gets a type that is specified to be thrown by the declared function. */ Type getAThrownType() { result = this.getThrownType(_) } /** * Gets the `i`th type specified to be thrown by the declared function * (where `i` is indexed from 0). For example, if a function is declared * to `throw(int,float)`, then the thrown type with index 0 would be * `int`, and that with index 1 would be `float`. */ Type getThrownType(int i) { fun_decl_throws(underlyingElement(this), i, unresolveElement(result)) } /** * If this declaration has a noexcept-specification [N4140 15.4], then * this predicate returns the argument to `noexcept` if one was given. */ Expr getNoExceptExpr() { fun_decl_noexcept(underlyingElement(this), unresolveElement(result)) } /** * Holds if the declared function has an exception specification [N4140 * 15.4]. */ predicate hasExceptionSpecification() { fun_decl_throws(underlyingElement(this), _, _) or fun_decl_noexcept(underlyingElement(this), _) or this.isNoThrow() or this.isNoExcept() } /** * Holds if the declared function has a `throw()` exception specification. */ predicate isNoThrow() { fun_decl_empty_throws(underlyingElement(this)) } /** * Holds if the declared function has an empty `noexcept` exception * specification. */ predicate isNoExcept() { fun_decl_empty_noexcept(underlyingElement(this)) } /** * Gets a requires clause if this declaration is a template with such a clause. */ Expr getARequiresClause() { fun_requires(underlyingElement(this), _, unresolveElement(result)) } /** * Gets the requires clause that appears after the template argument list if this * declaration is a template with such a clause. */ Expr getTemplateRequiresClause() { fun_requires(underlyingElement(this), 1, unresolveElement(result)) } /** * Gets the requires clause that appears after the declarator if this declaration * is a template with such a clause. */ Expr getFunctionRequiresClause() { fun_requires(underlyingElement(this), 2, unresolveElement(result)) } } /** * A C/C++ non-member function (a function that is not a member of any * class). For example, in the following code, `MyFunction` is a * `TopLevelFunction` but `MyMemberFunction` is not: * ``` * void MyFunction() { * DoSomething(); * } * * class MyClass { * public: * void MyMemberFunction() { * DoSomething(); * } * }; * ``` */ class TopLevelFunction extends Function { TopLevelFunction() { not this.isMember() } override string getAPrimaryQlClass() { result = "TopLevelFunction" } } /** * A C++ user-defined operator [N4140 13.5]. */ class Operator extends Function { Operator() { functions(underlyingElement(this), _, 5) } override string getAPrimaryQlClass() { not this instanceof MemberFunction and result = "Operator" } } /** * A C++ function which has a non-empty template argument list. For example * the function `myTemplateFunction` in the following code: * ``` * template * void myTemplateFunction(T t) { * ... * } * ``` * * This comprises function declarations which are immediately preceded by * `template <...>`, where the "..." part is not empty, and therefore it does * not include: * * 1. Full specializations of template functions, as they have an empty * template argument list. * 2. Instantiations of template functions, as they don't have an * explicit template argument list. * 3. Member functions of template classes - unless they have their own * (non-empty) template argument list. */ class TemplateFunction extends Function { TemplateFunction() { is_function_template(underlyingElement(this)) and exists(this.getATemplateArgument()) } override string getAPrimaryQlClass() { result = "TemplateFunction" } /** * Gets a compiler-generated instantiation of this function template. */ Function getAnInstantiation() { result.isConstructedFrom(this) and not result.isSpecialization() } /** * Gets a full specialization of this function template. * * Note that unlike classes, functions overload rather than specialize * partially. Therefore this does not include things which "look like" * partial specializations, nor does it include full specializations of * such things -- see FunctionTemplateSpecialization for further details. */ FunctionTemplateSpecialization getASpecialization() { result.getPrimaryTemplate() = this } } /** * A function that is an instantiation of a template. For example * the instantiation `myTemplateFunction` in the following code: * ``` * template * void myTemplateFunction(T t) { * ... * } * * void caller(int i) { * myTemplateFunction(i); * } * ``` */ class FunctionTemplateInstantiation extends Function { TemplateFunction tf; FunctionTemplateInstantiation() { tf.getAnInstantiation() = this } override string getAPrimaryQlClass() { result = "FunctionTemplateInstantiation" } /** * Gets the function template from which this instantiation was instantiated. * * Example: For `int const& std::min(int const&, int const&)`, returns `T const& min(T const&, T const&)`. */ TemplateFunction getTemplate() { result = tf } } /** * An explicit specialization of a C++ function template. For example the * function `myTemplateFunction` in the following code: * ``` * template * void myTemplateFunction(T t) { * ... * } * * template<> * void myTemplateFunction(int i) { * ... * } * ``` * * Note that unlike classes, functions overload rather than specialize * partially. Therefore this only includes the last two of the following * four definitions, and in particular does not include the second one: * * ``` * template void f(T) {...} * template void f(T*) {...} * template <> void f(int *) {...} * template <> void f(int *) {...} * ``` * * Furthermore, this does not include compiler-generated instantiations of * function templates. * * For further reference on function template specializations, see: * http://www.gotw.ca/publications/mill17.htm */ class FunctionTemplateSpecialization extends Function { FunctionTemplateSpecialization() { this.isSpecialization() } override string getAPrimaryQlClass() { result = "FunctionTemplateSpecialization" } /** * Gets the primary template for the specialization (the function template * this specializes). */ TemplateFunction getPrimaryTemplate() { this.isConstructedFrom(result) } } /** * A GCC built-in function. For example: `__builtin___memcpy_chk`. */ class BuiltInFunction extends Function { BuiltInFunction() { functions(underlyingElement(this), _, 6) } /** Gets a dummy location for the built-in function. */ override Location getLocation() { suppressUnusedThis(this) and result instanceof UnknownDefaultLocation } } private predicate suppressUnusedThis(Function f) { any() } /** * A C++ user-defined literal [N4140 13.5.8]. */ class UserDefinedLiteral extends Function { UserDefinedLiteral() { functions(underlyingElement(this), _, 7) } } /** * A C++ deduction guide [N4659 17.9]. */ class DeductionGuide extends Function { DeductionGuide() { functions(underlyingElement(this), _, 8) } /** * Gets the class template for which this is a deduction guide. */ TemplateClass getTemplateClass() { deduction_guide_for_class(underlyingElement(this), unresolveElement(result)) } }