AnyCall.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //=== AnyCall.h - Abstraction over different callables --------*- C++ -*--//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // A utility class for performing generic operations over different callables.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. //
  18. #ifndef LLVM_CLANG_ANALYSIS_ANYCALL_H
  19. #define LLVM_CLANG_ANALYSIS_ANYCALL_H
  20. #include "clang/AST/Decl.h"
  21. #include "clang/AST/ExprCXX.h"
  22. #include "clang/AST/ExprObjC.h"
  23. #include <optional>
  24. namespace clang {
  25. /// An instance of this class corresponds to a call.
  26. /// It might be a syntactically-concrete call, done as a part of evaluating an
  27. /// expression, or it may be an abstract callee with no associated expression.
  28. class AnyCall {
  29. public:
  30. enum Kind {
  31. /// A function, function pointer, or a C++ method call
  32. Function,
  33. /// A call to an Objective-C method
  34. ObjCMethod,
  35. /// A call to an Objective-C block
  36. Block,
  37. /// An implicit C++ destructor call (called implicitly
  38. /// or by operator 'delete')
  39. Destructor,
  40. /// An implicit or explicit C++ constructor call
  41. Constructor,
  42. /// A C++ inherited constructor produced by a "using T::T" directive
  43. InheritedConstructor,
  44. /// A C++ allocation function call (operator `new`), via C++ new-expression
  45. Allocator,
  46. /// A C++ deallocation function call (operator `delete`), via C++
  47. /// delete-expression
  48. Deallocator
  49. };
  50. private:
  51. /// Either expression or declaration (but not both at the same time)
  52. /// can be null.
  53. /// Call expression, is null when is not known (then declaration is non-null),
  54. /// or for implicit destructor calls (when no expression exists.)
  55. const Expr *E = nullptr;
  56. /// Corresponds to a statically known declaration of the called function,
  57. /// or null if it is not known (e.g. for a function pointer).
  58. const Decl *D = nullptr;
  59. Kind K;
  60. public:
  61. AnyCall(const CallExpr *CE) : E(CE) {
  62. D = CE->getCalleeDecl();
  63. K = (CE->getCallee()->getType()->getAs<BlockPointerType>()) ? Block
  64. : Function;
  65. if (D && ((K == Function && !isa<FunctionDecl>(D)) ||
  66. (K == Block && !isa<BlockDecl>(D))))
  67. D = nullptr;
  68. }
  69. AnyCall(const ObjCMessageExpr *ME)
  70. : E(ME), D(ME->getMethodDecl()), K(ObjCMethod) {}
  71. AnyCall(const CXXNewExpr *NE)
  72. : E(NE), D(NE->getOperatorNew()), K(Allocator) {}
  73. AnyCall(const CXXDeleteExpr *NE)
  74. : E(NE), D(NE->getOperatorDelete()), K(Deallocator) {}
  75. AnyCall(const CXXConstructExpr *NE)
  76. : E(NE), D(NE->getConstructor()), K(Constructor) {}
  77. AnyCall(const CXXInheritedCtorInitExpr *CIE)
  78. : E(CIE), D(CIE->getConstructor()), K(InheritedConstructor) {}
  79. AnyCall(const CXXDestructorDecl *D) : E(nullptr), D(D), K(Destructor) {}
  80. AnyCall(const CXXConstructorDecl *D) : E(nullptr), D(D), K(Constructor) {}
  81. AnyCall(const ObjCMethodDecl *D) : E(nullptr), D(D), K(ObjCMethod) {}
  82. AnyCall(const FunctionDecl *D) : E(nullptr), D(D) {
  83. if (isa<CXXConstructorDecl>(D)) {
  84. K = Constructor;
  85. } else if (isa <CXXDestructorDecl>(D)) {
  86. K = Destructor;
  87. } else {
  88. K = Function;
  89. }
  90. }
  91. /// If @c E is a generic call (to ObjC method /function/block/etc),
  92. /// return a constructed @c AnyCall object. Return std::nullopt otherwise.
  93. static std::optional<AnyCall> forExpr(const Expr *E) {
  94. if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
  95. return AnyCall(ME);
  96. } else if (const auto *CE = dyn_cast<CallExpr>(E)) {
  97. return AnyCall(CE);
  98. } else if (const auto *CXNE = dyn_cast<CXXNewExpr>(E)) {
  99. return AnyCall(CXNE);
  100. } else if (const auto *CXDE = dyn_cast<CXXDeleteExpr>(E)) {
  101. return AnyCall(CXDE);
  102. } else if (const auto *CXCE = dyn_cast<CXXConstructExpr>(E)) {
  103. return AnyCall(CXCE);
  104. } else if (const auto *CXCIE = dyn_cast<CXXInheritedCtorInitExpr>(E)) {
  105. return AnyCall(CXCIE);
  106. } else {
  107. return std::nullopt;
  108. }
  109. }
  110. /// If @c D is a callable (Objective-C method or a function), return
  111. /// a constructed @c AnyCall object. Return std::nullopt otherwise.
  112. // FIXME: block support.
  113. static std::optional<AnyCall> forDecl(const Decl *D) {
  114. if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
  115. return AnyCall(FD);
  116. } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
  117. return AnyCall(MD);
  118. }
  119. return std::nullopt;
  120. }
  121. /// \returns formal parameters for direct calls (including virtual calls)
  122. ArrayRef<ParmVarDecl *> parameters() const {
  123. if (!D)
  124. return std::nullopt;
  125. if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
  126. return FD->parameters();
  127. } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
  128. return MD->parameters();
  129. } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
  130. return BD->parameters();
  131. } else {
  132. return std::nullopt;
  133. }
  134. }
  135. using param_const_iterator = ArrayRef<ParmVarDecl *>::const_iterator;
  136. param_const_iterator param_begin() const { return parameters().begin(); }
  137. param_const_iterator param_end() const { return parameters().end(); }
  138. size_t param_size() const { return parameters().size(); }
  139. bool param_empty() const { return parameters().empty(); }
  140. QualType getReturnType(ASTContext &Ctx) const {
  141. switch (K) {
  142. case Function:
  143. if (E)
  144. return cast<CallExpr>(E)->getCallReturnType(Ctx);
  145. return cast<FunctionDecl>(D)->getReturnType();
  146. case ObjCMethod:
  147. if (E)
  148. return cast<ObjCMessageExpr>(E)->getCallReturnType(Ctx);
  149. return cast<ObjCMethodDecl>(D)->getReturnType();
  150. case Block:
  151. // FIXME: BlockDecl does not know its return type,
  152. // hence the asymmetry with the function and method cases above.
  153. return cast<CallExpr>(E)->getCallReturnType(Ctx);
  154. case Destructor:
  155. case Constructor:
  156. case InheritedConstructor:
  157. case Allocator:
  158. case Deallocator:
  159. return cast<FunctionDecl>(D)->getReturnType();
  160. }
  161. llvm_unreachable("Unknown AnyCall::Kind");
  162. }
  163. /// \returns Function identifier if it is a named declaration,
  164. /// @c nullptr otherwise.
  165. const IdentifierInfo *getIdentifier() const {
  166. if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
  167. return ND->getIdentifier();
  168. return nullptr;
  169. }
  170. const Decl *getDecl() const {
  171. return D;
  172. }
  173. const Expr *getExpr() const {
  174. return E;
  175. }
  176. Kind getKind() const {
  177. return K;
  178. }
  179. void dump() const {
  180. if (E)
  181. E->dump();
  182. if (D)
  183. D->dump();
  184. }
  185. };
  186. }
  187. #endif // LLVM_CLANG_ANALYSIS_ANYCALL_H
  188. #ifdef __GNUC__
  189. #pragma GCC diagnostic pop
  190. #endif