Skip to content

Commit

Permalink
Improve diagnostic message for C-style type syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
9rnsr committed Sep 24, 2014
1 parent cfe52d3 commit dc63a1d
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 23 deletions.
69 changes: 49 additions & 20 deletions src/parse.c
Expand Up @@ -1925,8 +1925,12 @@ EnumDeclaration *Parser::parseEnum()
if (token.value == TOKcolon)
{
nextToken();

int alt = 0;
Loc typeLoc = token.loc;
memtype = parseBasicType();
memtype = parseDeclarator(memtype, NULL, NULL);
memtype = parseDeclarator(memtype, &alt, NULL);
checkCstyleTypeSyntax(typeLoc, memtype, alt, NULL);
}
else
memtype = NULL;
Expand Down Expand Up @@ -2786,7 +2790,7 @@ Dsymbols *Parser::parseImport()
return decldefs;
}

Type *Parser::parseType(Identifier **pident, TemplateParameters **tpl)
Type *Parser::parseType(Identifier **pident, TemplateParameters **ptpl)
{
/* Take care of the storage class prefixes that
* serve as type attributes:
Expand Down Expand Up @@ -2838,9 +2842,15 @@ Type *Parser::parseType(Identifier **pident, TemplateParameters **tpl)
break;
}

Loc typeLoc = token.loc;

Type *t;
t = parseBasicType();
t = parseDeclarator(t, pident, tpl);

int alt = 0;
t = parseDeclarator(t, &alt, pident, ptpl);
checkCstyleTypeSyntax(typeLoc, t, alt, pident ? *pident : NULL);

t = t->addSTC(stc);
return t;
}
Expand Down Expand Up @@ -3076,7 +3086,7 @@ Type *Parser::parseBasicType2(Type *t)
return NULL;
}

Type *Parser::parseDeclarator(Type *t, Identifier **pident,
Type *Parser::parseDeclarator(Type *t, int *palt, Identifier **pident,
TemplateParameters **tpl, StorageClass storage_class, int* pdisable, Expressions **pudas)
{
//printf("parseDeclarator(tpl = %p)\n", tpl);
Expand All @@ -3095,6 +3105,7 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident,
break;

case TOKlparen:
{
// like: T (*fp)();
// like: T ((*fp))();
if (peekNext() == TOKmul ||
Expand All @@ -3105,14 +3116,14 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident,
* although the D style would be:
* int[]*[3] ident
*/
deprecation("C-style function pointer and pointer to array syntax is deprecated. Use 'function' to declare function pointers");
*palt |= 1;
nextToken();
ts = parseDeclarator(t, pident);
ts = parseDeclarator(t, palt, pident);
check(TOKrparen);
break;
}
ts = t;
{

Token *peekt = &token;
/* Completely disallow C-style things like:
* T (a);
Expand All @@ -3121,13 +3132,12 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident,
*/
if (isParameters(&peekt))
{
error("function declaration without return type. "
"(Note that constructors are always named 'this')");
error("function declaration without return type. (Note that constructors are always named 'this')");
}
else
error("unexpected ( in declarator");
}
break;
}

default:
ts = t;
Expand All @@ -3146,32 +3156,34 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident,
* int[] ident
*/
case TOKlbracket:
{ // This is the old C-style post [] syntax.
{
// This is the old C-style post [] syntax.
Loc loc = token.loc;
TypeNext *ta;
nextToken();
if (token.value == TOKrbracket)
{ // It's a dynamic array
{
// It's a dynamic array
ta = new TypeDArray(t); // []
nextToken();
warning(loc, "instead of C-style 'T id[]' syntax, use D-style 'T[]' id syntax");
*palt |= 2;
}
else if (isDeclaration(&token, 0, TOKrbracket, NULL))
{ // It's an associative array

{
// It's an associative array
//printf("it's an associative array\n");
Type *index = parseType(); // [ type ]
check(TOKrbracket);
ta = new TypeAArray(t, index);
warning(loc, "instead of C-style 'T id[type]' syntax, use D-style 'T[type]' id syntax");
*palt |= 2;
}
else
{
//printf("It's a static array\n");
Expression *e = parseAssignExp(); // [ expression ]
ta = new TypeSArray(t, e);
check(TOKrbracket);
warning(loc, "instead of C-style 'T id[exp]' syntax, use D-style 'T[exp] id' syntax");
*palt |= 2;
}

/* Insert ta into
Expand Down Expand Up @@ -3593,20 +3605,23 @@ Dsymbols *Parser::parseDeclarations(bool autodecl, PrefixAttributes *pAttrs, con

while (1)
{
loc = token.loc;
TemplateParameters *tpl = NULL;
int disable;
int alt = 0;

loc = token.loc;
ident = NULL;
t = parseDeclarator(ts, &ident, &tpl, storage_class, &disable, &udas);
t = parseDeclarator(ts, &alt, &ident, &tpl, storage_class, &disable, &udas);
assert(t);
if (!tfirst)
tfirst = t;
else if (t != tfirst)
error("multiple declarations must have the same type, not %s and %s",
tfirst->toChars(), t->toChars());
bool isThis = (t->ty == Tident && ((TypeIdentifier *)t)->ident == Id::This);
if (!isThis && !ident)
if (ident)
checkCstyleTypeSyntax(loc, t, alt, ident);
else if (!isThis)
error("no identifier for declarator %s", t->toChars());

if (tok == TOKtypedef || tok == TOKalias)
Expand Down Expand Up @@ -4305,6 +4320,20 @@ void Parser::checkDanglingElse(Loc elseloc)
}
}

void Parser::checkCstyleTypeSyntax(Loc loc, Type *t, int alt, Identifier *ident)
{
if (!alt)
return;

const char *sp = !ident ? "" : " ";
const char *s = !ident ? "" : ident->toChars();
if (alt & 1) // contains C-style function pointer syntax
::deprecation(loc, "C-style syntax is deprecated. Please use '%s%s%s' instead", t->toChars(), sp, s);
else
::warning(loc, "instead of C-style syntax, use D-style syntax '%s%s%s'", t->toChars(), sp, s);

}

/*****************************************
* Input:
* flags PSxxxx
Expand Down
7 changes: 4 additions & 3 deletions src/parse.h
Expand Up @@ -112,15 +112,16 @@ class Parser : public Lexer
Dsymbol *parseAggregate();
BaseClasses *parseBaseClasses();
Dsymbols *parseImport();
Type *parseType(Identifier **pident = NULL, TemplateParameters **tpl = NULL);
Type *parseType(Identifier **pident = NULL, TemplateParameters **ptpl = NULL);
Type *parseBasicType();
Type *parseBasicType2(Type *t);
Type *parseDeclarator(Type *t, Identifier **pident,
TemplateParameters **tpl = NULL, StorageClass storage_class = 0, int* pdisable = NULL, Expressions **pudas = NULL);
Type *parseDeclarator(Type *t, int *alt, Identifier **pident,
TemplateParameters **tpl = NULL, StorageClass storage_class = 0, int *pdisable = NULL, Expressions **pudas = NULL);
void parseStorageClasses(StorageClass &storage_class, LINK &link, unsigned &structalign, Expressions *&udas);
Dsymbols *parseDeclarations(bool autodecl, PrefixAttributes *pAttrs, const utf8_t *comment);
FuncDeclaration *parseContracts(FuncDeclaration *f);
void checkDanglingElse(Loc elseloc);
void checkCstyleTypeSyntax(Loc loc, Type *t, int alt, Identifier *ident);
/** endPtr used for documented unittests */
Statement *parseStatement(int flags, const utf8_t** endPtr = NULL);
Initializer *parseInitializer();
Expand Down
21 changes: 21 additions & 0 deletions test/fail_compilation/diag_cstyle.d
@@ -0,0 +1,21 @@
// REQUIRED_ARGS: -w
/*
TEST_OUTPUT:
---
fail_compilation/diag_cstyle.d(14): Deprecation: C-style syntax is deprecated. Please use 'int function(int) fp1' instead
fail_compilation/diag_cstyle.d(15): Deprecation: C-style syntax is deprecated. Please use 'int function(int)* fp3' instead
fail_compilation/diag_cstyle.d(17): Deprecation: C-style syntax is deprecated. Please use 'int function(int) FP' instead
fail_compilation/diag_cstyle.d(19): Deprecation: C-style syntax is deprecated. Please use 'int function() fp' instead
fail_compilation/diag_cstyle.d(19): Warning: instead of C-style syntax, use D-style syntax 'int[] arr'
fail_compilation/diag_cstyle.d(21): Warning: instead of C-style syntax, use D-style syntax 'string[] result'
---
*/

int (*fp1)(int);
int (*(*fp3))(int);

alias int(*FP)(int);

void foo(int(*fp)(), int arr[]) {}

string result[]() = "abc";

0 comments on commit dc63a1d

Please sign in to comment.