clang 24.0.0git
MemberPointer.cpp
Go to the documentation of this file.
1//===------------------------- MemberPointer.cpp ----------------*- 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#include "MemberPointer.h"
10#include "Context.h"
11#include "Program.h"
12#include "Record.h"
13
14namespace clang {
15namespace interp {
16
17std::optional<Pointer> MemberPointer::toPointer(const Context &Ctx) const {
19 return Base;
21
22 if (!Base.isBlockPointer())
23 return std::nullopt;
24
25 if (PtrOffset >= 0) {
26 // If the resulting base would be too small, return nullopt.
27 if (Base.BS.Base < static_cast<unsigned>(PtrOffset))
28 return std::nullopt;
29 }
30
31 Pointer CastedBase =
32 (PtrOffset < 0 ? Base.atField(-PtrOffset) : Base.atFieldSub(PtrOffset));
33
34 const Record *BaseRecord = CastedBase.getRecord();
35 if (!BaseRecord)
36 return std::nullopt;
37
38 unsigned Offset = 0;
39
40 if (const auto *FD = dyn_cast<FieldDecl>(getDecl())) {
41 if (FD->getParent() == BaseRecord->getDecl())
42 return CastedBase.atField(BaseRecord->getField(FD)->Offset);
43
44 const RecordDecl *FieldParent = FD->getParent();
45 const Record *FieldRecord = Ctx.getRecord(FieldParent);
46
47 Offset += FieldRecord->getField(FD)->Offset;
48 if (Offset > CastedBase.block()->getSize())
49 return std::nullopt;
50
51 if (const RecordDecl *BaseDecl = Base.getDeclPtr().getRecord()->getDecl();
52 BaseDecl != FieldParent)
53 Offset += Ctx.collectBaseOffset(FieldParent, BaseDecl);
54
55 } else {
56 const auto *IFD = cast<IndirectFieldDecl>(getDecl());
57
58 for (const NamedDecl *ND : IFD->chain()) {
59 const FieldDecl *F = cast<FieldDecl>(ND);
60 const RecordDecl *FieldParent = F->getParent();
61 const Record *FieldRecord = Ctx.getRecord(FieldParent);
62 Offset += FieldRecord->getField(F)->Offset;
63 }
64 }
65
66 assert(BaseRecord);
67 if (Offset > CastedBase.block()->getSize())
68 return std::nullopt;
69
70 assert(Offset <= CastedBase.block()->getSize());
71 return Pointer(const_cast<Block *>(Base.block()), Offset, Offset);
72}
73
75 if (isZero())
76 return APValue(static_cast<ValueDecl *>(nullptr), /*IsDerivedMember=*/false,
77 /*Path=*/{});
78
79 if (hasBase())
80 return Base.toAPValue(ASTCtx);
81
82 return APValue(getDecl(), /*IsDerivedMember=*/isDerivedMember(),
83 /*Path=*/ArrayRef(Path, PathLength));
84}
85
87MemberPointer::compare(const MemberPointer &RHS) const {
88 assert(!isZero());
89 assert(!RHS.isZero());
90
91 const auto getCmpDecl = [](const MemberPointer &P) -> const Decl * {
92 const Decl *D = P.getDecl()->getMostRecentDecl();
93 if (const auto *FD = dyn_cast<FieldDecl>(D))
94 D = FD->getFirstDecl();
95 return D;
96 };
97
98 const Decl *LHSCmpDecl = getCmpDecl(*this);
99 const Decl *RHSCmpDecl = getCmpDecl(RHS);
100
101 if (LHSCmpDecl == RHSCmpDecl) {
102 if (this->PathLength != RHS.PathLength)
104
105 if (PathLength != 0 &&
106 std::memcmp(Path, RHS.Path, PathLength * sizeof(CXXRecordDecl *)) != 0)
108
110 }
112}
113
114} // namespace interp
115} // namespace clang
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:158
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2108
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
Decl * getMostRecentDecl()
Retrieve the most recent declaration that declares the same entity as this declaration (which may be ...
Definition DeclBase.h:1094
Represents a member of a struct/union/class.
Definition Decl.h:3311
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3547
This represents a decl that may have a name.
Definition Decl.h:276
Represents a struct/union/class.
Definition Decl.h:4476
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:714
A memory block, either on the stack or in the heap.
Definition Block.h:68
unsigned getSize() const
Returns the size of the block, excluding metadata.
Definition Block.h:123
Holds all information required to evaluate constexpr code in a module.
Definition Context.h:49
unsigned collectBaseOffset(const RecordDecl *BaseDecl, const RecordDecl *DerivedDecl) const
Definition Context.cpp:808
const Record * getRecord(const RecordDecl *D) const
Definition Context.cpp:839
const ValueDecl * getDecl() const
Return the base declaration. Might be null.
APValue toAPValue(const ASTContext &) const
ComparisonCategoryResult compare(const MemberPointer &RHS) const
std::optional< Pointer > toPointer(const Context &Ctx) const
A pointer to a memory block, live or dead.
Definition Pointer.h:547
Pointer atField(unsigned Off) const
Creates a pointer to a field.
Definition Pointer.h:632
const Block * block() const
Definition Pointer.h:1018
const Record * getRecord() const
Returns the record descriptor of a class.
Definition Pointer.h:881
Structure/Class descriptor.
Definition Record.h:27
const RecordDecl * getDecl() const
Returns the underlying declaration.
Definition Record.h:67
const Field * getField(unsigned I) const
Definition Record.h:100
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
U cast(CodeGen::Address addr)
Definition Address.h:327