1*e038c9c4Sjoerg //=======- ASTUtils.cpp ------------------------------------------*- C++ -*-==// 2*e038c9c4Sjoerg // 3*e038c9c4Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*e038c9c4Sjoerg // See https://llvm.org/LICENSE.txt for license information. 5*e038c9c4Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*e038c9c4Sjoerg // 7*e038c9c4Sjoerg //===----------------------------------------------------------------------===// 8*e038c9c4Sjoerg 9*e038c9c4Sjoerg #include "ASTUtils.h" 10*e038c9c4Sjoerg #include "PtrTypesSemantics.h" 11*e038c9c4Sjoerg #include "clang/AST/CXXInheritance.h" 12*e038c9c4Sjoerg #include "clang/AST/Decl.h" 13*e038c9c4Sjoerg #include "clang/AST/DeclCXX.h" 14*e038c9c4Sjoerg #include "clang/AST/ExprCXX.h" 15*e038c9c4Sjoerg 16*e038c9c4Sjoerg using llvm::Optional; 17*e038c9c4Sjoerg namespace clang { 18*e038c9c4Sjoerg 19*e038c9c4Sjoerg std::pair<const Expr *, bool> tryToFindPtrOrigin(const Expr * E,bool StopAtFirstRefCountedObj)20*e038c9c4SjoergtryToFindPtrOrigin(const Expr *E, bool StopAtFirstRefCountedObj) { 21*e038c9c4Sjoerg while (E) { 22*e038c9c4Sjoerg if (auto *cast = dyn_cast<CastExpr>(E)) { 23*e038c9c4Sjoerg if (StopAtFirstRefCountedObj) { 24*e038c9c4Sjoerg if (auto *ConversionFunc = 25*e038c9c4Sjoerg dyn_cast_or_null<FunctionDecl>(cast->getConversionFunction())) { 26*e038c9c4Sjoerg if (isCtorOfRefCounted(ConversionFunc)) 27*e038c9c4Sjoerg return {E, true}; 28*e038c9c4Sjoerg } 29*e038c9c4Sjoerg } 30*e038c9c4Sjoerg // FIXME: This can give false "origin" that would lead to false negatives 31*e038c9c4Sjoerg // in checkers. See https://reviews.llvm.org/D37023 for reference. 32*e038c9c4Sjoerg E = cast->getSubExpr(); 33*e038c9c4Sjoerg continue; 34*e038c9c4Sjoerg } 35*e038c9c4Sjoerg if (auto *call = dyn_cast<CallExpr>(E)) { 36*e038c9c4Sjoerg if (auto *memberCall = dyn_cast<CXXMemberCallExpr>(call)) { 37*e038c9c4Sjoerg Optional<bool> IsGetterOfRefCt = 38*e038c9c4Sjoerg isGetterOfRefCounted(memberCall->getMethodDecl()); 39*e038c9c4Sjoerg if (IsGetterOfRefCt && *IsGetterOfRefCt) { 40*e038c9c4Sjoerg E = memberCall->getImplicitObjectArgument(); 41*e038c9c4Sjoerg if (StopAtFirstRefCountedObj) { 42*e038c9c4Sjoerg return {E, true}; 43*e038c9c4Sjoerg } 44*e038c9c4Sjoerg continue; 45*e038c9c4Sjoerg } 46*e038c9c4Sjoerg } 47*e038c9c4Sjoerg 48*e038c9c4Sjoerg if (auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(E)) { 49*e038c9c4Sjoerg if (operatorCall->getNumArgs() == 1) { 50*e038c9c4Sjoerg E = operatorCall->getArg(0); 51*e038c9c4Sjoerg continue; 52*e038c9c4Sjoerg } 53*e038c9c4Sjoerg } 54*e038c9c4Sjoerg 55*e038c9c4Sjoerg if (auto *callee = call->getDirectCallee()) { 56*e038c9c4Sjoerg if (isCtorOfRefCounted(callee)) { 57*e038c9c4Sjoerg if (StopAtFirstRefCountedObj) 58*e038c9c4Sjoerg return {E, true}; 59*e038c9c4Sjoerg 60*e038c9c4Sjoerg E = call->getArg(0); 61*e038c9c4Sjoerg continue; 62*e038c9c4Sjoerg } 63*e038c9c4Sjoerg 64*e038c9c4Sjoerg if (isPtrConversion(callee)) { 65*e038c9c4Sjoerg E = call->getArg(0); 66*e038c9c4Sjoerg continue; 67*e038c9c4Sjoerg } 68*e038c9c4Sjoerg } 69*e038c9c4Sjoerg } 70*e038c9c4Sjoerg if (auto *unaryOp = dyn_cast<UnaryOperator>(E)) { 71*e038c9c4Sjoerg // FIXME: Currently accepts ANY unary operator. Is it OK? 72*e038c9c4Sjoerg E = unaryOp->getSubExpr(); 73*e038c9c4Sjoerg continue; 74*e038c9c4Sjoerg } 75*e038c9c4Sjoerg 76*e038c9c4Sjoerg break; 77*e038c9c4Sjoerg } 78*e038c9c4Sjoerg // Some other expression. 79*e038c9c4Sjoerg return {E, false}; 80*e038c9c4Sjoerg } 81*e038c9c4Sjoerg isASafeCallArg(const Expr * E)82*e038c9c4Sjoergbool isASafeCallArg(const Expr *E) { 83*e038c9c4Sjoerg assert(E); 84*e038c9c4Sjoerg if (auto *Ref = dyn_cast<DeclRefExpr>(E)) { 85*e038c9c4Sjoerg if (auto *D = dyn_cast_or_null<VarDecl>(Ref->getFoundDecl())) { 86*e038c9c4Sjoerg if (isa<ParmVarDecl>(D) || D->isLocalVarDecl()) 87*e038c9c4Sjoerg return true; 88*e038c9c4Sjoerg } 89*e038c9c4Sjoerg } 90*e038c9c4Sjoerg 91*e038c9c4Sjoerg // TODO: checker for method calls on non-refcounted objects 92*e038c9c4Sjoerg return isa<CXXThisExpr>(E); 93*e038c9c4Sjoerg } 94*e038c9c4Sjoerg 95*e038c9c4Sjoerg } // namespace clang 96