unsigned TypeResolver::checkUnresolvedType(const UnresolvedType* type, bool used_public) { IdentifierExpr* moduleName = type->getModuleName(); IdentifierExpr* typeName = type->getTypeName(); SourceLocation tLoc = typeName->getLocation(); const std::string& tName = typeName->getName(); Decl* D = 0; if (moduleName) { // mod.type const std::string& mName = moduleName->getName(); const Module* mod = globals.findUsedModule(mName, moduleName->getLocation(), used_public); if (!mod) return 1; Decl* modDecl = globals.findSymbol(mName, moduleName->getLocation(), true, used_public); assert(modDecl); moduleName->setDecl(modDecl); D = globals.findSymbolInModule(tName, tLoc, mod); } else { D = globals.findSymbol(tName, tLoc, true, used_public); } if (!D) return 1; TypeDecl* TD = dyncast<TypeDecl>(D); if (!TD) { StringBuilder name; type->printLiteral(name); Diags.Report(tLoc, diag::err_not_a_typename) << name.c_str(); return 1; } bool external = globals.isExternal(D->getModule()); if (used_public &&!external && !TD->isPublic()) { StringBuilder name; type->printLiteral(name); Diags.Report(tLoc, diag::err_non_public_type) << AnalyserUtils::fullName(TD->getModule()->getName(), TD->getName()); //Diags.Report(tLoc, diag::err_non_public_type) << name; return 1; } D->setUsed(); if (used_public || external) D->setUsedPublic(); typeName->setDecl(TD); return 0; }
int FileScope::checkUserType(Type* type, Expr* id, bool used_public) { // TODO refactor const Package* pkg = 0; switch (id->getKind()) { case EXPR_IDENTIFIER: // unqualified { IdentifierExpr* I = cast<IdentifierExpr>(id); ScopeResult res = findSymbol(I->getName()); if (!res.decl) { Diags.Report(I->getLocation(), diag::err_unknown_typename) << I->getName(); return 1; } if (res.ambiguous) { Diags.Report(I->getLocation(), diag::err_ambiguous_symbol) << I->getName(); // TODO show alternatives return 1; } if (res.external && !res.decl->isPublic()) { Diags.Report(I->getLocation(), diag::err_not_public) << I->getName(); return 1; } TypeDecl* td = dyncast<TypeDecl>(res.decl); if (!td) { Diags.Report(I->getLocation(), diag::err_not_a_typename) << I->getName(); return 1; } if (used_public && !res.external && !td->isPublic()) { Diags.Report(I->getLocation(), diag::err_non_public_type) << I->getName(); return 1; } // ok assert(res.pkg && "pkg should be set"); I->setPackage(res.pkg); I->setDecl(res.decl); type->setRefType(td->getType()); } break; case EXPR_MEMBER: // fully qualified { MemberExpr* M = cast<MemberExpr>(id); Expr* base = M->getBase(); IdentifierExpr* pkg_id = cast<IdentifierExpr>(base); const std::string& pkgName = pkg_id->getName(); // check if package exists pkg = findPackage(pkgName); if (!pkg) { // check if used with alias (then fullname is forbidden) for (PackagesConstIter iter = packages.begin(); iter != packages.end(); ++iter) { const Package* p = iter->second; if (p->getName() == pkgName) { Diags.Report(pkg_id->getLocation(), diag::err_package_has_alias) << pkgName << iter->first; return 1; } } // TODO use function PkgsConstIter iter = allPackages.find(pkgName); if (iter == allPackages.end()) { Diags.Report(pkg_id->getLocation(), diag::err_unknown_package) << pkgName; } else { Diags.Report(pkg_id->getLocation(), diag::err_package_not_used) << pkgName; } return 1; } // check member Expr* member = M->getMember(); IdentifierExpr* member_id = cast<IdentifierExpr>(member); // check Type Decl* symbol = pkg->findSymbol(member_id->getName()); if (!symbol) { Diags.Report(member_id->getLocation(), diag::err_unknown_typename) << M->getFullName(); return 1; } TypeDecl* td = dyncast<TypeDecl>(symbol); if (!td) { Diags.Report(member_id->getLocation(), diag::err_not_a_typename) << M->getFullName(); return 1; } // if external package, check visibility if (isExternal(pkg) && !td->isPublic()) { Diags.Report(member_id->getLocation(), diag::err_not_public) << M->getFullName(); return 1; } if (used_public && !isExternal(pkg) && !td->isPublic()) { Diags.Report(member_id->getLocation(), diag::err_non_public_type) << M->getFullName(); return 1; } // ok member_id->setPackage(pkg); type->setRefType(td->getType()); } break; default: assert(0); } return 0; }