11import cpp
22
3- private string getATgMathMacroName ( boolean allowComplex ) {
3+ private string getATgMathMacroName ( boolean allowComplex , int numberOfParameters ) {
44 allowComplex = true and
5+ numberOfParameters = 1 and
56 result =
67 [
78 "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" ,
923 ]
1024 or
1125 allowComplex = false and
26+ numberOfParameters = 2 and
1227 result =
1328 [
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"
1831 ]
32+ or
33+ allowComplex = false and
34+ numberOfParameters = 3 and
35+ result = [ "fma" , "remquo" ]
1936}
2037
2138private predicate hasOutputArgument ( string macroName , int index ) {
@@ -27,19 +44,41 @@ private predicate hasOutputArgument(string macroName, int index) {
2744class TgMathInvocation extends MacroInvocation {
2845 Call call ;
2946 boolean allowComplex ;
47+ int numberOfParameters ;
3048
3149 TgMathInvocation ( ) {
32- this .getMacro ( ) .getName ( ) = getATgMathMacroName ( allowComplex ) and
50+ this .getMacro ( ) .getName ( ) = getATgMathMacroName ( allowComplex , numberOfParameters ) and
3351 call = getBestCallInExpansion ( this )
3452 }
3553
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+
3662 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+ )
3978 }
4079
4180 int getNumberOfOperandArguments ( ) {
42- result = call . getNumberOfArguments ( ) - count ( int i | hasOutputArgument ( getMacroName ( ) , i ) )
81+ result = numberOfParameters - count ( int i | hasOutputArgument ( getMacroName ( ) , i ) )
4382 }
4483
4584 Expr getAnOperandArgument ( ) { result = getOperandArgument ( _) }
0 commit comments