1
1
import cpp
2
2
3
- private string getATgMathMacroName ( boolean allowComplex ) {
3
+ private string getATgMathMacroName ( boolean allowComplex , int numberOfParameters ) {
4
4
allowComplex = true and
5
+ numberOfParameters = 1 and
5
6
result =
6
7
[
7
8
"acos" , "acosh" , "asin" , "asinh" , "atan" , "atanh" , "carg" , "cimag" , "conj" , "cos" , "cosh" ,
8
- "cproj" , "creal" , "exp" , "fabs" , "log" , "pow" , "sin" , "sinh" , "sqrt" , "tan" , "tanh"
9
+ "cproj" , "creal" , "exp" , "fabs" , "log" , "sin" , "sinh" , "sqrt" , "tan" , "tanh"
10
+ ]
11
+ or
12
+ allowComplex = true and
13
+ numberOfParameters = 2 and
14
+ result = "pow"
15
+ or
16
+ allowComplex = false and
17
+ numberOfParameters = 1 and
18
+ result =
19
+ [
20
+ "cbrt" , "ceil" , "erf" , "erfc" , "exp2" , "expm1" , "floor" , "ilogb" , "lgamma" , "llrint" ,
21
+ "llround" , "log10" , "log1p" , "log2" , "logb" , "lrint" , "lround" , "nearbyint" , "rint" , "round" ,
22
+ "tgamma" , "trunc" ,
9
23
]
10
24
or
11
25
allowComplex = false and
26
+ numberOfParameters = 2 and
12
27
result =
13
28
[
14
- "atan2" , "cbrt" , "ceil" , "copysign" , "erf" , "erfc" , "exp2" , "expm1" , "fdim" , "floor" , "fma" ,
15
- "fmax" , "fmin" , "fmod" , "frexp" , "hypot" , "ilogb" , "ldexp" , "lgamma" , "llrint" , "llround" ,
16
- "log10" , "log1p" , "log2" , "logb" , "lrint" , "lround" , "nearbyint" , "nextafter" , "nexttoward" ,
17
- "remainder" , "remquo" , "rint" , "round" , "scalbn" , "scalbln" , "tgamma" , "trunc" ,
29
+ "atan2" , "copysign" , "fdim" , "fmax" , "fmin" , "fmod" , "frexp" , "hypot" , "ldexp" , "nextafter" ,
30
+ "nexttoward" , "remainder" , "scalbn" , "scalbln"
18
31
]
32
+ or
33
+ allowComplex = false and
34
+ numberOfParameters = 3 and
35
+ result = [ "fma" , "remquo" ]
19
36
}
20
37
21
38
private predicate hasOutputArgument ( string macroName , int index ) {
@@ -27,19 +44,41 @@ private predicate hasOutputArgument(string macroName, int index) {
27
44
class TgMathInvocation extends MacroInvocation {
28
45
Call call ;
29
46
boolean allowComplex ;
47
+ int numberOfParameters ;
30
48
31
49
TgMathInvocation ( ) {
32
- this .getMacro ( ) .getName ( ) = getATgMathMacroName ( allowComplex ) and
50
+ this .getMacro ( ) .getName ( ) = getATgMathMacroName ( allowComplex , numberOfParameters ) and
33
51
call = getBestCallInExpansion ( this )
34
52
}
35
53
54
+ /** Account for extra parameters added by gcc */
55
+ private int getParameterOffset ( ) {
56
+ // Gcc calls look something like: `__builtin_tgmath(cosf, cosd, cosl, arg)`, in this example
57
+ // there is a parameter offset of 3, so `getOperandArgument(0)` is equivalent to
58
+ // `call.getArgument(3)`.
59
+ result = call .getNumberOfArguments ( ) - numberOfParameters
60
+ }
61
+
36
62
Expr getOperandArgument ( int i ) {
37
- result = call .getArgument ( i ) and
38
- not hasOutputArgument ( call .getTarget ( ) .getName ( ) , i )
63
+ i >= 0 and
64
+ result = call .getArgument ( i + getParameterOffset ( ) ) and
65
+ //i in [0..numberOfParameters - 1] and
66
+ not hasOutputArgument ( getMacro ( ) .getName ( ) , i )
67
+ }
68
+
69
+ /** Get all explicit conversions, except those added by clang in the macro body */
70
+ Expr getExplicitlyConvertedOperandArgument ( int i ) {
71
+ exists ( Expr explicitConv |
72
+ explicitConv = getOperandArgument ( i ) .getExplicitlyConverted ( ) and
73
+ // clang explicitly casts most arguments, but not some integer arguments such as in `scalbn`.
74
+ if call .getTarget ( ) .getName ( ) .matches ( "__tg_%" ) and explicitConv instanceof Conversion
75
+ then result = explicitConv .( Conversion ) .getExpr ( )
76
+ else result = explicitConv
77
+ )
39
78
}
40
79
41
80
int getNumberOfOperandArguments ( ) {
42
- result = call . getNumberOfArguments ( ) - count ( int i | hasOutputArgument ( getMacroName ( ) , i ) )
81
+ result = numberOfParameters - count ( int i | hasOutputArgument ( getMacroName ( ) , i ) )
43
82
}
44
83
45
84
Expr getAnOperandArgument ( ) { result = getOperandArgument ( _) }
0 commit comments