Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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