/** * \file decl_read.cpp * \brief Declaration Parsing * * This module provides a class, Declaration_reader, which reads a * declarator or a sequence thereof. * * \author Stefan Reuther */ INTERFACE: #include #include #include "type_rep.h" #include "ptree_nodes.h" class Abstract_scope; class Block_scope; class Declaration_reader { Abstract_scope* current_scope; Block_scope* block_scope; public: typedef std::vector > Arg_vec; virtual void declare_variable(Type type, Ptree* name, Ptree* initializer, Ptree* bitsize) = 0; Abstract_scope* get_scope() const { return current_scope; } Arg_vec* get_args() const { return function_args; } private: Arg_vec* function_args; }; class Function_declaration_reader : public Declaration_reader { Function_type_maker maker; bool had_void_arg, had_parameter; Arg_vec* args; public: Function_type_maker& get_maker() { return maker; } }; IMPLEMENTATION: #include #include "except.h" #include "symbol_table.h" #include "ptree_util.h" #include "scope.h" #include "downcast.h" #include "symbol_name.h" #include "class.h" /*************************** Declaration_reader **************************/ /** Create a general Declaration_reader. Names will be looked up in scope. */ PUBLIC Declaration_reader::Declaration_reader(Abstract_scope* scope) : current_scope(scope), function_args(0) { assert(current_scope); } /** Create a Declaration_reader which collects function parameters. This one only accepts one call to parse_declarator(), not parse_declarator_list(). \param scope names will be looked up here \param args parameters will be stored there */ PUBLIC Declaration_reader::Declaration_reader(Abstract_scope* scope, Arg_vec* args) : current_scope(scope), function_args(args) { assert(current_scope); assert(function_args); } PUBLIC virtual Declaration_reader::~Declaration_reader() { } /** \func Declaration_reader::declare_variable(Type type, Ptree* name, Ptree* initializer, Ptree* bitsize) \brief Process one definition/declaration \param type declared type \param name name. May be null (unnamed), leaf (unqualified name), or a list (qualified name / operator) \param initializer initializer. Null if none, otherwise a list ["(" args ")"] or ["=" expression] or ["=" [brace-thing]] \param bitsize bitfield size. Null if none, otherwise an expression. */ /** Read a declarator, and call declare_variable for it. Declarator syntax from standard: declarator: direct-declarator ptr-operator declarator direct-declarator: declarator-id direct-declarator ( parameter-declaration-clause ) cv-qualifier-seq opt exception-specification opt direct-declarator [ constant-expression opt ] ( declarator ) ptr-operator: * cv-qualifier-seq opt & ::opt nested-name-specifier * cv-qualifier-seq opt "abstract-declarator" is essentially the same except that it has no "declarator-id". OpenC++ parses the above grammar and "flattens" it into one big list, including initializers and bitfields: declarator ::= identifier // sublist if qualified identifier | "*" : declarator | "&" : declarator | cv-qualifier : declarator | [ namepart... "::" "*" ] : declarator | declarator : postfix-expression* initializer? // declarator | postfix-expression* initializer? // abstract declarator postfix-expression ::= "(" : list-with-function-args : ")" ++ cv-qualifier-seq-opt | "[" : expression-with-array-size-or-nil : "]" initializer ::= "=" : expression | [ "(" : expression-list : ")" ] | ":" : expression // bitfield */ PUBLIC void Declaration_reader::parse_declarator(Type type, Ptree* tree) { parse_declarator_internal(type, tree, 0, 0, current_scope); } PRIVATE void Declaration_reader::parse_declarator_internal(Type type, Ptree* tree, Ptree* initializer, Ptree* bitsize, Abstract_scope* scope) { // declarators: [dcl.decl] if (tree->IsLeaf()) bogus_ptree_error("expected a list in parse_declarator", tree); while (tree) { Ptree* f = tree->Car(); if (!f) { tree = tree->Cdr(); break; } else if (parse_qualifier(f, type)) { /* const, volatile or restrict */ if (type.get_kind() == Type::k_Reference) compile_error("references may not be cv-qualified"); tree = tree->Cdr(); } else if (f->Eq('*')) { if (type.get_kind() == Type::k_Reference) compile_error("pointers to references are not allowed"); type = type.make_pointer_type(); tree = tree->Cdr(); } else if (f->Eq('&')) { if (type.get_kind() == Type::k_Reference) compile_error("references to references are not allowed"); type = type.make_reference_type(); tree = tree->Cdr(); } else if (!f->IsLeaf()) { /* ARGH! */ int len = f->Length(); if (len > 2 && f->Nth(len-2)->Eq("::") && f->Nth(len-1)->Eq("*")) { /* member pointer. Class name is f->Car() .. f->Nth(len-3). Parsed as a symbol name, this appears as a symbol with basename "*". */ Symbol_name name(f, scope, false); assert(name.get_name() == "*"); assert(!name.is_template()); // that'd be "class::*" Class_scope* class_scope = dynamic_cast(name.get_scope()); if (!class_scope) compile_error("invalid class type in member pointer declaration"); type = class_scope->get_class_symbol()->get_type().make_member_type(type); tree = tree->Cdr(); } else { break; } } else { break; } } /* isn't there a simpler way to do this? */ Ptree* name_ptr = 0; if (tree && tree->Car()) { name_ptr = tree->Car(); if (name_ptr->Eq('(') || name_ptr->Eq('[') || name_ptr->Eq(':') || name_ptr->Eq('=') || name_ptr->Eq('*') || name_ptr->Eq(')')) name_ptr = 0; } bool do_function_args = false; if (name_ptr) { tree = tree->Cdr(); // skip over name /* Function args are parsed within the symbol name's scope. In "void a::foo(p x)", p is looked up in scope a. */ // FIXME: this parses the symbol name twice. I'm unsure whether // the interface of declare_variable should accept a Symbol_name // instead? That'd waste an anonymous variable per abstract // declarator, though. if (name_ptr->IsLeaf() || !name_ptr->Car() || !name_ptr->Car()->Eq('(')) { scope = Symbol_name(name_ptr, scope, true).get_scope(); assert(scope); do_function_args = true; } } Ptree* p = tree; while (p) { // FIXME: this parses () and [] combinations wrong!!!1 if (p->Car()->Eq('(')) { /* Function header */ // Note that we parse the function args while we are in // the function's enclosing scope. This should satisfy // 3.3.1p5.2. The only difference I see would be a type // definition inside a parameter list (whose scope would // be inside the prototype only) which isn't allowed in // C++. Function_declaration_reader reader(scope, do_function_args ? function_args : 0); do_function_args = false; Ptree* arg = p->Second(); while (arg) { if (arg->Car()->Eq("...")) { reader.add_ellipsis(); arg = arg->Cdr(); break; } Ptree* item = arg->Car(); Type t = parse_type(item->First(), scope, 0, false); reader.parse_declarator(t, item->Second()); arg = arg->Cdr(); if (!arg) break; arg = arg->Cdr(); } type = reader.get_maker().make_function_type(type); p = p->Cdr()->Cdr()->Cdr(); /* parse function's cv-qualifiers, as in `void (Foo::*x)() const' for a pointer to a const member function */ while (p && p->Car() && parse_qualifier(p->Car(), type)) p = p->Cdr(); // FIXME: exception-specification } else if (p->Car()->Eq('[')) { /* Array */ type = type.make_array_type(p->Cdr()->Car()); p = p->Cdr()->Cdr()->Cdr(); } else if (p->Car()->Eq('=')) { /* initializer */ assert(!initializer); initializer = p; p = p->Cdr()->Cdr(); break; } else if (p->Car()->Eq(':')) { assert(!bitsize); bitsize = p->Cdr(); p = p->Cdr()->Cdr(); break; } else if (!p->Car()->IsLeaf()) { /* initializer */ assert(!initializer); initializer = p->Car(); p = p->Cdr(); break; } else { bogus_ptree_error("expected '[' or '('", p); } } if (p) bogus_ptree_error("declaration not terminated yet?", p); if (name_ptr && !name_ptr->IsLeaf() && name_ptr->Car() && name_ptr->Car()->Eq('(')) parse_declarator_internal(type, name_ptr->Cdr()->Car(), initializer, bitsize, scope); else declare_variable(type, name_ptr, initializer, bitsize); } /** Read a declarator list. Syntax is decl-list ::= declarator | declarator "," decl-list */ PUBLIC void Declaration_reader::parse_declarator_list(Type type, Ptree* list) { assert(!function_args); while (list) { parse_declarator(type, list->Car()); list = list->Cdr(); if (!list) break; expect_ptree(list->Car(), ','); list = list->Cdr(); } } /** A boiled-down version of parse_declarator: parse declarator, and just return its name. */ PUBLIC Ptree* Declaration_reader::parse_declarator_get_name(Ptree* tree) { if (tree->IsLeaf()) bogus_ptree_error("expected a list in parse_declarator", tree); Type dummy; while (tree) { Ptree* f = tree->Car(); if (!f) { tree = tree->Cdr(); break; } if (parse_qualifier(f, dummy) || f->Eq('*') || f->Eq('&')) { tree = tree->Cdr(); } else if (!f->IsLeaf()) { /* ARGH! */ int len = f->Length(); if (len > 2 && f->Nth(len-2)->Eq("::") && f->Nth(len-1)->Eq("*")) { tree = tree->Cdr(); } else { break; } } else { break; } } Ptree* name_ptr = 0; if (tree && tree->Car()) { name_ptr = tree->Car(); if (name_ptr->Eq('(') || name_ptr->Eq('[') || name_ptr->Eq(':') || name_ptr->Eq('=') || name_ptr->Eq('*') || name_ptr->Eq(')')) name_ptr = 0; } if (name_ptr && !name_ptr->IsLeaf() && name_ptr->Car() && name_ptr->Car()->Eq('(')) return parse_declarator_get_name(tree); else return name_ptr; } /********************** Function_declaration_reader **********************/ /** \class Function_declaration_reader Declaration reader for function args. This class will add all parameters to a Function_type_maker. */ /** Constructor. \param s names will be looked up in this scope \param b parameters will be added to this list */ PUBLIC Function_declaration_reader::Function_declaration_reader(Abstract_scope* s, Arg_vec* args) : Declaration_reader(s), had_void_arg(false), had_parameter(false), args(args) { } PUBLIC void Function_declaration_reader::declare_variable(Type type, Ptree* name, Ptree* initializer, Ptree* bitsize) { if (bitsize) compile_error("function arguments must not have bitsizes"); if (initializer) compile_error("FIXME: function default args not supported"); if (had_void_arg) compile_error("`void' argument must be the only one"); if (type == void_type) if (had_parameter) compile_error("`void' argument must be the only one"); else if (name) compile_error("`void' argument with a name? you're kidding."); else had_void_arg = true; else if (type.get_unqualified_type() == void_type) compile_error("qualified void as a type is bullshit"); else { maker.add_parameter(type), had_parameter = true; if (args) args->push_back(std::make_pair(type, name)); } } PUBLIC void Function_declaration_reader::add_ellipsis() { if (had_void_arg) compile_error("`void' argument must be the only one"); maker.add_ellipsis(); } /************************** Abstract Declarator **************************/ class Ad_reader : public Declaration_reader { public: Type t; Ad_reader(Abstract_scope* as) : Declaration_reader(as) { } void declare_variable(Type type, Ptree* name, Ptree* initializer, Ptree* bitsize) { t = type; assert(!name); assert(!initializer); assert(!bitsize); } }; /** Parse abstract declarator. These are used in cast syntax. \param tree input tree \param scope scope to look up for names \param t [in] type from parse_type(), [out] final type \return true on success */ bool parse_abstract_declarator(Ptree* tree, Abstract_scope* scope, Type* t) { Ad_reader r(scope); r.parse_declarator(*t, tree); if (!r.t.is_valid()) return false; *t = r.t; return true; } /********************************* Names *********************************/ class Name_decl_reader : public Declaration_reader { public: Name_decl_reader(Abstract_scope* as) : Declaration_reader(as) { } void declare_variable(Type, Ptree*, Ptree*, Ptree*) { } }; /** Given a declarator, return the declared name. The scope is required, but is not used. */ Ptree* get_name_from_declarator(Ptree* tree, Abstract_scope* scope) { return Name_decl_reader(scope).parse_declarator_get_name(tree); }