Merge pull request #15257 from rintaro/parse-eliminate-square_lit

[Parse] Eliminate {l,r}_square_lit tokens.
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index 6ff2ef6..592481b 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -1190,14 +1190,15 @@
       "expected ']' in container literal expression", ())
 
 // Object literal expressions
-ERROR(expected_object_literal_identifier,none,
-      "expected identifier after '#' in object literal expression", ())
-ERROR(expected_arg_list_in_object_literal,none,
+ERROR(expected_arg_list_in_object_literal,PointsToFirstBadToken,
       "expected argument list in object literal", ())
-ERROR(object_literal_legacy_name,none,
-      "'%0' has been renamed to '%1", (StringRef, StringRef))
-ERROR(legacy_object_literal_syntax,none,
-       "object literal syntax no longer uses '[# ... #]'", ())
+ERROR(legacy_object_literal,none,
+      "'%select{|[}0#%1(...)%select{|#]}0' has been renamed to '#%2(...)'",
+      (bool, StringRef, StringRef))
+
+// Unknown pound expression.
+ERROR(unknown_pound_expr,none,
+      "use of unknown directive '#%0'", (StringRef))
 
 // If expressions
 ERROR(expected_expr_after_if_question,none,
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index 19891ae..4dbfa12 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -1281,15 +1281,14 @@
   /// Parse an object literal.
   ///
   /// \param LK The literal kind as determined by the first token.
-  /// \param NewName New name for a legacy literal.
   ParserResult<Expr> parseExprObjectLiteral(ObjectLiteralExpr::LiteralKind LK,
-                                            bool isExprBasic,
-                                            StringRef NewName = StringRef());
+                                            bool isExprBasic);
   ParserResult<Expr> parseExprCallSuffix(ParserResult<Expr> fn,
                                          bool isExprBasic);
-  ParserResult<Expr> parseExprCollection(SourceLoc LSquareLoc = SourceLoc());
+  ParserResult<Expr> parseExprCollection();
   ParserResult<Expr> parseExprArray(SourceLoc LSquareLoc);
   ParserResult<Expr> parseExprDictionary(SourceLoc LSquareLoc);
+  ParserResult<Expr> parseExprPoundUnknown(SourceLoc LSquareLoc);
 
   UnresolvedDeclRefExpr *parseExprOperator();
 
diff --git a/include/swift/Syntax/TokenKinds.def b/include/swift/Syntax/TokenKinds.def
index 13238ad..eb33fac 100644
--- a/include/swift/Syntax/TokenKinds.def
+++ b/include/swift/Syntax/TokenKinds.def
@@ -22,7 +22,6 @@
 ///     SIL_KEYWORD(kw)
 ///   POUND_KEYWORD(kw)
 ///     POUND_OBJECT_LITERAL(kw, desc, proto)
-///     POUND_OLD_OBJECT_LITERAL(kw, new_kw, old_arg, new_arg)
 ///     POUND_CONFIG(kw)
 ///     POUND_DIRECTIVE_KEYWORD(kw)
 ///       POUND_COND_DIRECTIVE_KEYWORD(kw)
@@ -96,13 +95,6 @@
 #define POUND_OBJECT_LITERAL(kw, desc, proto) POUND_KEYWORD(kw)
 #endif
 
-/// POUND_OLD_OBJECT_LITERAL(kw, new_kw, old_arg, new_arg)
-///   Every keyword prefixed with a '#' representing the obsoleted form of an
-///   object literal.
-#ifndef POUND_OLD_OBJECT_LITERAL
-#define POUND_OLD_OBJECT_LITERAL(kw, new_kw, old_arg, new_arg) POUND_KEYWORD(kw)
-#endif
-
 /// POUND_CONFIG(kw)
 ///   Every keyword prefixed with a '#' representing a configuration.
 #ifndef POUND_CONFIG
@@ -261,11 +253,6 @@
 PUNCTUATOR(string_quote, "\"")
 PUNCTUATOR(multiline_string_quote, "\"\"\"")
 
-// Legacy punctuators used for migrating old object literal syntax.
-// NOTE: Remove in the future.
-PUNCTUATOR(l_square_lit,  "[#")
-PUNCTUATOR(r_square_lit,  "#]")
-
 // Keywords prefixed with a '#'.  "keyPath" becomes "tok::pound_keyPath".
 POUND_KEYWORD(keyPath)
 POUND_KEYWORD(line)
@@ -294,10 +281,6 @@
 POUND_OBJECT_LITERAL(imageLiteral, "image", ExpressibleByImageLiteral)
 POUND_OBJECT_LITERAL(colorLiteral, "color", ExpressibleByColorLiteral)
 
-POUND_OLD_OBJECT_LITERAL(FileReference, fileLiteral, fileReferenceLiteral, resourceName)
-POUND_OLD_OBJECT_LITERAL(Image, imageLiteral, imageLiteral, resourceName)
-POUND_OLD_OBJECT_LITERAL(Color, colorLiteral, colorLiteralRed, red)
-
 // Single-token literals
 LITERAL(integer_literal)
 LITERAL(floating_literal)
@@ -330,7 +313,6 @@
 #undef SIL_KEYWORD
 #undef POUND_KEYWORD
 #undef POUND_OBJECT_LITERAL
-#undef POUND_OLD_OBJECT_LITERAL
 #undef POUND_CONFIG
 #undef POUND_DIRECTIVE_KEYWORD
 #undef POUND_COND_DIRECTIVE_KEYWORD
diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp
index e79980a..56623da 100644
--- a/lib/IDE/SyntaxModel.cpp
+++ b/lib/IDE/SyntaxModel.cpp
@@ -100,8 +100,6 @@
         Kind = SyntaxNodeKind::Keyword;
         break;
 
-#define POUND_OLD_OBJECT_LITERAL(Name, NewName, OldArg, NewArg) \
-      case tok::pound_##Name:
 #define POUND_OBJECT_LITERAL(Name, Desc, Proto) case tok::pound_##Name:
 #include "swift/Syntax/TokenKinds.def"
         LiteralStartLoc = Loc;
@@ -119,7 +117,6 @@
         break;
 
 #define POUND_OBJECT_LITERAL(Name, Desc, Proto)
-#define POUND_OLD_OBJECT_LITERAL(Name, NewName, OldArg, NewArg)
 #define POUND_DIRECTIVE_KEYWORD(Name)
 #define POUND_KEYWORD(Name) case tok::pound_##Name:
 #include "swift/Syntax/TokenKinds.def"
diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp
index 816c6b4..3c504dc 100644
--- a/lib/Parse/Lexer.cpp
+++ b/lib/Parse/Lexer.cpp
@@ -637,12 +637,6 @@
 void Lexer::lexHash() {
   const char *TokStart = CurPtr-1;
 
-  // NOTE: legacy punctuator.  Remove in the future.
-  if (*CurPtr == ']') { // #]
-     ++CurPtr;
-     return formToken(tok::r_square_lit, TokStart);
-  }
-
   // Scan for [a-zA-Z]+ to see what we match.
   const char *tmpPtr = CurPtr;
   if (clang::isIdentifierHead(*tmpPtr)) {
@@ -2224,29 +2218,16 @@
 
   case '@': return formToken(tok::at_sign, TokStart);
   case '{': return formToken(tok::l_brace, TokStart);
-  case '[': {
-     // NOTE: Legacy punctuator for old object literal syntax.
-     // Remove in the future.
-     if (*CurPtr == '#') { // [#
-       // NOTE: Do NOT include the '#' in the token, unlike in earlier
-       // versions of Swift that supported the old object literal syntax
-       // directly.  The '#' will be lexed as part of the object literal
-       // keyword token itself.
-       return formToken(tok::l_square_lit, TokStart);
-     }
-     return formToken(tok::l_square, TokStart);
-  }
+  case '[': return formToken(tok::l_square, TokStart);
   case '(': return formToken(tok::l_paren, TokStart);
   case '}': return formToken(tok::r_brace, TokStart);
   case ']': return formToken(tok::r_square, TokStart);
-  case ')':
-    return formToken(tok::r_paren, TokStart);
+  case ')': return formToken(tok::r_paren, TokStart);
 
   case ',': return formToken(tok::comma, TokStart);
   case ';': return formToken(tok::semi, TokStart);
   case ':': return formToken(tok::colon, TokStart);
-  case '\\':
-    return formToken(tok::backslash, TokStart);
+  case '\\': return formToken(tok::backslash, TokStart);
 
   case '#':
     return lexHash();
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 66e0fdb..d933169 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -883,14 +883,6 @@
                                              /*Implicit=*/false));
   }
 
-  // NOTE: l_square_lit is for migrating the old object literal syntax.
-  // Eventually this block can be removed.
-  if (Tok.is(tok::l_square_lit) && !Tok.isAtStartOfLine() &&
-      isCollectionLiteralStartingWithLSquareLit()) {
-    assert(Tok.getLength() == 1);
-    Tok.setKind(tok::l_square);
-  }
-
   if (Tok.isFollowingLSquare()) {
     // super[expr]
     SourceLoc lSquareLoc, rSquareLoc;
@@ -1240,14 +1232,6 @@
       continue;
     }
 
-    // NOTE: l_square_lit is for migrating the old object literal syntax.
-    // Eventually this block can be removed.
-    if (Tok.is(tok::l_square_lit) && !Tok.isAtStartOfLine() &&
-        isCollectionLiteralStartingWithLSquareLit()) {
-      assert(Tok.getLength() == 1);
-      Tok.setKind(tok::l_square);
-    }
-
     // Check for a [expr] suffix.
     // Note that this cannot be the start of a new line.
     if (Tok.isFollowingLSquare()) {
@@ -1804,61 +1788,12 @@
     break;
   }
 
-  // NOTE: This is for migrating the old object literal syntax.
-  // Eventually this block can be removed.
-  case tok::l_square_lit: {// [#Color(...)#], [#Image(...)#]
-    // If this is actually a collection literal starting with '[#', handle it
-    // as such.
-    if (isCollectionLiteralStartingWithLSquareLit()) {
-      // Split the token into two.
-      SourceLoc LSquareLoc =
-          consumeStartingCharacterOfCurrentToken(tok::l_square);
-      // Consume the '[' token.
-      Result = parseExprCollection(LSquareLoc);
-      break;
-    }     
-
-    auto LSquareLoc = Tok.getLoc();
-    auto LSquareTokRange = Tok.getRange();
-    (void)consumeToken(tok::l_square_lit);
-    
-    if (Tok.is(tok::pound)) {
-      consumeToken();
-      if (!Tok.is(tok::identifier))
-        diagnose(LSquareLoc, diag::expected_object_literal_identifier);
-      skipUntil(tok::r_square_lit);
-      Result = makeParserError();
-    }
-    else {
-      Result = parseExprPostfix(ID, isExprBasic);
-    }
-
-    // This should be an invariant based on the check in
-    // isCollectionLiteralStartingWithLSquareLit().
-    auto RSquareTokRange = Tok.getRange();
-    (void)consumeToken(tok::r_square_lit);
-
-    // Issue a diagnostic for the legacy syntax and provide a fixit
-    // to strip away the '[#' and '#]'
-    diagnose(LSquareLoc, diag::legacy_object_literal_syntax)
-      .fixItRemoveChars(LSquareTokRange.getStart(), LSquareTokRange.getEnd())
-      .fixItRemoveChars(RSquareTokRange.getStart(), RSquareTokRange.getEnd());
-    
-    break;
-  }
 
 #define POUND_OBJECT_LITERAL(Name, Desc, Proto) case tok::pound_##Name:  \
   Result = parseExprObjectLiteral(ObjectLiteralExpr::Name, isExprBasic); \
   break;
 #include "swift/Syntax/TokenKinds.def"
 
-#define POUND_OLD_OBJECT_LITERAL(Name, NewName, NewArg, OldArg)\
-  case tok::pound_##Name:                                               \
-    Result = parseExprObjectLiteral(ObjectLiteralExpr::NewName, isExprBasic, \
-    "#" #NewName);                                                      \
-  break;
-#include "swift/Syntax/TokenKinds.def"
-
   case tok::code_complete:
     Result = makeParserResult(new (Context) CodeCompletionExpr(Tok.getLoc()));
     Result.setHasCodeCompletion();
@@ -1870,6 +1805,13 @@
     consumeToken(tok::code_complete);
     break;
 
+  case tok::pound:
+    if (peekToken().is(tok::identifier) && !peekToken().isEscapedIdentifier() &&
+        Tok.getLoc().getAdvancedLoc(1) == peekToken().getLoc()) {
+      return parseExprPoundUnknown(SourceLoc());
+    }
+    goto UnknownCharacter;
+
   // Eat an invalid token in an expression context.  Error tokens are diagnosed
   // by the lexer, so there is no reason to emit another diagnostic.
   case tok::unknown:
@@ -3052,7 +2994,7 @@
       if (!exprLabels.empty()) {
         exprLabels.push_back(FieldName);
         exprLabelLocs.push_back(FieldNameLoc);
-      } else if (FieldName.get()) {
+      } else if (FieldNameLoc.isValid()) {
         exprLabels.resize(exprs.size());
         exprLabels.push_back(FieldName);
 
@@ -3117,32 +3059,6 @@
 
   return closure;
 }
-
-// NOTE: this is to detect the old object literal syntax.
-// This will be removed in the future.
-bool Parser::isCollectionLiteralStartingWithLSquareLit() {
-   BacktrackingScope backtracking(*this);
-   (void)consumeToken(tok::l_square_lit);
-   switch (Tok.getKind()) {
-     // Handle both degenerate '#' and '# identifier'.
-     case tok::pound:
-      (void) consumeToken();
-      if (Tok.is(tok::identifier)) skipSingle();
-      break;
-#define POUND_OBJECT_LITERAL(kw, desc, proto)\
-     case tok::pound_##kw: (void)consumeToken(); break;
-#define POUND_OLD_OBJECT_LITERAL(kw, new_kw, old_arg, new_arg)\
-     case tok::pound_##kw: (void)consumeToken(); break;
-#include "swift/Syntax/TokenKinds.def"
-     default:
-       return true;
-   }
-
-   // Skip over a parenthesized argument, if present.
-   if (Tok.is(tok::l_paren)) skipSingle();
- 
-   return Tok.isNot(tok::r_square_lit);
- }
  
 /// \brief Parse an object literal expression.
 ///
@@ -3150,11 +3066,9 @@
 ///   '#' identifier expr-paren
 ParserResult<Expr>
 Parser::parseExprObjectLiteral(ObjectLiteralExpr::LiteralKind LitKind,
-                               bool isExprBasic,
-                               StringRef NewName) {
+                               bool isExprBasic) {
   SyntaxParsingContext ObjectLiteralContext(SyntaxContext,
                                             SyntaxKind::ObjectLiteralExpr);
-  auto PoundTok = Tok;
   SourceLoc PoundLoc = consumeToken();
   // Parse a tuple of args
   if (!Tok.is(tok::l_paren)) {
@@ -3181,49 +3095,94 @@
   if (status.isError())
     return makeParserError();
 
-  // If the legacy name was used (e.g., #Image instead of #imageLiteral)
-  // prompt an error and a fixit.
-  if (!NewName.empty()) {
-    auto diag =
-      diagnose(PoundTok, diag::object_literal_legacy_name, 
-               PoundTok.getText(), NewName);
-    auto Range = PoundTok.getRange();
-    
-    // Create a FixIt for the keyword.
-    diag.fixItReplaceChars(Range.getStart(), Range.getEnd(), NewName);
-
-    // Try and construct a FixIt for the argument label.
-    if (!argLabelLocs.empty() && !argLabels[0].empty()) {
-      auto ArgLoc = argLabelLocs[0];
-      auto FirstElementName = argLabels[0];
-            
-      if (ArgLoc.isValid() && !FirstElementName.empty()) { 
-        auto OldArg = FirstElementName.str();
-        auto NewArg =
-          llvm::StringSwitch<StringRef>(OldArg)
-#define POUND_OLD_OBJECT_LITERAL(kw, new_kw, old_arg, new_arg)\
-            .Case(#old_arg, #new_arg)
-#include "swift/Syntax/TokenKinds.def"
-            .Default("");
-       
-        if (!NewArg.empty()) {    
-          auto Loc = argLabelLocs[0];
-          diag.fixItReplaceChars(Loc,
-                                 Loc.getAdvancedLocOrInvalid(OldArg.size()),
-                                 NewArg);
-        }
-      }
-    }
-    
-    return makeParserError();
-  }
-
   return makeParserResult(
     ObjectLiteralExpr::create(Context, PoundLoc, LitKind, lParenLoc, args,
                               argLabels, argLabelLocs, rParenLoc,
                               trailingClosure, /*implicit=*/false));
 }
 
+/// \brief Parse and diagnose unknown pound expression
+///
+/// If it look like a legacy (Swift 2) object literal expression, suggest fix-it
+/// to use new object literal syntax.
+///
+/// expr-unknown-pound:
+///   '#' identifier expr-paren?
+///   '[' '#' identifier expr-paren? '#' ']' ; Legacy object literal
+ParserResult<Expr> Parser::parseExprPoundUnknown(SourceLoc LSquareLoc) {
+  SourceLoc PoundLoc = consumeToken(tok::pound);
+
+  assert(Tok.is(tok::identifier) && !Tok.isEscapedIdentifier() &&
+         PoundLoc.getAdvancedLoc(1) == Tok.getLoc());
+
+  Identifier Name;
+  SourceLoc NameLoc = consumeIdentifier(&Name);
+
+  // Parse arguments if exist.
+  SourceLoc LParenLoc, RParenLoc;
+  SmallVector<SourceLoc, 2> argLabelLocs;
+  SmallVector<Expr *, 2> args;
+  SmallVector<Identifier, 2> argLabels;
+  Expr *trailingClosure;
+  if (Tok.isFollowingLParen()) {
+    // Parse arguments.
+    ParserStatus status =
+        parseExprList(tok::l_paren, tok::r_paren,
+                      /*isPostfix=*/false, /*isExprBasic*/ false, LParenLoc,
+                      args, argLabels, argLabelLocs, RParenLoc, trailingClosure,
+                      SyntaxKind::FunctionCallArgumentList);
+    if (status.hasCodeCompletion())
+      return makeParserCodeCompletionResult<Expr>();
+    if (status.isError())
+      return makeParserError();
+  }
+
+  std::pair<StringRef, StringRef> NewNameArgPair =
+      llvm::StringSwitch<std::pair<StringRef, StringRef>>(Name.str())
+          .Case("Color", {"colorLiteral", "red"})
+          .Case("Image", {"imageLiteral", "resourceName"})
+          .Case("FileReference", {"fileLiteral", "resourceName"})
+          .Default({});
+
+  // If it's not legacy object literal, we don't know how to handle this.
+  if (NewNameArgPair.first.empty()) {
+    diagnose(PoundLoc, diag::unknown_pound_expr, Name.str());
+    return makeParserError();
+  }
+
+  // Diagnose legacy object literal.
+
+  // Didn't have arguments.
+  if (LParenLoc.isInvalid()) {
+    diagnose(Tok.getLoc(), diag::expected_arg_list_in_object_literal);
+    return makeParserError();
+  }
+
+  // If it's started with '[', try to parse closing '#]'.
+  SourceLoc RPoundLoc, RSquareLoc;
+  if (LSquareLoc.isValid() && consumeIf(tok::pound, RPoundLoc))
+    consumeIf(tok::r_square, RSquareLoc);
+
+  auto diag = diagnose(LSquareLoc.isValid() ? LSquareLoc : PoundLoc,
+                       diag::legacy_object_literal, LSquareLoc.isValid(),
+                       Name.str(), NewNameArgPair.first);
+
+  // Remove '[' if exist.
+  if (LSquareLoc.isValid())
+    diag.fixItRemove(LSquareLoc);
+  // Replace the literal name.
+  diag.fixItReplace(NameLoc, NewNameArgPair.first);
+  // Replace the first argument.
+  if (!argLabelLocs.empty() && argLabelLocs[0].isValid())
+    diag.fixItReplace(argLabelLocs[0], NewNameArgPair.second);
+  // Remove '#]' if exist.
+  if (RPoundLoc.isValid())
+    diag.fixItRemove(
+        {RPoundLoc, RSquareLoc.isValid() ? RSquareLoc : RPoundLoc});
+
+  return makeParserError();
+}
+
 /// \brief Parse an expression call suffix.
 ///
 /// expr-call-suffix:
@@ -3293,12 +3252,9 @@
 ///     expr-array
 ///     expr-dictionary
 //      lsquare-starting ']'
-ParserResult<Expr> Parser::parseExprCollection(SourceLoc LSquareLoc) {
+ParserResult<Expr> Parser::parseExprCollection() {
   SyntaxParsingContext ArrayOrDictContext(SyntaxContext);
-
-  // If the caller didn't already consume the '[', do so now.
-  if (LSquareLoc.isInvalid())
-    LSquareLoc = consumeToken(tok::l_square);
+  SourceLoc LSquareLoc = consumeToken(tok::l_square);
 
   Parser::StructureMarkerRAII ParsingCollection(
                                 *this, LSquareLoc,
@@ -3324,6 +3280,15 @@
                DictionaryExpr::create(Context, LSquareLoc, {}, {}, RSquareLoc));
   }
 
+  // [#identifier is likely to be a legacy object literal.
+  if (Tok.is(tok::pound) && peekToken().is(tok::identifier) &&
+      !peekToken().isEscapedIdentifier() &&
+      LSquareLoc.getAdvancedLoc(1) == Tok.getLoc() &&
+      Tok.getLoc().getAdvancedLoc(1) == peekToken().getLoc()) {
+    ArrayOrDictContext.setCoerceKind(SyntaxContextKind::Expr);
+    return parseExprPoundUnknown(LSquareLoc);
+  }
+
   bool ParseDict;
   {
     BacktrackingScope Scope(*this);
diff --git a/test/Parse/object_literals.swift b/test/Parse/object_literals.swift
index 9cb7e5a..ca00bd6 100644
--- a/test/Parse/object_literals.swift
+++ b/test/Parse/object_literals.swift
@@ -1,6 +1,19 @@
 // RUN: %target-typecheck-verify-swift
 
-let _ = [##] // expected-error{{expected identifier after '#' in object literal expression}} expected-error{{object literal syntax no longer uses '[# ... #]'}} {{9-10=}} {{11-13=}}
-let _ = [#what#] // expected-error{{object literal syntax no longer uses '[# ... #]'}} {{9-10=}} {{15-17=}}
-let _ = [#what()#] // expected-error{{object literal syntax no longer uses '[# ... #]'}} {{9-10=}} {{17-19=}}
-let _ = [#colorLiteral( // expected-error@+1 {{expected expression in list of expressions}}
+let _ = [#Color(colorLiteralRed: red, green: green, blue: blue, alpha: alpha)#] // expected-error {{'[#Color(...)#]' has been renamed to '#colorLiteral(...)}} {{9-10=}} {{11-16=colorLiteral}} {{17-32=red}} {{78-80=}}
+let _ = [#Image(imageLiteral: localResourceNameAsString)#] // expected-error {{'[#Image(...)#]' has been renamed to '#imageLiteral(...)'}} {{9-10=}} {{11-16=imageLiteral}} {{17-29=resourceName}} {{57-59=}}
+let _ = [#FileReference(fileReferenceLiteral: localResourceNameAsString)#] // expected-error {{'[#FileReference(...)#]' has been renamed to '#fileLiteral(...)'}} {{9-10=}} {{11-24=fileLiteral}} {{25-45=resourceName}} {{73-75=}}
+
+let _ = #Color(colorLiteralRed: red, green: green, blue: blue, alpha: alpha) // expected-error {{'#Color(...)' has been renamed to '#colorLiteral(...)}} {{10-15=colorLiteral}} {{16-31=red}}
+let _ = #Image(imageLiteral: localResourceNameAsString) // expected-error {{'#Image(...)' has been renamed to '#imageLiteral(...)'}} {{10-15=imageLiteral}} {{16-28=resourceName}}
+let _ = #FileReference(fileReferenceLiteral: localResourceNameAsString) // expected-error {{'#FileReference(...)' has been renamed to '#fileLiteral(...)'}} {{10-23=fileLiteral}} {{24-44=resourceName}}
+
+let _ = #notAPound // expected-error {{use of unknown directive '#notAPound'}}
+let _ = #notAPound(1, 2) // expected-error {{use of unknown directive '#notAPound'}}
+let _ = #Color // expected-error {{expected argument list in object literal}} {{none}}
+
+let _ = [##] // expected-error {{expected expression in container literal}} {{none}}
+let _ = [#Color(_: 1, green: 1, 2) // expected-error {{'[#Color(...)#]' has been renamed to '#colorLiteral(...)'}} {{9-10=}} {{11-16=colorLiteral}} {{17-18=red}}
+let _ = [#Color(red: 1, green: 1, blue: 1)# // expected-error {{'[#Color(...)#]' has been renamed to '#colorLiteral(...)'}} {{9-10=}} {{11-16=colorLiteral}} {{17-20=red}} {{43-44=}} 
+let _ = [#Color(withRed: 1, green: 1, whatever: 2)#] // expected-error {{'[#Color(...)#]' has been renamed to '#colorLiteral(...)'}} {{9-10=}} {{11-16=colorLiteral}} {{17-24=red}} {{51-53=}}
+let _ = #Color(_: 1, green: 1) // expected-error {{'#Color(...)' has been renamed to '#colorLiteral(...)'}} {{10-15=colorLiteral}} {{16-17=red}}
diff --git a/test/expr/postfix/keypath/keypath-objc.swift b/test/expr/postfix/keypath/keypath-objc.swift
index 24867a8..c130cfa 100644
--- a/test/expr/postfix/keypath/keypath-objc.swift
+++ b/test/expr/postfix/keypath/keypath-objc.swift
@@ -112,6 +112,7 @@
 
   let dict: [String: Int] = [:]
   let _: Int? = dict[#keyPath(A.propB)]
+  let _ = [#keyPath(A.propB)]
 }
 
 func testAsStaticString() {
diff --git a/test/expr/unary/selector/selector.swift b/test/expr/unary/selector/selector.swift
index 7b7a468..6f488c2 100644
--- a/test/expr/unary/selector/selector.swift
+++ b/test/expr/unary/selector/selector.swift
@@ -86,6 +86,7 @@
 
   let dict: [Selector: Int] = [:]
   let _: Int? = dict[#selector(c1.method1)]
+  let _ = [#selector(c1.method1)]
 }
 
 func testAmbiguity() {