Commit d121ed961a
Changed files (6)
src/analyze.cpp
@@ -2914,6 +2914,11 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
AstNodeParamDecl *param_decl = ¶m_decl_node->data.param_decl;
TypeTableEntry *type = unwrapped_node_type(param_decl->type);
+ if (param_decl->is_noalias && type->id != TypeTableEntryIdPointer) {
+ add_node_error(g, param_decl_node,
+ buf_sprintf("noalias on non-pointer parameter"));
+ }
+
if (is_exported && type->id == TypeTableEntryIdStruct) {
add_node_error(g, param_decl_node,
buf_sprintf("byvalue struct parameters not yet supported on exported functions"));
src/codegen.cpp
@@ -2034,9 +2034,8 @@ static void do_code_gen(CodeGen *g) {
AstNode *type_node = param_node->data.param_decl.type;
TypeTableEntry *param_type = fn_proto_type_from_type_node(g, type_node);
LLVMValueRef argument_val = LLVMGetParam(fn, gen_param_index);
- if (param_type->id == TypeTableEntryIdPointer &&
- false) // TODO test if parameter is noalias
- {
+ bool param_is_noalias = param_node->data.param_decl.is_noalias;
+ if (param_type->id == TypeTableEntryIdPointer && param_is_noalias) {
LLVMAddAttribute(argument_val, LLVMNoAliasAttribute);
} else if (param_type->id == TypeTableEntryIdPointer &&
param_type->data.pointer.is_const)
src/parser.cpp
@@ -913,9 +913,13 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool ma
static AstNode *ast_parse_unwrap_maybe_expr(ParseContext *pc, int *token_index, bool mandatory);
static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {
- if (token->id != token_id) {
- ast_invalid_token_error(pc, token);
+ if (token->id == token_id) {
+ return;
}
+
+ Buf token_value = BUF_INIT;
+ ast_buf_from_token(pc, token, &token_value);
+ ast_error(pc, token, "expected token '%s', found '%s'", token_name(token_id), token_name(token->id));
}
static Token *ast_eat_token(ParseContext *pc, int *token_index, TokenId token_id) {
src/tokenizer.cpp
@@ -994,94 +994,101 @@ void tokenize(Buf *buf, Tokenization *out) {
break;
}
if (t.state != TokenizeStateError) {
- t.pos = -1;
+ if (t.tokens->length > 0) {
+ Token *last_token = &t.tokens->last();
+ t.line = last_token->start_line;
+ t.column = last_token->start_column;
+ t.pos = last_token->start_pos;
+ } else {
+ t.pos = 0;
+ }
begin_token(&t, TokenIdEof);
end_token(&t);
assert(!t.cur_tok);
}
}
-static const char * token_name(Token *token) {
- switch (token->id) {
+const char * token_name(TokenId id) {
+ switch (id) {
case TokenIdEof: return "EOF";
case TokenIdSymbol: return "Symbol";
- case TokenIdKeywordFn: return "Fn";
- case TokenIdKeywordConst: return "Const";
- case TokenIdKeywordVar: return "Var";
- case TokenIdKeywordReturn: return "Return";
- case TokenIdKeywordExtern: return "Extern";
- case TokenIdKeywordPub: return "Pub";
- case TokenIdKeywordExport: return "Export";
- case TokenIdKeywordAs: return "As";
- case TokenIdKeywordUse: return "Use";
- case TokenIdKeywordTrue: return "True";
- case TokenIdKeywordFalse: return "False";
- case TokenIdKeywordIf: return "If";
- case TokenIdKeywordElse: return "Else";
- case TokenIdKeywordGoto: return "Goto";
- case TokenIdKeywordVolatile: return "Volatile";
- case TokenIdKeywordAsm: return "Asm";
- case TokenIdKeywordStruct: return "Struct";
- case TokenIdKeywordEnum: return "Enum";
- case TokenIdKeywordWhile: return "While";
- case TokenIdKeywordContinue: return "Continue";
- case TokenIdKeywordBreak: return "Break";
- case TokenIdKeywordNull: return "Null";
- case TokenIdKeywordNoAlias: return "NoAlias";
- case TokenIdLParen: return "LParen";
- case TokenIdRParen: return "RParen";
- case TokenIdComma: return "Comma";
- case TokenIdStar: return "Star";
- case TokenIdLBrace: return "LBrace";
- case TokenIdRBrace: return "RBrace";
- case TokenIdLBracket: return "LBracket";
- case TokenIdRBracket: return "RBracket";
+ case TokenIdKeywordFn: return "fn";
+ case TokenIdKeywordConst: return "const";
+ case TokenIdKeywordVar: return "var";
+ case TokenIdKeywordReturn: return "return";
+ case TokenIdKeywordExtern: return "extern";
+ case TokenIdKeywordPub: return "pub";
+ case TokenIdKeywordExport: return "export";
+ case TokenIdKeywordAs: return "as";
+ case TokenIdKeywordUse: return "use";
+ case TokenIdKeywordTrue: return "true";
+ case TokenIdKeywordFalse: return "false";
+ case TokenIdKeywordIf: return "if";
+ case TokenIdKeywordElse: return "else";
+ case TokenIdKeywordGoto: return "goto";
+ case TokenIdKeywordVolatile: return "volatile";
+ case TokenIdKeywordAsm: return "asm";
+ case TokenIdKeywordStruct: return "struct";
+ case TokenIdKeywordEnum: return "enum";
+ case TokenIdKeywordWhile: return "while";
+ case TokenIdKeywordContinue: return "continue";
+ case TokenIdKeywordBreak: return "break";
+ case TokenIdKeywordNull: return "null";
+ case TokenIdKeywordNoAlias: return "noalias";
+ case TokenIdLParen: return "(";
+ case TokenIdRParen: return ")";
+ case TokenIdComma: return ",";
+ case TokenIdStar: return "*";
+ case TokenIdLBrace: return "{";
+ case TokenIdRBrace: return "}";
+ case TokenIdLBracket: return "[";
+ case TokenIdRBracket: return "]";
case TokenIdStringLiteral: return "StringLiteral";
case TokenIdCharLiteral: return "CharLiteral";
- case TokenIdSemicolon: return "Semicolon";
+ case TokenIdSemicolon: return ";";
case TokenIdNumberLiteral: return "NumberLiteral";
- case TokenIdPlus: return "Plus";
- case TokenIdColon: return "Colon";
- case TokenIdArrow: return "Arrow";
- case TokenIdFatArrow: return "FatArrow";
- case TokenIdDash: return "Dash";
- case TokenIdNumberSign: return "NumberSign";
- case TokenIdBinOr: return "BinOr";
- case TokenIdAmpersand: return "Ampersand";
- case TokenIdBinXor: return "BinXor";
- case TokenIdBoolOr: return "BoolOr";
- case TokenIdBoolAnd: return "BoolAnd";
- case TokenIdEq: return "Eq";
- case TokenIdTimesEq: return "TimesEq";
- case TokenIdDivEq: return "DivEq";
- case TokenIdModEq: return "ModEq";
- case TokenIdPlusEq: return "PlusEq";
- case TokenIdMinusEq: return "MinusEq";
- case TokenIdBitShiftLeftEq: return "BitShiftLeftEq";
- case TokenIdBitShiftRightEq: return "BitShiftRightEq";
- case TokenIdBitAndEq: return "BitAndEq";
- case TokenIdBitXorEq: return "BitXorEq";
- case TokenIdBitOrEq: return "BitOrEq";
- case TokenIdBoolAndEq: return "BoolAndEq";
- case TokenIdBoolOrEq: return "BoolOrEq";
- case TokenIdBang: return "Bang";
- case TokenIdTilde: return "Tilde";
- case TokenIdCmpEq: return "CmpEq";
- case TokenIdCmpNotEq: return "CmpNotEq";
- case TokenIdCmpLessThan: return "CmpLessThan";
- case TokenIdCmpGreaterThan: return "CmpGreaterThan";
- case TokenIdCmpLessOrEq: return "CmpLessOrEq";
- case TokenIdCmpGreaterOrEq: return "CmpGreaterOrEq";
- case TokenIdBitShiftLeft: return "BitShiftLeft";
- case TokenIdBitShiftRight: return "BitShiftRight";
- case TokenIdSlash: return "Slash";
- case TokenIdPercent: return "Percent";
- case TokenIdDot: return "Dot";
- case TokenIdEllipsis: return "Ellipsis";
- case TokenIdMaybe: return "Maybe";
- case TokenIdDoubleQuestion: return "DoubleQuestion";
- case TokenIdMaybeAssign: return "MaybeAssign";
- case TokenIdAtSign: return "AtSign";
+ case TokenIdPlus: return "+";
+ case TokenIdColon: return ":";
+ case TokenIdArrow: return "->";
+ case TokenIdFatArrow: return "=>";
+ case TokenIdDash: return "-";
+ case TokenIdNumberSign: return "#";
+ case TokenIdBinOr: return "|";
+ case TokenIdAmpersand: return "&";
+ case TokenIdBinXor: return "^";
+ case TokenIdBoolOr: return "||";
+ case TokenIdBoolAnd: return "&&";
+ case TokenIdEq: return "=";
+ case TokenIdTimesEq: return "*=";
+ case TokenIdDivEq: return "/=";
+ case TokenIdModEq: return "%=";
+ case TokenIdPlusEq: return "+=";
+ case TokenIdMinusEq: return "-=";
+ case TokenIdBitShiftLeftEq: return "<<=";
+ case TokenIdBitShiftRightEq: return ">>=";
+ case TokenIdBitAndEq: return "&=";
+ case TokenIdBitXorEq: return "^=";
+ case TokenIdBitOrEq: return "|=";
+ case TokenIdBoolAndEq: return "&&=";
+ case TokenIdBoolOrEq: return "||=";
+ case TokenIdBang: return "!";
+ case TokenIdTilde: return "~";
+ case TokenIdCmpEq: return "==";
+ case TokenIdCmpNotEq: return "!=";
+ case TokenIdCmpLessThan: return "<";
+ case TokenIdCmpGreaterThan: return ">";
+ case TokenIdCmpLessOrEq: return "<=";
+ case TokenIdCmpGreaterOrEq: return ">=";
+ case TokenIdBitShiftLeft: return "<<";
+ case TokenIdBitShiftRight: return ">>";
+ case TokenIdSlash: return "/";
+ case TokenIdPercent: return "%";
+ case TokenIdDot: return ".";
+ case TokenIdEllipsis: return "...";
+ case TokenIdMaybe: return "?";
+ case TokenIdDoubleQuestion: return "??";
+ case TokenIdMaybeAssign: return "?=";
+ case TokenIdAtSign: return "@";
}
return "(invalid token)";
}
@@ -1089,7 +1096,7 @@ static const char * token_name(Token *token) {
void print_tokens(Buf *buf, ZigList<Token> *tokens) {
for (int i = 0; i < tokens->length; i += 1) {
Token *token = &tokens->at(i);
- fprintf(stderr, "%s ", token_name(token));
+ fprintf(stderr, "%s ", token_name(token->id));
if (token->start_pos >= 0) {
fwrite(buf_ptr(buf) + token->start_pos, 1, token->end_pos - token->start_pos, stderr);
}
src/tokenizer.hpp
@@ -122,4 +122,6 @@ void print_tokens(Buf *buf, ZigList<Token> *tokens);
bool is_printable(uint8_t c);
int get_digit_value(uint8_t c);
+const char * token_name(TokenId id);
+
#endif
test/run_tests.cpp
@@ -1396,6 +1396,10 @@ fn f() @bogus(foo) => {
const a : @typeof(b) = 0;
const b : @typeof(a) = 0;
)SOURCE", 1, ".tmp_source.zig:3:19: error: use of undeclared identifier 'a'");
+
+ add_compile_fail_case("noalias on non pointer param", R"SOURCE(
+fn f(noalias x: i32) => {}
+ )SOURCE", 1, ".tmp_source.zig:2:6: error: noalias on non-pointer parameter");
}
static void print_compiler_invocation(TestCase *test_case) {