|
16 | 16 |
|
17 | 17 | import cpp |
18 | 18 | private import ExceptionFlow |
| 19 | +private import codingstandards.cpp.Function |
19 | 20 | private import codingstandards.cpp.Swap |
20 | 21 | private import codingstandards.cpp.EncapsulatingFunctions |
21 | 22 | private import codingstandards.cpp.exceptions.ExceptionFlow |
22 | 23 |
|
23 | 24 | /** A special function. */ |
24 | 25 | class SpecialFunction extends Function { |
| 26 | + string specialDescription; |
| 27 | + |
25 | 28 | SpecialFunction() { |
26 | | - this instanceof MoveAssignmentOperator |
| 29 | + this instanceof MoveAssignmentOperator and |
| 30 | + specialDescription = "move assignment operator" |
27 | 31 | or |
28 | | - this instanceof MoveConstructor |
| 32 | + this instanceof MoveConstructor and |
| 33 | + specialDescription = "move constructor" |
29 | 34 | or |
30 | | - this instanceof Destructor |
| 35 | + this instanceof Destructor and |
| 36 | + specialDescription = "destructor" |
31 | 37 | or |
32 | | - this instanceof DeallocationFunction |
| 38 | + this instanceof DeallocationFunction and |
| 39 | + specialDescription = "deallocation function" |
33 | 40 | or |
34 | | - this instanceof SwapFunction |
| 41 | + this instanceof SwapFunction and |
| 42 | + specialDescription = "swap function" |
| 43 | + } |
| 44 | + |
| 45 | + string getSpecialDescription() { result = specialDescription } |
| 46 | +} |
| 47 | + |
| 48 | +/** |
| 49 | + * A function which isn't special by itself, but is used in a special context. |
| 50 | + * |
| 51 | + * For example, functions which are reachable from initializers of static or thread-local |
| 52 | + * variables can result in implementation-defined behavior if they throw exceptions. |
| 53 | + */ |
| 54 | +abstract class SpecialUseOfFunction extends Expr { |
| 55 | + abstract Function getFunction(); |
| 56 | + |
| 57 | + abstract string getSpecialDescription(Locatable extra, string extraString); |
| 58 | +} |
| 59 | + |
| 60 | +class FunctionUsedInInitializer extends FunctionCall, SpecialUseOfFunction { |
| 61 | + Variable var; |
| 62 | + |
| 63 | + FunctionUsedInInitializer() { |
| 64 | + (var.isStatic() or var.isThreadLocal() or var.isTopLevel()) and |
| 65 | + exists(Expr initializer | |
| 66 | + var.getInitializer().getExpr() = initializer and |
| 67 | + getParent*() = initializer |
| 68 | + ) |
| 69 | + } |
| 70 | + |
| 71 | + override Function getFunction() { result = this.getTarget() } |
| 72 | + |
| 73 | + override string getSpecialDescription(Locatable extra, string extraString) { |
| 74 | + result = "used to initialize variable $@" and |
| 75 | + extra = var and |
| 76 | + extraString = var.getName() |
| 77 | + } |
| 78 | +} |
| 79 | + |
| 80 | +class FunctionGivenToStdExitHandler extends FunctionAccess, SpecialUseOfFunction { |
| 81 | + Function exitHandler; |
| 82 | + FunctionCall exitHandlerCall; |
| 83 | + |
| 84 | + FunctionGivenToStdExitHandler() { |
| 85 | + exitHandler.hasGlobalOrStdName(["atexit", "at_quick_exit", "set_terminate"]) and |
| 86 | + exitHandlerCall.getTarget() = exitHandler and |
| 87 | + exitHandlerCall.getArgument(0) = this |
| 88 | + } |
| 89 | + |
| 90 | + override Function getFunction() { result = getTarget() } |
| 91 | + |
| 92 | + override string getSpecialDescription(Locatable extra, string extraString) { |
| 93 | + result = "$@" and |
| 94 | + extra = exitHandlerCall and |
| 95 | + extraString = "passed to the exit handler std::" + exitHandler.getName() |
| 96 | + } |
| 97 | +} |
| 98 | + |
| 99 | +class FunctionPassedToExternC extends FunctionAccessLikeExpr, SpecialUseOfFunction { |
| 100 | + Function cFunction; |
| 101 | + FunctionCall cFunctionCall; |
| 102 | + |
| 103 | + FunctionPassedToExternC() { |
| 104 | + cFunction.hasCLinkage() and |
| 105 | + cFunction = cFunctionCall.getTarget() and |
| 106 | + cFunctionCall.getAnArgument() = this |
| 107 | + } |
| 108 | + |
| 109 | + override Function getFunction() { result = this.(FunctionAccessLikeExpr).getFunction() } |
| 110 | + |
| 111 | + override string getSpecialDescription(Locatable extra, string extraString) { |
| 112 | + result = "$@ extern \"C\" function '" + cFunction.getName() + "'" and |
| 113 | + extra = cFunctionCall and |
| 114 | + extraString = "passed to" |
35 | 115 | } |
36 | 116 | } |
37 | 117 |
|
|
0 commit comments