Skip to content

Commit c00fc31

Browse files
committed
Fixed -reflect-function when a definition is found but the fwd declare is missing
1 parent 5652f2a commit c00fc31

File tree

2 files changed

+97
-31
lines changed

2 files changed

+97
-31
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// RUN: %dxreflector -reflect-functions %s | FileCheck %s
2+
3+
struct PSInput {
4+
float4 color : COLOR;
5+
};
6+
7+
struct Test;
8+
9+
struct A {
10+
float a;
11+
float t(Test t);
12+
};
13+
14+
struct Test {
15+
float a;
16+
};
17+
18+
float A::t(Test t) {
19+
return 2;
20+
}
21+
22+
[[oxc::stage("pixel")]]
23+
float4 PSMain(PSInput input) : SV_TARGET
24+
{
25+
A a;
26+
Test t;
27+
return input.color * a.t(t);
28+
}
29+
30+
// CHECK: {
31+
// CHECK: "Features": [
32+
// CHECK: "Functions",
33+
// CHECK: "Symbols"
34+
// CHECK: ],
35+
// CHECK: "Children": [
36+
// CHECK: {
37+
// CHECK: "Name": "PSMain",
38+
// CHECK: "NodeType": "Function",
39+
// CHECK: "Semantic": "SV_TARGET",
40+
// CHECK: "Annotations": [
41+
// CHECK: {{"\[\[oxc::stage\(\\\"pixel\\\"\)\]\]"}}
42+
// CHECK: ],
43+
// CHECK: "Function": {
44+
// CHECK: "Params": {
45+
// CHECK: "input": {
46+
// CHECK: "TypeName": "PSInput"
47+
// CHECK: }
48+
// CHECK: },
49+
// CHECK: "ReturnType": {
50+
// CHECK: "TypeName": "float4"
51+
// CHECK: }
52+
// CHECK: }
53+
// CHECK: }
54+
// CHECK: ]
55+
// CHECK: }

tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,48 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM,
9797
if (LocalId >= (1u << 24))
9898
return HLSL_REFL_ERR("LocalId overflow");
9999

100+
bool isFwdDeclare = false;
101+
bool canHaveFwdDeclare = false;
102+
const Decl *fwdDeclare = nullptr;
103+
104+
if (DeclSelf) {
105+
106+
if (const FunctionDecl *func = dyn_cast<FunctionDecl>(DeclSelf)) {
107+
isFwdDeclare = !func->doesThisDeclarationHaveABody();
108+
fwdDeclare = func->getCanonicalDecl();
109+
canHaveFwdDeclare = true;
110+
}
111+
112+
else if (const EnumDecl *enm = dyn_cast<EnumDecl>(DeclSelf)) {
113+
isFwdDeclare = !enm->isCompleteDefinition();
114+
fwdDeclare = enm->getCanonicalDecl();
115+
canHaveFwdDeclare = true;
116+
}
117+
118+
else if (const RecordDecl *rec = dyn_cast<RecordDecl>(DeclSelf)) {
119+
120+
isFwdDeclare = !rec->isThisDeclarationADefinition();
121+
fwdDeclare = rec->getCanonicalDecl();
122+
canHaveFwdDeclare = true;
123+
124+
if (isFwdDeclare && rec->isImplicit()) { // Inner ghost node
125+
NodeId = uint32_t(-1);
126+
return ReflectionErrorSuccess;
127+
}
128+
}
129+
}
130+
131+
//There is a forward declare, but we haven't seen it before.
132+
//This happens for example if we have a fwd func declare in a struct, but define it in global namespace.
133+
//(only) -reflect-function will hide this struct from us, but will still find a function in the global scope.
134+
//This fixes that problem.
135+
136+
if (!isFwdDeclare && fwdDeclare && fwdDeclare != DeclSelf &&
137+
FwdDecls->find(fwdDeclare) == FwdDecls->end()) {
138+
NodeId = uint32_t(-1);
139+
return ReflectionErrorSuccess;
140+
}
141+
100142
uint32_t nodeId = Refl.Nodes.size();
101143

102144
uint16_t annotationStart = uint16_t(Refl.Annotations.size());
@@ -179,37 +221,6 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM,
179221

180222
D3D_INTERPOLATION_MODE interpolationMode = GetInterpolationMode(DeclSelf);
181223

182-
bool isFwdDeclare = false;
183-
bool canHaveFwdDeclare = false;
184-
const Decl *fwdDeclare = nullptr;
185-
186-
if (DeclSelf) {
187-
188-
if (const FunctionDecl *func = dyn_cast<FunctionDecl>(DeclSelf)) {
189-
isFwdDeclare = !func->doesThisDeclarationHaveABody();
190-
fwdDeclare = func->getCanonicalDecl();
191-
canHaveFwdDeclare = true;
192-
}
193-
194-
else if (const EnumDecl *enm = dyn_cast<EnumDecl>(DeclSelf)) {
195-
isFwdDeclare = !enm->isCompleteDefinition();
196-
fwdDeclare = enm->getCanonicalDecl();
197-
canHaveFwdDeclare = true;
198-
}
199-
200-
else if (const RecordDecl *rec = dyn_cast<RecordDecl>(DeclSelf)) {
201-
202-
isFwdDeclare = !rec->isThisDeclarationADefinition();
203-
fwdDeclare = rec->getCanonicalDecl();
204-
canHaveFwdDeclare = true;
205-
206-
if (isFwdDeclare && rec->isImplicit()) { // Inner ghost node
207-
NodeId = uint32_t(-1);
208-
return ReflectionErrorSuccess;
209-
}
210-
}
211-
}
212-
213224
uint32_t currId = uint32_t(Refl.Nodes.size());
214225

215226
if (canHaveFwdDeclare) {

0 commit comments

Comments
 (0)