From d121ed961ac9fa58a5a6e2695dc62dbb01c60523 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 13 Jan 2016 22:18:10 -0700 Subject: [PATCH] fix noalias codegen also make some parsing error messages better --- src/analyze.cpp | 5 ++ src/codegen.cpp | 5 +- src/parser.cpp | 8 ++- src/tokenizer.cpp | 163 +++++++++++++++++++++++---------------------- src/tokenizer.hpp | 2 + test/run_tests.cpp | 4 ++ 6 files changed, 104 insertions(+), 83 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index f5212e1a88..c60e6481b8 100644 --- a/src/analyze.cpp +++ b/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")); diff --git a/src/codegen.cpp b/src/codegen.cpp index ae548b16a7..2503548c51 100644 --- a/src/codegen.cpp +++ b/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) diff --git a/src/parser.cpp b/src/parser.cpp index de9dcf0a17..d910189e7e 100644 --- a/src/parser.cpp +++ b/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) { diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index a74c03358c..f792f80a40 100644 --- a/src/tokenizer.cpp +++ b/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 *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); } diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp index b5eac3f050..efbe1c3fe1 100644 --- a/src/tokenizer.hpp +++ b/src/tokenizer.hpp @@ -122,4 +122,6 @@ void print_tokens(Buf *buf, ZigList *tokens); bool is_printable(uint8_t c); int get_digit_value(uint8_t c); +const char * token_name(TokenId id); + #endif diff --git a/test/run_tests.cpp b/test/run_tests.cpp index 04cf942c37..71bef5309c 100644 --- a/test/run_tests.cpp +++ b/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) {