Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5196685
declcall-squashed
hanickadot Feb 13, 2025
c8090b3
Adapt declcall port to intel/llvm drift (KEYCXX26, visitor, return type)
koparasy Aug 11, 2026
69e2852
[clang] Add baseline tests for declcall (P2825)
koparasy Aug 11, 2026
e258c75
[clang] Serialize the devirtualized flag of CXXDeclcallExpr
koparasy Aug 11, 2026
a43876d
[clang] Return ExprError from failed declcall instead of a live node
koparasy Aug 11, 2026
4d66abc
[clang] Mangle declcall as an Itanium vendor extended expression
koparasy Aug 11, 2026
3dcc7ce
[clang] Emit declcall via constant evaluation instead of fragile AST …
koparasy Aug 11, 2026
9475d8f
[clang] Implement declcall in the bytecode interpreter, incl. devirtu…
koparasy Aug 11, 2026
d792da1
[clang] Diagnose declcall of a pointer-to-member call instead of cras…
koparasy Aug 11, 2026
292ab53
[clang][test] Lock that unqualified virtual declcall is not devirtual…
koparasy Aug 11, 2026
66d0635
[clang][test] Cover declcall noexcept type fidelity
koparasy Aug 11, 2026
156cf6c
[clang][test] Cover declcall function-template selection and instanti…
koparasy Aug 11, 2026
3f15eb8
[clang][test] Cover declcall on free and member operator calls
koparasy Aug 11, 2026
5360b04
[clang][test] Cover declcall on static member functions
koparasy Aug 11, 2026
775dad8
[clang] Reject declcall of a destructor or builtin function
koparasy Aug 11, 2026
3505ddb
[clang][test] Cover declcall SFINAE-friendliness
koparasy Aug 11, 2026
e239061
[clang][test] Cover declcall devirtualization through C++20 modules
koparasy Aug 11, 2026
a8cefd2
[clang][test] Cover declcall on cv/ref-qualified member overloads
koparasy Aug 11, 2026
6442e7f
[clang][test] Check the devirtualized marker in declcall AST dump
koparasy Aug 11, 2026
d7663d5
[clang][NFC] clang-format declcall changes
koparasy Aug 11, 2026
22d36fc
[clang][NFC] Fix placeholder standard reference in CXXDeclcallExpr doc
koparasy Aug 11, 2026
a23dc43
[clang][docs] Document the declcall extension
koparasy Aug 11, 2026
e9c5aa2
[clang] Gate declcall: native under -fsycl, Clang extension otherwise
koparasy Aug 11, 2026
8577357
[clang] Don't disable member-function address-of diagnostics for decl…
koparasy Aug 11, 2026
a690fc3
[clang] Parse declcall's operand as an unevaluated operand
koparasy Aug 11, 2026
2e59913
[clang] Honor declcall devirtualization in the Microsoft C++ ABI
koparasy Aug 11, 2026
656c55d
[clang] Include declcall's devirtualized flag in the statement profile
koparasy Aug 11, 2026
be5cd3c
[clang] Honor declcall devirtualization when calling a member pointer…
koparasy Aug 11, 2026
b10c186
[clang] Keep declcall's original call expression for pretty-printing
koparasy Aug 11, 2026
42bbf64
[clang][docs] Regenerate LibASTMatchersReference.html for cxxDeclcall…
koparasy Aug 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion clang-tools-extra/clang-tidy/utils/Matchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ AST_MATCHER(QualType, isSimpleChar) {
}

AST_MATCHER(Expr, hasUnevaluatedContext) {
if (isa<CXXNoexceptExpr>(Node) || isa<RequiresExpr>(Node))
if (isa<CXXNoexceptExpr>(Node) || isa<CXXDeclcallExpr>(Node) ||
isa<RequiresExpr>(Node))
return true;
if (const auto *UnaryExpr = dyn_cast<UnaryExprOrTypeTraitExpr>(&Node)) {
switch (UnaryExpr->getKind()) {
Expand Down
21 changes: 21 additions & 0 deletions clang/docs/LanguageExtensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,27 @@ These spellings result in the type of the operand, stripping all qualifiers.
`char32_t` respectively, but are also available in C++ modes before C++11.
They are only supported in C++. `__char8_t` is not available.

### declcall

`declcall(call-expression)` yields a pointer, or pointer to member, to the
function that overload resolution would select for the *call-expression*, which
is an unevaluated operand:

```c++
int f(int);
int f(char);
constexpr auto p = declcall(f(0)); // &f(int)
```

For a member function it produces a pointer to member; a qualified call to a
virtual member is devirtualized. `declcall` is ill-formed if the operand is not
a call expression, names a constructor, destructor, or builtin function, or does
not select a function at compile time.

`declcall` implements P2825, which is not yet standardized. It is enabled as a
native feature under `-fsycl`; otherwise it is a Clang extension diagnosed by
`-Wdeclcall-extension`.

% FIXME: This should list all the keyword extensions

(langext-vectors)=
Expand Down
5 changes: 5 additions & 0 deletions clang/docs/LibASTMatchersReference.html
Original file line number Diff line number Diff line change
Expand Up @@ -1667,6 +1667,11 @@ <h2 id="decl-matchers">Node Matchers</h2>
</pre></td></tr>


<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxDeclcallExpr0')"><a name="cxxDeclcallExpr0Anchor">cxxDeclcallExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDeclcallExpr.html">CXXDeclcallExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxDeclcallExpr0"><pre>Matches declcall expressions.
</pre></td></tr>


<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxDefaultArgExpr0')"><a name="cxxDefaultArgExpr0Anchor">cxxDefaultArgExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDefaultArgExpr.html">CXXDefaultArgExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxDefaultArgExpr0"><pre>Matches the value of a default argument at the call site.

Expand Down
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the

- `__is_trivially_equality_comparable` no longer returns false for all enum types. (#GH132672)
- `auto` parameters are now available in all C++ language modes as an extension.
- Clang now supports `declcall` ([P2825](https://wg21.link/p2825)) as an extension, yielding a pointer to the function that overload resolution would select for an unevaluated call expression.

#### C++2d Feature Support

Expand Down
10 changes: 6 additions & 4 deletions clang/include/clang/AST/APValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -436,9 +436,9 @@ class APValue {
/// \param IsDerivedMember Whether member is a derived one.
/// \param Path The path of the member.
APValue(const ValueDecl *Member, bool IsDerivedMember,
ArrayRef<const CXXRecordDecl *> Path)
ArrayRef<const CXXRecordDecl *> Path, bool DeVirtualized = false)
: Kind(None), AllowConstexprUnknown(false) {
MakeMemberPointer(Member, IsDerivedMember, Path);
MakeMemberPointer(Member, IsDerivedMember, Path, DeVirtualized);
}
/// Creates a new address label diff APValue.
/// \param LHSExpr The left-hand side of the difference.
Expand Down Expand Up @@ -691,6 +691,7 @@ class APValue {
const ValueDecl *getMemberPointerDecl() const;
bool isMemberPointerToDerivedMember() const;
ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
bool isDeVirtualized() const;

const AddrLabelExpr* getAddrLabelDiffLHS() const {
assert(isAddrLabelDiff() && "Invalid accessor");
Expand Down Expand Up @@ -799,7 +800,8 @@ class APValue {
Kind = Union;
}
void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
ArrayRef<const CXXRecordDecl*> Path);
ArrayRef<const CXXRecordDecl *> Path,
bool DeVirtualized);
void MakeAddrLabelDiff() {
assert(isAbsent() && "Bad state change");
new ((void *)(char *)&Data) AddrLabelDiffData();
Expand Down Expand Up @@ -831,7 +833,7 @@ class APValue {
bool OnePastTheEnd, bool IsNullPtr);
MutableArrayRef<const CXXRecordDecl *>
setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember,
unsigned Size);
unsigned Size, bool DeVirtualized);
};

} // end namespace clang.
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/AST/ComputeDependence.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class CXXDeleteExpr;
class ArrayTypeTraitExpr;
class ExpressionTraitExpr;
class CXXNoexceptExpr;
class CXXDeclcallExpr;
class PackExpansionExpr;
class PackIndexingExpr;
class SubstNonTypeTemplateParmExpr;
Expand Down Expand Up @@ -161,6 +162,7 @@ ExprDependence computeDependence(CXXDeleteExpr *E);
ExprDependence computeDependence(ArrayTypeTraitExpr *E);
ExprDependence computeDependence(ExpressionTraitExpr *E);
ExprDependence computeDependence(CXXNoexceptExpr *E, CanThrowResult CT);
ExprDependence computeDependence(CXXDeclcallExpr *E);
ExprDependence computeDependence(PackExpansionExpr *E);
ExprDependence computeDependence(PackIndexingExpr *E);
ExprDependence computeDependence(SubstNonTypeTemplateParmExpr *E);
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/EvaluatedExprVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class EvaluatedExprVisitorBase : public StmtVisitorBase<Ptr, ImplClass, void> {
void VisitBlockExpr(PTR(BlockExpr) E) { }
void VisitCXXUuidofExpr(PTR(CXXUuidofExpr) E) { }
void VisitCXXNoexceptExpr(PTR(CXXNoexceptExpr) E) { }
void VisitCXXDeclcallExpr(PTR(CXXDeclcallExpr) E) {}

void VisitMemberExpr(PTR(MemberExpr) E) {
// Only the base matters.
Expand Down
49 changes: 49 additions & 0 deletions clang/include/clang/AST/ExprCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -4343,6 +4343,55 @@ class CXXNoexceptExpr : public Expr {
}
};

/// Represents a C++26 declcall expression (P2825).
///
/// An object which gives you member function pointer or function pointer
class CXXDeclcallExpr : public Expr {
friend class ASTStmtReader;

Stmt *Operand;
/// The original call expression the declcall was written with, kept for
/// source fidelity (e.g. -ast-print). Evaluation and codegen use Operand,
/// which is the resolved callee (a pointer or pointer to member).
Stmt *SourceExpr;
SourceRange Range;

bool Devirtualize = false;

public:
CXXDeclcallExpr(QualType Ty, Expr *Operand, Expr *SourceExpr,
bool Devirtualize, SourceLocation Keyword,
SourceLocation RParen)
: Expr(CXXDeclcallExprClass, Ty, VK_PRValue, OK_Ordinary),
Operand(Operand), SourceExpr(SourceExpr), Range(Keyword, RParen),
Devirtualize(Devirtualize) {
setDependence(computeDependence(this));
}

CXXDeclcallExpr(EmptyShell Empty) : Expr(CXXDeclcallExprClass, Empty) {}

Expr *getOperand() const { return static_cast<Expr *>(Operand); }
/// The original call expression, for printing / source fidelity.
Expr *getSourceExpr() const { return static_cast<Expr *>(SourceExpr); }

SourceLocation getBeginLoc() const { return Range.getBegin(); }
SourceLocation getEndLoc() const { return Range.getEnd(); }
SourceRange getSourceRange() const { return Range; }

static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDeclcallExprClass;
}

bool isDevirtualized() const { return Devirtualize; }

// Iterators
child_range children() { return child_range(&Operand, &Operand + 1); }

const_child_range children() const {
return const_child_range(&Operand, &Operand + 1);
}
};

/// Represents a C++11 pack expansion that produces a sequence of
/// expressions.
///
Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/AST/PropertiesBase.td
Original file line number Diff line number Diff line change
Expand Up @@ -466,11 +466,14 @@ let Class = PropertyTypeCase<APValue, "MemberPointer"> in {
def : Property<"memberPath", Array<CXXRecordDeclRef>> {
let Read = [{ node.getMemberPointerPath() }];
}
def : Property<"isDeVirtualized", Bool> {
let Read = [{ node.isDeVirtualized() }];
}
def : Creator<[{
APValue result;
unsigned pathSize = memberPath.size();
const CXXRecordDecl **pathArray =
result.setMemberPointerUninit(member, isDerived, pathSize).data();
result.setMemberPointerUninit(member, isDerived, pathSize, isDeVirtualized).data();
for (unsigned i = 0; i < pathSize; ++i)
pathArray[i] = memberPath[i]->getCanonicalDecl();
return result;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -3121,6 +3121,7 @@ DEF_TRAVERSE_STMT(UnaryOperator, {})
DEF_TRAVERSE_STMT(BinaryOperator, {})
DEF_TRAVERSE_STMT(CompoundAssignOperator, {})
DEF_TRAVERSE_STMT(CXXNoexceptExpr, {})
DEF_TRAVERSE_STMT(CXXDeclcallExpr, {})
DEF_TRAVERSE_STMT(PackExpansionExpr, {})
DEF_TRAVERSE_STMT(SizeOfPackExpr, {})
DEF_TRAVERSE_STMT(PackIndexingExpr, {})
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/TextNodeDumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ class TextNodeDumper
void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node);
void VisitCXXStaticCastExpr(const CXXStaticCastExpr *Node);
void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *Node);
void VisitCXXNoexceptExpr(const CXXNoexceptExpr *Node);
void VisitCXXConstructExpr(const CXXConstructExpr *Node);
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node);
void VisitCXXNewExpr(const CXXNewExpr *Node);
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/ASTMatchers/ASTMatchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -2057,6 +2057,10 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNoexceptExpr>
cxxNoexceptExpr;

/// Matches declcall expressions.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeclcallExpr>
cxxDeclcallExpr;

/// Matches a loop initializing the elements of an array in a number of contexts:
/// * in the implicit copy/move constructor for a class with an array member
/// * when a lambda-expression captures an array by value
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ def UndefinedFuncTemplate : DiagGroup<"undefined-func-template">;
def MissingNoEscape : DiagGroup<"missing-noescape">;

def DefaultedFunctionDeleted : DiagGroup<"defaulted-function-deleted">;
def DeclcallExtension : DiagGroup<"declcall-extension">;
def DeleteIncomplete : DiagGroup<"delete-incomplete">;
def DeleteNonAbstractNonVirtualDtor : DiagGroup<"delete-non-abstract-non-virtual-dtor">;
def DeleteAbstractNonVirtualDtor : DiagGroup<"delete-abstract-non-virtual-dtor">;
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticLexKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ def warn_cxx11_keyword : Warning<"'%0' is a keyword in C++11">,
InGroup<CXX11Compat>, DefaultIgnore;
def warn_cxx20_keyword : Warning<"'%0' is a keyword in C++20">,
InGroup<CXX20Compat>, DefaultIgnore;
def warn_cxx26_keyword : Warning<"'%0' is a keyword in C++26">,
InGroup<CXX26Compat>, DefaultIgnore;
def warn_c99_keyword : Warning<"'%0' is a keyword in C99">,
InGroup<C99Compat>, DefaultIgnore;
def warn_c23_keyword : Warning<"'%0' is a keyword in C23">,
Expand Down
9 changes: 9 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -10161,6 +10161,15 @@ def note_inequality_comparison_to_or_assign : Note<
def err_incomplete_type_used_in_type_trait_expr : Error<
"incomplete type %0 used in type trait expression">, NoSFINAE;

def ext_declcall : ExtWarn<
"'declcall' is a Clang extension">, InGroup<DeclcallExtension>;
def err_declcall_must_contain_a_call : Error<
"declcall doesn't contain a call">;
def err_declcall_not_implemented_for : Error<
"declcall doesn't support %0 yet">;
def err_declcall_must_be_constant_evaluable : Error<
"declcall must not depend on runtime known value">;

// C++20 constinit and require_constant_initialization attribute
def warn_cxx20_compat_constinit
: Warning<"'constinit' specifier is incompatible with C++ standards before "
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/StmtNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ def OverloadExpr : StmtNode<Expr, 1>;
def UnresolvedLookupExpr : StmtNode<OverloadExpr>;
def UnresolvedMemberExpr : StmtNode<OverloadExpr>;
def CXXNoexceptExpr : StmtNode<Expr>;
def CXXDeclcallExpr : StmtNode<Expr>;
def PackExpansionExpr : StmtNode<Expr>;
def SizeOfPackExpr : StmtNode<Expr>;
def PackIndexingExpr : StmtNode<Expr>;
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/TokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
#ifndef CXX20_KEYWORD
#define CXX20_KEYWORD(X,Y) KEYWORD(X,KEYCXX20|(Y))
#endif
#ifndef CXX26_KEYWORD
#define CXX26_KEYWORD(X,Y) KEYWORD(X,KEYCXX26|(Y))
#endif
#ifndef C99_KEYWORD
#define C99_KEYWORD(X,Y) KEYWORD(X,KEYC99|(Y))
#endif
Expand Down Expand Up @@ -444,6 +447,9 @@ CXX20_KEYWORD(constinit , 0)
CXX20_KEYWORD(concept , 0)
CXX20_KEYWORD(requires , 0)

// C++26 keywords.
CXX26_KEYWORD(declcall , KEYSYCL)

// Not a CXX20_KEYWORD because it is disabled by -fno-char8_t.
KEYWORD(char8_t , CHAR8SUPPORT)

Expand Down
7 changes: 4 additions & 3 deletions clang/include/clang/Basic/TokenKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,11 @@ enum TokenKey : unsigned {
KEYFIXEDPOINT = 0x8000000,
KEYDEFERTS = 0x10000000,
KEYNOHLSL = 0x20000000,
KEYMAX = KEYNOHLSL, // The maximum key
KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
KEYCXX26 = 0x40000000,
KEYMAX = KEYCXX26, // The maximum key
KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20 | KEYCXX26,
KEYALL = (KEYMAX | (KEYMAX - 1)) & ~KEYNOMS18 & ~KEYNOOPENCL &
~KEYNOHLSL // KEYNOMS18, KEYNOOPENCL, KEYNOHLSL excluded.
~KEYNOHLSL // KEYNOMS18, KEYNOOPENCL, KEYNOHLSL excluded.
};

namespace tok {
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -8730,6 +8730,11 @@ class Sema final : public SemaBase {
ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
SourceLocation RParen);

ExprResult ActOnDeclcallExpr(SourceLocation KeyLoc, SourceLocation LParen,
Expr *Operand, SourceLocation RParen);
ExprResult BuildCXXDeclcallExpr(SourceLocation KeyLoc, Expr *Operand,
SourceLocation RParen);

ExprResult ActOnStartCXXMemberReference(Scope *S, Expr *Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1937,6 +1937,7 @@ enum StmtCode {

EXPR_CXX_EXPRESSION_TRAIT, // ExpressionTraitExpr
EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr
EXPR_CXX_DECLCALL, // CXXDeclCallExpr

EXPR_OPAQUE_VALUE, // OpaqueValueExpr
EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator
Expand Down
26 changes: 20 additions & 6 deletions clang/lib/AST/APValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ namespace {
struct MemberPointerBase {
llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember;
unsigned PathLength;
bool DeVirtualized;
};
}

Expand All @@ -254,7 +255,10 @@ struct APValue::MemberPointerData : MemberPointerBase {
PathElem *PathPtr;
};

MemberPointerData() { PathLength = 0; }
MemberPointerData() {
PathLength = 0;
DeVirtualized = false;
}
~MemberPointerData() { resizePath(0); }

void resizePath(unsigned Length) {
Expand Down Expand Up @@ -362,7 +366,7 @@ APValue::APValue(const APValue &RHS)
case MemberPointer:
MakeMemberPointer(RHS.getMemberPointerDecl(),
RHS.isMemberPointerToDerivedMember(),
RHS.getMemberPointerPath());
RHS.getMemberPointerPath(), RHS.isDeVirtualized());
break;
case AddrLabelDiff:
MakeAddrLabelDiff();
Expand Down Expand Up @@ -621,6 +625,7 @@ void APValue::Profile(llvm::FoldingSetNodeID &ID) const {
case MemberPointer:
ID.AddPointer(getMemberPointerDecl());
ID.AddInteger(isMemberPointerToDerivedMember());
ID.AddInteger(isDeVirtualized());
for (const CXXRecordDecl *D : getMemberPointerPath())
ID.AddPointer(D);
return;
Expand Down Expand Up @@ -1102,6 +1107,13 @@ ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const {
return {MPD.getPath(), MPD.PathLength};
}

bool APValue::isDeVirtualized() const {
assert(isMemberPointer() && "Invalid accessor");
const MemberPointerData &MPD =
*((const MemberPointerData *)(const char *)&Data);
return MPD.DeVirtualized;
}

void APValue::MakeLValue() {
assert(isAbsent() && "Bad state change");
static_assert(sizeof(LV) <= DataSize, "LV too big");
Expand All @@ -1117,10 +1129,11 @@ void APValue::MakeArray(unsigned InitElts, unsigned Size) {

MutableArrayRef<const CXXRecordDecl *>
APValue::setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember,
unsigned Size) {
unsigned Size, bool DeVirtualized) {
assert(isAbsent() && "Bad state change");
MemberPointerData *MPD = new ((void *)(char *)&Data) MemberPointerData;
Kind = MemberPointer;
MPD->DeVirtualized = DeVirtualized;
MPD->MemberAndIsDerivedMember.setPointer(
Member ? cast<ValueDecl>(Member->getCanonicalDecl()) : nullptr);
MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
Expand All @@ -1129,9 +1142,10 @@ APValue::setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember,
}

void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
ArrayRef<const CXXRecordDecl *> Path) {
MutableArrayRef<const CXXRecordDecl *> InternalPath =
setMemberPointerUninit(Member, IsDerivedMember, Path.size());
ArrayRef<const CXXRecordDecl *> Path,
bool DeVirtualized) {
MutableArrayRef<const CXXRecordDecl *> InternalPath = setMemberPointerUninit(
Member, IsDerivedMember, Path.size(), DeVirtualized);
for (unsigned I = 0; I != Path.size(); ++I)
InternalPath[I] = Path[I]->getCanonicalDecl();
}
Expand Down
Loading
Loading