xref: /freebsd/contrib/llvm-project/clang/lib/AST/Interp/FunctionPointer.h (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
1 //===--- FunctionPointer.h - Types for the constexpr VM ---------*- 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 #ifndef LLVM_CLANG_AST_INTERP_FUNCTION_POINTER_H
10 #define LLVM_CLANG_AST_INTERP_FUNCTION_POINTER_H
11 
12 #include "Function.h"
13 #include "Primitives.h"
14 #include "clang/AST/APValue.h"
15 
16 namespace clang {
17 class ASTContext;
18 namespace interp {
19 
20 class FunctionPointer final {
21 private:
22   const Function *Func;
23   bool Valid;
24 
25 public:
26   FunctionPointer(const Function *Func) : Func(Func), Valid(true) {
27     assert(Func);
28   }
29 
30   FunctionPointer(uintptr_t IntVal = 0, const Descriptor *Desc = nullptr)
31       : Func(reinterpret_cast<const Function *>(IntVal)), Valid(false) {}
32 
33   const Function *getFunction() const { return Func; }
34   bool isZero() const { return !Func; }
35   bool isValid() const { return Valid; }
36   bool isWeak() const {
37     if (!Func || !Valid)
38       return false;
39 
40     return Func->getDecl()->isWeak();
41   }
42 
43   APValue toAPValue(const ASTContext &) const {
44     if (!Func)
45       return APValue(static_cast<Expr *>(nullptr), CharUnits::Zero(), {},
46                      /*OnePastTheEnd=*/false, /*IsNull=*/true);
47 
48     if (!Valid)
49       return APValue(static_cast<Expr *>(nullptr),
50                      CharUnits::fromQuantity(getIntegerRepresentation()), {},
51                      /*OnePastTheEnd=*/false, /*IsNull=*/false);
52 
53     return APValue(Func->getDecl(), CharUnits::Zero(), {},
54                    /*OnePastTheEnd=*/false, /*IsNull=*/false);
55   }
56 
57   void print(llvm::raw_ostream &OS) const {
58     OS << "FnPtr(";
59     if (Func && Valid)
60       OS << Func->getName();
61     else if (Func)
62       OS << reinterpret_cast<uintptr_t>(Func);
63     else
64       OS << "nullptr";
65     OS << ")";
66   }
67 
68   std::string toDiagnosticString(const ASTContext &Ctx) const {
69     if (!Func)
70       return "nullptr";
71 
72     return toAPValue(Ctx).getAsString(Ctx, Func->getDecl()->getType());
73   }
74 
75   uint64_t getIntegerRepresentation() const {
76     return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Func));
77   }
78 
79   ComparisonCategoryResult compare(const FunctionPointer &RHS) const {
80     if (Func == RHS.Func)
81       return ComparisonCategoryResult::Equal;
82     return ComparisonCategoryResult::Unordered;
83   }
84 };
85 
86 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
87                                      FunctionPointer FP) {
88   FP.print(OS);
89   return OS;
90 }
91 
92 } // namespace interp
93 } // namespace clang
94 
95 #endif
96