@@ -87,10 +87,9 @@ void IR::addVarDefine(std::string name, std::shared_ptr<Variable> variable) {
8787}
8888
8989bool IR::libObjEmpty () const {
90- return functions.empty () && !hasOutputtedDeclaration (typeDefs) &&
91- !hasOutputtedDeclaration (structs) &&
92- !hasOutputtedDeclaration (unions) && varDefines.empty () &&
93- variables.empty ();
90+ return functions.empty () && !hasOutputtedType (typeDefs) &&
91+ !hasOutputtedType (structs) && !hasOutputtedType (unions) &&
92+ varDefines.empty () && variables.empty ();
9493}
9594
9695llvm::raw_ostream &operator <<(llvm::raw_ostream &s, const IR &ir) {
@@ -100,7 +99,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
10099 s << " package " << ir.packageName << " \n\n " ;
101100 }
102101
103- if (!ir.libObjEmpty () || ir.hasOutputtedDeclaration (ir.enums ) ||
102+ if (!ir.libObjEmpty () || ir.hasOutputtedType (ir.enums ) ||
104103 !ir.literalDefines .empty ()) {
105104 s << " import scala.scalanative._\n "
106105 << " import scala.scalanative.native._\n\n " ;
@@ -123,8 +122,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
123122
124123 for (const auto &typeDef : ir.typeDefs ) {
125124 visitedTypes.clear ();
126- if (ir.shouldOutput (typeDef, visitedTypes)) {
127- s << * typeDef;
125+ if (ir.shouldOutputTypeDef (typeDef, visitedTypes)) {
126+ s << typeDef-> getDefinition (ir. locationManager ) ;
128127 } else if (typeDef->hasLocation () &&
129128 isAliasForOpaqueType (typeDef.get ()) &&
130129 ir.locationManager .inMainFile (*typeDef->getLocation ())) {
@@ -138,7 +137,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
138137
139138 for (const auto &variable : ir.variables ) {
140139 if (!variable->hasIllegalUsageOfOpaqueType ()) {
141- s << * variable;
140+ s << variable-> getDefinition (ir. locationManager ) ;
142141 } else {
143142 llvm::errs () << " Error: Variable " << variable->getName ()
144143 << " is skipped because it has incomplete type.\n " ;
@@ -147,7 +146,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
147146
148147 for (const auto &varDefine : ir.varDefines ) {
149148 if (!varDefine->hasIllegalUsageOfOpaqueType ()) {
150- s << * varDefine;
149+ s << varDefine-> getDefinition (ir. locationManager ) ;
151150 } else {
152151 llvm::errs () << " Error: Variable alias " << varDefine->getName ()
153152 << " is skipped because it has incomplete type.\n " ;
@@ -162,7 +161,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
162161 " passing structs and arrays by value.\n " ;
163162 llvm::errs ().flush ();
164163 } else {
165- s << * func;
164+ s << func-> getDefinition (ir. locationManager ) ;
166165 }
167166 }
168167
@@ -173,16 +172,16 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
173172 if (!ir.literalDefines .empty ()) {
174173 s << " object " << ir.libName << " Defines {\n " ;
175174 for (const auto &literalDefine : ir.literalDefines ) {
176- s << * literalDefine;
175+ s << literalDefine-> getDefinition (ir. locationManager ) ;
177176 }
178177 s << " }\n\n " ;
179178 }
180179
181- if (ir.hasOutputtedDeclaration (ir.enums ) || ir.hasHelperMethods ()) {
180+ if (ir.hasOutputtedType (ir.enums ) || ir.hasHelperMethods ()) {
182181 s << " import " << objectName << " ._\n\n " ;
183182 }
184183
185- if (ir.hasOutputtedDeclaration (ir.enums )) {
184+ if (ir.hasOutputtedType (ir.enums )) {
186185 s << " object " << ir.libName << " Enums {\n " ;
187186
188187 std::string sep = " " ;
@@ -203,14 +202,14 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
203202 for (const auto &st : ir.structs ) {
204203 visitedTypes.clear ();
205204 if (ir.shouldOutput (st, visitedTypes) && st->hasHelperMethods ()) {
206- s << " \n " << st->generateHelperClass ();
205+ s << " \n " << st->generateHelperClass (ir. locationManager );
207206 }
208207 }
209208
210209 for (const auto &u : ir.unions ) {
211210 visitedTypes.clear ();
212211 if (ir.shouldOutput (u, visitedTypes) && u->hasHelperMethods ()) {
213- s << " \n " << u->generateHelperClass ();
212+ s << " \n " << u->generateHelperClass (ir. locationManager );
214213 }
215214 }
216215
@@ -327,7 +326,7 @@ bool IR::isTypeUsed(
327326 for (const auto &typeDef : typeDefs) {
328327 visitedTypesInner.clear ();
329328 if (typeDef->usesType (type, false , visitedTypesInner)) {
330- if (shouldOutput (typeDef, visitedTypes)) {
329+ if (shouldOutputTypeDef (typeDef, visitedTypes)) {
331330 return true ;
332331 }
333332 }
@@ -462,13 +461,21 @@ IR::~IR() {
462461}
463462
464463template <typename T>
465- bool IR::hasOutputtedDeclaration (
464+ bool IR::hasOutputtedType (
466465 const std::vector<std::shared_ptr<T>> &declarations) const {
467466 std::vector<std::shared_ptr<const Type>> visitedTypes;
468467 for (const auto &declaration : declarations) {
469468 visitedTypes.clear ();
470- if (shouldOutput (declaration, visitedTypes)) {
471- return true ;
469+ auto typeDefPointer =
470+ std::dynamic_pointer_cast<const TypeDef>(declaration);
471+ if (typeDefPointer) {
472+ if (shouldOutputTypeDef (typeDefPointer, visitedTypes)) {
473+ return true ;
474+ }
475+ } else {
476+ if (shouldOutput (declaration, visitedTypes)) {
477+ return true ;
478+ }
472479 }
473480 }
474481 return false ;
@@ -477,12 +484,31 @@ bool IR::hasOutputtedDeclaration(
477484bool IR::shouldOutput (
478485 const std::shared_ptr<const LocatableType> &type,
479486 std::vector<std::shared_ptr<const Type>> &visitedTypes) const {
487+ if (locationManager.isImported (*type->getLocation ())) {
488+ return false ;
489+ }
480490 if (isTypeUsed (type, visitedTypes)) {
481491 return true ;
482492 }
483- if (isAliasForOpaqueType (type.get ())) {
493+ /* remove unused types from included files */
494+ return locationManager.inMainFile (*type->getLocation ());
495+ }
496+
497+ bool IR::shouldOutputTypeDef (
498+ const std::shared_ptr<const TypeDef> &typeDef,
499+ std::vector<std::shared_ptr<const Type>> &visitedTypes) const {
500+ if (isTypeUsed (typeDef, visitedTypes)) {
501+ if (typeDef->wrapperForOpaqueType ()) {
502+ /* it is not possible to get location of this typedef
503+ * so the typedef cannot be imported from other bindings */
504+ return true ;
505+ }
506+ return !locationManager.isImported (*typeDef->getLocation ());
507+ }
508+ if (isAliasForOpaqueType (typeDef.get ())) {
509+ /* it does not matter where unused alias for opaque type is located */
484510 return false ;
485511 }
486512 /* remove unused types from included files */
487- return locationManager.inMainFile (*type ->getLocation ());
513+ return locationManager.inMainFile (*typeDef ->getLocation ());
488514}
0 commit comments