/* decls.cc: Implementations of common declaration-processing routines */ /* Copyright (C) 1996, Paul N. Hilfinger. All Rights Reserved. */ #include #include #include #include #include "AST.h" #include "ClassDecl.h" #include "FieldDecl.h" #include "MethodDecl.h" #include "compiler.h" #include "ctBox.h" #include "decls.h" #include "errors.h" #include "utils.h" /***** DECLARATION *****/ /***********************************************************************/ /* Default member declarations for Declaration */ /***********************************************************************/ const string* ErrorNameString = new string(""); /* A new Decl of an entity named NAME0 . If NAME0 is null, then */ /* name() is set to a special string and erroneous() is true. (see */ /* below). Otherwise, erroneous is false. */ Decl::Decl (const string* name0) : visits(0), mark(0), _name(name0 == NULL ? ErrorNameString : name0), _forward(NULL) {} void Decl::fatal (const string& msg) const { cout << thisClassName() << ": fatal error: " << msg << endl; abort(); } void Decl::invalidOperation (const char* opname) const { fatal (string("invalid operation: ") + opname); } Subst *Decl::templateArgs() { invalidOperation("templateArgs"); return NULL; } void Decl::templateArgs(Subst *) { invalidOperation("templateArgs"); } bool Decl::isTemplateBasis() const { return false; } Decl* Decl::container() const { invalidOperation ("container"); return 0; } void Decl::drequire() { invalidOperation ("drequire"); } void Decl::container (Decl* ) { invalidOperation ("container"); } bool Decl::hasContainer() const { return false; } MethodSet *Decl::overriders() { invalidOperation("overriders"); return 0; } const MethodSet *Decl::overriders() const { invalidOperation("overriders"); return 0; } void Decl::overriders(MethodDecl *) { invalidOperation("overriders"); } bool Decl::hasOverriders() const { return false; } static MethodSet nothing; MethodSet &Decl::implements() { invalidOperation("implements"); return nothing; } const MethodSet &Decl::implements() const { invalidOperation("implements"); return nothing; } void Decl::implements(MethodDecl *) { invalidOperation("implements"); } bool Decl::hasImplements() const { return false; } TypeNode* Decl::type() const { invalidOperation ("type"); return 0; } void Decl::type (TypeNode* ) { invalidOperation ("type"); } bool Decl::hasType() const { return false; } Common::Modifiers Decl::modifiers() const { #if 1 invalidOperation ("modifiers"); #else // DOB: this is totally bogus and was responsible for a code-gen bug // if we don't have a modifiers child, we certainly shouldn't // quietly claim that we do and that it's the empty set if (hasModifiers()) invalidOperation ("modifiers"); #endif return (Common::Modifiers)0; } void Decl::modifiers (Common::Modifiers ) { invalidOperation ("modifiers"); } bool Decl::hasModifiers() const { return false; } TreeNode* Decl::source() const { invalidOperation ("source"); return 0; } void Decl::source (TreeNode* ) { invalidOperation ("source"); } bool Decl::hasSource() const { return false; } Environ* Decl::environ() { invalidOperation ("environ"); return 0; } Environ* Decl::environ(bool build) { return environ(); } void Decl::environ (Environ* ) { invalidOperation ("environ"); } bool Decl::hasEnviron() const { return false; } void Decl::superClass (ClassDecl* ) { invalidOperation ("superClass"); } bool Decl::hasSuperClass() { return false; } ClassDecl* Decl::superClass() const { invalidOperation ("superClass"); return 0; } void Decl::overrides (Decl* ) { invalidOperation ("overrides"); } bool Decl::hasOverrides() const { return false; } Decl* Decl::overrides() const { invalidOperation ("overrides"); return 0; } llist* Decl::interfaces() { invalidOperation ("interfaces"); return 0; } bool Decl::hasInterfaces() const { return false; } void Decl::interfaces (llist* ) { invalidOperation ("interfaces"); } bool Decl::broken() const { invalidOperation ("broken"); return false; } void Decl::broken (bool) { invalidOperation ("broken"); } bool Decl::continued() const { invalidOperation ("continued"); return false; } void Decl::continued (bool) { invalidOperation ("continued"); } bool Decl::valid() const { invalidOperation ("valid"); return false; } void Decl::valid (bool) { invalidOperation ("valid"); } TypeNode* Decl::asType() const { invalidOperation ("asType"); return NULL; } string Decl::signature() const { invalidOperation ("signature"); return ""; } string Decl::cFieldName() const { invalidOperation ("cFieldName"); return ""; } bool Decl::isType() const { return false; } bool Decl::erroneous() const { return _name == ErrorNameString; } /***********************************************************************/ /* Definitions of category and thisClassName for all Decl derivates. */ /***********************************************************************/ const char* PackageDecl::thisClassName() const { return "PackageDecl"; } Decl::Category PackageDecl::category() const { return Package; } const char* ClassDecl::thisClassName() const { return "ClassDecl"; } Decl::Category ClassDecl::category() const { if ((modifiers() & Common::Interface) == 0) return Class; else return Interface; } const char* LocalVarDecl::thisClassName() const { return "LocalVarDecl"; } Decl::Category LocalVarDecl::category() const { return LocalVar; } const char* FormalParameterDecl::thisClassName() const { return "FormalParameterDecl"; } Decl::Category FormalParameterDecl::category() const { return Formal; } const char* FieldDecl::thisClassName() const { return "FieldDecl"; } Decl::Category FieldDecl::category() const { return Field; } const char* MethodDecl::thisClassName() const { return "MethodDecl"; } Decl::Category MethodDecl::category() const { return _category; } const char* StmtLblDecl::thisClassName() const { return "StmtLblDecl" ; } Decl::Category StmtLblDecl::category() const { return StmtLabel; } /* Odds and ends */ PackageDecl* const PackageDecl::System = new PackageDecl (new string(""), NULL); ClassDecl::ClassDecl (const string* name, Decl* container, Modifiers mods, TreeNode* source) : TypeDecl (name, invalid(name)), instantiations( 0 ), numInstantiations( 0 ), templateActuals( 0 ), templateBasis( 0 ), templateDepth( 0 ), _container (container), _modifiers (mods), _source (source), _environ (NULL), _superClass (NULL), _interfaces (NULL), _valid(false), _allFieldsShared( Maybe ), _declaredName(name) { } ClassDecl::ClassDecl (const string* name, Decl* container, Modifiers mods, TreeNode* source, TypeNode* as_type) : TypeDecl (name, as_type), instantiations( 0 ), numInstantiations( 0 ), templateActuals( 0 ), templateBasis( 0 ), templateDepth( 0 ), _container (container), _modifiers (mods), _source (source), _environ (NULL), _superClass (NULL), _interfaces (NULL), _valid(false), _allFieldsShared( Maybe ), _declaredName(name) { } ClassDecl::ClassDecl (const string* name, Decl* container) : TypeDecl (name, invalid(name)), instantiations( 0 ), numInstantiations( 0 ), templateActuals( 0 ), templateBasis( 0 ), templateDepth( 0 ), _container (container), _modifiers ((Modifiers) 0), _source (NULL), _environ (NULL), _superClass (NULL), _interfaces (NULL), _valid(false), _allFieldsShared( Maybe ), _declaredName(name) { } ClassDecl::ClassDecl (const string* name, const string* declaredName, Decl* container, Modifiers mods, TreeNode* source) : TypeDecl (name, invalid(name)), instantiations( 0 ), numInstantiations( 0 ), templateActuals( 0 ), templateBasis( 0 ), templateDepth( 0 ), _container (container), _modifiers (mods), _source (source), _environ (NULL), _superClass (NULL), _interfaces (NULL), _valid(false), _allFieldsShared( Maybe ), _declaredName(declaredName) { } ClassDecl::ClassDecl (const string* name, const string* declaredName, Decl* container, Modifiers mods, TreeNode* source, TypeNode* as_type) : TypeDecl (name, as_type), instantiations( 0 ), numInstantiations( 0 ), templateActuals( 0 ), templateBasis( 0 ), templateDepth( 0 ), _container (container), _modifiers (mods), _source (source), _environ (NULL), _superClass (NULL), _interfaces (NULL), _valid(false), _allFieldsShared( Maybe ), _declaredName(declaredName) { } ClassDecl::ClassDecl (const string* name, const string* declaredName, Decl* container) : TypeDecl (name, invalid(name)), instantiations( 0 ), numInstantiations( 0 ), templateActuals( 0 ), templateBasis( 0 ), templateDepth( 0 ), _container (container), _modifiers ((Modifiers) 0), _source (NULL), _environ (NULL), _superClass (NULL), _interfaces (NULL), _valid(false), _allFieldsShared( Maybe ), _declaredName(declaredName) { } TypeNameNode *ClassDecl::invalid( const string *name ) { return new TypeNameNode (new NameNode (TreeNode::omitted, name, this)); } string ClassDecl::signature() const { string res; if (container() == NULL) { if (! erroneous()) Warning() << "class " << *name() << " has no container" << endl; res = 'L'; } else res = container()->signature(); return res + *name() + ';'; } string PackageDecl::signature() const { string res; if (container() == NULL) res = 'L'; else res = container()->signature(); if (name()->size() == 0) return res; else return res + *name() + '/'; } /* Printing */ void db_print_decl (Decl* d) { d->print (cerr); cerr << endl; } void Decl::print (ostream& os) const { if (this == NULL) os << "#"; else { os << "#<" << thisClassName() << " 0x" << setbase (16) << (unsigned long) this << ": " << *name(); if (name() != intern (name()->c_str())) os << " (not interned)"; os << ">" << setbase (10); } } /* the errorName and fullName methods */ string Decl::errorName() { invalidOperation("errorName"); return string(); } string PackageDecl::errorName() { if (this == unnamedPackage) return "unnamed package"; else if (this == PackageDecl::System) return "system root package"; else return "package " + fullName(); } string LocalVarDecl::errorName() { return fullName(); } string FormalParameterDecl::errorName() { return "parameter " + fullName(); } string FieldDecl::errorName() { return "field " + fullName(); } string MethodDecl::errorName() { if (category() == Method) return "method " + fullName(); else return "constructor for " + fullName(); } string ClassDecl::errorName() { string result; if (instantiations) result += "template "; switch (category()) { case Class: result += "class"; break; case Interface: result += "interface"; break; default: assert( 0 ); } result += ' '; result += fullName(); return result; } string StmtLblDecl::errorName() { return "label " + fullName(); } string Decl::fullName( char delimiter ) { string prefix; if (hasContainer() && container()) prefix += container()->fullName( delimiter ); if (!prefix.empty()) prefix += delimiter; return prefix + *name(); } string ClassDecl::fullName( char delimiter ) { string result = Decl::fullName( delimiter ); if (asType()->isArrayType()) return asType()->typeName(); else if (source() && !source()->absent() && source()->enclosingType()) { if (modifiers() & Common::AnonymousClass) result = source()->enclosingType()->decl()->fullName(delimiter) + delimiter + int2string(source()->classNum()); else if (modifiers() & Common::LocalClass) result = source()->enclosingType()->decl()->fullName(delimiter) + delimiter + *declaredName() + "-" + int2string(source()->classNum()); else result = source()->enclosingType()->decl()->fullName(delimiter) + delimiter + *declaredName(); } if (templateActuals) { result += "< "; bool first = true; foriter (f, templateActuals->allChildren(), TreeNode::ChildIter) { if (first) first = false; else result += ", "; if ((*f)->isTypeNode()) result += (*f)->decl()->fullName(); else result += (*f)->typeName(); } result += " >"; } return result; } string FieldDecl::fullName( char delimiter ) { return container()->fullName( delimiter ) + delimiter + *name(); } string MethodDecl::fullName( char delimiter ) { if (category() == Method) return container()->fullName( delimiter ) + delimiter + *name(); else return container()->fullName( delimiter ); } /* mangledName and mangledFullName methods */ string Decl::mangledName( bool ) { return string(); } string Decl::mangledFullName( bool ) { if (hasContainer() && container()) return container()->mangledFullName( false ); else return string(); } static string mangleTemplateActuals(TreeListNode *templateActuals) { string result; if (templateActuals) { result += MANGLE_GENERIC_MARKER; result += int2string(templateActuals->arity()); result += MANGLE_GENERIC_MARKER; foriter (child, templateActuals->allChildren(), TreeNode::ChildIter) { string childstr = (*child)->mangle(); result += int2string( childstr.length() ) + childstr; } } return result; } string ClassDecl::mangledName( bool first ) { string result = mangleTemplateActuals(templateActuals); if (!first) result += MANGLE_INNER_CLASS_MARKER; assert( !name()->empty() ); result += MANGLE_QID(+, *name()); return result; } string ClassDecl::mangledFullName( bool first ) { string result = mangledName(first); result += Decl::mangledFullName( false ); return result; } string PackageDecl::mangledFullName( bool ) { string result; if (name()->length() > 0) result += MANGLE_QID(+, *name()); result += Decl::mangledFullName( false ); return result; } /* Given the fully-qualified name of a class, return the Decl for it. */ Decl* declFromFullClassName (string name) { Decl* d; string::size_type p, np; p = 0; d = PackageDecl::System; do { Decl* nd; np = name.find ('/', p); if (np == string::npos) np = name.size(); if (d->category() != Decl::Package) { Error() << "qualifier " << name.substr (0, p) << " is not a package" << endl; return UnknownClassDecl; } nd = d->environ() ->lookupProper (intern (name.substr (p, np-p))); if (nd == NULL) { Error() << "could not find " << name.substr (0, np) << endl; return UnknownClassDecl; } d = nd; p = np + 1; } while (p < name.size()); return d; } void printNode (const Decl* decl, ostream& os) { if (decl == NULL) os << "-*-"; else decl->print (os); }