diff options
Diffstat (limited to 'gcc/d/dmd/cparse.d')
-rw-r--r-- | gcc/d/dmd/cparse.d | 117 |
1 files changed, 90 insertions, 27 deletions
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d index bb12aa7c995..2b2046f3da3 100644 --- a/gcc/d/dmd/cparse.d +++ b/gcc/d/dmd/cparse.d @@ -213,16 +213,12 @@ final class CParser(AST) : Parser!AST goto Lexp; case TOK.leftParenthesis: - { - /* If tokens look like a function call, assume it is one, - * As any type-name won't be resolved until semantic, this - * could be rewritten later. - */ - auto tk = &token; - if (isFunctionCall(tk)) - goto Lexp; - goto default; - } + if (auto pt = lookupTypedef(token.ident)) + { + if (*pt) + goto Ldeclaration; + } + goto Lexp; // function call default: { @@ -259,6 +255,7 @@ final class CParser(AST) : Parser!AST case TOK.plusPlus: case TOK.minusMinus: case TOK.sizeof_: + case TOK._Generic: Lexp: auto exp = cparseExpression(); if (token.value == TOK.identifier && exp.op == EXP.identifier) @@ -1625,10 +1622,21 @@ final class CParser(AST) : Parser!AST */ if (token.value == TOK.semicolon) { - nextToken(); if (!tspec) + { + nextToken(); return; // accept empty declaration as an extension + } + if (auto ti = tspec.isTypeIdentifier()) + { + // C11 6.7.2-2 + error("type-specifier missing for declaration of `%s`", ti.ident.toChars()); + nextToken(); + return; + } + + nextToken(); auto tt = tspec.isTypeTag(); if (!tt || !tt.id && (tt.tok == TOK.struct_ || tt.tok == TOK.union_)) @@ -1660,6 +1668,22 @@ final class CParser(AST) : Parser!AST specifier.mod &= ~MOD.xnone; // 'used' it } + void scanPastSemicolon() + { + while (token.value != TOK.semicolon && token.value != TOK.endOfFile) + nextToken(); + nextToken(); + } + + if (token.value == TOK.assign && tspec && tspec.isTypeIdentifier()) + { + /* C11 6.7.2-2 + * Special check for `const b = 1;` because some compilers allow it + */ + error("type-specifier omitted for declaration of `%s`", tspec.isTypeIdentifier().ident.toChars()); + return scanPastSemicolon(); + } + bool first = true; while (1) { @@ -1879,10 +1903,7 @@ final class CParser(AST) : Parser!AST default: error("`=`, `;` or `,` expected to end declaration instead of `%s`", token.toChars()); Lend: - while (token.value != TOK.semicolon && token.value != TOK.endOfFile) - nextToken(); - nextToken(); - return; + return scanPastSemicolon(); } } } @@ -2399,15 +2420,13 @@ final class CParser(AST) : Parser!AST if (idx.length > 2 && idx[0] == '_' && idx[1] == '_') // leading double underscore importBuiltins = true; // probably one of those compiler extensions t = null; - if (scw & SCW.xtypedef) - { - /* Punch through to what the typedef is, to support things like: - * typedef T* T; - */ - auto pt = lookupTypedef(previd); - if (pt && *pt) // if previd is a known typedef - t = *pt; - } + + /* Punch through to what the typedef is, to support things like: + * typedef T* T; + */ + auto pt = lookupTypedef(previd); + if (pt && *pt) // if previd is a known typedef + t = *pt; if (!t) t = new AST.TypeIdentifier(loc, previd); @@ -2529,7 +2548,14 @@ final class CParser(AST) : Parser!AST default: if (declarator == DTR.xdirect) { - error("identifier or `(` expected"); // ) + if (!t || t.isTypeIdentifier()) + { + // const arr[1]; + error("no type-specifier for declarator"); + t = AST.Type.tint32; + } + else + error("identifier or `(` expected"); // ) panic(); } ts = t; @@ -2745,6 +2771,16 @@ final class CParser(AST) : Parser!AST Specifier specifier; specifier.packalign.setDefault(); auto tspec = cparseSpecifierQualifierList(LVL.global, specifier); + if (!tspec) + { + error("type-specifier is missing"); + tspec = AST.Type.tint32; + } + if (tspec && specifier.mod & MOD.xconst) + { + tspec = toConst(tspec); + specifier.mod = MOD.xnone; // 'used' it + } Identifier id; return cparseDeclarator(DTR.xabstract, tspec, id, specifier); } @@ -2825,8 +2861,18 @@ final class CParser(AST) : Parser!AST Specifier specifier; specifier.packalign.setDefault(); auto tspec = cparseDeclarationSpecifiers(LVL.prototype, specifier); - if (tspec && specifier.mod & MOD.xconst) + if (!tspec) { + error("no type-specifier for parameter"); + tspec = AST.Type.tint32; + } + + if (specifier.mod & MOD.xconst) + { + if ((token.value == TOK.rightParenthesis || token.value == TOK.comma) && + tspec.isTypeIdentifier()) + error("type-specifier omitted for parameter `%s`", tspec.isTypeIdentifier().ident.toChars()); + tspec = toConst(tspec); specifier.mod = MOD.xnone; // 'used' it } @@ -3396,7 +3442,12 @@ final class CParser(AST) : Parser!AST Specifier specifier; specifier.packalign = this.packalign; auto tspec = cparseSpecifierQualifierList(LVL.member, specifier); - if (tspec && specifier.mod & MOD.xconst) + if (!tspec) + { + error("no type-specifier for struct member"); + tspec = AST.Type.tint32; + } + if (specifier.mod & MOD.xconst) { tspec = toConst(tspec); specifier.mod = MOD.xnone; // 'used' it @@ -3409,7 +3460,13 @@ final class CParser(AST) : Parser!AST nextToken(); auto tt = tspec.isTypeTag(); if (!tt) + { + if (auto ti = tspec.isTypeIdentifier()) + { + error("type-specifier omitted before declaration of `%s`", ti.ident.toChars()); + } return; // legal but meaningless empty declaration + } /* If anonymous struct declaration * struct { ... members ... }; @@ -3449,6 +3506,12 @@ final class CParser(AST) : Parser!AST AST.Type dt; if (token.value == TOK.colon) { + if (auto ti = tspec.isTypeIdentifier()) + { + error("type-specifier omitted before bit field declaration of `%s`", ti.ident.toChars()); + tspec = AST.Type.tint32; + } + // C11 6.7.2.1-12 unnamed bit-field id = Identifier.generateAnonymousId("BitField"); dt = tspec; |