Skip to content

Commit 1d60272

Browse files
Merge pull request jacob-carlborg#292 from Inkrementator/brokentests
libclang 19.1.7
2 parents d62a12a + fc74e90 commit 1d60272

File tree

6 files changed

+55
-11
lines changed

6 files changed

+55
-11
lines changed

dstep/translator/Context.d

+16-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import dstep.translator.Output;
2121
import dstep.translator.Translator;
2222
import dstep.translator.TypedefIndex;
2323
import dstep.translator.HeaderIndex;
24+
import dstep.translator.Util;
2425

2526
class Context
2627
{
@@ -194,7 +195,7 @@ class Context
194195

195196
private string translateSpellingImpl(in Cursor cursor)
196197
{
197-
return cursor.spelling == ""
198+
return cursor.spelling.isUnnamed()
198199
? generateAnonymousName(cursor)
199200
: cursor.spelling;
200201
}
@@ -272,7 +273,7 @@ class Context
272273
{
273274
auto typedefp = typedefParent(cursor.canonical);
274275

275-
if (typedefp.isValid && cursor.spelling == "")
276+
if (typedefp.isValid && cursor.spelling.isUnnamed)
276277
{
277278
spelling = typedefp.spelling;
278279
}
@@ -378,8 +379,19 @@ bool variablesInParentScope(Cursor cursor)
378379
*/
379380
bool shouldBeAnonymous(Context context, Cursor cursor)
380381
{
381-
return cursor.type.isAnonymous &&
382-
context.typedefIndex.typedefParent(cursor).isEmpty;
382+
import std.string: startsWith;
383+
384+
/* Unfortunately, libclang isAnonymous doesn't seem to work on enums
385+
* https://stackoverflow.com/a/35184821
386+
* Checking for the string value instead is brittle and might break in a future
387+
* version, but I don't think there's a better way
388+
*/
389+
if (cursor.kind == CXCursorKind.enumDecl)
390+
return cursor.spelling.isUnnamed
391+
&& context.typedefIndex.typedefParent(cursor).isEmpty;
392+
else
393+
return cursor.type.isAnonymous &&
394+
context.typedefIndex.typedefParent(cursor).isEmpty;
383395
}
384396

385397
/**

dstep/translator/Declaration.d

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import clang.Cursor;
1010

1111
import dstep.translator.Translator;
1212
import dstep.translator.Output;
13+
import dstep.translator.Util;
1314

1415
abstract class Declaration
1516
{
@@ -44,6 +45,6 @@ abstract class Declaration
4445
@property string spelling ()
4546
{
4647
auto name = cursor.spelling;
47-
return name.length || parent.isEmpty ? name : translator.context.generateAnonymousName(cursor);
48+
return !name.isUnnamed && (name.length || parent.isEmpty) ? name : translator.context.generateAnonymousName(cursor);
4849
}
4950
}

dstep/translator/Enum.d

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import dstep.translator.Declaration;
1919
import dstep.translator.Output;
2020
import dstep.translator.Translator;
2121
import dstep.translator.Type;
22+
import dstep.translator.Util;
2223

2324
void translateEnumConstantDecl(
2425
Output output,

dstep/translator/Record.d

+14-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import dstep.translator.Declaration;
1919
import dstep.translator.Output;
2020
import dstep.translator.Translator;
2121
import dstep.translator.Type;
22+
import dstep.translator.Util;
2223

2324
string translateRecordTypeKeyword(in Cursor cursor)
2425
{
@@ -140,7 +141,14 @@ void translateRecordDef(
140141
auto canonical = cursor.canonical;
141142

142143
auto spelling = keepUnnamed ? "" : context.translateTagSpelling(cursor);
143-
spelling = spelling == "" ? spelling : " " ~ spelling;
144+
/* Spaghetti warning: Since unnamed values might in at least clang 19.1
145+
* contain "unnamed enum" or something as the name instead of being empty,
146+
* explicitly set it our variable to the empty string.
147+
*
148+
* Preferably, this would be disentagled and it would be ensured that there
149+
* is only one source of the spelling in this whole function.
150+
*/
151+
spelling = spelling.isUnnamed ? "" : " " ~ spelling;
144152
auto type = translateRecordTypeKeyword(cursor);
145153

146154
output.subscopeStrong(cursor.extent, "%s%s", type, spelling) in {
@@ -195,7 +203,7 @@ void translateRecordDef(
195203

196204
case CXCursorKind.unionDecl:
197205
case CXCursorKind.structDecl:
198-
if (cursor.type.isAnonymous)
206+
if (cursor.type.isAnonymous || cursor.spelling.isUnnamed)
199207
translateAnonymousRecord(output, context, cursor);
200208

201209
break;
@@ -216,7 +224,8 @@ void translateRecordDecl(Output output, Context context, Cursor cursor)
216224
context.markAsDefined(cursor);
217225

218226
auto spelling = context.translateTagSpelling(cursor);
219-
spelling = spelling == "" ? spelling : " " ~ spelling;
227+
//spelling = spelling == "" ? spelling : " " ~ spelling;
228+
spelling = spelling.isUnnamed ? "" : " " ~ spelling;
220229
auto type = translateRecordTypeKeyword(cursor);
221230
output.singleLine(cursor.extent, "%s%s;", type, spelling);
222231
}
@@ -233,7 +242,7 @@ bool shouldSkipRecord(Context context, Cursor cursor)
233242
cursor.kind == CXCursorKind.unionDecl)
234243
{
235244
auto typedefp = context.typedefParent(cursor.canonical);
236-
auto spelling = typedefp.isValid && cursor.spelling == ""
245+
auto spelling = typedefp.isValid && isUnnamed(cursor.spelling)
237246
? typedefp.spelling
238247
: cursor.spelling;
239248

@@ -249,7 +258,7 @@ bool shouldSkipRecordDefinition(Context context, Cursor cursor)
249258
cursor.kind == CXCursorKind.unionDecl)
250259
{
251260
auto typedefp = context.typedefParent(cursor.canonical);
252-
auto spelling = typedefp.isValid && cursor.spelling == ""
261+
auto spelling = typedefp.isValid && cursor.spelling.isUnnamed
253262
? typedefp.spelling
254263
: cursor.spelling;
255264

dstep/translator/Util.d

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
module dstep.translator.Util;
2+
3+
/** In recent versions of clang (at least 19.1.7), unnamed (anonymous) types will not
4+
* set the spelling field to an empty string, but instead to a message like
5+
* "enum (unnamed at [declaration_file.h:48]"
6+
* "struct (anonymous at [declaration_file.h:48]"
7+
* Either unnamed or anonymous is used.
8+
* This applies to structs, enums and unions.
9+
*
10+
* structs and unions additionally have the isAnonymous() helper which doesn't for enums.
11+
*
12+
* Usage:
13+
* cursor.spelling.isUnnamed()
14+
*/
15+
bool isUnnamed(string s){
16+
import std.algorithm.searching;
17+
return s == "" ||
18+
s.canFind("(unnamed at") ||
19+
s.canFind("(anonymous at");
20+
}
21+

tests/unit/issues/Issue8.d

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ typedef struct rd_kafka_metadata {
3333
char *orig_broker_name; /* Name of originating broker */
3434
} rd_kafka_metadata_t;
3535
36-
rd_kafka_metadata (rd_kafka_t *rk, int all_topics,
36+
int rd_kafka_metadata (rd_kafka_t *rk, int all_topics,
3737
rd_kafka_topic_t *only_rkt,
3838
const struct rd_kafka_metadata **metadatap,
3939
int timeout_ms);

0 commit comments

Comments
 (0)