| 388 | private: |
| 389 | |
| 390 | Annotator::DeclType classify() { |
| 391 | bool first = true; |
| 392 | clang::Expr *previous = nullptr; |
| 393 | for (auto expr : expr_stack) { |
| 394 | if (first) { |
| 395 | previous = expr; |
| 396 | first = false; |
| 397 | continue; //skip the first element (ourself) |
| 398 | } |
| 399 | if (llvm::isa<clang::MemberExpr>(expr)) { |
| 400 | return Annotator::Use_MemberAccess; |
| 401 | } |
| 402 | if (auto op = llvm::dyn_cast<clang::ImplicitCastExpr>(expr)) { |
| 403 | if (op->getCastKind() == clang::CK_LValueToRValue) |
| 404 | return Annotator::Use_Read; |
| 405 | } |
| 406 | if (auto op = llvm::dyn_cast<clang::BinaryOperator>(expr)) { |
| 407 | if (op->isAssignmentOp() && op->getLHS() == previous) |
| 408 | return Annotator::Use_Write; |
| 409 | return Annotator::Use_Read; |
| 410 | } |
| 411 | if (auto op = llvm::dyn_cast<clang::UnaryOperator>(expr)) { |
| 412 | if (op->isIncrementDecrementOp()) |
| 413 | return Annotator::Use_Write; |
| 414 | if (op->isArithmeticOp() || op->getOpcode() == clang::UO_Deref) |
| 415 | return Annotator::Use_Read; |
| 416 | if (op->getOpcode() == clang::UO_AddrOf) |
| 417 | return Annotator::Use_Address; |
| 418 | return Annotator::Use; |
| 419 | } |
| 420 | if (auto op = llvm::dyn_cast<clang::CXXOperatorCallExpr>(expr)) { |
| 421 | // Special case for some of the CXXOperatorCallExpr to check if it is Use_Write |
| 422 | // Anything else goes through normal CallExpr |
| 423 | auto o = op->getOperator(); |
| 424 | if (o == clang::OO_Equal || (o >= clang::OO_PlusEqual && o <= clang::OO_PipeEqual) |
| 425 | || (o >= clang::OO_LessLessEqual && o <= clang::OO_GreaterGreaterEqual) |
| 426 | || (o >= clang::OO_PlusPlus && o <= clang::OO_MinusMinus) ) { |
| 427 | if (op->getNumArgs() >= 1 && op->getArg(0) == previous) { |
| 428 | return Annotator::Use_Write; |
| 429 | } |
| 430 | } |
| 431 | } |
| 432 | if (auto call = llvm::dyn_cast<clang::CallExpr>(expr)) { |
| 433 | if (previous == call->getCallee()) |
| 434 | return Annotator::Use_Call; |
| 435 | auto decl = call->getDirectCallee(); |
| 436 | if (!decl) return Annotator::Use; |
| 437 | for (uint i = 0; i < call->getNumArgs(); ++i) { |
| 438 | if (call->getArg(i) != previous) |
| 439 | continue; |
| 440 | if (llvm::isa<clang::CXXOperatorCallExpr>(call) |
| 441 | && decl->getNumParams() < call->getNumArgs()) { |
| 442 | // For example, member operators: first argument is the 'this' |
| 443 | if (i == 0) |
| 444 | return Annotator::Use_MemberAccess; |
| 445 | i--; |
| 446 | } |
| 447 | if (i >= decl->getNumParams()) |
nothing calls this directly
no outgoing calls
no test coverage detected