From 1b932b9282df6ed312b6da0031417ea0d4f8faa5 Mon Sep 17 00:00:00 2001 From: k-hara Date: Fri, 27 Jun 2014 00:20:39 +0900 Subject: [PATCH] Refactor redundant/conflicting storage class handling Check redundant/conflicting attributes between prefix and postfix --- src/parse.c | 223 +++++++++++------------------- src/parse.h | 4 +- test/fail_compilation/fail183.d | 6 +- test/fail_compilation/fail184.d | 2 +- test/fail_compilation/parseStc.d | 12 +- test/fail_compilation/parseStc2.d | 18 +-- test/fail_compilation/parseStc3.d | 42 +++--- test/fail_compilation/parseStc4.d | 17 +++ test/runnable/xtest46.d | 2 +- 9 files changed, 143 insertions(+), 183 deletions(-) create mode 100644 test/fail_compilation/parseStc4.d diff --git a/src/parse.c b/src/parse.c index 60afed0a1192..ddc74abe87b8 100644 --- a/src/parse.c +++ b/src/parse.c @@ -500,15 +500,7 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl, PrefixAttributes goto Lautodecl; } Lstc: - if (pAttrs->storageClass & stc) - { - if (token.value == TOKidentifier) - error("redundant storage class '@%s'", token.ident->toChars()); - else - error("redundant storage class '%s'", Token::toChars(token.value)); - } - composeStorageClass(pAttrs->storageClass | stc); - pAttrs->storageClass |= stc; + pAttrs->storageClass = appendStorageClass(pAttrs->storageClass, stc); nextToken(); Lautodecl: @@ -910,23 +902,45 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl, PrefixAttributes } /********************************************* - * Give error on conflicting storage classes. + * Give error on redundant/conflicting storage class. */ -void Parser::composeStorageClass(StorageClass stc) +StorageClass Parser::appendStorageClass(StorageClass storageClass, StorageClass stc) { - StorageClass u = stc; - u &= STCconst | STCimmutable | STCmanifest; - if (u & (u - 1)) - error("conflicting storage class %s", Token::toChars(token.value)); - u = stc; - u &= STCgshared | STCshared | STCtls; - if (u & (u - 1)) - error("conflicting storage class %s", Token::toChars(token.value)); - u = stc; - u &= STCsafe | STCsystem | STCtrusted; - if (u & (u - 1)) - error("conflicting attribute @%s", token.toChars()); + if ((storageClass & stc) || + (storageClass & STCin && stc & (STCconst | STCscope)) || + (stc & STCin && storageClass & (STCconst | STCscope))) + { + OutBuffer buf; + StorageClassDeclaration::stcToCBuffer(&buf, stc); + if (buf.data[buf.offset - 1] == ' ') + buf.data[buf.offset - 1] = '\0'; + error("redundant attribute '%s'", buf.peekString()); + return storageClass | stc; + } + + storageClass |= stc; + + if (stc & (STCconst | STCimmutable | STCmanifest)) + { + StorageClass u = storageClass & (STCconst | STCimmutable | STCmanifest); + if (u & (u - 1)) + error("conflicting attribute '%s'", Token::toChars(token.value)); + } + if (stc & (STCgshared | STCshared | STCtls)) + { + StorageClass u = storageClass & (STCgshared | STCshared | STCtls); + if (u & (u - 1)) + error("conflicting attribute '%s'", Token::toChars(token.value)); + } + if (stc & (STCsafe | STCsystem | STCtrusted)) + { + StorageClass u = storageClass & (STCsafe | STCsystem | STCtrusted); + if (u & (u - 1)) + error("conflicting attribute '@%s'", token.toChars()); + } + + return storageClass; } /*********************************************** @@ -1002,24 +1016,23 @@ StorageClass Parser::parseAttribute(Expressions **pudas) * Parse const/immutable/shared/inout/nothrow/pure postfix */ -StorageClass Parser::parsePostfix(Expressions **pudas) +StorageClass Parser::parsePostfix(StorageClass storageClass, Expressions **pudas) { - StorageClass stc = STCundefined; - while (1) { + StorageClass stc; switch (token.value) { - case TOKconst: stc |= STCconst; break; - case TOKimmutable: stc |= STCimmutable; break; - case TOKshared: stc |= STCshared; break; - case TOKwild: stc |= STCwild; break; - case TOKnothrow: stc |= STCnothrow; break; - case TOKpure: stc |= STCpure; break; + case TOKconst: stc = STCconst; break; + case TOKimmutable: stc = STCimmutable; break; + case TOKshared: stc = STCshared; break; + case TOKwild: stc = STCwild; break; + case TOKnothrow: stc = STCnothrow; break; + case TOKpure: stc = STCpure; break; case TOKat: { Expressions *udas = NULL; - stc |= parseAttribute(&udas); + stc = parseAttribute(&udas); if (udas) { if (pudas) @@ -1036,31 +1049,35 @@ StorageClass Parser::parsePostfix(Expressions **pudas) break; } - default: return stc; + default: + return storageClass; } - composeStorageClass(stc); + storageClass = appendStorageClass(storageClass, stc); nextToken(); } } StorageClass Parser::parseTypeCtor() { - StorageClass stc = 0; + StorageClass storageClass = STCundefined; while (1) { if (peek(&token)->value == TOKlparen) - return stc; + return storageClass; + + StorageClass stc; switch (token.value) { - case TOKconst: stc |= STCconst; break; - case TOKimmutable: stc |= STCimmutable; break; - case TOKshared: stc |= STCshared; break; - case TOKwild: stc |= STCwild; break; + case TOKconst: stc = STCconst; break; + case TOKimmutable: stc = STCimmutable; break; + case TOKshared: stc = STCshared; break; + case TOKwild: stc = STCwild; break; - default: return stc; + default: + return storageClass; } - composeStorageClass(stc); + storageClass = appendStorageClass(storageClass, stc); nextToken(); } } @@ -1414,7 +1431,7 @@ Dsymbol *Parser::parseCtor() nextToken(); check(TOKrparen); - StorageClass stc = parsePostfix(&udas); + StorageClass stc = parsePostfix(STCundefined, &udas); PostBlitDeclaration *f = new PostBlitDeclaration(loc, Loc(), stc, Id::_postblit); Dsymbol *s = parseContracts(f); if (udas) @@ -1437,7 +1454,7 @@ Dsymbol *Parser::parseCtor() int varargs; Parameters *parameters = parseParameters(&varargs); - StorageClass stc = parsePostfix(&udas); + StorageClass stc = parsePostfix(STCundefined, &udas); Expression *constraint = tpl ? parseConstraint() : NULL; @@ -1465,7 +1482,7 @@ Dsymbol *Parser::parseCtor() */ int varargs; Parameters *parameters = parseParameters(&varargs); - StorageClass stc = parsePostfix(&udas); + StorageClass stc = parsePostfix(STCundefined, &udas); Type *tf = new TypeFunction(parameters, NULL, varargs, linkage, stc); // RetrunType -> auto tf = tf->addSTC(stc); @@ -1496,7 +1513,7 @@ Dsymbol *Parser::parseDtor() check(TOKlparen); check(TOKrparen); - StorageClass stc = parsePostfix(&udas); + StorageClass stc = parsePostfix(STCundefined, &udas); DtorDeclaration *f = new DtorDeclaration(loc, Loc(), stc, Id::dtor); Dsymbol *s = parseContracts(f); if (udas) @@ -1523,7 +1540,7 @@ Dsymbol *Parser::parseStaticCtor() nextToken(); check(TOKlparen); check(TOKrparen); - StorageClass stc = parsePostfix(NULL); + StorageClass stc = parsePostfix(STCundefined, NULL); StaticCtorDeclaration *f = new StaticCtorDeclaration(loc, Loc(), stc); Dsymbol *s = parseContracts(f); @@ -1546,7 +1563,7 @@ Dsymbol *Parser::parseSharedStaticCtor() nextToken(); check(TOKlparen); check(TOKrparen); - StorageClass stc = parsePostfix(NULL); + StorageClass stc = parsePostfix(STCundefined, NULL); SharedStaticCtorDeclaration *f = new SharedStaticCtorDeclaration(loc, Loc(), stc); Dsymbol *s = parseContracts(f); @@ -1570,7 +1587,7 @@ Dsymbol *Parser::parseStaticDtor() check(TOKlparen); check(TOKrparen); - StorageClass stc = parsePostfix(&udas); + StorageClass stc = parsePostfix(STCundefined, &udas); if (stc & STCshared) error("to create a 'shared' static destructor, move 'shared' in front of the declaration"); @@ -1603,7 +1620,7 @@ Dsymbol *Parser::parseSharedStaticDtor() check(TOKlparen); check(TOKrparen); - StorageClass stc = parsePostfix(&udas); + StorageClass stc = parsePostfix(STCundefined, &udas); if (stc & STCshared) error("static destructor is 'shared' already"); @@ -1791,13 +1808,7 @@ Parameters *Parser::parseParameters(int *pvarargs, TemplateParameters **tpl) case TOKfinal: stc = STCfinal; goto L2; case TOKauto: stc = STCauto; goto L2; L2: - if (storageClass & stc || - (storageClass & STCin && stc & (STCconst | STCscope)) || - (stc & STCin && storageClass & (STCconst | STCscope)) - ) - error("redundant storage class '%s'", Token::toChars(token.value)); - storageClass |= stc; - composeStorageClass(storageClass); + storageClass = appendStorageClass(storageClass, stc); continue; #if 0 @@ -3060,7 +3071,7 @@ Type *Parser::parseBasicType2(Type *t) nextToken(); arguments = parseParameters(&varargs); - StorageClass stc = parsePostfix(NULL); + StorageClass stc = parsePostfix(STCundefined, NULL); TypeFunction *tf = new TypeFunction(arguments, t, varargs, linkage, stc); if (stc & (STCconst | STCimmutable | STCshared | STCwild)) { @@ -3087,7 +3098,7 @@ Type *Parser::parseBasicType2(Type *t) } Type *Parser::parseDeclarator(Type *t, int *palt, Identifier **pident, - TemplateParameters **tpl, StorageClass storage_class, int* pdisable, Expressions **pudas) + TemplateParameters **tpl, StorageClass storageClass, int* pdisable, Expressions **pudas) { //printf("parseDeclarator(tpl = %p)\n", tpl); t = parseBasicType2(t); @@ -3229,8 +3240,8 @@ Type *Parser::parseDeclarator(Type *t, int *palt, Identifier **pident, /* Parse const/immutable/shared/inout/nothrow/pure postfix */ - StorageClass stc = parsePostfix(pudas); - stc |= storage_class; // merge prefix storage classes + StorageClass stc = parsePostfix(storageClass, pudas); + // merge prefix storage classes Type *tf = new TypeFunction(arguments, t, varargs, linkage, stc); tf = tf->addSTC(stc); if (pdisable) @@ -3309,10 +3320,7 @@ void Parser::parseStorageClasses(StorageClass &storage_class, LINK &link, unsign continue; } L1: - if (storage_class & stc) - error("redundant storage class '%s'", token.toChars()); - storage_class = storage_class | stc; - composeStorageClass(storage_class); + storage_class = appendStorageClass(storage_class, stc); nextToken(); continue; @@ -3603,6 +3611,12 @@ Dsymbols *Parser::parseDeclarations(bool autodecl, PrefixAttributes *pAttrs, con tfirst = NULL; Dsymbols *a = new Dsymbols(); + if (pAttrs) + { + storage_class |= pAttrs->storageClass; + pAttrs->storageClass = STCundefined; + } + while (1) { TemplateParameters *tpl = NULL; @@ -3701,71 +3715,6 @@ Dsymbols *Parser::parseDeclarations(bool autodecl, PrefixAttributes *pAttrs, con #endif //printf("%s funcdecl t = %s, storage_class = x%lx\n", loc.toChars(), t->toChars(), storage_class); - if (pAttrs) - { - StorageClass prefixStc = pAttrs->storageClass; - t = t->addSTC(prefixStc); - - TypeFunction *tf = (TypeFunction *)t; - if (prefixStc & STCpure) - { - if (tf->purity == PUREfwdref) - error("redundant storage class 'pure'"); - tf->purity = PUREfwdref; - } - if (prefixStc & STCnothrow) - { - if (tf->isnothrow) - error("redundant storage class 'nothrow'"); - tf->isnothrow = true; - } - if (prefixStc & STCnogc) - { - if (tf->isnogc) - error("redundant storage class '@nogc'"); - tf->isnogc = true; - } - if (prefixStc & STCproperty) - { - if (tf->isproperty) - error("redundant storage class '@property'"); - tf->isproperty = true; - } - - if (prefixStc & STCref) - { - if (tf->isref) - error("redundant storage class 'ref'"); - tf->isref = true; - } - - StorageClass postfixTrustStc; - switch (tf->trust) - { - case TRUSTdefault: - if (prefixStc & STCsafe) tf->trust = TRUSTsafe; - if (prefixStc & STCsystem) tf->trust = TRUSTsystem; - if (prefixStc & STCtrusted) tf->trust = TRUSTtrusted; - break; - case TRUSTsafe: postfixTrustStc = STCsafe; goto Ltrust; - case TRUSTsystem: postfixTrustStc = STCsystem; goto Ltrust; - case TRUSTtrusted: postfixTrustStc = STCtrusted; goto Ltrust; - Ltrust: - { - if (prefixStc & postfixTrustStc) - error("redundant storage class '%s'", trustToChars(tf->trust)); - else if (prefixStc & (STCsafe | STCsystem | STCtrusted)) - error("conflicting storage class '%s'", trustToChars(tf->trust)); - break; - } - default: - assert(0); - } - - storage_class |= prefixStc & ~(STC_TYPECTOR | STC_FUNCATTR); - pAttrs->storageClass = STCundefined; - } - FuncDeclaration *f = new FuncDeclaration(loc, Loc(), ident, storage_class | (disable ? STCdisable : 0), t); if (tpl) @@ -4715,10 +4664,7 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr) Lagain: if (stc) { - if (storageClass & stc) - error("redundant storage class '%s'", Token::toChars(token.value)); - storageClass |= stc; - composeStorageClass(storageClass); + storageClass = appendStorageClass(storageClass, stc); nextToken(); } switch (token.value) @@ -4815,10 +4761,7 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr) LagainStc: if (stc) { - if (storageClass & stc) - error("redundant storage class '%s'", Token::toChars(token.value)); - storageClass |= stc; - composeStorageClass(storageClass); + storageClass = appendStorageClass(storageClass, stc); nextToken(); } switch (token.value) @@ -6682,7 +6625,7 @@ Expression *Parser::parsePrimaryExp() // (parameters) => expression // (parameters) { statements... } parameters = parseParameters(&varargs, &tpl); - stc = parsePostfix(NULL); + stc = parsePostfix(STCundefined, NULL); if (stc & (STCconst | STCimmutable | STCshared | STCwild)) error("const/immutable/shared/inout attributes are only valid for non-static member functions"); break; diff --git a/src/parse.h b/src/parse.h index 70d121b91d69..193eccffa648 100644 --- a/src/parse.h +++ b/src/parse.h @@ -78,9 +78,9 @@ class Parser : public Lexer Dsymbols *parseDeclDefs(int once, Dsymbol **pLastDecl = NULL, PrefixAttributes *pAttrs = NULL); Dsymbols *parseAutoDeclarations(StorageClass storageClass, const utf8_t *comment); Dsymbols *parseBlock(Dsymbol **pLastDecl, PrefixAttributes *pAttrs = NULL); - void composeStorageClass(StorageClass stc); + StorageClass appendStorageClass(StorageClass storageClass, StorageClass stc); StorageClass parseAttribute(Expressions **pexps); - StorageClass parsePostfix(Expressions **pudas); + StorageClass parsePostfix(StorageClass storageClass, Expressions **pudas); StorageClass parseTypeCtor(); Expression *parseConstraint(); TemplateDeclaration *parseTemplateDeclaration(bool ismixin = false); diff --git a/test/fail_compilation/fail183.d b/test/fail_compilation/fail183.d index d7451f921671..b0a00ba83af7 100644 --- a/test/fail_compilation/fail183.d +++ b/test/fail_compilation/fail183.d @@ -1,9 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation/fail183.d(10): Error: redundant storage class 'const' -fail_compilation/fail183.d(10): Error: redundant storage class 'scope' -fail_compilation/fail183.d(11): Error: redundant storage class 'in' +fail_compilation/fail183.d(10): Error: redundant attribute 'const' +fail_compilation/fail183.d(10): Error: redundant attribute 'scope' +fail_compilation/fail183.d(11): Error: redundant attribute 'in' --- */ diff --git a/test/fail_compilation/fail184.d b/test/fail_compilation/fail184.d index 7a84dbfb57dd..dc31bdeacd3e 100644 --- a/test/fail_compilation/fail184.d +++ b/test/fail_compilation/fail184.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail184.d(8): Error: redundant storage class 'final' +fail_compilation/fail184.d(8): Error: redundant attribute 'final' --- */ diff --git a/test/fail_compilation/parseStc.d b/test/fail_compilation/parseStc.d index 63403547d1cf..3379e2316dd7 100644 --- a/test/fail_compilation/parseStc.d +++ b/test/fail_compilation/parseStc.d @@ -2,7 +2,7 @@ TEST_OUTPUT: --- fail_compilation/parseStc.d(10): Error: if (v; e) is deprecated, use if (auto v = e) -fail_compilation/parseStc.d(11): Error: redundant storage class 'const' +fail_compilation/parseStc.d(11): Error: redundant attribute 'const' --- */ void test1() @@ -14,9 +14,9 @@ void test1() /* TEST_OUTPUT: --- -fail_compilation/parseStc.d(24): Error: redundant storage class 'const' -fail_compilation/parseStc.d(25): Error: redundant storage class 'const' -fail_compilation/parseStc.d(26): Error: conflicting storage class immutable +fail_compilation/parseStc.d(24): Error: redundant attribute 'const' +fail_compilation/parseStc.d(25): Error: redundant attribute 'const' +fail_compilation/parseStc.d(26): Error: conflicting attribute 'immutable' --- */ void test2() @@ -29,8 +29,8 @@ void test2() /* TEST_OUTPUT: --- -fail_compilation/parseStc.d(36): Error: redundant storage class 'const' -fail_compilation/parseStc.d(37): Error: redundant storage class 'const' +fail_compilation/parseStc.d(36): Error: redundant attribute 'const' +fail_compilation/parseStc.d(37): Error: redundant attribute 'const' --- */ struct S3 { const const test3() {} } diff --git a/test/fail_compilation/parseStc2.d b/test/fail_compilation/parseStc2.d index a0c66442a96e..840024a3472e 100644 --- a/test/fail_compilation/parseStc2.d +++ b/test/fail_compilation/parseStc2.d @@ -1,11 +1,11 @@ /* TEST_OUTPUT: --- -fail_compilation/parseStc2.d(11): Error: conflicting storage class const -fail_compilation/parseStc2.d(12): Error: conflicting attribute @system -fail_compilation/parseStc2.d(13): Error: conflicting attribute @safe -fail_compilation/parseStc2.d(14): Error: conflicting attribute @trusted -fail_compilation/parseStc2.d(15): Error: conflicting storage class __gshared +fail_compilation/parseStc2.d(11): Error: conflicting attribute 'const' +fail_compilation/parseStc2.d(12): Error: conflicting attribute '@system' +fail_compilation/parseStc2.d(13): Error: conflicting attribute '@safe' +fail_compilation/parseStc2.d(14): Error: conflicting attribute '@trusted' +fail_compilation/parseStc2.d(15): Error: conflicting attribute '__gshared' --- */ immutable const void f4() {} @@ -17,10 +17,10 @@ shared __gshared f4() {} /* TEST_OUTPUT: --- -fail_compilation/parseStc2.d(26): Error: redundant storage class 'static' -fail_compilation/parseStc2.d(27): Error: redundant storage class 'pure' -fail_compilation/parseStc2.d(28): Error: redundant storage class '@property' -fail_compilation/parseStc2.d(29): Error: redundant storage class '@safe' +fail_compilation/parseStc2.d(26): Error: redundant attribute 'static' +fail_compilation/parseStc2.d(27): Error: redundant attribute 'pure' +fail_compilation/parseStc2.d(28): Error: redundant attribute '@property' +fail_compilation/parseStc2.d(29): Error: redundant attribute '@safe' --- */ static static void f1() {} diff --git a/test/fail_compilation/parseStc3.d b/test/fail_compilation/parseStc3.d index 167d9970adf0..a4329aa1375a 100644 --- a/test/fail_compilation/parseStc3.d +++ b/test/fail_compilation/parseStc3.d @@ -1,10 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/parseStc3.d(10): Error: redundant storage class 'pure' -fail_compilation/parseStc3.d(11): Error: redundant storage class 'nothrow' -fail_compilation/parseStc3.d(12): Error: redundant storage class '@nogc' -fail_compilation/parseStc3.d(13): Error: redundant storage class '@property' +fail_compilation/parseStc3.d(10): Error: redundant attribute 'pure' +fail_compilation/parseStc3.d(11): Error: redundant attribute 'nothrow' +fail_compilation/parseStc3.d(12): Error: redundant attribute '@nogc' +fail_compilation/parseStc3.d(13): Error: redundant attribute '@property' --- */ pure void f1() pure {} @@ -16,9 +16,9 @@ nothrow void f2() nothrow {} /* TEST_OUTPUT: --- -fail_compilation/parseStc3.d(24): Error: redundant storage class '@safe' -fail_compilation/parseStc3.d(25): Error: redundant storage class '@system' -fail_compilation/parseStc3.d(26): Error: redundant storage class '@trusted' +fail_compilation/parseStc3.d(24): Error: redundant attribute '@safe' +fail_compilation/parseStc3.d(25): Error: redundant attribute '@system' +fail_compilation/parseStc3.d(26): Error: redundant attribute '@trusted' --- */ @safe void f6() @safe {} @@ -28,12 +28,12 @@ fail_compilation/parseStc3.d(26): Error: redundant storage class '@trusted' /* TEST_OUTPUT: --- -fail_compilation/parseStc3.d(39): Error: conflicting storage class '@system' -fail_compilation/parseStc3.d(40): Error: conflicting storage class '@trusted' -fail_compilation/parseStc3.d(41): Error: conflicting storage class '@safe' -fail_compilation/parseStc3.d(42): Error: conflicting storage class '@trusted' -fail_compilation/parseStc3.d(43): Error: conflicting storage class '@safe' -fail_compilation/parseStc3.d(44): Error: conflicting storage class '@system' +fail_compilation/parseStc3.d(39): Error: conflicting attribute '@system' +fail_compilation/parseStc3.d(40): Error: conflicting attribute '@trusted' +fail_compilation/parseStc3.d(41): Error: conflicting attribute '@safe' +fail_compilation/parseStc3.d(42): Error: conflicting attribute '@trusted' +fail_compilation/parseStc3.d(43): Error: conflicting attribute '@safe' +fail_compilation/parseStc3.d(44): Error: conflicting attribute '@system' --- */ @safe void f9() @system {} @@ -46,14 +46,14 @@ fail_compilation/parseStc3.d(44): Error: conflicting storage class '@system' /* TEST_OUTPUT: --- -fail_compilation/parseStc3.d(59): Error: conflicting attribute @system -fail_compilation/parseStc3.d(59): Error: conflicting storage class '@trusted' -fail_compilation/parseStc3.d(60): Error: conflicting attribute @system -fail_compilation/parseStc3.d(60): Error: redundant storage class '@system' -fail_compilation/parseStc3.d(61): Error: conflicting attribute @safe -fail_compilation/parseStc3.d(61): Error: redundant storage class '@system' -fail_compilation/parseStc3.d(62): Error: conflicting attribute @safe -fail_compilation/parseStc3.d(62): Error: redundant storage class '@trusted' +fail_compilation/parseStc3.d(59): Error: conflicting attribute '@system' +fail_compilation/parseStc3.d(59): Error: conflicting attribute '@trusted' +fail_compilation/parseStc3.d(60): Error: conflicting attribute '@system' +fail_compilation/parseStc3.d(60): Error: redundant attribute '@system' +fail_compilation/parseStc3.d(61): Error: conflicting attribute '@safe' +fail_compilation/parseStc3.d(61): Error: redundant attribute '@system' +fail_compilation/parseStc3.d(62): Error: conflicting attribute '@safe' +fail_compilation/parseStc3.d(62): Error: redundant attribute '@trusted' --- */ @safe @system void f15() @trusted {} diff --git a/test/fail_compilation/parseStc4.d b/test/fail_compilation/parseStc4.d new file mode 100644 index 000000000000..dac915dc7460 --- /dev/null +++ b/test/fail_compilation/parseStc4.d @@ -0,0 +1,17 @@ + +/* +TEST_OUTPUT: +--- +fail_compilation/parseStc4.d(14): Error: redundant attribute 'pure' +fail_compilation/parseStc4.d(14): Error: redundant attribute 'nothrow' +fail_compilation/parseStc4.d(14): Error: conflicting attribute '@system' +fail_compilation/parseStc4.d(14): Error: redundant attribute '@nogc' +fail_compilation/parseStc4.d(14): Error: redundant attribute '@property' +--- +*/ +pure nothrow @safe @nogc @property +int foo() +pure nothrow @system @nogc @property +{ + return 0; +} diff --git a/test/runnable/xtest46.d b/test/runnable/xtest46.d index 531457401fb6..660e7fc7ba73 100644 --- a/test/runnable/xtest46.d +++ b/test/runnable/xtest46.d @@ -3685,7 +3685,7 @@ auto ref boo(int i) pure nothrow { return i; } class A152 { auto hoo(int i) pure { return i; } - const boo(int i) const { return i; } + const boo(int i) nothrow { return i; } auto coo(int i) const { return i; } auto doo(int i) immutable { return i; } auto eoo(int i) shared { return i; }