@@ -102,40 +102,61 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
102102
103103 std::string objectName = handleReservedWords (ir.objectName );
104104
105- if (!ir.libObjEmpty ()) {
105+ bool isLibObjectEmpty = ir.libObjEmpty ();
106+
107+ if (!isLibObjectEmpty) {
106108 if (!ir.linkName .empty ()) {
107109 s << " @native.link(\" " << ir.linkName << " \" )\n " ;
108110 }
109111
110112 s << " @native.extern\n "
111113 << " object " << objectName << " {\n " ;
114+ }
112115
113- for (const auto &typeDef : ir.typeDefs ) {
114- if (ir.shouldOutput (typeDef)) {
115- s << *typeDef;
116- }
116+ for (const auto &typeDef : ir.typeDefs ) {
117+ if (ir.shouldOutput (typeDef)) {
118+ s << *typeDef;
119+ } else if (isAliasForOpaqueType (typeDef.get ()) &&
120+ ir.inMainFile (*typeDef)) {
121+ llvm::errs () << " Warning: type alias " + typeDef->getName ()
122+ << " is skipped because it is an unused alias for "
123+ " incomplete type."
124+ << " \n " ;
125+ llvm::errs ().flush ();
117126 }
127+ }
118128
119- for (const auto &variable : ir.variables ) {
129+ for (const auto &variable : ir.variables ) {
130+ if (!variable->hasIllegalUsageOfOpaqueType ()) {
120131 s << *variable;
132+ } else {
133+ llvm::errs () << " Error: Variable " << variable->getName ()
134+ << " is skipped because it has incomplete type.\n " ;
121135 }
136+ }
122137
123- for (const auto &varDefine : ir.varDefines ) {
138+ for (const auto &varDefine : ir.varDefines ) {
139+ if (!varDefine->hasIllegalUsageOfOpaqueType ()) {
124140 s << *varDefine;
141+ } else {
142+ llvm::errs () << " Error: Variable alias " << varDefine->getName ()
143+ << " is skipped because it has incomplete type.\n " ;
144+ llvm::errs ().flush ();
125145 }
146+ }
126147
127- for (const auto &func : ir.functions ) {
128- if (func->isLegalScalaNativeFunction ()) {
129- s << *func;
130- } else {
131- llvm::errs ()
132- << " Warning: Function " << func->getName ()
133- << " is skipped because Scala Native does not support "
134- " passing structs and arrays by value.\n " ;
135- llvm::errs ().flush ();
136- }
148+ for (const auto &func : ir.functions ) {
149+ if (!func->isLegalScalaNativeFunction ()) {
150+ llvm::errs () << " Warning: Function " << func->getName ()
151+ << " is skipped because Scala Native does not support "
152+ " passing structs and arrays by value.\n " ;
153+ llvm::errs ().flush ();
154+ } else {
155+ s << *func;
137156 }
157+ }
138158
159+ if (!isLibObjectEmpty) {
139160 s << " }\n\n " ;
140161 }
141162
@@ -449,5 +470,18 @@ bool IR::hasOutputtedDeclaration(
449470
450471template <typename T>
451472bool IR::shouldOutput (const std::shared_ptr<T> &type) const {
452- return inMainFile (*type) || isTypeUsed (type, true );
473+ if (isTypeUsed (type, true )) {
474+ return true ;
475+ }
476+ if (!inMainFile (*type)) {
477+ /* remove unused types from included files */
478+ return false ;
479+ }
480+ auto *typeDef = dynamic_cast <TypeDef *>(type.get ());
481+ if (typeDef) {
482+ /* unused typedefs from main file are printed only if they are not
483+ * aliases for an opaque type. */
484+ return !isAliasForOpaqueType (typeDef);
485+ }
486+ return true ;
453487}
0 commit comments