// -*- mode: java; c-basic-offset: 4 -*- // // Copyright 2001-2002 by the Regents of the University of California. // All rights reserved. // // HARMONIA: C language module name resolution // // RCS Info: $Revision: 1.1 $ on $Date: 2003/05/12 01:49:32 $ // $Source: /home/cs/harmonia/cvsroot/www/harmonia/projects/langs/c/c-resolve.def,v $ // // Not usable yet, alas: // -*- mode: harmonia-astdef2; c-basic-offset: 4 -*- import "Node.def"; import "ParentNode.def"; import "ListNode.def"; import "AmbigNode.def"; import "GLRStateMixin.def"; include "common/stl.h" include "common/PooledString.h" include "lk/isemant/Scope.h" include "lk/isemant/NestedScope.h" include "lk/isemant/OverlayScope.h" include "lk/isemant/SemantErrors.h" include "lk/node/UltraRoot.h" include "c.h" phylum trans_unit { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } public virtual method void semant() {} } // trans_unit -> SeqR0E0:ext_decls operator TranslationUnit extends ParentNode, trans_unit, GLRStateMixin { public slot TypecheckContext *type_context; public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { for (ext_decls_iterator i = get_ext_decls(); i; ++i) { if (!i.get_ext_decl()->resolve_idents(ctx, idents)) return false; } return true; } public virtual method void semant() { clear_semant_errors_subtree(cast_to_Node()); for (ext_decls_iterator i = get_ext_decls(); i; ++i) { bool keep_going = root()->get_bool_prop(ALWAYS_DO_SEMANTICS); //fprintf(stderr, "keep_going is %d\n", keep_going); bool is_preproc = i.get_ext_decl()->is_preproc_directive(keep_going); if (is_preproc) return; } { ResolveContext ctx; RootIdentTable filescope_idents; if (!resolve_idents(&ctx, &filescope_idents)) error("Unexpected mismatch at top level!\n"); } { type_context = new TypecheckContext(); check_types(type_context); } } } operator no_trans_unit extends Node, trans_unit, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } public virtual method void semant() {} } operator trans_unit_sym extends AmbigNode, trans_unit, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected ambiguity in translation unit!\n"); return false; } public virtual method void semant() { error("Unexpected ambiguity in translation unit!\n"); } } phylum ext_decl depends on trans_unit { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } public virtual method bool is_preproc_directive(bool keep_going) { return false; } } // ext_decl -> SeqR1E0:specs declr:declr SeqR1E2:decls comp_stmt:body operator FunctionDefinition extends ParentNode, ext_decl, GLRStateMixin depends on decl, declr, Declaration { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { decl::ResolveType base_type; Localizer save(&ctx->decl_cx); Localizer save2(&ctx->labels); // not really needed ctx->decl_cx = FUNC_DEF; for (specs_iterator i = get_specs(); i; ++i) { if (!i.get_spec()->resolve_idents(ctx, idents)) return false; i.get_spec()->get_resolve_type(ctx, &base_type); } if (!Declaration::check_resolve_type(ctx, &base_type, this)) return false; if (!get_declr()->resolve_idents(ctx, idents, &base_type)) return false; ctx->decl_cx = FUNC_DEF; declr::FunctionDeclType type = get_declr()->declares_func(); if (type == declr::NOT_A_FUNCTION) { ambig_semant_error(ctx, this, "function declaration " "does not declare a function"); if (ctx->inside_ambig) return false; } NestedIdentTable func_idents; func_idents.add_parent(idents); if (type == declr::ANSI_FUNCTION) { if (get_decls()) set_semant_error(this, "ANSI functions cannot take extra " "declarations"); get_declr()->declare_ansi_idents(ctx, &func_idents); } else if (type == declr::K_AND_R_FUNCTION) { ctx->decl_cx = KnR_PARAM; for (decls_iterator i = get_decls(); i; ++i) { if (!i.get_decl()->resolve_idents(ctx, &func_idents)) return false; } get_declr()->check_KnR_idents(ctx, &func_idents); } ctx->decl_cx = NO_DECL; ctx->labels = new LabelTable(); int ret = get_body()->resolve_idents(ctx, &func_idents, false); for (LabelTable::iterator i = ctx->labels->get_bindings(); i; ++i) { LabelInfo *info = i.get_entity(); if (info->defs.size() == 0) { for (vector::iterator i = info->uses.begin(); i != info->uses.end(); ++i) { set_semant_error(*i, "Undefined label %s", info->name.chars()); } } else if (info->defs.size() > 1) { for (vector::iterator i = info->defs.begin(); i != info->defs.end(); ++i) { set_semant_error(*i, "Duplicate definition of label %s", info->name.chars()); } } else { for (vector::iterator i = info->uses.begin(); i != info->uses.end(); ++i) { (*i)->target.set_value(vg(), info->defs[0]); (*i)->compute_synth_attrs(true); } } } ctx->labels = 0; return ret; } } // ext_decl -> decl:decl operator OtherExtDeclaration extends ParentNode, ext_decl, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { Localizer save(&ctx->decl_cx); ctx->decl_cx = FILE_SCOPE; bool res = get_decl()->resolve_idents(ctx, idents); // cerr << "Ident table is now:" << endl; // idents->dump(cerr); return res; } } operator PreprocessorJunk { public virtual method bool is_preproc_directive(bool keep_going) { if (!keep_going) { set_semant_error(this, "Can't run semantics with preprocessor " "directives"); return true; } return false; } } operator no_ext_decl extends Node, ext_decl, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } operator ext_decl_sym extends AmbigNode, ext_decl, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return resolve_idents_func(ctx, idents, this); } } phylum decl_spec depends on decl { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { error("Unexpected call to decl_spec::get_resolve_type\n"); } } // decl_spec -> stor_class_spec:spec operator StorageDeclSpec extends ParentNode, decl_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { get_spec()->get_resolve_type(ctx, type); } } // decl_spec -> type_spec:spec operator TypeSpecDeclSpec extends ParentNode, decl_spec, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_spec()->resolve_idents(ctx, idents); } public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { get_spec()->get_resolve_type(ctx, type); } } // decl_spec -> type_qual:qual operator TypeQualDeclSpec extends ParentNode, decl_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { get_qual()->get_resolve_type(ctx, type); } } // decl_spec -> INLINE:qual operator FunctionQualDeclSpec extends ParentNode, decl_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { /* nothing to do */ } } operator decl_spec_sym extends AmbigNode, decl_spec, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected ambiguity in declaration specifier!\n"); return true; } public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { error("Unexpected ambiguity in declaration specifier!\n"); } } phylum declr depends on decl { public enum FunctionDeclType { NOT_A_FUNCTION, K_AND_R_FUNCTION, ANSI_FUNCTION }; public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents, decl::ResolveType *base_type) { return true; } public virtual method declr::FunctionDeclType declares_func() { error("Not reached\n"); return NOT_A_FUNCTION; } public virtual method IDSYM* find_name() { return 0; } public virtual method void declare_ansi_idents(ResolveContext *ctx, IdentTable *func_idents) { error("Unexpected call to declr::declare_ansi_idents\n"); } public virtual method void declare_ident(ResolveContext *ctx, IdentTable *func_idents) { error("Unexpected call to declr::declare_ident\n"); } public virtual method void check_KnR_idents(ResolveContext *ctx, IdentTable *func_idents) { error("Unexpected call to declr::check_KnR-idents\n"); } } // declr -> OptR47E0:ptr direct_declr:direct operator Declarator extends ParentNode, declr, GLRStateMixin { public versioned slot Vptr identifier = NULL; versioned Semantics attribute identifier = TypedVal((Node*)identifier.value(vg(), gvid)); public versioned slot Vptr linkage_link = NULL; versioned Semantics attribute linkage_link = TypedVal((Node*)linkage_link.value(vg(), gvid)); public slot int decl_context; public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents, decl::ResolveType *base_type) { // decl TypeInfo my_type = *base_type; // if (has_ptr()) // get_ptr()->specify(my_type) if (!get_direct()->resolve_idents(ctx, idents)) return false; IDSYM *name_node = find_name(); identifier.set_value(vg(), name_node->cast_to_Node()); compute_synth_attrs(true); PooledString id_name = name_node->pooled_string(); IdentInfo::IdentType id_type; if (base_type->storage == decl::TYPEDEF_STORAGE) { id_type = IdentInfo::TYPEDEF_ID; name_node->set_subspecies(ctx, IDSYM::TYPEDEF_DECL_NAME); } else { id_type = IdentInfo::OBJECT_ID; name_node->set_subspecies(ctx, IDSYM::DECLARATION_NAME); } IdentInfo *info = new IdentInfo(id_name, id_type, this); decl_context = ctx->decl_cx; switch (ctx->decl_cx) { case FOR_INIT: case BLOCK: if (base_type->storage != decl::EXTERN_STORAGE) { if (idents->has_ident_binding(id_name)) { set_semant_error(this, "Identifier `%s' redefined", id_name.chars()); return true; } break; } /* fall through */ case FILE_SCOPE: case FUNC_DEF: { IdentInfo *prev_info = idents->resolve_ident(id_name); info->link = prev_info; if (prev_info) { linkage_link.set_value(vg(), prev_info->definition); compute_synth_attrs(true); } info->defined = (ctx->decl_init || ctx->decl_cx == FUNC_DEF); if (prev_info && prev_info->type != IdentInfo::OBJECT_ID) set_semant_error(this, "Identifier `%s' redeclared as a " "different kind of identifier", id_name.chars()); if (prev_info && prev_info->defined && info->defined) set_semant_error(this, "Duplicate definition of `%s'", id_name.chars()); if (base_type->storage == decl::STATIC_STORAGE) { if (prev_info && prev_info->linkage != IdentInfo::INTERNAL_LINKAGE) { set_semant_error(this, "Identifier `%s' was declared " "non-static and then static", id_name.chars()); } info->linkage = IdentInfo::INTERNAL_LINKAGE; } else if (base_type->storage == decl::EXTERN_STORAGE || (ctx->decl_cx == FUNC_DEF && base_type->storage == decl::NO_STORAGE)) { if (prev_info && prev_info->linkage != IdentInfo::NO_LINKAGE) { info->linkage = prev_info->linkage; } else { info->linkage = IdentInfo::EXTERNAL_LINKAGE; } } else if (base_type->storage == decl::NO_STORAGE) { if (!prev_info) { info->linkage = IdentInfo::EXTERNAL_LINKAGE; } else if (prev_info->linkage == IdentInfo::INTERNAL_LINKAGE) { set_semant_error(this, "Identifier `%s' was declared " "static and then non-static", id_name.chars()); } else { info->linkage = prev_info->linkage; } } else if (base_type->storage == decl::TYPEDEF_STORAGE) { if (idents->has_ident_binding(id_name)) { set_semant_error(this, "Identifier `%s' redefined", id_name.chars()); return true; } } else { error("Unexpected storage class in declaration\n"); } break; } case KnR_PARAM: name_node->set_subspecies(ctx, IDSYM::KNR_PARAM_DECL_NAME); goto parameter; case DEF_PARAM: case DECL_PARAM: name_node->set_subspecies(ctx, IDSYM::PARAM_DECL_NAME); parameter: if (idents->has_ident_binding(id_name)) { set_semant_error(this, "Duplicate parameter `%s'", id_name.chars()); return true; } break; case STRUCT_UNION_CX: assert(ctx->aggr_members); name_node->set_subspecies(ctx, IDSYM::AGGR_MEMBER_DECL_NAME); if (ctx->aggr_members->has_binding(id_name)) { set_semant_error(this, "Duplicate member `%s'", id_name.chars()); } else { info->type = IdentInfo::STRUCT_UNION_MEMBER; ctx->aggr_members->add(id_name, info); } return true; case NO_DECL: default: error("Strange decl context\n"); break; } idents->add_ident(id_name, info); return true; } public virtual method void declare_ident(ResolveContext *ctx, IdentTable *func_idents) { PooledString id_name = find_name()->pooled_string(); IdentInfo *info = new IdentInfo(id_name, IdentInfo::OBJECT_ID, this); func_idents->add_ident(id_name, info); } public virtual method declr::FunctionDeclType declares_func() { return get_direct()->declares_func(); } public virtual method IDSYM* find_name() { return get_direct()->find_name(); } public virtual method void declare_ansi_idents(ResolveContext *ctx, IdentTable *func_idents) { get_direct()->declare_ansi_idents(ctx, func_idents); } public virtual method void check_KnR_idents(ResolveContext *ctx, IdentTable *func_idents) { get_direct()->check_KnR_idents(ctx, func_idents); } } operator declr_sym extends AmbigNode, declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents, decl::ResolveType *base_type) { error("Unexpected ambiguity in declarator!\n"); return false; } public virtual method IDSYM* find_name() { error("Unexpected ambiguity in declarator!\n"); return 0; } public virtual method declr::FunctionDeclType declares_func() { error("Unexpected ambiguity in declarator!\n"); return NOT_A_FUNCTION; } public virtual method void declare_ansi_idents(ResolveContext *ctx, IdentTable *func_idents) { error("Unexpected ambiguity in declarator!\n"); } public virtual method void declare_ident(ResolveContext *ctx, IdentTable *func_idents) { error("Unexpected ambiguity in declarator!\n"); } public virtual method void check_KnR_idents(ResolveContext *ctx, IdentTable *func_idents) { error("Unexpected call to declr::check_KnR-idents\n"); } } phylum direct_declr depends on trans_unit, declr { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected call too direct_declr::resolve_idents\n"); return true; } public virtual method IDSYM* find_name() { return 0; } public virtual method declr::FunctionDeclType declares_func() { return declr::NOT_A_FUNCTION; } public virtual method void declare_ansi_idents(ResolveContext *ctx, IdentTable *func_idents) { error("Unexpected call to direct_declr::declare_ansi_idents\n"); } public virtual method void check_KnR_idents(ResolveContext *ctx, IdentTable *func_idents) { error("Unexpected call to direct_declr::check_KnR_idents\n"); } public virtual method bool could_be_typedef(ResolveContext *ctx, IdentTable *idents) { return false; } } // direct_declr -> IDSYM:name operator DeclarNameDirDeclr extends ParentNode, direct_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } public virtual method IDSYM* find_name() { return get_name(); } public virtual method bool could_be_typedef(ResolveContext *ctx, IdentTable *idents) { IdentInfo *info = idents->resolve_ident(get_name()->pooled_string()); if (info && info->type == IdentInfo::TYPEDEF_ID) return true; return false; } } // direct_declr -> '(' ptr:(ptr:pointer)? direct:direct_declr ')' operator ParenNameDirDeclr extends ParentNode, direct_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if ((ctx->decl_cx == DEF_PARAM || ctx->decl_cx == DECL_PARAM) && get_direct()->could_be_typedef(ctx, idents) && ctx->inside_ambig) { ambig_semant_error(ctx, this, "single parenthesized typename in " "parameter must be abstract function " "declaration"); return false; } return get_direct()->resolve_idents(ctx, idents); } public virtual method IDSYM* find_name() { return get_direct()->find_name(); } public virtual method declr::FunctionDeclType declares_func() { return get_direct()->declares_func(); } } // direct_declr -> direct_declr:declr '[' SeqR52E2:quals OptR52E3 ']' operator BasicArrayDirDeclr extends ParentNode, direct_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_declr()->resolve_idents(ctx, idents)) return false; if (has_expr()) return get_expr_expr()->resolve_idents(ctx, idents); else return true; } public virtual method IDSYM* find_name() { return get_declr()->find_name(); } } // direct_declr -> direct_declr:declr '[' SeqR52E2:quals1 STATIC SeqR52E2:quals2 assign_expr:expr ']' operator StaticArrayDirDeclr extends ParentNode, direct_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_declr()->resolve_idents(ctx, idents)) return false; return get_expr()->resolve_idents(ctx, idents); } public virtual method IDSYM* find_name() { return get_declr()->find_name(); } } // direct_declr -> direct_declr:declr '[' SeqR52E2:quals '*' ']' operator VariableArrayDirDeclr extends ParentNode, direct_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_declr()->resolve_idents(ctx, idents); } public virtual method IDSYM* find_name() { return get_declr()->find_name(); } } // direct_declr -> direct_declr:declr '(' param_type_list:params ')' operator TypeFuncListDirDeclr extends ParentNode, direct_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_declr()->resolve_idents(ctx, idents)) return false; Localizer save(&ctx->decl_cx); if (ctx->decl_cx == FUNC_DEF) ctx->decl_cx = DEF_PARAM; else ctx->decl_cx = DECL_PARAM; NestedIdentTable param_table; param_table.add_parent(idents); return get_params()->resolve_idents(ctx, ¶m_table); } public virtual method IDSYM* find_name() { return get_declr()->find_name(); } public virtual method declr::FunctionDeclType declares_func() { return declr::ANSI_FUNCTION; } public virtual method void declare_ansi_idents(ResolveContext *ctx, IdentTable *func_idents) { get_params()->declare_ansi_idents(ctx, func_idents); } } // direct_declr -> direct_declr:declr '(' SeqR56E2:idents ')' operator IDFuncListDirDeclr extends ParentNode, direct_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_declr()->resolve_idents(ctx, idents)) return false; NestedIdentTable param_ids; param_ids.add_parent(idents); for (idents_iterator i = get_idents(); i; ++i) { IDSYM *token = i.get_ident(); PooledString id_name = token->pooled_string(); IdentInfo *info = new IdentInfo(id_name, IdentInfo::OBJECT_ID, this); IdentInfo *old_info = idents->resolve_ident(id_name); if (old_info && old_info->type == IdentInfo::TYPEDEF_ID) { ambig_semant_error(ctx, this, "typedef name can't be " "redeclared as an old-style function " "parameter"); if (ctx->inside_ambig) return false; } if (param_ids.has_ident_binding(id_name)) { // It would be nice to put this on "token" rather than "this", // but tokens are shared between alternatives, so the error // message would leak out to the other alternative. // We could fix this by postponing setting error messages, // but that would be a pain. set_semant_error(this, "Parameter `%s' redefined", id_name.chars()); } else { param_ids.add_ident(id_name, info); } } return true; } public virtual method void check_KnR_idents(ResolveContext *ctx, IdentTable *func_idents) { int num_params = 0; for (idents_iterator i = get_idents(); i; ++i) { IDSYM *token = i.get_ident(); PooledString id_name = token->pooled_string(); token->set_subspecies(ctx, IDSYM::KNR_PARAM_LIST_NAME); if (!func_idents->has_ident_binding(id_name)) { set_semant_error(token, "Parameter %s was not declared", id_name.chars()); } num_params++; } if (num_params < func_idents->idents_size()) { int extra = func_idents->idents_size() - num_params; set_semant_error(this, "%d variable%s declared but " "not present in prototype", extra, (extra != 1 ? "s" : "")); } } public virtual method IDSYM* find_name() { return get_declr()->find_name(); } public virtual method declr::FunctionDeclType declares_func() { return declr::K_AND_R_FUNCTION; } } operator direct_declr_sym extends AmbigNode, direct_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return resolve_idents_func (ctx, idents, this); } public virtual method IDSYM* find_name() { return direct_declr::phylum_cast(primary_alternative())->find_name(); } public virtual method declr::FunctionDeclType declares_func() { return direct_declr::phylum_cast(primary_alternative()) ->declares_func(); } public virtual method void check_KnR_idents(ResolveContext *ctx, IdentTable *func_idents) { return direct_declr::phylum_cast(primary_alternative()) ->check_KnR_idents(ctx, func_idents); } } phylum decl depends on trans_unit { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } public enum StorageClass { NO_STORAGE, TYPEDEF_STORAGE, STATIC_STORAGE, EXTERN_STORAGE, AUTO_STORAGE, REGISTER_STORAGE }; public struct ResolveType : public Collectable { bool declares_typedef : 1; bool uses_typename : 1; bool uses_nontypename : 1; bool multiple_typename : 1; StorageClass storage; ResolveType() : declares_typedef(false), uses_typename(false), uses_nontypename(false), multiple_typename(false), storage(NO_STORAGE) {} }; } // decl -> SeqR1E0:specs SeqR8E1:declrs ';' operator Declaration extends ParentNode, decl, GLRStateMixin { public slot StorageClass storage_class; public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { ResolveType base_type; for (specs_iterator i = get_specs(); i; ++i) { if (!i.get_spec()->resolve_idents(ctx, idents)) return false; i.get_spec()->get_resolve_type(ctx, &base_type); } if (!check_resolve_type(ctx, &base_type, this)) return false; storage_class = base_type.storage; for (declrs_iterator i = get_declrs(); i; ++i) { if (!i.get_declr()->resolve_idents(ctx, idents, &base_type)) return false; } return true; } public static method bool check_resolve_type(ResolveContext *ctx, ResolveType *type, Node *node) { if (type->multiple_typename) { ambig_semant_error(ctx, node, "too many typedef " "names in declaration"); if (ctx->inside_ambig) return false; } else if (type->uses_typename && type->uses_nontypename) { ambig_semant_error(ctx, node, "specifiers include both a typedef name and " "another type specifier"); if (ctx->inside_ambig) return false; } else if (!type->uses_typename && !type->uses_nontypename) { ambig_semant_error(ctx, node, "C99 forbids a declaration with " "no type"); if (ctx->inside_ambig) return false; } return true; } } operator no_decl extends Node, decl, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } operator decl_sym extends AmbigNode, decl, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return resolve_idents_func(ctx, idents, this); } } phylum init_declr depends on decl { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents, decl::ResolveType *base_type) { return true; } } // init_declr -> declr:declr OptR39E1:init operator InitDeclr extends ParentNode, init_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents, decl::ResolveType *base_type) { Localizer save(&ctx->decl_init); ctx->decl_init = has_init(); if (!get_declr()->resolve_idents(ctx, idents, base_type)) return false; if (has_init()) { return get_init_init()->resolve_idents(ctx, idents); } return true; } } operator init_declr_sym extends AmbigNode, init_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents, decl::ResolveType *base_type) { error("Unexpected ambiguity in declrator!\n"); return true; } } phylum comp_stmt depends on trans_unit { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents, bool new_scope = true) { return true; } } // comp_stmt -> '{' SeqR88E1:items '}' operator BlockStatement extends ParentNode, comp_stmt, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents, bool new_scope = true) { NestedIdentTable local_idents; IdentTable *table; if (new_scope) { local_idents.add_parent(idents); table = &local_idents; } else { table = idents; } for (items_iterator i = get_items(); i; ++i) { if (!i.get_item_()->resolve_idents(ctx, table)) return false; } return true; } } operator comp_stmt_sym extends AmbigNode, comp_stmt, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents, bool new_scope) { error("Unexpected ambiguity in block!\n"); return true; } } phylum stor_class_spec depends on decl { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { error("Unexpected call to stor_class_spec::get_resolve_type\n"); } } // stor_class_spec -> AUTO operator AutoStrClassSpec extends ParentNode, stor_class_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { if (type->storage != decl::NO_STORAGE) set_semant_error(this, "Duplicate storage class specifier"); if (ctx->decl_cx != BLOCK && ctx->decl_cx != FOR_INIT) set_semant_error(this, "'auto' is not allowed in this context"); type->storage = decl::AUTO_STORAGE; } } // stor_class_spec -> REGISTER operator RegisterStrClassSpec extends ParentNode, stor_class_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { if (type->storage != decl::NO_STORAGE) set_semant_error(this, "Duplicate storage class specifier"); if (ctx->decl_cx == FILE_SCOPE || ctx->decl_cx == FUNC_DEF) set_semant_error(this, "File-scope identifiers may not " "be declared 'register'"); type->storage = decl::REGISTER_STORAGE; } } // stor_class_spec -> STATIC operator StaticStrClassSpec extends ParentNode, stor_class_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { if (type->storage != decl::NO_STORAGE) set_semant_error(this, "Duplicate storage class specifier"); if (ctx->decl_cx != FILE_SCOPE && ctx->decl_cx != BLOCK && ctx->decl_cx != FUNC_DEF) set_semant_error(this, "'static' is not allowed in this context"); type->storage = decl::STATIC_STORAGE; } } // stor_class_spec -> EXTERN operator ExternStrClassSpec extends ParentNode, stor_class_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { if (type->storage != decl::NO_STORAGE) set_semant_error(this, "Duplicate storage class specifier"); if (ctx->decl_cx == KnR_PARAM || ctx->decl_cx == DEF_PARAM || ctx->decl_cx == DECL_PARAM) set_semant_error(this, "Parameters can't be 'extern'"); type->storage = decl::EXTERN_STORAGE; } } // stor_class_spec -> TYPEDEF operator TypedefStrClassSpec extends ParentNode, stor_class_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { if (type->storage != decl::NO_STORAGE) set_semant_error(this, "Duplicate storage class specifier"); if (ctx->decl_cx != BLOCK && ctx->decl_cx != FILE_SCOPE) set_semant_error(this, "You can't make a typedef out of that"); type->storage = decl::TYPEDEF_STORAGE; } } operator no_stor_class_spec extends Node, stor_class_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { /* nothing */ } } operator stor_class_spec_sym extends AmbigNode, stor_class_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { error("Unexpected ambiguity in storage class specifier\n"); } } phylum type_spec depends on decl { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { error("Unexpected call to type_spec::get_resolve_type\n"); } } // type_spec -> VOID operator VoidTypeSpec extends ParentNode, type_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> CHAR operator CharTypeSpec extends ParentNode, type_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> SHORT operator ShortTypeSpec extends ParentNode, type_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> INT operator IntTypeSpec extends ParentNode, type_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> LONG operator LongTypeSpec extends ParentNode, type_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> FLOAT operator FloatTypeSpec extends ParentNode, type_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> DOUBLE operator DoubleTypeSpec extends ParentNode, type_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> SIGNED operator SignedTypeSpec extends ParentNode, type_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> UNSIGNED operator UnsignedTypeSpec extends ParentNode, type_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> _BOOL operator BooleanTypeSpec extends ParentNode, type_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> _COMPLEX operator ComplexTypeSpec extends ParentNode, type_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> _IMAGINARY operator ImaginaryTypeSpec extends ParentNode, type_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> STRUCT OptR29E1:name '{' SeqR29E3:decls '}' operator StructDefinitionSpec extends ParentNode, type_spec, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (has_name()) { get_name_name()->set_subspecies(ctx, IDSYM::STRUCT_TAG_NAME); PooledString tag = get_name_name()->pooled_string(); IdentInfo *info; if (idents->has_tag_binding(tag)) { info = idents->resolve_tag(tag); assert(info); if (info->type != IdentInfo::STRUCT_TAG) set_semant_error(this,"`%s' is a %s tag, not a struct tag", tag.chars(), info->type == IdentInfo::UNION_TAG ? "union" : "enum"); /* There's a subtle bug here with the interaction of this check with ambiguity. If there's a forward declaration of the struct before the current ambiguous region, as well as this definition inside, we might have already seen this definition before, and made a note that it's already been defined. However, because we only localize changes to the pointers in the symbol table, changes to members of the info struct 'leak out'. The second condition here is a quick check to avoid giving an error in that case. If ambiguities covered larger portions of the syntax tree, we'd need a better fix of actually saving and possibly restoring all these fields. */ else if (info->defined && info->definition != this) set_semant_error(this, "Duplicate definition of" " struct `%s'", tag.chars()); else if (info->definition && !info->defined) { StructReferenceSpec *ref = (StructReferenceSpec *)info->definition; ref->completion.set_value(vg(), this); ref->compute_synth_attrs(true); } } else { info = new IdentInfo(tag, IdentInfo::STRUCT_TAG, this); idents->add_tag(tag, info); } info->definition = this; info->defined = true; } Localizer save(&ctx->decl_cx); ctx->decl_cx = STRUCT_UNION_CX; Localizer save2(&ctx->aggr_members); ctx->aggr_members = new SingleIdentTable(); for (decls_iterator i = get_decls(); i; ++i) { if (!i.get_decl()->resolve_idents(ctx, idents)) return false; } return true; } public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> UNION OptR29E1:name '{' SeqR29E3:decls '}' operator UnionDefinitionSpec extends ParentNode, type_spec, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (has_name()) { get_name_name()->set_subspecies(ctx, IDSYM::UNION_TAG_NAME); PooledString tag = get_name_name()->pooled_string(); IdentInfo *info; if (idents->has_tag_binding(tag)) { info = idents->resolve_tag(tag); assert(info); if (info->type != IdentInfo::UNION_TAG) set_semant_error(this, "`%s' is a %s tag, not a union tag", tag.chars(), info->type == IdentInfo::STRUCT_TAG ? "struct" : "enum"); else if (info->defined && info->definition != this) set_semant_error(this,"Duplicate definition of union `%s'", tag.chars()); else if (info->definition && !info->defined) { StructReferenceSpec *ref = (StructReferenceSpec *)info->definition; ref->completion.set_value(vg(), this); ref->compute_synth_attrs(true); } } else { info = new IdentInfo(tag, IdentInfo::UNION_TAG, this); idents->add_tag(tag, info); } info->definition = this; info->defined = true; } Localizer save(&ctx->decl_cx); ctx->decl_cx = STRUCT_UNION_CX; Localizer save2(&ctx->aggr_members); ctx->aggr_members = new SingleIdentTable(); for (decls_iterator i = get_decls(); i; ++i) { if (!i.get_decl()->resolve_idents(ctx, idents)) return false; } return true; } public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> STRUCT IDSYM:name operator StructReferenceSpec extends ParentNode, type_spec, GLRStateMixin { public versioned slot Vptr definition = NULL; versioned Semantics attribute definition = TypedVal((Node*)definition.value(vg(), gvid)); public versioned slot Vptr completion = NULL; versioned Semantics attribute completion = TypedVal((Node*)completion.value(vg(), gvid)); public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { PooledString tag = get_name()->pooled_string(); get_name()->set_subspecies(ctx, IDSYM::STRUCT_TAG_NAME); IdentInfo *info = idents->resolve_tag(tag); if (info) { if (info->type != IdentInfo::STRUCT_TAG) set_semant_error(this, "`%s' is a %s tag, not a struct tag", tag.chars(), info->type == IdentInfo::UNION_TAG ? "union" : "enum"); definition.set_value(vg(), info->definition); compute_synth_attrs(true); } else { IdentInfo *info = new IdentInfo(tag, IdentInfo::STRUCT_TAG, this); idents->add_tag(tag, info); } return true; } public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> UNION IDSYM:name operator UnionReferenceSpec extends ParentNode, type_spec, GLRStateMixin { public versioned slot Vptr definition = NULL; versioned Semantics attribute definition = TypedVal((Node*)definition.value(vg(), gvid)); public versioned slot Vptr completion = NULL; versioned Semantics attribute completion = TypedVal((Node*)completion.value(vg(), gvid)); public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { get_name()->set_subspecies(ctx, IDSYM::UNION_TAG_NAME); PooledString tag = get_name()->pooled_string(); IdentInfo *info = idents->resolve_tag(tag); if (info) { if (info->type != IdentInfo::UNION_TAG) set_semant_error(this, "`%s' is a %s tag, not a union tag", tag.chars(), info->type == IdentInfo::STRUCT_TAG ? "struct" : "enum"); definition.set_value(vg(), info->definition); compute_synth_attrs(true); } else { IdentInfo *info = new IdentInfo(tag, IdentInfo::UNION_TAG, this); idents->add_tag(tag, info); } return true; } public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> ENUM OptR29E1:name '{' SeqR33E3:enums OptR33E4 '}' operator DefinedEnumSpec extends ParentNode, type_spec, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (has_name()) { get_name_name()->set_subspecies(ctx, IDSYM::ENUM_TAG_NAME); PooledString tag = get_name_name()->pooled_string(); if (idents->has_tag_binding(tag)) { set_semant_error(this, "Aggregate tag `%s' redefined", tag.chars()); } else { IdentInfo *info = new IdentInfo(tag, IdentInfo::ENUM_TAG, this); idents->add_tag(tag, info); } } for (enums_iterator i = get_enums(); i; ++i) { if (!i.get_enum_()->resolve_idents(ctx, idents)) return false; } return true; } public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> ENUM IDSYM:name operator ReferencedEnumSpec extends ParentNode, type_spec, GLRStateMixin { public versioned slot Vptr definition = NULL; versioned Semantics attribute definition = TypedVal((Node*)definition.value(vg(), gvid)); public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { get_name()->set_subspecies(ctx, IDSYM::ENUM_TAG_NAME); PooledString tag = get_name()->pooled_string(); IdentInfo *info = idents->resolve_tag(tag); if (!info) { /* GCC allows you to forward declare enums, but the C99 standard doesn't */ set_semant_error(this, "Undefined enum `%s'", tag.chars()); } else if (info->type != IdentInfo::ENUM_TAG) { set_semant_error(this, "`%s' is a %s tag, not an enum tag", tag.chars(), info->type == IdentInfo::STRUCT_TAG ? "struct" : "union"); } else { definition.set_value(vg(), info->definition); compute_synth_attrs(true); } return true; } public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { type->uses_nontypename = true; } } // type_spec -> IDSYM:type_name operator TypedefTypeSpec extends ParentNode, type_spec, GLRStateMixin { public versioned slot Vptr definition = NULL; versioned Semantics attribute definition = TypedVal((Node*)definition.value(vg(), gvid)); public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { PooledString id = get_type_name()->pooled_string(); get_type_name()->set_subspecies(ctx, IDSYM::TYPEDEF_NAME); // cerr << "Before TTS, idents are:" << endl; // idents->dump(cerr); if (!idents->resolve_ident(id)) { assert(!idents->has_ident_binding(id)); ambig_semant_error(ctx, this, "undefined typedef name" " %s", id.chars()); return !ctx->inside_ambig; } // cerr << "In the middle of TTS, idents are:" << endl; // idents->dump(cerr); IdentInfo *info = idents->resolve_ident(id); assert(info); if (info->type != IdentInfo::TYPEDEF_ID) { ambig_semant_error(ctx, this, "identifier is not " "a typedef name: %s", id.chars()); return !ctx->inside_ambig; } else { // cerr << "After TTS, idents are:" << endl; // idents->dump(cerr); definition.set_value(vg(), info->definition); compute_synth_attrs(true); return true; } } public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { if (type->uses_typename) type->multiple_typename = true; else type->uses_typename = true; } } operator type_spec_sym extends AmbigNode, type_spec, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { error("Unexpected ambiguity in type_spec::get_resolve_type\n"); } } phylum type_qual depends on decl { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { /* nothing */ } } operator type_qual_sym extends AmbigNode, type_qual, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { error("Unexpected ambiguity in type qualifier!\n"); } } phylum type_name depends on trans_unit { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // type_name -> SeqR14E0:spec_quals OptR14E1:declr operator TypeName extends ParentNode, type_name, GLRStateMixin depends on Declaration { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { decl::ResolveType base_type; for (spec_quals_iterator i = get_spec_quals(); i; ++i) { if (!i.get_spec_qual()->resolve_idents(ctx, idents)) return false; i.get_spec_qual()->get_resolve_type(ctx, &base_type); } if (!Declaration::check_resolve_type(ctx, &base_type, this)) return false; if (has_declr()) return get_declr_declr()->resolve_idents(ctx, idents); else return true; } } operator type_name_sym extends AmbigNode, type_name, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected ambiguity in type name!\n"); return true; } } phylum type_spec_qual depends on trans_unit { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { error("Unexpected call to type_spec_qual::get_resolve_type\n"); } } // type_spec_qual -> type_spec:spec operator TypeSpecifier extends ParentNode, type_spec_qual, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_spec()->resolve_idents(ctx, idents); } public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { get_spec()->get_resolve_type(ctx, type); } } // type_spec_qual -> type_qual:qual operator TypeQualifier extends ParentNode, type_spec_qual, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { /* nothing to do */ } } operator no_type_spec_qual extends Node, type_spec_qual, GLRStateMixin { public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { } } operator type_spec_qual_sym extends AmbigNode, type_spec_qual, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected ambiguity in type specifier/qualifier\n"); return true; } public virtual method void get_resolve_type(ResolveContext *ctx, decl::ResolveType *type) { error("Unexpected ambiguity in type specifier/qualifier\n"); } } phylum abst_declr { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // abst_declr -> OptR47E0:ptr direct_abst_declr:direct operator DirectAbstDecl extends ParentNode, abst_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_direct()->resolve_idents(ctx, idents); } } operator abst_declr_sym extends AmbigNode, abst_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected ambiguity in abst_declr\n"); return true; } } phylum struct_decl depends on decl { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected call to struct_decl::resolve_idents()\n"); return true; } } // struct_decl -> SeqR14E0:spec_quals SeqR62E1:declrs ';' operator StructDecl extends ParentNode, struct_decl, GLRStateMixin depends on Declaration { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { decl::ResolveType base_type; for (spec_quals_iterator i = get_spec_quals(); i; ++i) { if (!i.get_spec_qual()->resolve_idents(ctx, idents)) return false; i.get_spec_qual()->get_resolve_type(ctx, &base_type); } if (!Declaration::check_resolve_type(ctx, &base_type, this)) return false; for (declrs_iterator i = get_declrs(); i; ++i) { if (!i.get_declr()->resolve_idents(ctx, idents, &base_type)) return false; } return true; } } // struct_decl -> PREPROC operator PreprocMember extends ParentNode, struct_decl depends on Declaration { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { set_semant_error(this, "Can't run semantics with preprocessor " "directives"); return true; } } operator no_struct_decl extends Node, struct_decl, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } operator struct_decl_sym extends AmbigNode, struct_decl, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return resolve_idents_func(ctx, idents, this); } } phylum enum_ { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected call to enum_::resolve_idents\n"); return true; } } // enum_ -> IDSYM:name OptR46E1:init operator EnumerationItem extends ParentNode, enum_, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (has_init() && !get_init_val()->resolve_idents(ctx, idents)) return false; IDSYM *ident = get_name(); PooledString id_name = ident->pooled_string(); ident->set_subspecies(ctx, IDSYM::ENUM_CONST_DECL_NAME); if (idents->has_ident_binding(id_name)) { set_semant_error(this, "Identifier `%s' redefined as enumeration" " constant", id_name.chars()); } else { IdentInfo *info = new IdentInfo(id_name, IdentInfo::ENUM_CONST, this); idents->add_ident(id_name, info); } return true; } } operator no_enum_ extends Node, enum_, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } operator enum__sym extends AmbigNode, enum_, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected ambiguity in enumeration member declaration\n"); return false; } } phylum init_ depends on trans_unit { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // init_ -> assign_expr operator ExprInit extends ParentNode, init_, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } // init_ -> '{' SeqR45E1:inits OptR33E4 '}' operator BlockInit extends ParentNode, init_, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { for (inits_iterator i = get_inits(); i; ++i) if (!i.get_init()->resolve_idents(ctx, idents)) return false; return true; } } operator init__sym extends AmbigNode, init_, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected ambiguity in initializer!\n"); return false; } } phylum designator { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // designator -> '[' expr:idx ']' operator ArrayElemDesignator extends ParentNode, designator, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_idx()->resolve_idents(ctx, idents); } } // designator -> '.' IDSYM:field operator FieldDesignator extends ParentNode, designator, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { get_field()->set_subspecies(ctx, IDSYM::AGGR_MEMBER_NAME); return true; } } operator designator_sym extends AmbigNode, designator, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected ambiguity in designator\n"); return true; } } phylum expr depends on trans_unit { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // expr -> expr:pred '?' expr:texpr ':' expr:fexpr operator TernaryOp extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_pred()->resolve_idents(ctx, idents)) return false; if (has_texpr() && !get_texpr_expr()->resolve_idents(ctx, idents)) return false; return get_fexpr()->resolve_idents(ctx, idents); } } // expr -> expr:left LOR expr:right operator LogicalOr extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left LAND expr:right operator LogicalAnd extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left '|' expr:right operator BitwiseOr extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left '^' expr:right operator BitwiseXor extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left '&' expr:right operator BitwiseAnd extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left EQ expr:right operator Equals extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left NE expr:right operator NotEquals extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left '<' expr:right operator LessThan extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left '>' expr:right operator GreaterThan extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left LE expr:right operator LessThanEquals extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left GE expr:right operator GreaterThanEquals extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left LSHIFT expr:right operator LeftShift extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left RSHIFT expr:right operator RightShift extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left '+' expr:right operator Add extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left '-' expr:right operator Subtract extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left '*' expr:right operator Multiply extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left '/' expr:right operator Divide extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> expr:left '%' expr:right operator Modulo extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // expr -> '(' type_name:name ')' expr:expr operator TypeCast extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_name()->resolve_idents(ctx, idents)) return false; return get_expr()->resolve_idents(ctx, idents); } } // expr -> '&' expr:expr operator AddressOf extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } // expr -> '+' expr:expr operator Positive extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } // expr -> '-' expr:expr operator Negate extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } // expr -> '~' expr:expr operator BitwiseNegate extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } // expr -> '!' expr:expr operator LogicalNot extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } // expr -> expr:func '(' SeqR128E2:exprs ')' operator FunctionCall extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_func()->resolve_idents(ctx, idents)) return false; for (exprs_iterator i = get_exprs(); i; ++i) if (!i.get_expr()->resolve_idents(ctx, idents)) return false; return true; } } // expr -> INC expr:expr operator PreIncrement extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } // expr -> DEC expr:expr operator PreDecrement extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } // expr -> expr INC operator PostIncrement extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } // expr -> expr DEC operator PostDecrement extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } // expr -> SIZEOF expr operator VarSizeof extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } // expr -> SIZEOF '(' type_name ')' operator TypeSizeof extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { get_type()->resolve_idents(ctx, idents); return true; } } // expr -> '(' exprs:expr ')' operator ParenthExpr extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } // expr -> int_const:val operator IntegerConstant extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // expr -> char_const:val operator CharacterConstant extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // expr -> float_const:val operator FloatingConstant extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // expr -> str_const:val operator StringConstant extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // expr -> '(' type_name ')' '{' SeqR45E1:inits OptR33E4 '}' operator CompoundLiteral extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_type()->resolve_idents(ctx, idents)) return false; for (inits_iterator i = get_inits(); i; ++i) if (!i.get_init()->resolve_idents(ctx, idents)) return false; return true; } } // expr -> IDSYM:name operator VariableExpr extends ParentNode, expr, GLRStateMixin depends on decl { public versioned slot Vptr declarator = NULL; versioned Semantics attribute declarator = TypedVal((Node*)declarator.value(vg(), gvid)); public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { PooledString ident = get_name()->pooled_string(); IdentInfo *info; if ((info = idents->resolve_ident(ident))) { switch (info->type) { case IdentInfo::TYPEDEF_ID: get_name()->set_subspecies(ctx, IDSYM::TYPEDEF_NAME); ambig_semant_error(ctx, this, "tried to use " "typedef name %s in expression", ident.chars()); return !ctx->inside_ambig; case IdentInfo::ENUM_CONST: get_name()->set_subspecies(ctx, IDSYM::ENUM_CONST_NAME); break; case IdentInfo::OBJECT_ID: get_name()->set_subspecies(ctx, IDSYM::PLAIN_NAME); declarator.set_value(vg(), info->definition); compute_synth_attrs(true); break; default: error("Unexpected type for identifier"); } } else { set_semant_error(this, "Undefined identifier `%s'", ident.chars()); } return true; } } // expr -> expr '.' IDSYM:field operator StructAccess extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { get_expr()->resolve_idents(ctx, idents); get_field()->set_subspecies(ctx, IDSYM::AGGR_MEMBER_NAME); // resolve field? return true; } } // expr -> expr PTR IDSYM:field operator PointerAccess extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { get_expr()->resolve_idents(ctx, idents); get_field()->set_subspecies(ctx, IDSYM::AGGR_MEMBER_NAME); // resolve field? return true; } } // expr -> expr '[' exprs:index ']' operator ArrayAccess extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_expr()->resolve_idents(ctx, idents)) return false; return get_index()->resolve_idents(ctx, idents); } } // expr -> '*' expr:expr operator PointerDereference extends ParentNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } operator expr_sym extends AmbigNode, expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return resolve_idents_func(ctx, idents, this); } } phylum designation { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // designation -> SeqR42E0:desigs '=' operator Designation extends ParentNode, designation, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { for (desigs_iterator i = get_desigs();i ; ++i) if (!i.get_desig()->resolve_idents(ctx, idents)) return false; return true; } } operator designation_sym extends AmbigNode, designation, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected ambiguity in initializer designator\n"); return true; } } phylum inner_init { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // inner_init -> OptR43E0:desig init_:init operator InnerInitializer extends ParentNode, inner_init, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (has_desig() && !get_desig_desig()->resolve_idents(ctx, idents)) return false; return get_init()->resolve_idents(ctx, idents); } } operator inner_init_sym extends AmbigNode, inner_init, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected ambiguity in inner initializer\n"); return true; } } phylum arg_expr depends on trans_unit { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // arg_expr -> assign_expr:expr operator ExpressionArgument extends arg_expr { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } // arg_expr -> type_name:type operator FakeTypeArgument extends arg_expr { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { ambig_semant_error(ctx, this, "only macros can take type arguments"); return !ctx->inside_ambig; } } operator arg_expr_sym extends AmbigNode, arg_expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return resolve_idents_func(ctx, idents, this); } } phylum assign_expr depends on trans_unit { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // assign_expr -> expr:left '=' assign_expr:right operator NormalAssign extends ParentNode, assign_expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // assign_expr -> expr:left MULASSIGN assign_expr:right operator MultiplyAssign extends ParentNode, assign_expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // assign_expr -> expr:left DIVASSIGN assign_expr:right operator DivideAssign extends ParentNode, assign_expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // assign_expr -> expr:left MODASSIGN assign_expr:right operator ModAssign extends ParentNode, assign_expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // assign_expr -> expr:left ADDASSIGN assign_expr:right operator AddAssign extends ParentNode, assign_expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // assign_expr -> expr:left SUBASSIGN assign_expr:right operator SubtractAssign extends ParentNode, assign_expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // assign_expr -> expr:left SHLASSIGN assign_expr:right operator ShiftLeftAssign extends ParentNode, assign_expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // assign_expr -> expr:left SHRASSIGN assign_expr:right operator ShiftRightAssign extends ParentNode, assign_expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // assign_expr -> expr:left ANDASSIGN assign_expr:right operator AndAssign extends ParentNode, assign_expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // assign_expr -> expr:left XORASSIGN assign_expr:right operator XorAssign extends ParentNode, assign_expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // assign_expr -> expr:left ORASSIGN assign_expr:right operator OrAssign extends ParentNode, assign_expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // assign_expr -> expr:expr operator SimpleExpression extends ParentNode, assign_expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } operator assign_expr_sym extends AmbigNode, assign_expr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected ambiguity in expression!\n"); return false; } } phylum direct_abst_declr { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // direct_abst_declr -> '(' abst_declr:declr ')' operator ParenAbstDecl extends ParentNode, direct_abst_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_declr()->resolve_idents(ctx, idents); } } // direct_abst_declr -> OptR58E0:declr '[' OptR58E2:expr ']' operator ArrayAbstDecl extends ParentNode, direct_abst_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (has_declr() && !get_declr_declr()->resolve_idents(ctx, idents)) return false; if (has_expr() && !get_expr_expr()->resolve_idents(ctx, idents)) return false; return true; } } // direct_abst_declr -> OptR58E0:declr '[' '*' ']' operator VariableAbstDecl extends ParentNode, direct_abst_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (has_declr() && !get_declr_declr()->resolve_idents(ctx, idents)) return false; return true; } } // direct_abst_declr -> direct_abst_declr:declr '(' OptR60E2:params ')' operator NestedFuncAbstDecl extends ParentNode, direct_abst_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_declr()->resolve_idents(ctx, idents)) return false; Localizer save(&ctx->decl_cx); ctx->decl_cx = DECL_PARAM; NestedIdentTable param_table; param_table.add_parent(idents); if (has_params()) return get_params_params()->resolve_idents(ctx, ¶m_table); else return true; } } // direct_abst_declr -> '(' OptR60E2:params ')' operator FuncAbstDecl extends ParentNode, direct_abst_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { Localizer save(&ctx->decl_cx); ctx->decl_cx = DECL_PARAM; NestedIdentTable param_table; param_table.add_parent(idents); if (has_params()) return get_params_params()->resolve_idents(ctx, ¶m_table); else return true; } } operator direct_abst_declr_sym extends AmbigNode, direct_abst_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected ambiguity in direct_abst_declr\n"); return true; } } phylum param_type_list depends on trans_unit { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } public virtual method void declare_ansi_idents(ResolveContext *ctx, IdentTable *func_idents) { error("Unexpected call to param_type_list::declare_ansi_idents\n"); } } // param_type_list -> SeqR68E0:decls OptR68E1:dotdotdot operator ParameterTypeList extends ParentNode, param_type_list, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { for (decls_iterator i = get_decls(); i; ++i) { if (!i.get_decl()->resolve_idents(ctx, idents)) return false; } return true; } public virtual method void declare_ansi_idents(ResolveContext *ctx, IdentTable *func_idents) { bool first_param = true; for (decls_iterator i = get_decls(); i; ++i) { i.get_decl()->declare_ansi_idents(ctx, func_idents); first_param = false; } } } operator param_type_list_sym extends AmbigNode, param_type_list, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected ambiguity in parameter list!\n"); return false; } public virtual method void declare_ansi_idents(ResolveContext *ctx, IdentTable *func_idents) { error("Unexpected ambiguity in parameter list!\n"); } } phylum struct_declr depends on decl { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents, decl::ResolveType *base_type) { error("Unexpected call to struct_declr::resolve_idents\n"); return true; } } // struct_declr -> declr:declr operator StructDeclr extends ParentNode, struct_declr, GLRStateMixin depends on decl { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents, decl::ResolveType *base_type) { return get_declr()->resolve_idents(ctx, idents, base_type); } } // struct_declr -> OptR64E0:declr ':' expr:expr operator BitfieldDeclr extends ParentNode, struct_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents, decl::ResolveType *base_type) { if (has_declr()) { if (!get_declr_declr()->resolve_idents(ctx, idents, base_type)) return false; } return get_expr()->resolve_idents(ctx, idents); } } operator no_struct_declr extends Node, struct_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents, decl::ResolveType *base_type) { return true; } } operator struct_declr_sym extends AmbigNode, struct_declr, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents, decl::ResolveType *base_type) { error("Unexpected ambiguity in structure member declarator\n"); return true; } } phylum param_decl depends on trans_unit, decl { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } public virtual method void declare_ansi_idents(ResolveContext *ctx, IdentTable *func_idents) { error("Unexpected call to param_type_list::declare_ansi_idents\n"); } } // param_decl -> SeqR1E0:specs declr:declr operator NamedParamDecl extends ParentNode, param_decl, GLRStateMixin depends on Declaration { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { decl::ResolveType base_type; for (specs_iterator i = get_specs(); i; ++i) { if (!i.get_spec()->resolve_idents(ctx, idents)) return false; i.get_spec()->get_resolve_type(ctx, &base_type); } if (!Declaration::check_resolve_type(ctx, &base_type, this)) return false; return get_declr()->resolve_idents(ctx, idents, &base_type); } public virtual method void declare_ansi_idents(ResolveContext *ctx, IdentTable *func_idents) { get_declr()->declare_ident(ctx, func_idents); } } // param_decl -> SeqR1E0:specs OptR14E1:declr operator UnnamedParamDecl extends ParentNode, param_decl, GLRStateMixin depends on Declaration { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { decl::ResolveType base_type; for (specs_iterator i = get_specs(); i; ++i) { if (!i.get_spec()->resolve_idents(ctx, idents)) return false; i.get_spec()->get_resolve_type(ctx, &base_type); // XXX This still allows foo(void, void) {} } if (!Declaration::check_resolve_type(ctx, &base_type, this)) return false; if (has_declr()) { return get_declr_declr()->resolve_idents(ctx, idents); } return true; } public virtual method void declare_ansi_idents(ResolveContext *ctx, IdentTable *func_idents) { } } operator param_decl_sym extends AmbigNode, param_decl, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return resolve_idents_func(ctx, idents, this); } public virtual method void declare_ansi_idents(ResolveContext *ctx, IdentTable *func_idents) { param_decl::phylum_cast(primary_alternative()) ->declare_ansi_idents(ctx, func_idents); } } phylum for_init depends on trans_unit { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // for_init -> OptR69E0:expr ';' operator ExpressionInit extends ParentNode, for_init, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (has_expr()) return get_expr_expr()->resolve_idents(ctx, idents); return true; } } // for_init -> decl:decl operator DeclarationInit extends ParentNode, for_init, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { Localizer save(&ctx->decl_cx); ctx->decl_cx = FOR_INIT; return get_decl()->resolve_idents(ctx, idents); } } operator for_init_sym extends AmbigNode, for_init, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return resolve_idents_func(ctx, idents, this); } } phylum exprs depends on trans_unit { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // exprs -> exprs:left ',' assign_expr:right operator CommaList extends ParentNode, exprs, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_left()->resolve_idents(ctx, idents)) return false; return get_right()->resolve_idents(ctx, idents); } } // exprs -> assign_expr:expr operator SingleExpr extends ParentNode, exprs, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_expr()->resolve_idents(ctx, idents); } } operator exprs_sym extends AmbigNode, exprs, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected ambiguity in expressions!\n"); return false; } } phylum stmt depends on trans_unit { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // stmt -> IDSYM:label ':' stmt:stmt operator LabeledStatement extends ParentNode, stmt, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { PooledString label = get_label()->pooled_string(); get_label()->set_subspecies(ctx, IDSYM::LABEL_DECL_NAME); LabelInfo *info; if (!ctx->labels->has_binding(label)) { info = new LabelInfo(label); ctx->labels->add(label, info); } else { info = ctx->labels->resolve(label); } info->defs.push_back(this); return get_stmt()->resolve_idents(ctx, idents); } } // stmt -> CASE expr:expr ':' stmt:stmt operator CaseLabelStatement extends ParentNode, stmt, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_expr()->resolve_idents(ctx, idents)) return false; return get_stmt()->resolve_idents(ctx, idents); } } // stmt -> DEFAULT ':' stmt:stmt operator DefaultLabelStatement extends ParentNode, stmt, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_stmt()->resolve_idents(ctx, idents); } } // stmt -> OptR69E0:expr ';' operator ExprStatement extends ParentNode, stmt, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (has_expr()) return get_expr_expr()->resolve_idents(ctx, idents); return true; } } // stmt -> comp_stmt:stmt operator CompoundStatement extends ParentNode, stmt, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_stmt()->resolve_idents(ctx, idents); } } // stmt -> IF '(' exprs:pred ')' stmt:t_stmt operator IfNoElseStatement extends ParentNode, stmt, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_pred()->resolve_idents(ctx, idents)) return false; return get_t_stmt()->resolve_idents(ctx, idents); } } // stmt -> IF '(' exprs:pred ')' stmt:t_stmt ELSE stmt:f_stmt operator IfElseStatement extends ParentNode, stmt, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_pred()->resolve_idents(ctx, idents)) return false; if (!get_t_stmt()->resolve_idents(ctx, idents)) return false; return get_f_stmt()->resolve_idents(ctx, idents); } } // stmt -> SWITCH '(' exprs:val ')' stmt:stmt operator SwitchStatement extends ParentNode, stmt, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_val()->resolve_idents(ctx, idents)) return false; return get_stmt()->resolve_idents(ctx, idents); } } // stmt -> WHILE '(' exprs:val ')' stmt:stmt operator WhileStatement extends ParentNode, stmt, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_val()->resolve_idents(ctx, idents)) return false; return get_stmt()->resolve_idents(ctx, idents); } } // stmt -> DO stmt:stmt WHILE '(' exprs:val ')' ';' operator DoWhileStatement extends ParentNode, stmt, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_stmt()->resolve_idents(ctx, idents)) return false; return get_val()->resolve_idents(ctx, idents); } } // stmt -> FOR '(' for_init:init OptR69E0:pred ';' OptR69E0:inc ')' stmt:stmt operator ForStatement extends ParentNode, stmt, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (!get_init()->resolve_idents(ctx, idents)) return false; if (has_pred() && !get_pred_expr()->resolve_idents(ctx, idents)) return false; if (has_inc() && !get_inc_expr()->resolve_idents(ctx, idents)) return false; return get_stmt()->resolve_idents(ctx, idents); } } // stmt -> GOTO IDSYM:label ';' operator GotoStatement extends ParentNode, stmt, GLRStateMixin { public versioned slot Vptr target = NULL; versioned Semantics attribute target = TypedVal((Node*)target.value(vg(), gvid)); public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { PooledString label = get_label()->pooled_string(); get_label()->set_subspecies(ctx, IDSYM::LABEL_NAME); LabelInfo *info; if (!ctx->labels->has_binding(label)) { info = new LabelInfo(label); ctx->labels->add(label, info); } else { info = ctx->labels->resolve(label); } info->uses.push_back(this); return true; } } // stmt -> RETURN OptR69E0:ret ';' operator ReturnStatement extends ParentNode, stmt, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { if (has_ret()) return get_ret_expr()->resolve_idents(ctx, idents); return true; } } operator stmt_sym extends AmbigNode, stmt, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { error("Unexpected ambiguity in statement!\n"); return true; } } phylum block_item depends on trans_unit { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return true; } } // block_item -> decl:decl operator DeclarationItem extends ParentNode, block_item, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { Localizer save(&ctx->decl_cx); ctx->decl_cx = BLOCK; return get_decl()->resolve_idents(ctx, idents); } } // block_item -> stmt:stmt operator StatementItem extends ParentNode, block_item, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return get_stmt()->resolve_idents(ctx, idents); } } operator block_item_sym extends AmbigNode, block_item, GLRStateMixin { public virtual method bool resolve_idents(ResolveContext *ctx, IdentTable *idents) { return resolve_idents_func(ctx, idents, this); } } operator IDSYM { public enum NameType { PLAIN_NAME = 0, DECLARATION_NAME, TYPEDEF_NAME, TYPEDEF_DECL_NAME, LABEL_NAME, LABEL_DECL_NAME, STRUCT_TAG_NAME, UNION_TAG_NAME, ENUM_TAG_NAME, AGGR_MEMBER_NAME, AGGR_MEMBER_DECL_NAME, ENUM_CONST_NAME, ENUM_CONST_DECL_NAME, PARAM_DECL_NAME, KNR_PARAM_LIST_NAME, KNR_PARAM_DECL_NAME }; // Note -- this enum has to be kept in sync with the definition // of harmonia-c-idsym-face-array in harmonia-c.el public static slot const char *subspecies_names[] = { "Plain", "Declaration", "Typedef", "TypedefDecl", "Label", "LabelDecl", "StructTag", "UnionTag", "EnumTag", "AggregateMember", "AggregateMemberDecl", "EnumerationConstant", "EnumerationConstantDecl", "ParameterDecl", "K&RParameterList", "K&RParameterDecl"}; public versioned slot Vint subspecies = 0; versioned Semantics attribute subspecies = TypedVal(subspecies.value(vg(), gvid)); versioned Semantics attribute subspecies_name = TypedVal(subspecies_names[subspecies.value(vg(), gvid)]); public virtual method void set_subspecies(ResolveContext *ctx, int type) { if (ctx->inside_ambig) { ctx->deferred_classifications ->push_back(pair(this, type)); } else { subspecies.set_value(vg(), type); compute_synth_attrs(true); } } }