summaryrefslogtreecommitdiff
path: root/gcc/d/dmd/cparse.d
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/d/dmd/cparse.d')
-rw-r--r--gcc/d/dmd/cparse.d117
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;