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(Quantity: 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, Ty: 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 | |