diff -r e3c851a14f16 -r 18f3010a358c src/compiler/NameBinding.cpp --- a/src/compiler/NameBinding.cpp Tue Dec 25 18:13:02 2012 -0800 +++ b/src/compiler/NameBinding.cpp Wed Dec 26 17:14:12 2012 -0800 @@ -543,11 +543,14 @@ if (node->initialization()) node->initialization()->accept(this); - Local type(zone_, bindType(node->type())); + Local type(zone_, bindType(node->type(), node->quals())); if (!type) return; - if (node->dims() || type->isArray()) { + // We don't allow array typedefs yet. + assert(!type->isArray()); + + if (node->dims()) { int dims[MAX_ARRAY_DEPTH]; int levels = evaluateDimensions(node->pos(), type, node->dims(), dims); if (levels < 0) @@ -568,11 +571,25 @@ // If we got extra dimensions, we need to build a new type. if (node->dims()) { - if ((type = buildArrayType(type, dims, node->dims()->length())) == NULL) + if ((type = buildArrayType(type, node->quals(), dims, node->dims()->length())) == NULL) return; } } + // If we're in global scope, and we received a |const| qualifier, then + // we extend this to array reference as well. This is to sort of mimic + // SP1 functionality, but also means that you cannot have changeable + // const pointers in global scope. + if ((node->quals() & TypeQual_Const) && + type->isArray() && + link_->scope()->kind() == Scope::GLOBAL) + { + if ((type = zone_->types()->qualify(type, TypeQual_Const)) == NULL) + return; + if ((type = zone_->types()->qualify(type, TypeQual_Const)) == NULL) + return; + } + // If the node already has a symbol (meaning it was a global), then // we don't have to do anything more. if (node->sym()) { @@ -817,15 +834,17 @@ return true; } - ArrayType *buildArrayType(Handle contained, int dims[MAX_ARRAY_DEPTH], size_t postlevels) { + ArrayType *buildArrayType(Handle contained, TypeQualifiers quals, int dims[MAX_ARRAY_DEPTH], size_t postlevels) { Local type(zone_, contained); + for (size_t i = postlevels - 1; i < postlevels; i--) { int size = dims[i] > 0 ? dims[i] : ArrayType::DYNAMIC_ARRAY_SIZE; - type = zone_->types()->newArray(contained, size); - if (!type) + if ((type = zone_->types()->newArray(contained, size)) == NULL) + return NULL; + if ((type = zone_->types()->qualify(type, quals)) == NULL) return NULL; } return ArrayType::cast(type); @@ -834,7 +853,7 @@ bool fillFunctionType(Handle fun, const FunctionSignature &sig) { Local type(zone_); if (!fun->returnType()) { - if ((type = bindType(sig.returnType())) == NULL) + if ((type = bindType(sig.returnType(), TypeQual_None)) == NULL) return false; fun->setReturnType(type); } @@ -845,10 +864,12 @@ for (size_t i = 0; i < sig.parameters()->length(); i++) { Parameter *param = sig.parameters()->at(i); - if ((type = bindType(param->type())) == NULL) + if ((type = bindType(param->type(), param->quals())) == NULL) return false; - if (type->isArray() || param->dims()) { + assert(!type->isArray()); + + if (param->dims()) { int dims[MAX_ARRAY_DEPTH]; int levels = evaluateDimensions(param->pos(), type, param->dims(), dims); if (levels < 0) @@ -858,7 +879,7 @@ // Unlike variables, we do not infer anything about array // sizes from its default initializer. if (param->dims()) { - if ((type = buildArrayType(type, dims, param->dims()->length())) == NULL) + if ((type = buildArrayType(type, param->quals(), dims, param->dims()->length())) == NULL) return false; } @@ -873,9 +894,19 @@ cc_.reportError(param->pos(), Message_ArrayCantBeReference); return false; } + if (param->quals() & TypeQual_Const) { + cc_.reportError(param->pos(), Message_CannotConstReference); + return false; + } if ((type = zone_->types()->getReference(type, false)) == NULL) return false; } + if (param->quals() & TypeQual_Const) { + if (!type->isArray() && !type->isStruct()) { + cc_.reportError(param->pos(), Message_InvalidConstOnFormal); + return false; + } + } if (type->isVoid()) { cc_.reportError(param->type()->pos(), Message_CannotDeclareVoid); @@ -891,27 +922,31 @@ return true; } - Type *bindType(Expression *expr) { + Type *bindType(Expression *expr, TypeQualifiers quals) { + Local type(zone_); + if (!expr) { // If no type was declared, we return int32. - return zone_->types()->getPrimitive(PrimitiveType_Int32); - } - - expr->accept(this); + type = zone_->types()->getPrimitive(PrimitiveType_Int32); + } else { + expr->accept(this); - NameProxy *proxy = expr->asNameProxy(); - assert(proxy); + NameProxy *proxy = expr->asNameProxy(); + assert(proxy); - Symbol *sym = proxy->sym(); - if (!sym) - return NULL; + Symbol *sym = proxy->sym(); + if (!sym) + return NULL; - if (!sym->isType()) { - cc_.reportError(expr->pos(), Message_IdentifierIsNotAType, sym->name()->chars()); - return NULL; + if (!sym->isType()) { + cc_.reportError(expr->pos(), Message_IdentifierIsNotAType, sym->name()->chars()); + return NULL; + } + + type = sym->type(); } - return sym->type(); + return zone_->types()->qualify(type, quals); } private: