1 /** 2 Copyright: Copyright (c) 2017, Joakim Brännström. All rights reserved. 3 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 This file uses the same license as the C++ source code. 7 */ 8 module dextool.clang_extensions; 9 10 import clang.c.Index; 11 12 extern (C++,dextool_clang_extension) { 13 extern (C++,McCabe) { 14 extern (C++) struct Result { 15 /// Only valid values if true. 16 bool hasValue; 17 /// McCabe complexity 18 int value; 19 } 20 21 /** Calculate the McCabe complexity. 22 * 23 * Valid cursors are those with a body. 24 * decl.isDefinition must be true. 25 * 26 * Tested CXCursor kinds that are definitions: 27 * - FunctionDecl 28 * - ConversionFunction 29 * - Constructor 30 * - Destructor 31 * - CXXMethod 32 */ 33 extern (C++) Result calculate(CXCursor decl); 34 } 35 36 /// Represent the operator of an expression that contains an operator (binary or unary). 37 extern (C++) struct DXOperator { 38 /// Only valid values if true. 39 bool hasValue; 40 OpKind kind; 41 42 /// The location of the operator 43 CXSourceLocation location; 44 /// Character length of the operator 45 byte opLength; 46 47 /// The cursor for the operator. 48 CXCursor cursor; 49 } 50 51 enum ValueKind { 52 unknown, 53 lvalue, 54 rvalue, 55 xvalue, 56 glvalue 57 } 58 59 enum OpKind { 60 // See: include/clang/AST/OperationKinds.def under section Binary Operations 61 62 // [C++ 5.5] Pointer-to-member operators. 63 PtrMemD, // ".*" 64 PtrMemI, // "->*" 65 // [C99 6.5.5] Multiplicative operators. 66 Mul, // "*" 67 Div, // "/" 68 Rem, // "%" 69 // [C99 6.5.6] Additive operators. 70 Add, // "+" 71 Sub, // "-" 72 // [C99 6.5.7] Bitwise shift operators. 73 Shl, // "<<" 74 Shr, // ">>" 75 // [C99 6.5.8] Relational operators. 76 LT, // "<" 77 GT, // ">" 78 LE, // "<=" 79 GE, // ">=" 80 // [C99 6.5.9] Equality operators. 81 EQ, // "==" 82 NE, // "!=" 83 // [C99 6.5.10] Bitwise AND operator. 84 And, // "&" 85 // [C99 6.5.11] Bitwise XOR operator. 86 Xor, // "^" 87 // [C99 6.5.12] Bitwise OR operator. 88 Or, // "|" 89 // [C99 6.5.13] Logical AND operator. 90 LAnd, // "&&" 91 // [C99 6.5.14] Logical OR operator. 92 LOr, // "||" 93 // [C99 6.5.16] Assignment operators. 94 Assign, // "=" 95 MulAssign, // "*=" 96 DivAssign, // "/=" 97 RemAssign, // "%=" 98 AddAssign, // "+=" 99 SubAssign, // "-=" 100 ShlAssign, // "<<=" 101 ShrAssign, // ">>=" 102 AndAssign, // "&=" 103 XorAssign, // "^=" 104 OrAssign, // "|=" 105 // [C99 6.5.17] Comma operator. 106 Comma, // "," 107 108 // See: include/clang/AST/OperationKinds.def under section Unary Operations 109 // [C99 6.5.2.4] Postfix increment and decrement 110 PostInc, // "++" 111 PostDec, // "--" 112 // [C99 6.5.3.1] Prefix increment and decrement 113 PreInc, // "++" 114 PreDec, // "--" 115 // [C99 6.5.3.2] Address and indirection 116 AddrOf, // "&" 117 Deref, // "*" 118 // [C99 6.5.3.3] Unary arithmetic 119 Plus, // "+" 120 Minus, // "-" 121 Not, // "~" 122 LNot, // "!" 123 // "__real expr"/"__imag expr" Extension. 124 Real, // "__real" 125 Imag, // "__imag" 126 // __extension__ marker. 127 Extension, // "__extension__" 128 // [C++ Coroutines] co_await operator 129 Coawait, // "co_await" 130 131 // See: include/clang/Basic/OperationKinds.def 132 // CXXOperatorCallExpr->getOperator kinds 133 OO_New, // "new" 134 OO_Delete, // "delete" 135 OO_Array_New, // "new[] 136 OO_Array_Delete, // "delete[] 137 OO_Plus, // "+" 138 OO_Minus, // "-" 139 OO_Star, // "*" 140 OO_Slash, // "/" 141 OO_Percent, // "%" 142 OO_Caret, // "^" 143 OO_Amp, // "&" 144 OO_Pipe, // "|" 145 OO_Tilde, // "~" 146 OO_Exclaim, // "!" 147 OO_Equal, // "=" 148 OO_Less, // "<" 149 OO_Greater, // ">" 150 OO_PlusEqual, // "+=" 151 OO_MinusEqual, // "-=" 152 OO_StarEqual, // "*=" 153 OO_SlashEqual, // "/=" 154 OO_PercentEqual, // "%=" 155 OO_CaretEqual, // "^=" 156 OO_AmpEqual, // "&=" 157 OO_PipeEqual, // "|=" 158 OO_LessLess, // "<<" 159 OO_GreaterGreater, // ">>" 160 OO_LessLessEqual, // "<<=" 161 OO_GreaterGreaterEqual, // ">>=" 162 OO_EqualEqual, // "==" 163 OO_ExclaimEqual, // "!=" 164 OO_LessEqual, // "<=" 165 OO_GreaterEqual, // ">=" 166 OO_AmpAmp, // "&&" 167 OO_PipePipe, // "||" 168 OO_PlusPlus, // "++" 169 OO_MinusMinus, // "--" 170 OO_Comma, // "," 171 OO_ArrowStar, // "->*" 172 OO_Arrow, // "->" 173 OO_Call, // "()" 174 OO_Subscript, // "[]" 175 OO_Conditional, // "?" 176 OO_Coawait, // "co_await" 177 } 178 179 /** Retrieve the operator of an expression. 180 * 181 * Acceptable CXCursor kinds are: 182 * - binaryOperator 183 * - unaryOperator 184 * - callExpr 185 */ 186 extern (C++) DXOperator dex_getExprOperator(const CXCursor expr); 187 188 /// The sub-expressions of an operator expression. 189 extern (C++) struct DXOperatorExprs { 190 CXCursor lhs; 191 CXCursor rhs; 192 } 193 194 /** Retrieve the left and right side of an operator expression. 195 * 196 * Acceptable CXCursor kinds are: 197 * - binaryOperator 198 * - unaryOperator 199 * - callExpr 200 */ 201 extern (C++) DXOperatorExprs dex_getOperatorExprs(const CXCursor expr); 202 203 /// Retrieve the value kind of the expression. 204 extern (C++) ValueKind dex_getExprValueKind(const CXCursor expr); 205 206 /// Get the first node after the expressions. 207 extern (C++) CXCursor dex_getUnderlyingExprNode(const CXCursor expr); 208 209 /// The cursors that make up the inside of the if statement. 210 extern (C++) struct DXIfStmt { 211 CXCursor init_; 212 CXCursor cond; 213 CXCursor then; 214 CXCursor else_; 215 } 216 217 extern (C++) DXIfStmt dex_getIfStmt(const CXCursor cx); 218 219 extern (C++) struct DXCaseStmt { 220 bool hasValue; 221 CXSourceLocation colonLoc; 222 CXCursor subStmt; 223 } 224 225 extern (C++) DXCaseStmt dex_getCaseStmt(const CXCursor cx); 226 } 227 228 Operator getExprOperator(const CXCursor expr) @trusted { 229 import std.algorithm : among; 230 231 // This check is technically not needed because the C++ source code try to 232 // do a dynamic cast. But by having a check here it is easier to review 233 // that THIS function is correctly implemented. 234 // This function is safe for all possible inputs. 235 // Note: CXXOperatorCallExpr is denoted callExpr in the C API. 236 if (clang_getCursorKind(expr).among(CXCursorKind.binaryOperator, 237 CXCursorKind.unaryOperator, CXCursorKind.callExpr)) { 238 return Operator(dex_getExprOperator(expr)); 239 } 240 241 return Operator(); 242 } 243 244 /** 245 * trusted: the C++ impl check that the node is an expression. 246 * It can handle any CursorKind. 247 */ 248 ValueKind exprValueKind(const CXCursor expr) @trusted { 249 return dex_getExprValueKind(expr); 250 } 251 252 /** 253 * trusted: the C++ impl check that the node is an expression. 254 * It can handle any CursorKind. 255 */ 256 auto getUnderlyingExprNode(const CXCursor expr) @trusted { 257 return dex_getUnderlyingExprNode(expr); 258 } 259 260 @safe struct OperatorSubExprs { 261 import clang.Cursor; 262 263 Cursor lhs, rhs; 264 } 265 266 @safe struct Operator { 267 import std.format : FormatSpec; 268 import clang.Cursor; 269 import clang.SourceLocation; 270 271 private DXOperator dx; 272 273 this(DXOperator v) { 274 dx = v; 275 } 276 277 bool isValid() const { 278 return dx.hasValue; 279 } 280 281 auto kind() const { 282 return dx.kind; 283 } 284 285 /// Cursor for the expression that the operator reside in. 286 Cursor cursor() const { 287 return Cursor(dx.cursor); 288 } 289 290 /** Retrieve the sub expressions of an operator expressions. 291 * 292 * rhs is the null cursor for unary operators. 293 * 294 * Returns: The sides of the expression. 295 * 296 * trusted: 297 * dex_getOperatorExprs is limited to only being able to handle operator 298 * expressions. 299 * getExprOperator only processes binary, unary and callExpr cursors. 300 * This lead to isValid only returning true when the cursor is of that type. 301 * Thus the limitation of dex_getOperatorExprs is fulfilled. 302 * 303 * TODO Further audit of the C++ implementation of dex_getOperatorExprs is 304 * needed. 305 */ 306 OperatorSubExprs sides() const @trusted { 307 OperatorSubExprs r; 308 309 if (isValid) { 310 auto sub_exprs = dex_getOperatorExprs(dx.cursor); 311 r = OperatorSubExprs(Cursor(sub_exprs.lhs), Cursor(sub_exprs.rhs)); 312 } 313 314 return r; 315 } 316 317 SourceLocation location() const { 318 return SourceLocation(dx.location); 319 } 320 321 /// The character length of the operator. 322 size_t length() const { 323 return dx.opLength; 324 } 325 326 void toString(Writer, Char)(scope Writer w, FormatSpec!Char fmt) const { 327 import std.format : formatValue, formattedWrite; 328 import std.range.primitives : put; 329 330 put(w, "Operator("); 331 formatValue(w, kind, fmt); 332 put(w, " len:"); 333 formatValue(w, length, fmt); 334 put(w, " "); 335 formatValue(w, location, fmt); 336 put(w, ")"); 337 } 338 } 339 340 IfStmt getIfStmt(const CXCursor cx) @trusted { 341 if (clang_getCursorKind(cx) == CXCursorKind.ifStmt) 342 return IfStmt(cx, dex_getIfStmt(cx)); 343 344 return IfStmt(); 345 } 346 347 @safe struct IfStmt { 348 import std.format : FormatSpec; 349 import clang.Cursor; 350 351 private Cursor cx; 352 private DXIfStmt stmt; 353 354 this(const CXCursor parent_, DXIfStmt stmt) { 355 this.cx = Cursor(parent_); 356 this.stmt = stmt; 357 } 358 359 Cursor cursor() const { 360 return cx; 361 } 362 363 Cursor init_() const { 364 return Cursor(stmt.init_); 365 } 366 367 Cursor cond() const { 368 return Cursor(stmt.cond); 369 } 370 371 Cursor then() const { 372 return Cursor(stmt.then); 373 } 374 375 Cursor else_() const { 376 return Cursor(stmt.else_); 377 } 378 379 string toString() const { 380 import std.exception : assumeUnique; 381 import std.format : FormatSpec; 382 383 char[] buf; 384 buf.reserve(100); 385 auto fmt = FormatSpec!char("%s"); 386 toString((const(char)[] s) { buf ~= s; }, fmt); 387 auto trustedUnique(T)(T t) @trusted { 388 return assumeUnique(t); 389 } 390 391 return trustedUnique(buf); 392 } 393 394 void toString(Writer, Char)(scope Writer w, FormatSpec!Char fmt) const { 395 import std.algorithm : copy, map, joiner, filter; 396 import std.range : put; 397 398 put(w, "if ("); 399 if (init_.isValid) { 400 () @trusted { 401 init_.tokens.map!(a => a.spelling).joiner(" ").copy(w); 402 }(); 403 put(w, "; "); 404 } 405 () @trusted { cond.tokens.map!(a => a.spelling).joiner(" ").copy(w); }(); 406 put(w, ") "); 407 408 foreach (c; [then, else_].filter!(a => a.isValid)) { 409 () @trusted { 410 auto toks = c.tokens; 411 // only one case here and that is a `return foo;`. The trailing 412 // `;` is not part of the token range so an extra has to be 413 // appended at the end. 414 bool is_keyword = toks.length > 0 && toks[0].kind == CXTokenKind.keyword; 415 c.tokens.map!(a => a.spelling).joiner(" ").copy(w); 416 if (is_keyword) 417 put(w, "; "); 418 }(); 419 } 420 } 421 } 422 423 @safe struct CaseStmt { 424 import std.format : FormatSpec; 425 import clang.Cursor; 426 import clang.SourceLocation; 427 428 private DXCaseStmt dx; 429 430 this(DXCaseStmt dx) { 431 this.dx = dx; 432 } 433 434 bool isValid() const { 435 return dx.hasValue; 436 } 437 438 /// Cursor for the sub-stmt that reside inside the case. 439 Cursor subStmt() const { 440 return Cursor(dx.subStmt); 441 } 442 443 SourceLocation colonLocation() const { 444 return SourceLocation(dx.colonLoc); 445 } 446 447 void toString(Writer, Char)(scope Writer w, FormatSpec!Char fmt) const { 448 import std.format : formatValue; 449 import std.range.primitives : put; 450 451 put(w, "CaseStmt(colon:"); 452 put(w, subStmt.spelling); 453 put(w, " colon:"); 454 formatValue(w, location, fmt); 455 put(w, ")"); 456 } 457 } 458 459 CaseStmt getCaseStmt(const CXCursor c) @trusted { 460 // This check is technically not needed because the C++ source code perform a dynamic cast. 461 // But extra safety can't hurt? 462 if (clang_getCursorKind(c) == CXCursorKind.caseStmt) { 463 return CaseStmt(dex_getCaseStmt(c)); 464 } 465 466 return CaseStmt(); 467 }