From 06e5074ada05aca7818c49dcf416b559f59d013f Mon Sep 17 00:00:00 2001 From: zhangziyao Date: Tue, 16 Sep 2025 14:06:02 +0800 Subject: [PATCH 1/2] [source2source] fixed the bug where source2source generated incorrect C files when handling unnamed structs --- clang/lib/AST/DeclPrinter.cpp | 5 +- clang/lib/AST/TypePrinter.cpp | 7 +++ clang/lib/Frontend/Rewrite/RewriteBSC.cpp | 17 +++---- .../unnamed_struct_or_union.cbs | 51 +++++++++++++++++++ 4 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 clang/test/BSC/Positive/Driver/rewrite-bsc/unnamed_struct_or_union/unnamed_struct_or_union.cbs diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index c7cd98eebf87..533074ec34bc 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -674,9 +674,12 @@ void DeclPrinter::VisitRecordDecl(RecordDecl *D) { Out << ' ' << *D; #if ENABLE_BSC // Handling anonymous struct/union defined through typedef for rewriting - else if (Context.getLangOpts().BSC) { + else if (Policy.RewriteBSC) { if (TypedefNameDecl *TND = D->getTypedefNameForAnonDecl()) Out << ' ' << "_TD_" << TND->getName(); + else if (!D->isAnonymousStructOrUnion()) { + Out << ' ' << "__unnamed_" << D->getID(); + } } #endif diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 1319623c6531..fc5e9bfdf5ba 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1450,6 +1450,13 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { assert(Typedef->getIdentifier() && "Typedef without identifier?"); OS << Typedef->getIdentifier()->getName(); } else { +#if ENABLE_BSC + if (Policy.RewriteBSC) { + OS << "__unnamed_" << D->getID(); + spaceBeforePlaceHolder(OS); + return; + } +#endif // Make an unambiguous representation for anonymous types, e.g. // (anonymous enum at /usr/include/string.h:120:9) OS << (Policy.MSVCFormatting ? '`' : '('); diff --git a/clang/lib/Frontend/Rewrite/RewriteBSC.cpp b/clang/lib/Frontend/Rewrite/RewriteBSC.cpp index 38ee46fa29b8..38a5d24e7190 100644 --- a/clang/lib/Frontend/Rewrite/RewriteBSC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteBSC.cpp @@ -35,9 +35,7 @@ public: } // recording appear index - void addNode(RecordDecl *RD) { - nodes.insert({RD, nodes.size()}); - } + void addNode(RecordDecl *RD) { nodes.insert({RD, nodes.size()}); } std::vector topologicalSort() { std::map inDegree; @@ -92,7 +90,7 @@ private: // use T as the key and add S to its value. std::map> typeDependencyMap; // map to memo the appear index - std::map nodes; + std::map nodes; }; class TypeDependencyVisitor : public DeclVisitor { @@ -591,14 +589,15 @@ void RewriteBSC::RewriteDecls() { Buf << ";\n\n"; } else { if (TagDecl *TD = dyn_cast(D)) { - // For an anonymous tagdecl with typedef, use pretty printer. Otherwise, - // use original string text. - if (!TD->getTypedefNameForAnonDecl()) { + // For an anonymous tagdecl with typedef or unnamed recorddecl, use + // pretty printer. Otherwise, use original string text. + if (TD->getTypedefNameForAnonDecl() || + (!TD->getIdentifier() && isa(TD))) { + D->print(Buf, Policy); + } else { const char *startBuf = SM->getCharacterData(D->getBeginLoc()); const char *endBuf = SM->getCharacterData(D->getEndLoc()); Buf << std::string(startBuf, endBuf - startBuf + 1); - } else { - D->print(Buf, Policy); } Buf << ";\n\n"; } else { diff --git a/clang/test/BSC/Positive/Driver/rewrite-bsc/unnamed_struct_or_union/unnamed_struct_or_union.cbs b/clang/test/BSC/Positive/Driver/rewrite-bsc/unnamed_struct_or_union/unnamed_struct_or_union.cbs new file mode 100644 index 000000000000..4b198228250d --- /dev/null +++ b/clang/test/BSC/Positive/Driver/rewrite-bsc/unnamed_struct_or_union/unnamed_struct_or_union.cbs @@ -0,0 +1,51 @@ +// RUN: %clang %s -o %t.output +// RUN: %t.output +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output + +struct { + int a; +} s = { 2 }; + +static struct { + int b; +} p = { 3 }; + +union { + char c; + int a; +} q; + +int main() { + q.a = 4; + return q.a + 1 - s.a - p.b; +} + +// CHECK: struct __unnamed_{{[0-9]+}}; +// CHECK-NEXT: struct __unnamed_{{[0-9]+}}; +// CHECK-NEXT: union __unnamed_{{[0-9]+}}; +// CHECK-NEXT: struct __unnamed_{{[0-9]+}} { +// CHECK-NEXT: int a; +// CHECK-NEXT: }; + +// CHECK: struct __unnamed_{{[0-9]+}} { +// CHECK-NEXT: int b; +// CHECK-NEXT: }; + +// CHECK: union __unnamed_{{[0-9]+}} { +// CHECK-NEXT: char c; +// CHECK-NEXT: int a; +// CHECK-NEXT: }; + +// CHECK: struct __unnamed_{{[0-9]+}} s = {2}; + +// CHECK: static struct __unnamed_{{[0-9]+}} p = {3}; + +// CHECK: union __unnamed_{{[0-9]+}} q; + +// CHECK: int main() { +// CHECK-NEXT: q.a = 4; +// CHECK-NEXT: return q.a + 1 - s.a - p.b; +// CHECK-NEXT: } \ No newline at end of file -- Gitee From 0e4f78152256acad6f760ba145bc731993f6e9e4 Mon Sep 17 00:00:00 2001 From: zhangziyao Date: Tue, 16 Sep 2025 19:20:44 +0800 Subject: [PATCH 2/2] [source2source] fixed the bug of missing extern function declaration in generated C files --- clang/lib/Frontend/Rewrite/RewriteBSC.cpp | 5 --- .../extern_func_decl_in_header/extern.cbs | 5 +++ .../extern_func_decl_in_header.cbs | 34 +++++++++++++++++++ .../extern_func_decl_in_header.hbs | 12 +++++++ .../extern_func_decl_in_header/lit.local.cfg | 4 +++ 5 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/extern.cbs create mode 100644 clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/extern_func_decl_in_header.cbs create mode 100644 clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/extern_func_decl_in_header.hbs create mode 100644 clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/lit.local.cfg diff --git a/clang/lib/Frontend/Rewrite/RewriteBSC.cpp b/clang/lib/Frontend/Rewrite/RewriteBSC.cpp index 38a5d24e7190..6ef36d311821 100644 --- a/clang/lib/Frontend/Rewrite/RewriteBSC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteBSC.cpp @@ -820,11 +820,6 @@ void RewriteBSC::RewriteNonGenericFuncAndVar(std::vector &DeclList) { if (FD->isAsyncSpecified()) break; if (!FD->isTemplateInstantiation()) { - if (!SM->isWrittenInMainFile(SM->getSpellingLoc(FD->getBeginLoc())) && - !SM->isWrittenInMainFile(SM->getSpellingLoc(FD->getEndLoc())) && - FD->getStorageClass() == StorageClass::SC_Extern) - break; - // If it is BscMethod or macro expansion function, output the code // according to AST; Otherwise, simply retrieve the source code if (DeclsWithoutBSCFeature.find(FD) == DeclsWithoutBSCFeature.end() || diff --git a/clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/extern.cbs b/clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/extern.cbs new file mode 100644 index 000000000000..f39fc3716856 --- /dev/null +++ b/clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/extern.cbs @@ -0,0 +1,5 @@ +#include "extern_func_decl_in_header.hbs" + +int Entryf1(struct S **p) { + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/extern_func_decl_in_header.cbs b/clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/extern_func_decl_in_header.cbs new file mode 100644 index 000000000000..929fd8863a63 --- /dev/null +++ b/clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/extern_func_decl_in_header.cbs @@ -0,0 +1,34 @@ +// RUN: %clang %s %S/extern.cbs -o %t.output +// RUN: %t.output +// RUN: %clang -rewrite-bsc %s -o %t-rw1.c +// RUN: %clang -rewrite-bsc %S/extern.cbs -o %t-rw2.c +// RUN: FileCheck --input-file=%t-rw1.c %s +// RUN: %clang %t-rw1.c %t-rw2.c -o %t-rw.output +// RUN: %t-rw.output + +#include "extern_func_decl_in_header.hbs" + +Foo(f1) + +Ptr table = { Entryf1 }; + +int main(void) { + return 0; +} + +// CHECK: #define Foo(Name) extern int Entry##Name(struct S **p); + +// CHECK: struct S; +// CHECK-NEXT: typedef int (*Ptr)(struct S **); + +// CHECK: struct S { +// CHECK-NEXT: int x; +// CHECK-NEXT: }; + +// CHECK: extern int Entryf1(struct S **p); + +// CHECK: Ptr table = {Entryf1}; + +// CHECK: int main(void) { +// CHECK-NEXT: return 0; +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/extern_func_decl_in_header.hbs b/clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/extern_func_decl_in_header.hbs new file mode 100644 index 000000000000..828c110217fc --- /dev/null +++ b/clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/extern_func_decl_in_header.hbs @@ -0,0 +1,12 @@ +#ifndef HEADER_H +#define HEADER_H + +struct S { + int x; +}; + +typedef int (*Ptr)(struct S **p); + +#define Foo(Name) extern int Entry##Name(struct S **p); + +#endif diff --git a/clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/lit.local.cfg b/clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/lit.local.cfg new file mode 100644 index 000000000000..1a5b1b56de8d --- /dev/null +++ b/clang/test/BSC/Positive/Driver/rewrite-bsc/extern_func_decl_in_header/lit.local.cfg @@ -0,0 +1,4 @@ +import os +import lit.formats + +config.excludes = ['extern.cbs'] \ No newline at end of file -- Gitee