@@ -5678,6 +5678,29 @@ ParserResult<ImportDecl> Parser::parseDeclImport(ParseDeclOptions Flags,
56785678 return DCC.fixupParserResult (ID);
56795679}
56805680
5681+ static void addMoveOnlyAttrIf (SourceLoc const &parsedTildeCopyable,
5682+ ASTContext &Context,
5683+ Decl *decl) {
5684+ if (parsedTildeCopyable.isInvalid ())
5685+ return ;
5686+
5687+ auto &attrs = decl->getAttrs ();
5688+
5689+ // Don't add if it's already explicitly written on the decl, but error about
5690+ // the duplication and point to the `~Copyable`.
5691+ if (auto attr = attrs.getAttribute <MoveOnlyAttr>()) {
5692+ const bool sayModifier = false ;
5693+ Context.Diags .diagnose (attr->getLocation (), diag::duplicate_attribute,
5694+ sayModifier)
5695+ .fixItRemove (attr->getRange ());
5696+ Context.Diags .diagnose (parsedTildeCopyable, diag::previous_attribute,
5697+ sayModifier);
5698+ return ;
5699+ }
5700+
5701+ attrs.add (new (Context) MoveOnlyAttr (/* IsImplicit=*/ true ));
5702+ }
5703+
56815704// / Parse an inheritance clause.
56825705// /
56835706// / \verbatim
@@ -5687,15 +5710,19 @@ ParserResult<ImportDecl> Parser::parseDeclImport(ParseDeclOptions Flags,
56875710// / inherited:
56885711// / 'class'
56895712// / type-identifier
5713+ // / '~' 'Copyable'
56905714// / \endverbatim
56915715ParserStatus Parser::parseInheritance (
56925716 SmallVectorImpl<InheritedEntry> &Inherited,
5693- bool allowClassRequirement, bool allowAnyObject) {
5717+ bool allowClassRequirement,
5718+ bool allowAnyObject,
5719+ SourceLoc *parseTildeCopyable) {
56945720 consumeToken (tok::colon);
56955721
56965722 SourceLoc classRequirementLoc;
56975723
56985724 ParserStatus Status;
5725+ SourceLoc TildeCopyableLoc;
56995726 SourceLoc prevComma;
57005727 bool HasNextType;
57015728 do {
@@ -5749,6 +5776,38 @@ ParserStatus Parser::parseInheritance(
57495776 continue ;
57505777 }
57515778
5779+ // Is suppression permitted?
5780+ if (parseTildeCopyable) {
5781+ // Try to find '~' 'Copyable'
5782+ //
5783+ // We do this knowing that Copyable is not a real type as of now, so we
5784+ // can't rely on parseType.
5785+ if (Tok.isTilde ()) {
5786+ const auto &nextTok = peekToken (); // lookahead
5787+ if (isIdentifier (nextTok, Context.Id_Copyable .str ())) {
5788+ auto tildeLoc = consumeToken ();
5789+ consumeToken (); // the 'Copyable' token
5790+
5791+ if (TildeCopyableLoc)
5792+ diagnose (tildeLoc, diag::already_suppressed, Context.Id_Copyable );
5793+ else
5794+ TildeCopyableLoc = tildeLoc;
5795+
5796+ continue ;
5797+ }
5798+
5799+ // can't suppress whatever is between '~' and ',' or '{'.
5800+ diagnose (Tok, diag::only_suppress_copyable);
5801+ consumeToken ();
5802+ }
5803+
5804+ } else if (Tok.isTilde ()) {
5805+ // a suppression isn't allowed here, so emit an error eat the token to
5806+ // prevent further parsing errors.
5807+ diagnose (Tok, diag::cannot_suppress_here);
5808+ consumeToken ();
5809+ }
5810+
57525811 auto ParsedTypeResult = parseType ();
57535812 Status |= ParsedTypeResult;
57545813
@@ -5757,6 +5816,9 @@ ParserStatus Parser::parseInheritance(
57575816 Inherited.push_back (InheritedEntry (ParsedTypeResult.get ()));
57585817 } while (HasNextType);
57595818
5819+ if (parseTildeCopyable)
5820+ *parseTildeCopyable = TildeCopyableLoc;
5821+
57605822 return Status;
57615823}
57625824
@@ -8219,10 +8281,14 @@ ParserResult<EnumDecl> Parser::parseDeclEnum(ParseDeclOptions Flags,
82198281 // Parse optional inheritance clause within the context of the enum.
82208282 if (Tok.is (tok::colon)) {
82218283 SmallVector<InheritedEntry, 2 > Inherited;
8284+ SourceLoc parsedTildeCopyable;
82228285 Status |= parseInheritance (Inherited,
82238286 /* allowClassRequirement=*/ false ,
8224- /* allowAnyObject=*/ false );
8287+ /* allowAnyObject=*/ false ,
8288+ &parsedTildeCopyable);
82258289 ED->setInherited (Context.AllocateCopy (Inherited));
8290+
8291+ addMoveOnlyAttrIf (parsedTildeCopyable, Context, ED);
82268292 }
82278293
82288294 diagnoseWhereClauseInGenericParamList (GenericParams);
@@ -8482,10 +8548,14 @@ ParserResult<StructDecl> Parser::parseDeclStruct(ParseDeclOptions Flags,
84828548 // Parse optional inheritance clause within the context of the struct.
84838549 if (Tok.is (tok::colon)) {
84848550 SmallVector<InheritedEntry, 2 > Inherited;
8551+ SourceLoc parsedTildeCopyable;
84858552 Status |= parseInheritance (Inherited,
84868553 /* allowClassRequirement=*/ false ,
8487- /* allowAnyObject=*/ false );
8554+ /* allowAnyObject=*/ false ,
8555+ &parsedTildeCopyable);
84888556 SD->setInherited (Context.AllocateCopy (Inherited));
8557+
8558+ addMoveOnlyAttrIf (parsedTildeCopyable, Context, SD);
84898559 }
84908560
84918561 diagnoseWhereClauseInGenericParamList (GenericParams);
0 commit comments