1414#define LLVM_CLANG_AST_INTERP_POINTER_H
1515
1616#include " Descriptor.h"
17+ #include " FunctionPointer.h"
1718#include " InterpBlock.h"
1819#include " clang/AST/ComparisonCategories.h"
1920#include " clang/AST/Decl.h"
@@ -45,7 +46,7 @@ struct IntPointer {
4546 uint64_t Value;
4647};
4748
48- enum class Storage { Block, Int };
49+ enum class Storage { Block, Int, Fn };
4950
5051// / A pointer to a memory block, live or dead.
5152// /
@@ -96,6 +97,10 @@ class Pointer {
9697 PointeeStorage.Int .Value = Address;
9798 PointeeStorage.Int .Desc = Desc;
9899 }
100+ Pointer (const Function *F, uint64_t Offset = 0 )
101+ : Offset(Offset), StorageKind(Storage::Fn) {
102+ PointeeStorage.Fn = FunctionPointer (F);
103+ }
99104 ~Pointer ();
100105
101106 void operator =(const Pointer &P);
@@ -126,6 +131,8 @@ class Pointer {
126131 uint64_t getIntegerRepresentation () const {
127132 if (isIntegralPointer ())
128133 return asIntPointer ().Value + (Offset * elemSize ());
134+ if (isFunctionPointer ())
135+ return asFunctionPointer ().getIntegerRepresentation ();
129136 return reinterpret_cast <uint64_t >(asBlockPointer ().Pointee ) + Offset;
130137 }
131138
@@ -137,6 +144,8 @@ class Pointer {
137144 [[nodiscard]] Pointer atIndex (uint64_t Idx) const {
138145 if (isIntegralPointer ())
139146 return Pointer (asIntPointer ().Value , asIntPointer ().Desc , Idx);
147+ if (isFunctionPointer ())
148+ return Pointer (asFunctionPointer ().getFunction (), Idx);
140149
141150 if (asBlockPointer ().Base == RootPtrMark)
142151 return Pointer (asBlockPointer ().Pointee , RootPtrMark,
@@ -247,18 +256,20 @@ class Pointer {
247256 bool isZero () const {
248257 if (isBlockPointer ())
249258 return asBlockPointer ().Pointee == nullptr ;
259+ if (isFunctionPointer ())
260+ return asFunctionPointer ().isZero ();
250261 assert (isIntegralPointer ());
251262 return asIntPointer ().Value == 0 && Offset == 0 ;
252263 }
253264 // / Checks if the pointer is live.
254265 bool isLive () const {
255- if (isIntegralPointer ())
266+ if (! isBlockPointer ())
256267 return true ;
257268 return asBlockPointer ().Pointee && !asBlockPointer ().Pointee ->IsDead ;
258269 }
259270 // / Checks if the item is a field in an object.
260271 bool isField () const {
261- if (isIntegralPointer ())
272+ if (! isBlockPointer ())
262273 return false ;
263274
264275 return !isRoot () && getFieldDesc ()->asDecl ();
@@ -268,6 +279,8 @@ class Pointer {
268279 const Descriptor *getDeclDesc () const {
269280 if (isIntegralPointer ())
270281 return asIntPointer ().Desc ;
282+ if (isFunctionPointer ())
283+ return nullptr ;
271284
272285 assert (isBlockPointer ());
273286 assert (asBlockPointer ().Pointee );
@@ -279,7 +292,10 @@ class Pointer {
279292 DeclTy getSource () const {
280293 if (isBlockPointer ())
281294 return getDeclDesc ()->getSource ();
282-
295+ if (isFunctionPointer ()) {
296+ const Function *F = asFunctionPointer ().getFunction ();
297+ return F ? F->getDecl () : DeclTy ();
298+ }
283299 assert (isIntegralPointer ());
284300 return asIntPointer ().Desc ? asIntPointer ().Desc ->getSource () : DeclTy ();
285301 }
@@ -354,6 +370,7 @@ class Pointer {
354370 // / Returns the offset into an array.
355371 unsigned getOffset () const {
356372 assert (Offset != PastEndMark && " invalid offset" );
373+ assert (isBlockPointer ());
357374 if (asBlockPointer ().Base == RootPtrMark)
358375 return Offset;
359376
@@ -421,8 +438,14 @@ class Pointer {
421438 assert (isIntegralPointer ());
422439 return PointeeStorage.Int ;
423440 }
441+ [[nodiscard]] const FunctionPointer &asFunctionPointer () const {
442+ assert (isFunctionPointer ());
443+ return PointeeStorage.Fn ;
444+ }
445+
424446 bool isBlockPointer () const { return StorageKind == Storage::Block; }
425447 bool isIntegralPointer () const { return StorageKind == Storage::Int; }
448+ bool isFunctionPointer () const { return StorageKind == Storage::Fn; }
426449
427450 // / Returns the record descriptor of a class.
428451 const Record *getRecord () const { return getFieldDesc ()->ElemRecord ; }
@@ -445,7 +468,7 @@ class Pointer {
445468 }
446469 // / Checks if the storage is static.
447470 bool isStatic () const {
448- if (isIntegralPointer ())
471+ if (! isBlockPointer ())
449472 return true ;
450473 assert (asBlockPointer ().Pointee );
451474 return asBlockPointer ().Pointee ->isStatic ();
@@ -469,7 +492,7 @@ class Pointer {
469492 }
470493
471494 bool isWeak () const {
472- if (isIntegralPointer ())
495+ if (! isBlockPointer ())
473496 return false ;
474497
475498 assert (isBlockPointer ());
@@ -528,8 +551,8 @@ class Pointer {
528551
529552 // / Returns the number of elements.
530553 unsigned getNumElems () const {
531- if (isIntegralPointer ())
532- return ~unsigned ( 0 ) ;
554+ if (! isBlockPointer ())
555+ return ~0u ;
533556 return getSize () / elemSize ();
534557 }
535558
@@ -555,7 +578,7 @@ class Pointer {
555578
556579 // / Checks if the index is one past end.
557580 bool isOnePastEnd () const {
558- if (isIntegralPointer ())
581+ if (isIntegralPointer () || isFunctionPointer () )
559582 return false ;
560583
561584 if (!asBlockPointer ().Pointee )
@@ -692,6 +715,7 @@ class Pointer {
692715 union {
693716 BlockPointer BS;
694717 IntPointer Int;
718+ FunctionPointer Fn;
695719 } PointeeStorage;
696720 Storage StorageKind = Storage::Int;
697721};
0 commit comments