Update aosp/master Clang for rebase to r222490.

Change-Id: Ic557ac55e97fbf6ee08771c7b7c3594777b0aefd
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index 2b248cc..473be54 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -12,6 +12,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "RAIIObjectsForParser.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/TargetInfo.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Parse/ParseDiagnostic.h"
 #include "clang/Parse/Parser.h"
@@ -148,6 +150,12 @@
                     Token &FirstToken) override;
 };
 
+struct PragmaUnrollHintHandler : public PragmaHandler {
+  PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
+  void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+                    Token &FirstToken) override;
+};
+
 }  // end namespace
 
 void Parser::initializePragmaHandlers() {
@@ -218,6 +226,12 @@
 
   LoopHintHandler.reset(new PragmaLoopHintHandler());
   PP.AddPragmaHandler("clang", LoopHintHandler.get());
+
+  UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
+  PP.AddPragmaHandler(UnrollHintHandler.get());
+
+  NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
+  PP.AddPragmaHandler(NoUnrollHintHandler.get());
 }
 
 void Parser::resetPragmaHandlers() {
@@ -278,6 +292,12 @@
 
   PP.RemovePragmaHandler("clang", LoopHintHandler.get());
   LoopHintHandler.reset();
+
+  PP.RemovePragmaHandler(UnrollHintHandler.get());
+  UnrollHintHandler.reset();
+
+  PP.RemovePragmaHandler(NoUnrollHintHandler.get());
+  NoUnrollHintHandler.reset();
 }
 
 /// \brief Handle the annotation token produced for #pragma unused(...)
@@ -467,11 +487,12 @@
   PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
   SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
   assert(Tok.isAnyIdentifier());
-  llvm::StringRef PragmaName = Tok.getIdentifierInfo()->getName();
+  StringRef PragmaName = Tok.getIdentifierInfo()->getName();
   PP.Lex(Tok); // pragma kind
+
   // Figure out which #pragma we're dealing with.  The switch has no default
   // because lex shouldn't emit the annotation token for unrecognized pragmas.
-  typedef unsigned (Parser::*PragmaHandler)(llvm::StringRef, SourceLocation);
+  typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
   PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
     .Case("data_seg", &Parser::HandlePragmaMSSegment)
     .Case("bss_seg", &Parser::HandlePragmaMSSegment)
@@ -479,79 +500,118 @@
     .Case("code_seg", &Parser::HandlePragmaMSSegment)
     .Case("section", &Parser::HandlePragmaMSSection)
     .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
-  if (auto DiagID = (this->*Handler)(PragmaName, PragmaLocation)) {
-    PP.Diag(PragmaLocation, DiagID) << PragmaName;
+
+  if (!(this->*Handler)(PragmaName, PragmaLocation)) {
+    // Pragma handling failed, and has been diagnosed.  Slurp up the tokens
+    // until eof (really end of line) to prevent follow-on errors.
     while (Tok.isNot(tok::eof))
       PP.Lex(Tok);
     PP.Lex(Tok);
   }
 }
 
-unsigned Parser::HandlePragmaMSSection(llvm::StringRef PragmaName,
-                                       SourceLocation PragmaLocation) {
-  if (Tok.isNot(tok::l_paren))
-    return diag::warn_pragma_expected_lparen;
+bool Parser::HandlePragmaMSSection(StringRef PragmaName,
+                                   SourceLocation PragmaLocation) {
+  if (Tok.isNot(tok::l_paren)) {
+    PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
+    return false;
+  }
   PP.Lex(Tok); // (
   // Parsing code for pragma section
-  if (Tok.isNot(tok::string_literal))
-    return diag::warn_pragma_expected_section_name;
-  StringLiteral *SegmentName =
-    cast<StringLiteral>(ParseStringLiteralExpression().get());
-  int SectionFlags = 0;
+  if (Tok.isNot(tok::string_literal)) {
+    PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
+        << PragmaName;
+    return false;
+  }
+  ExprResult StringResult = ParseStringLiteralExpression();
+  if (StringResult.isInvalid())
+    return false; // Already diagnosed.
+  StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
+  if (SegmentName->getCharByteWidth() != 1) {
+    PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
+        << PragmaName;
+    return false;
+  }
+  int SectionFlags = ASTContext::PSF_Read;
+  bool SectionFlagsAreDefault = true;
   while (Tok.is(tok::comma)) {
     PP.Lex(Tok); // ,
-    if (!Tok.isAnyIdentifier())
-      return diag::warn_pragma_expected_action_or_r_paren;
-    Sema::PragmaSectionFlag Flag =
-      llvm::StringSwitch<Sema::PragmaSectionFlag>(
+    // Ignore "long" and "short".
+    // They are undocumented, but widely used, section attributes which appear
+    // to do nothing.
+    if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
+      PP.Lex(Tok); // long/short
+      continue;
+    }
+
+    if (!Tok.isAnyIdentifier()) {
+      PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
+          << PragmaName;
+      return false;
+    }
+    ASTContext::PragmaSectionFlag Flag =
+      llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
       Tok.getIdentifierInfo()->getName())
-      .Case("read", Sema::PSF_Read)
-      .Case("write", Sema::PSF_Write)
-      .Case("execute", Sema::PSF_Execute)
-      .Case("shared", Sema::PSF_Invalid)
-      .Case("nopage", Sema::PSF_Invalid)
-      .Case("nocache", Sema::PSF_Invalid)
-      .Case("discard", Sema::PSF_Invalid)
-      .Case("remove", Sema::PSF_Invalid)
-      .Default(Sema::PSF_None);
-    if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) {
-      PP.Diag(PragmaLocation, Flag == Sema::PSF_None ?
-                              diag::warn_pragma_invalid_specific_action :
-                              diag::warn_pragma_unsupported_action)
+      .Case("read", ASTContext::PSF_Read)
+      .Case("write", ASTContext::PSF_Write)
+      .Case("execute", ASTContext::PSF_Execute)
+      .Case("shared", ASTContext::PSF_Invalid)
+      .Case("nopage", ASTContext::PSF_Invalid)
+      .Case("nocache", ASTContext::PSF_Invalid)
+      .Case("discard", ASTContext::PSF_Invalid)
+      .Case("remove", ASTContext::PSF_Invalid)
+      .Default(ASTContext::PSF_None);
+    if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
+      PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
+                                  ? diag::warn_pragma_invalid_specific_action
+                                  : diag::warn_pragma_unsupported_action)
           << PragmaName << Tok.getIdentifierInfo()->getName();
-      while (Tok.isNot(tok::eof))
-        PP.Lex(Tok);
-      PP.Lex(Tok);
-      return 0;
+      return false;
     }
     SectionFlags |= Flag;
+    SectionFlagsAreDefault = false;
     PP.Lex(Tok); // Identifier
   }
-  if (Tok.isNot(tok::r_paren))
-    return diag::warn_pragma_expected_rparen;
+  // If no section attributes are specified, the section will be marked as
+  // read/write.
+  if (SectionFlagsAreDefault)
+    SectionFlags |= ASTContext::PSF_Write;
+  if (Tok.isNot(tok::r_paren)) {
+    PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
+    return false;
+  }
   PP.Lex(Tok); // )
-  if (Tok.isNot(tok::eof))
-    return diag::warn_pragma_extra_tokens_at_eol;
+  if (Tok.isNot(tok::eof)) {
+    PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
+        << PragmaName;
+    return false;
+  }
   PP.Lex(Tok); // eof
   Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
-  return 0;
+  return true;
 }
 
-unsigned Parser::HandlePragmaMSSegment(llvm::StringRef PragmaName,
-                                      SourceLocation PragmaLocation) {
-  if (Tok.isNot(tok::l_paren))
-    return diag::warn_pragma_expected_lparen;
+bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
+                                   SourceLocation PragmaLocation) {
+  if (Tok.isNot(tok::l_paren)) {
+    PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
+    return false;
+  }
   PP.Lex(Tok); // (
   Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
-  llvm::StringRef SlotLabel;
+  StringRef SlotLabel;
   if (Tok.isAnyIdentifier()) {
-    llvm::StringRef PushPop = Tok.getIdentifierInfo()->getName();
+    StringRef PushPop = Tok.getIdentifierInfo()->getName();
     if (PushPop == "push")
       Action = Sema::PSK_Push;
     else if (PushPop == "pop")
       Action = Sema::PSK_Pop;
-    else
-      return diag::warn_pragma_expected_section_push_pop_or_name;
+    else {
+      PP.Diag(PragmaLocation,
+              diag::warn_pragma_expected_section_push_pop_or_name)
+          << PragmaName;
+      return false;
+    }
     if (Action != Sema::PSK_Reset) {
       PP.Lex(Tok); // push | pop
       if (Tok.is(tok::comma)) {
@@ -562,75 +622,241 @@
           PP.Lex(Tok); // identifier
           if (Tok.is(tok::comma))
             PP.Lex(Tok);
-          else if (Tok.isNot(tok::r_paren))
-            return diag::warn_pragma_expected_punc;
+          else if (Tok.isNot(tok::r_paren)) {
+            PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
+                << PragmaName;
+            return false;
+          }
         }
-      } else if (Tok.isNot(tok::r_paren))
-        return diag::warn_pragma_expected_punc;
+      } else if (Tok.isNot(tok::r_paren)) {
+        PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
+        return false;
+      }
     }
   }
   // Grab the string literal for our section name.
   StringLiteral *SegmentName = nullptr;
   if (Tok.isNot(tok::r_paren)) {
-    if (Tok.isNot(tok::string_literal))
-      return Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
+    if (Tok.isNot(tok::string_literal)) {
+      unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
           diag::warn_pragma_expected_section_name :
           diag::warn_pragma_expected_section_label_or_name :
           diag::warn_pragma_expected_section_push_pop_or_name;
-    SegmentName = cast<StringLiteral>(ParseStringLiteralExpression().get());
+      PP.Diag(PragmaLocation, DiagID) << PragmaName;
+      return false;
+    }
+    ExprResult StringResult = ParseStringLiteralExpression();
+    if (StringResult.isInvalid())
+      return false; // Already diagnosed.
+    SegmentName = cast<StringLiteral>(StringResult.get());
+    if (SegmentName->getCharByteWidth() != 1) {
+      PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
+          << PragmaName;
+      return false;
+    }
     // Setting section "" has no effect
     if (SegmentName->getLength())
       Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
   }
-  if (Tok.isNot(tok::r_paren))
-    return diag::warn_pragma_expected_rparen;
+  if (Tok.isNot(tok::r_paren)) {
+    PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
+    return false;
+  }
   PP.Lex(Tok); // )
-  if (Tok.isNot(tok::eof))
-    return diag::warn_pragma_extra_tokens_at_eol;
+  if (Tok.isNot(tok::eof)) {
+    PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
+        << PragmaName;
+    return false;
+  }
   PP.Lex(Tok); // eof
   Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
                            SegmentName, PragmaName);
-  return 0;
+  return true;
 }
 
-unsigned Parser::HandlePragmaMSInitSeg(llvm::StringRef PragmaName,
-                                       SourceLocation PragmaLocation) {
-  return PP.getDiagnostics().getCustomDiagID(
-      DiagnosticsEngine::Error, "'#pragma %0' not implemented.");
+// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
+bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
+                                   SourceLocation PragmaLocation) {
+  if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
+    PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
+    return false;
+  }
+
+  if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
+                       PragmaName))
+    return false;
+
+  // Parse either the known section names or the string section name.
+  StringLiteral *SegmentName = nullptr;
+  if (Tok.isAnyIdentifier()) {
+    auto *II = Tok.getIdentifierInfo();
+    StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
+                            .Case("compiler", "\".CRT$XCC\"")
+                            .Case("lib", "\".CRT$XCL\"")
+                            .Case("user", "\".CRT$XCU\"")
+                            .Default("");
+
+    if (!Section.empty()) {
+      // Pretend the user wrote the appropriate string literal here.
+      Token Toks[1];
+      Toks[0].startToken();
+      Toks[0].setKind(tok::string_literal);
+      Toks[0].setLocation(Tok.getLocation());
+      Toks[0].setLiteralData(Section.data());
+      Toks[0].setLength(Section.size());
+      SegmentName =
+          cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
+      PP.Lex(Tok);
+    }
+  } else if (Tok.is(tok::string_literal)) {
+    ExprResult StringResult = ParseStringLiteralExpression();
+    if (StringResult.isInvalid())
+      return false;
+    SegmentName = cast<StringLiteral>(StringResult.get());
+    if (SegmentName->getCharByteWidth() != 1) {
+      PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
+          << PragmaName;
+      return false;
+    }
+    // FIXME: Add support for the '[, func-name]' part of the pragma.
+  }
+
+  if (!SegmentName) {
+    PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
+    return false;
+  }
+
+  if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
+                       PragmaName) ||
+      ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
+                       PragmaName))
+    return false;
+
+  Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
+  return true;
 }
 
 struct PragmaLoopHintInfo {
-  Token Loop;
-  Token Value;
+  Token PragmaName;
   Token Option;
+  Token *Toks;
+  size_t TokSize;
+  PragmaLoopHintInfo() : Toks(nullptr), TokSize(0) {}
 };
 
-LoopHint Parser::HandlePragmaLoopHint() {
+static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
+  std::string PragmaString;
+  if (PragmaName.getIdentifierInfo()->getName() == "loop") {
+    PragmaString = "clang loop ";
+    PragmaString += Option.getIdentifierInfo()->getName();
+  } else {
+    assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
+           "Unexpected pragma name");
+    PragmaString = "unroll";
+  }
+  return PragmaString;
+}
+
+bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
   assert(Tok.is(tok::annot_pragma_loop_hint));
   PragmaLoopHintInfo *Info =
       static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
 
-  LoopHint Hint;
-  Hint.LoopLoc =
-      IdentifierLoc::create(Actions.Context, Info->Loop.getLocation(),
-                            Info->Loop.getIdentifierInfo());
-  Hint.OptionLoc =
-      IdentifierLoc::create(Actions.Context, Info->Option.getLocation(),
-                            Info->Option.getIdentifierInfo());
-  Hint.ValueLoc =
-      IdentifierLoc::create(Actions.Context, Info->Value.getLocation(),
-                            Info->Value.getIdentifierInfo());
-  Hint.Range =
-      SourceRange(Info->Option.getLocation(), Info->Value.getLocation());
+  IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
+  Hint.PragmaNameLoc = IdentifierLoc::create(
+      Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
 
-  // FIXME: We should allow non-type template parameters for the loop hint
-  // value. See bug report #19610
-  if (Info->Value.is(tok::numeric_constant))
-    Hint.ValueExpr = Actions.ActOnNumericConstant(Info->Value).get();
-  else
-    Hint.ValueExpr = nullptr;
+  // It is possible that the loop hint has no option identifier, such as
+  // #pragma unroll(4).
+  IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
+                                   ? Info->Option.getIdentifierInfo()
+                                   : nullptr;
+  Hint.OptionLoc = IdentifierLoc::create(
+      Actions.Context, Info->Option.getLocation(), OptionInfo);
 
-  return Hint;
+  Token *Toks = Info->Toks;
+  size_t TokSize = Info->TokSize;
+
+  // Return a valid hint if pragma unroll or nounroll were specified
+  // without an argument.
+  bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
+  bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
+  if (TokSize == 0 && (PragmaUnroll || PragmaNoUnroll)) {
+    ConsumeToken(); // The annotation token.
+    Hint.Range = Info->PragmaName.getLocation();
+    return true;
+  }
+
+  // The constant expression is always followed by an eof token, which increases
+  // the TokSize by 1.
+  assert(TokSize > 0 &&
+         "PragmaLoopHintInfo::Toks must contain at least one token.");
+
+  // If no option is specified the argument is assumed to be a constant expr.
+  bool StateOption = false;
+  if (OptionInfo) { // Pragma unroll does not specify an option.
+    StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
+                      .Case("vectorize", true)
+                      .Case("interleave", true)
+                      .Case("unroll", true)
+                      .Default(false);
+  }
+
+  // Verify loop hint has an argument.
+  if (Toks[0].is(tok::eof)) {
+    ConsumeToken(); // The annotation token.
+    Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
+        << /*StateArgument=*/StateOption << /*FullKeyword=*/PragmaUnroll;
+    return false;
+  }
+
+  // Validate the argument.
+  if (StateOption) {
+    ConsumeToken(); // The annotation token.
+    bool OptionUnroll = OptionInfo->isStr("unroll");
+    SourceLocation StateLoc = Toks[0].getLocation();
+    IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
+    if (!StateInfo || ((OptionUnroll ? !StateInfo->isStr("full")
+                                     : !StateInfo->isStr("enable")) &&
+                       !StateInfo->isStr("disable"))) {
+      Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
+          << /*FullKeyword=*/OptionUnroll;
+      return false;
+    }
+    if (TokSize > 2)
+      Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+          << PragmaLoopHintString(Info->PragmaName, Info->Option);
+    Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
+  } else {
+    // Enter constant expression including eof terminator into token stream.
+    PP.EnterTokenStream(Toks, TokSize, /*DisableMacroExpansion=*/false,
+                        /*OwnsTokens=*/false);
+    ConsumeToken(); // The annotation token.
+
+    ExprResult R = ParseConstantExpression();
+
+    // Tokens following an error in an ill-formed constant expression will
+    // remain in the token stream and must be removed.
+    if (Tok.isNot(tok::eof)) {
+      Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+          << PragmaLoopHintString(Info->PragmaName, Info->Option);
+      while (Tok.isNot(tok::eof))
+        ConsumeAnyToken();
+    }
+
+    ConsumeToken(); // Consume the constant expression eof terminator.
+
+    if (R.isInvalid() ||
+        Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
+      return false;
+
+    // Argument is a constant expression with an integer type.
+    Hint.ValueExpr = R.get();
+  }
+
+  Hint.Range = SourceRange(Info->PragmaName.getLocation(),
+                           Info->Toks[TokSize - 1].getLocation());
+  return true;
 }
 
 // #pragma GCC visibility comes in two variants:
@@ -1601,7 +1827,8 @@
   Token Tok;
   PP.Lex(Tok);
   if (Tok.is(tok::eod)) {
-    PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_missing_argument);
+    PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
+        << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
     return;
   }
   if (Tok.isNot(tok::identifier)) {
@@ -1630,6 +1857,52 @@
   Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
 }
 
+/// \brief Parses loop or unroll pragma hint value and fills in Info.
+static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
+                               Token Option, bool ValueInParens,
+                               PragmaLoopHintInfo &Info) {
+  SmallVector<Token, 1> ValueList;
+  int OpenParens = ValueInParens ? 1 : 0;
+  // Read constant expression.
+  while (Tok.isNot(tok::eod)) {
+    if (Tok.is(tok::l_paren))
+      OpenParens++;
+    else if (Tok.is(tok::r_paren)) {
+      OpenParens--;
+      if (OpenParens == 0 && ValueInParens)
+        break;
+    }
+
+    ValueList.push_back(Tok);
+    PP.Lex(Tok);
+  }
+
+  if (ValueInParens) {
+    // Read ')'
+    if (Tok.isNot(tok::r_paren)) {
+      PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
+      return true;
+    }
+    PP.Lex(Tok);
+  }
+
+  Token EOFTok;
+  EOFTok.startToken();
+  EOFTok.setKind(tok::eof);
+  EOFTok.setLocation(Tok.getLocation());
+  ValueList.push_back(EOFTok); // Terminates expression for parsing.
+
+  Token *TokenArray = (Token *)PP.getPreprocessorAllocator().Allocate(
+      ValueList.size() * sizeof(Token), llvm::alignOf<Token>());
+  std::copy(ValueList.begin(), ValueList.end(), TokenArray);
+  Info.Toks = TokenArray;
+  Info.TokSize = ValueList.size();
+
+  Info.PragmaName = PragmaName;
+  Info.Option = Option;
+  return false;
+}
+
 /// \brief Handle the \#pragma clang loop directive.
 ///  #pragma clang 'loop' loop-hints
 ///
@@ -1639,7 +1912,7 @@
 ///  loop-hint:
 ///    'vectorize' '(' loop-hint-keyword ')'
 ///    'interleave' '(' loop-hint-keyword ')'
-///    'unroll' '(' loop-hint-keyword ')'
+///    'unroll' '(' unroll-hint-keyword ')'
 ///    'vectorize_width' '(' loop-hint-value ')'
 ///    'interleave_count' '(' loop-hint-value ')'
 ///    'unroll_count' '(' loop-hint-value ')'
@@ -1648,6 +1921,10 @@
 ///    'enable'
 ///    'disable'
 ///
+///  unroll-hint-keyword:
+///    'full'
+///    'disable'
+///
 ///  loop-hint-value:
 ///    constant-expression
 ///
@@ -1662,16 +1939,15 @@
 /// only works on inner loops.
 ///
 /// The unroll and unroll_count directives control the concatenation
-/// unroller. Specifying unroll(enable) instructs llvm to try to
+/// unroller. Specifying unroll(full) instructs llvm to try to
 /// unroll the loop completely, and unroll(disable) disables unrolling
 /// for the loop. Specifying unroll_count(_value_) instructs llvm to
 /// try to unroll the loop the number of times indicated by the value.
-/// If unroll(enable) and unroll_count are both specified only
-/// unroll_count takes effect.
 void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
                                          PragmaIntroducerKind Introducer,
                                          Token &Tok) {
-  Token Loop = Tok;
+  // Incoming token is "loop" from "#pragma clang loop".
+  Token PragmaName = Tok;
   SmallVector<Token, 1> TokenList;
 
   // Lex the optimization option and verify it is an identifier.
@@ -1687,57 +1963,37 @@
     IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
 
     bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
-        .Case("vectorize", true)
-        .Case("interleave", true)
-        .Case("unroll", true)
-        .Case("vectorize_width", true)
-        .Case("interleave_count", true)
-        .Case("unroll_count", true)
-        .Default(false);
+                           .Case("vectorize", true)
+                           .Case("interleave", true)
+                           .Case("unroll", true)
+                           .Case("vectorize_width", true)
+                           .Case("interleave_count", true)
+                           .Case("unroll_count", true)
+                           .Default(false);
     if (!OptionValid) {
       PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
           << /*MissingOption=*/false << OptionInfo;
       return;
     }
+    PP.Lex(Tok);
 
     // Read '('
-    PP.Lex(Tok);
     if (Tok.isNot(tok::l_paren)) {
       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
       return;
     }
-
-    // FIXME: All tokens between '(' and ')' should be stored and parsed as a
-    // constant expression.
-    PP.Lex(Tok);
-    if (Tok.is(tok::r_paren)) {
-      // Nothing between the parentheses.
-      PP.Diag(Tok.getLocation(), diag::err_pragma_loop_missing_argument)
-          << OptionInfo;
-      return;
-    }
-    Token Value = Tok;
-
-    // Read ')'
-    PP.Lex(Tok);
-    if (Tok.isNot(tok::r_paren)) {
-      PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
-      return;
-    }
-
-    // Get next optimization option.
     PP.Lex(Tok);
 
     auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
-    Info->Loop = Loop;
-    Info->Option = Option;
-    Info->Value = Value;
+    if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
+                           *Info))
+      return;
 
-    // Generate the vectorization hint token.
+    // Generate the loop hint token.
     Token LoopHintTok;
     LoopHintTok.startToken();
     LoopHintTok.setKind(tok::annot_pragma_loop_hint);
-    LoopHintTok.setLocation(Loop.getLocation());
+    LoopHintTok.setLocation(PragmaName.getLocation());
     LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
     TokenList.push_back(LoopHintTok);
   }
@@ -1755,3 +2011,72 @@
                       /*DisableMacroExpansion=*/false,
                       /*OwnsTokens=*/true);
 }
+
+/// \brief Handle the loop unroll optimization pragmas.
+///  #pragma unroll
+///  #pragma unroll unroll-hint-value
+///  #pragma unroll '(' unroll-hint-value ')'
+///  #pragma nounroll
+///
+///  unroll-hint-value:
+///    constant-expression
+///
+/// Loop unrolling hints can be specified with '#pragma unroll' or
+/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
+/// contained in parentheses. With no argument the directive instructs llvm to
+/// try to unroll the loop completely. A positive integer argument can be
+/// specified to indicate the number of times the loop should be unrolled.  To
+/// maximize compatibility with other compilers the unroll count argument can be
+/// specified with or without parentheses.  Specifying, '#pragma nounroll'
+/// disables unrolling of the loop.
+void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
+                                           PragmaIntroducerKind Introducer,
+                                           Token &Tok) {
+  // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
+  // "#pragma nounroll".
+  Token PragmaName = Tok;
+  PP.Lex(Tok);
+  auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
+  if (Tok.is(tok::eod)) {
+    // nounroll or unroll pragma without an argument.
+    Info->PragmaName = PragmaName;
+    Info->Option.startToken();
+  } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+        << "nounroll";
+    return;
+  } else {
+    // Unroll pragma with an argument: "#pragma unroll N" or
+    // "#pragma unroll(N)".
+    // Read '(' if it exists.
+    bool ValueInParens = Tok.is(tok::l_paren);
+    if (ValueInParens)
+      PP.Lex(Tok);
+
+    Token Option;
+    Option.startToken();
+    if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
+      return;
+
+    // In CUDA, the argument to '#pragma unroll' should not be contained in
+    // parentheses.
+    if (PP.getLangOpts().CUDA && ValueInParens)
+      PP.Diag(Info->Toks[0].getLocation(),
+              diag::warn_pragma_unroll_cuda_value_in_parens);
+
+    if (Tok.isNot(tok::eod)) {
+      PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+          << "unroll";
+      return;
+    }
+  }
+
+  // Generate the hint token.
+  Token *TokenArray = new Token[1];
+  TokenArray[0].startToken();
+  TokenArray[0].setKind(tok::annot_pragma_loop_hint);
+  TokenArray[0].setLocation(PragmaName.getLocation());
+  TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
+  PP.EnterTokenStream(TokenArray, 1, /*DisableMacroExpansion=*/false,
+                      /*OwnsTokens=*/true);
+}