Tyker updated this revision to Diff 193015.
Tyker added a comment.
Herald added a reviewer: martong.
Herald added a reviewer: shafik.

@riccibruno i fixed based on feedback everything except the CFG edit as i still 
need to analyse the situation.

added AST and CodeGen for For, While, Do and CXXFor.
added tests for Semantic, AST, PCH


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59467/new/

https://reviews.llvm.org/D59467

Files:
  clang/include/clang/AST/Stmt.h
  clang/include/clang/AST/StmtCXX.h
  clang/include/clang/AST/TextNodeDumper.h
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Scope.h
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ASTImporter.cpp
  clang/lib/AST/Stmt.cpp
  clang/lib/AST/StmtCXX.cpp
  clang/lib/AST/TextNodeDumper.cpp
  clang/lib/Analysis/CFG.cpp
  clang/lib/CodeGen/CGStmt.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Sema/Scope.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/lib/Sema/TreeTransform.h
  clang/lib/Serialization/ASTReaderStmt.cpp
  clang/lib/Serialization/ASTWriterStmt.cpp
  clang/test/CodeGenCXX/cxx2a-likelihood-attr.cpp
  clang/test/PCH/cxx2a-likelihood-attr.cpp
  clang/test/SemaCXX/cxx17-compat.cpp
  clang/test/SemaCXX/cxx2a-likelihood-attr.cpp

Index: clang/test/SemaCXX/cxx2a-likelihood-attr.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/cxx2a-likelihood-attr.cpp
@@ -0,0 +1,70 @@
+// RUN: %clang_cc1 -fsyntax-only %s -verify -std=c++2a
+
+// formating this file will break the test
+// clang-format off
+
+int f(int);
+
+int f(int i) {
+  if (i == 1)
+    [[unlikely]] { f(i); }
+  else if (i == 2)
+    [[likely]] return f(i);
+  else
+    [[unlikely]] { return f(i + 1); }
+  return i;
+}
+
+[[likely]] typedef int n1;
+// expected-error@-1 {{'likely' attribute cannot be applied to a declaration}}
+typedef int [[likely]] n2;
+// expected-error@-1 {{'likely' attribute cannot be applied to types}}
+typedef int n3 [[likely]];
+// expected-error@-1 {{'likely' attribute cannot be applied to a declaration}}
+
+enum [[likely]] E{One};
+// expected-error@-1 {{'likely' attribute cannot be applied to a declaration}}
+
+[[likely]]
+// expected-error@-1 {{'likely' attribute cannot be applied to a declaration}}
+
+void test(int i) {
+  [[likely]]
+  // expected-warning@-1 {{attribute 'likely' is not associated with a branch and is ignored}}
+  if (f(i)) [[likely, likely]] {
+    // expected-error@-1 {{likely attribute cannot be repeated}}
+    // expected-note@-2 {{previous attribute is here}}
+    [[unlikely]] return;
+    // expected-warning@-1 {{attribute 'unlikely' is not associated with a branch and is ignored}}
+  }
+  else [[unlikely]] if (f(i)) {
+    while (f(i))
+      [[likely]] {
+        switch (i) {
+          [[likely]] case 1 : default : [[likely]];
+          // expected-warning@-1 {{attribute 'likely' is not associated with a branch and is ignored}}
+          [[unlikely]] case 3 : f(i);
+          [[fallthrough]];
+        case 4:
+          return;
+        }
+      }
+    for (;;)
+      [[likely, unlikely]]
+      // expected-error@-1 {{unlikely and likely attributes are not compatible}}
+      // expected-note@-2 {{previous attribute is here}}
+      [[likely]] return;
+    // expected-error@-1 {{likely attribute cannot be repeated}}
+    // expected-note@-5 {{previous attribute is here}}
+  }
+  try { // expected-error {{cannot use 'try' with exceptions disabled}}
+    [[likely]];
+    // expected-warning@-1 {{attribute 'likely' is not associated with a branch and is ignored}}
+  } catch (int) {
+    [[likely]] test :
+        // expected-error@-1 {{'likely' attribute cannot be applied to a declaration}}
+        [[unlikely]] return;
+  }
+}
+
+// clang-format off
Index: clang/test/SemaCXX/cxx17-compat.cpp
===================================================================
--- clang/test/SemaCXX/cxx17-compat.cpp
+++ clang/test/SemaCXX/cxx17-compat.cpp
@@ -56,10 +56,33 @@
 };
 
 void ForRangeInit() {
-  for (int arr[3] = {1, 2, 3}; int n : arr) {}
+  for (int arr[3] = {1, 2, 3}; int n : arr) {
+  }
 #if __cplusplus <= 201703L
-    // expected-warning@-2 {{range-based for loop initialization statements are a C++2a extension}}
+  // expected-warning@-2 {{range-based for loop initialization statements are a
+  // C++2a extension}}
 #else
-    // expected-warning@-4 {{range-based for loop initialization statements are incompatible with C++ standards before C++2a}}
+  // expected-warning@-4 {{range-based for loop initialization statements are
+  // incompatible with C++ standards before C++2a}}
+#endif
+}
+
+int f(int i) {
+  if (i == 1)
+    [[unlikely]]
+#if __cplusplus <= 201703L
+    // expected-warning@-2 {{use of the 'unlikely' attribute is a C++2a
+    // extension}}
+#endif
+    {
+      f(i);
+    }
+  else if (i == 2)
+    [[likely]]
+#if __cplusplus <= 201703L
+    // expected-warning@-2 {{use of the 'likely' attribute is a C++2a
+    // extension}}
 #endif
+    return f(i);
+  return i;
 }
Index: clang/test/PCH/cxx2a-likelihood-attr.cpp
===================================================================
--- /dev/null
+++ clang/test/PCH/cxx2a-likelihood-attr.cpp
@@ -0,0 +1,57 @@
+// Test this without pch.
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only -verify %s -ast-dump | FileCheck %s
+
+// Test with pch. Use '-ast-dump' to force deserialization of function bodies.
+// RUN: %clang_cc1 -x c++-header -std=c++2a -emit-pch -o %t %s
+// RUN: %clang_cc1 -std=c++2a -include-pch %t -fsyntax-only -verify %s
+// -ast-dump-all | FileCheck %s
+
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+void test(int i) {
+  if (i)
+    [[likely]] { return; }
+  else
+    [[unlikely]] if (i) {
+      while (i)
+        [[likely]] {}
+      do {
+        for (; i;)
+          [[likely]] {}
+        [[unlikely]];
+      } while (i);
+    }
+}
+
+#endif
+
+// CHECK:       IfStmt {{.*}} likely
+
+// CHECK:       AttributedStmt
+// CHECK-NEXT:  LikelihoodAttr {{.*}} likely
+
+// CHECK:       AttributedStmt
+// CHECK-NEXT:  LikelihoodAttr {{.*}} unlikely
+// CHECK-NEXT:  IfStmt
+
+// CHECK:       WhileStmt {{.*}} likely
+
+// CHECK:  AttributedStmt
+// CHECK-NEXT:  LikelihoodAttr {{.*}} likely
+
+// CHECk-NEXT:  CompoundStmt
+
+// CHECK:       DoStmt {{.*}} unlikely
+
+// CHECk-NEXT:  CompoundStmt
+
+// CHECk-NEXT:  ForStmt {{.*}} likely
+
+// CHECK:  AttributedStmt
+// CHECK-NEXT:  LikelihoodAttr {{.*}} likely
+
+// CHECK:  AttributedStmt
+// CHECK-NEXT:  LikelihoodAttr {{.*}} unlikely
Index: clang/test/CodeGenCXX/cxx2a-likelihood-attr.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/cxx2a-likelihood-attr.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++2a -cc1 -emit-llvm -disable-llvm-passes -O3 %s -o -
+// -triple %itanium_abi_triple | FileCheck %s
+
+int test(int i) {
+  if (i == 0) {
+  // CHECK:       %expval = call i1 @llvm.expect.i1(i1 %cmp, i1 false)
+  // CHECK-NEXT:  br i1 %expval
+    i = i + 1;
+  } else
+    [[likely]] return 1;
+  while (i == 1)
+    [[unlikely]] { return 2; }
+  // CHECK:       %[[expval:.*]] = call i1 @llvm.expect.i1(i1 %[[cmp:.*]], i1 false)
+  // CHECK-NEXT:  br i1 %expval
+  for (; i == 4;)
+    [[unlikely]] { return 2; }
+  // CHECK:       %[[expval:.*]] = call i1 @llvm.expect.i1(i1 %[[cmp:.*]], i1 false)
+  // CHECK-NEXT:  br i1 %expval
+  do
+    [[likely]] { return 2; }
+  while (i == 3);
+  // CHECK:       %[[expval:.*]] = call i1 @llvm.expect.i1(i1 %[[cmp:.*]], i1 true)
+  // CHECK-NEXT:  br i1 %expval
+  return 0;
+}
Index: clang/lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTWriterStmt.cpp
+++ clang/lib/Serialization/ASTWriterStmt.cpp
@@ -140,6 +140,7 @@
   Record.push_back(HasElse);
   Record.push_back(HasVar);
   Record.push_back(HasInit);
+  Record.push_back(static_cast<uint64_t>(S->getBranchHint()));
 
   Record.AddStmt(S->getCond());
   Record.AddStmt(S->getThen());
@@ -186,6 +187,7 @@
 
   bool HasVar = S->getConditionVariableDeclStmt() != nullptr;
   Record.push_back(HasVar);
+  Record.push_back(static_cast<uint64_t>(S->getBranchHint()));
 
   Record.AddStmt(S->getCond());
   Record.AddStmt(S->getBody());
@@ -203,6 +205,7 @@
   Record.AddSourceLocation(S->getDoLoc());
   Record.AddSourceLocation(S->getWhileLoc());
   Record.AddSourceLocation(S->getRParenLoc());
+  Record.push_back(static_cast<uint64_t>(S->getBranchHint()));
   Code = serialization::STMT_DO;
 }
 
@@ -216,6 +219,7 @@
   Record.AddSourceLocation(S->getForLoc());
   Record.AddSourceLocation(S->getLParenLoc());
   Record.AddSourceLocation(S->getRParenLoc());
+  Record.push_back(static_cast<uint64_t>(S->getBranchHint()));
   Code = serialization::STMT_FOR;
 }
 
@@ -1287,6 +1291,7 @@
 
 void ASTStmtWriter::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
   VisitStmt(S);
+  Record.push_back(static_cast<uint64_t>(S->getBranchHint()));
   Record.AddSourceLocation(S->getForLoc());
   Record.AddSourceLocation(S->getCoawaitLoc());
   Record.AddSourceLocation(S->getColonLoc());
Index: clang/lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderStmt.cpp
+++ clang/lib/Serialization/ASTReaderStmt.cpp
@@ -223,6 +223,7 @@
   bool HasElse = Record.readInt();
   bool HasVar = Record.readInt();
   bool HasInit = Record.readInt();
+  S->setBranchHint(static_cast<BranchHint>(Record.readInt()));
 
   S->setCond(Record.readSubExpr());
   S->setThen(Record.readSubStmt());
@@ -272,6 +273,7 @@
   VisitStmt(S);
 
   bool HasVar = Record.readInt();
+  S->setBranchHint(static_cast<BranchHint>(Record.readInt()));
 
   S->setCond(Record.readSubExpr());
   S->setBody(Record.readSubStmt());
@@ -288,6 +290,7 @@
   S->setDoLoc(ReadSourceLocation());
   S->setWhileLoc(ReadSourceLocation());
   S->setRParenLoc(ReadSourceLocation());
+  S->setBranchHint(static_cast<BranchHint>(Record.readInt()));
 }
 
 void ASTStmtReader::VisitForStmt(ForStmt *S) {
@@ -300,6 +303,7 @@
   S->setForLoc(ReadSourceLocation());
   S->setLParenLoc(ReadSourceLocation());
   S->setRParenLoc(ReadSourceLocation());
+  S->setBranchHint(static_cast<BranchHint>(Record.readInt()));
 }
 
 void ASTStmtReader::VisitGotoStmt(GotoStmt *S) {
@@ -1324,6 +1328,7 @@
 
 void ASTStmtReader::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
   VisitStmt(S);
+  S->setBranchHint(static_cast<BranchHint>(Record.readInt()));
   S->ForLoc = ReadSourceLocation();
   S->CoawaitLoc = ReadSourceLocation();
   S->ColonLoc = ReadSourceLocation();
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -1264,9 +1264,10 @@
   /// Subclasses may override this routine to provide different behavior.
   StmtResult RebuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
                            Sema::ConditionResult Cond, Stmt *Init, Stmt *Then,
-                           SourceLocation ElseLoc, Stmt *Else) {
-    return getSema().ActOnIfStmt(IfLoc, IsConstexpr, Init, Cond, Then,
-                                 ElseLoc, Else);
+                           SourceLocation ElseLoc, Stmt *Else,
+                           BranchHint Hint) {
+    return getSema().ActOnIfStmt(IfLoc, IsConstexpr, Init, Cond, Then, ElseLoc,
+                                 Else, Hint);
   }
 
   /// Start building a new switch statement.
@@ -1292,8 +1293,9 @@
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
   StmtResult RebuildWhileStmt(SourceLocation WhileLoc,
-                              Sema::ConditionResult Cond, Stmt *Body) {
-    return getSema().ActOnWhileStmt(WhileLoc, Cond, Body);
+                              Sema::ConditionResult Cond, Stmt *Body,
+                              BranchHint Hint) {
+    return getSema().ActOnWhileStmt(WhileLoc, Cond, Body, Hint);
   }
 
   /// Build a new do-while statement.
@@ -1302,9 +1304,10 @@
   /// Subclasses may override this routine to provide different behavior.
   StmtResult RebuildDoStmt(SourceLocation DoLoc, Stmt *Body,
                            SourceLocation WhileLoc, SourceLocation LParenLoc,
-                           Expr *Cond, SourceLocation RParenLoc) {
-    return getSema().ActOnDoStmt(DoLoc, Body, WhileLoc, LParenLoc,
-                                 Cond, RParenLoc);
+                           Expr *Cond, SourceLocation RParenLoc,
+                           BranchHint Hint) {
+    return getSema().ActOnDoStmt(DoLoc, Body, WhileLoc, LParenLoc, Cond,
+                                 RParenLoc, Hint);
   }
 
   /// Build a new for statement.
@@ -1314,9 +1317,9 @@
   StmtResult RebuildForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
                             Stmt *Init, Sema::ConditionResult Cond,
                             Sema::FullExprArg Inc, SourceLocation RParenLoc,
-                            Stmt *Body) {
-    return getSema().ActOnForStmt(ForLoc, LParenLoc, Init, Cond,
-                                  Inc, RParenLoc, Body);
+                            Stmt *Body, BranchHint Hint) {
+    return getSema().ActOnForStmt(ForLoc, LParenLoc, Init, Cond, Inc, RParenLoc,
+                                  Body, Hint);
   }
 
   /// Build a new goto statement.
@@ -2102,8 +2105,9 @@
   ///
   /// By default, performs semantic analysis to finish the new statement.
   /// Subclasses may override this routine to provide different behavior.
-  StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body) {
-    return getSema().FinishCXXForRangeStmt(ForRange, Body);
+  StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body,
+                                   BranchHint Hint) {
+    return getSema().FinishCXXForRangeStmt(ForRange, Body, Hint);
   }
 
   StmtResult RebuildSEHTryStmt(bool IsCXXTry, SourceLocation TryLoc,
@@ -6755,12 +6759,11 @@
 
   return getDerived().RebuildIfStmt(S->getIfLoc(), S->isConstexpr(), Cond,
                                     Init.get(), Then.get(), S->getElseLoc(),
-                                    Else.get());
+                                    Else.get(), S->getBranchHint());
 }
 
-template<typename Derived>
-StmtResult
-TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) {
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) {
   // Transform the initialization statement
   StmtResult Init = getDerived().TransformStmt(S->getInit());
   if (Init.isInvalid())
@@ -6809,12 +6812,12 @@
       Body.get() == S->getBody())
     return Owned(S);
 
-  return getDerived().RebuildWhileStmt(S->getWhileLoc(), Cond, Body.get());
+  return getDerived().RebuildWhileStmt(S->getWhileLoc(), Cond, Body.get(),
+                                       S->getBranchHint());
 }
 
-template<typename Derived>
-StmtResult
-TreeTransform<Derived>::TransformDoStmt(DoStmt *S) {
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformDoStmt(DoStmt *S) {
   // Transform the body
   StmtResult Body = getDerived().TransformStmt(S->getBody());
   if (Body.isInvalid())
@@ -6831,13 +6834,12 @@
     return S;
 
   return getDerived().RebuildDoStmt(S->getDoLoc(), Body.get(), S->getWhileLoc(),
-                                    /*FIXME:*/S->getWhileLoc(), Cond.get(),
-                                    S->getRParenLoc());
+                                    /*FIXME:*/ S->getWhileLoc(), Cond.get(),
+                                    S->getRParenLoc(), S->getBranchHint());
 }
 
-template<typename Derived>
-StmtResult
-TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
   if (getSema().getLangOpts().OpenMP)
     getSema().startOpenMPLoop();
 
@@ -6872,23 +6874,20 @@
   if (Body.isInvalid())
     return StmtError();
 
-  if (!getDerived().AlwaysRebuild() &&
-      Init.get() == S->getInit() &&
+  if (!getDerived().AlwaysRebuild() && Init.get() == S->getInit() &&
       Cond.get() == std::make_pair(S->getConditionVariable(), S->getCond()) &&
-      Inc.get() == S->getInc() &&
-      Body.get() == S->getBody())
+      Inc.get() == S->getInc() && Body.get() == S->getBody())
     return S;
 
-  return getDerived().RebuildForStmt(S->getForLoc(), S->getLParenLoc(),
-                                     Init.get(), Cond, FullInc,
-                                     S->getRParenLoc(), Body.get());
+  return getDerived().RebuildForStmt(
+      S->getForLoc(), S->getLParenLoc(), Init.get(), Cond, FullInc,
+      S->getRParenLoc(), Body.get(), S->getBranchHint());
 }
 
-template<typename Derived>
-StmtResult
-TreeTransform<Derived>::TransformGotoStmt(GotoStmt *S) {
-  Decl *LD = getDerived().TransformDecl(S->getLabel()->getLocation(),
-                                        S->getLabel());
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformGotoStmt(GotoStmt *S) {
+  Decl *LD =
+      getDerived().TransformDecl(S->getLabel()->getLocation(), S->getLabel());
   if (!LD)
     return StmtError();
 
@@ -7567,13 +7566,12 @@
   if (NewStmt.get() == S)
     return S;
 
-  return FinishCXXForRangeStmt(NewStmt.get(), Body.get());
+  return FinishCXXForRangeStmt(NewStmt.get(), Body.get(), S->getBranchHint());
 }
 
-template<typename Derived>
-StmtResult
-TreeTransform<Derived>::TransformMSDependentExistsStmt(
-                                                    MSDependentExistsStmt *S) {
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformMSDependentExistsStmt(
+    MSDependentExistsStmt *S) {
   // Transform the nested-name-specifier, if any.
   NestedNameSpecifierLoc QualifierLoc;
   if (S->getQualifierLoc()) {
Index: clang/lib/Sema/SemaStmtAttr.cpp
===================================================================
--- clang/lib/Sema/SemaStmtAttr.cpp
+++ clang/lib/Sema/SemaStmtAttr.cpp
@@ -51,6 +51,58 @@
   return ::new (S.Context) auto(Attr);
 }
 
+static Attr *handleLikelihoodAttr(Sema &S, Stmt *St, const ParsedAttr &A,
+                                  SourceRange Range) {
+  LikelihoodAttr *Attr = ::new (S.Context) LikelihoodAttr(
+      A.getRange(), S.Context, A.getAttributeSpellingListIndex());
+
+  if (!S.getLangOpts().CPlusPlus2a && A.isCXX11Attribute())
+    S.Diag(A.getLoc(), diag::ext_cxx2a_attr) << A.getName();
+
+  // Handle attribute on case/default statement.
+  if (isa<CaseStmt>(St) || isa<DefaultStmt>(St)) {
+    FunctionScopeInfo *FnScope = S.getCurFunction();
+    if (FnScope->SwitchStack.empty()) {
+      S.Diag(A.getLoc(), diag::warn_likelihood_on_case_outside_switch)
+          << Attr->getSpelling() << (isa<CaseStmt>(St) ? "case" : "default");
+    }
+    return Attr;
+  }
+
+  // Handle attribute on If/For/while/Do/Catch statements.
+  Scope *CurScope = S.getCurScope();
+  if (CurScope) {
+    Scope *ControlScope = CurScope->getParent();
+    if (!ControlScope ||
+        !(ControlScope->getFlags() & Scope::ControlScope ||
+          ControlScope->getFlags() & Scope::BreakScope) ||
+        ControlScope->getFlags() & Scope::SwitchScope ||
+        ControlScope->getFlags() & Scope::SEHExceptScope ||
+        ControlScope->getFlags() & Scope::SEHTryScope ||
+        ControlScope->getFlags() & Scope::TryScope ||
+        ControlScope->getFlags() & Scope::FnTryCatchScope) {
+      S.Diag(A.getLoc(), diag::warn_no_likelihood_attr_associated_branch)
+          << A.getName();
+      return Attr;
+    }
+
+    if (ControlScope->getBranchLikelihoodAttr()) {
+      if (ControlScope->getBranchLikelihoodAttr()->getSpelling()[0] ==
+          Attr->getSpelling()[0])
+        S.Diag(Attr->getLocation(), diag::err_repeat_attribute)
+            << Attr->getSpelling();
+      else
+        S.Diag(Attr->getLocation(), diag::err_attributes_are_not_compatible)
+            << Attr->getSpelling()
+            << ControlScope->getBranchLikelihoodAttr()->getSpelling();
+      S.Diag(ControlScope->getBranchLikelihoodAttr()->getLocation(),
+             diag::note_previous_attribute);
+    } else
+      ControlScope->setBranchLikelihoodAttr(Attr);
+  }
+  return Attr;
+}
+
 static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A,
                                 SourceRange Range) {
   if (A.getNumArgs() < 1) {
@@ -336,6 +388,8 @@
     return nullptr;
   case ParsedAttr::AT_FallThrough:
     return handleFallThroughAttr(S, St, A, Range);
+  case ParsedAttr::AT_Likelihood:
+    return handleLikelihoodAttr(S, St, A, Range);
   case ParsedAttr::AT_LoopHint:
     return handleLoopHintAttr(S, St, A, Range);
   case ParsedAttr::AT_OpenCLUnrollHint:
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -519,13 +519,31 @@
     EvaluatedExprVisitor<CommaVisitor>::VisitBinaryOperator(E);
   }
 };
+} // namespace
+
+BranchHint Sema::HandleIfStmtHint(LikelihoodAttr *ThenLikelihoodAttr,
+                                  LikelihoodAttr *ElseLikelihoodAttr) {
+  if (ThenLikelihoodAttr) {
+    if (ElseLikelihoodAttr && ThenLikelihoodAttr->isEqual(ElseLikelihoodAttr)) {
+      Diag(ElseLikelihoodAttr->getLocation(),
+           diag::warn_conflicting_likelihood_attrs)
+          << ElseLikelihoodAttr->getSpelling()
+          << ThenLikelihoodAttr->getSpelling();
+      Diag(ThenLikelihoodAttr->getLocation(), diag::note_conflicting_attribute);
+    } else
+      return (ThenLikelihoodAttr->isLikely() ? BranchHint::BH_Taken
+                                             : BranchHint::BH_NotTaken);
+  } else if (ElseLikelihoodAttr) {
+    return (ElseLikelihoodAttr->isUnlikely() ? BranchHint::BH_Taken
+                                             : BranchHint::BH_NotTaken);
+  }
+  return BranchHint::BH_NoHint;
 }
 
-StmtResult
-Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt,
-                  ConditionResult Cond,
-                  Stmt *thenStmt, SourceLocation ElseLoc,
-                  Stmt *elseStmt) {
+StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr,
+                             Stmt *InitStmt, ConditionResult Cond,
+                             Stmt *thenStmt, SourceLocation ElseLoc,
+                             Stmt *elseStmt, BranchHint Hint) {
   if (Cond.isInvalid())
     Cond = ConditionResult(
         *this, nullptr,
@@ -545,13 +563,13 @@
                           diag::warn_empty_if_body);
 
   return BuildIfStmt(IfLoc, IsConstexpr, InitStmt, Cond, thenStmt, ElseLoc,
-                     elseStmt);
+                     elseStmt, Hint);
 }
 
 StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
                              Stmt *InitStmt, ConditionResult Cond,
                              Stmt *thenStmt, SourceLocation ElseLoc,
-                             Stmt *elseStmt) {
+                             Stmt *elseStmt, BranchHint Hint) {
   if (Cond.isInvalid())
     return StmtError();
 
@@ -559,25 +577,25 @@
     setFunctionHasBranchProtectedScope();
 
   return IfStmt::Create(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first,
-                        Cond.get().second, thenStmt, ElseLoc, elseStmt);
+                        Cond.get().second, thenStmt, ElseLoc, elseStmt, Hint);
 }
 
 namespace {
-  struct CaseCompareFunctor {
-    bool operator()(const std::pair<llvm::APSInt, CaseStmt*> &LHS,
-                    const llvm::APSInt &RHS) {
-      return LHS.first < RHS;
-    }
-    bool operator()(const std::pair<llvm::APSInt, CaseStmt*> &LHS,
-                    const std::pair<llvm::APSInt, CaseStmt*> &RHS) {
-      return LHS.first < RHS.first;
-    }
-    bool operator()(const llvm::APSInt &LHS,
-                    const std::pair<llvm::APSInt, CaseStmt*> &RHS) {
-      return LHS < RHS.first;
-    }
-  };
-}
+struct CaseCompareFunctor {
+  bool operator()(const std::pair<llvm::APSInt, CaseStmt *> &LHS,
+                  const llvm::APSInt &RHS) {
+    return LHS.first < RHS;
+  }
+  bool operator()(const std::pair<llvm::APSInt, CaseStmt *> &LHS,
+                  const std::pair<llvm::APSInt, CaseStmt *> &RHS) {
+    return LHS.first < RHS.first;
+  }
+  bool operator()(const llvm::APSInt &LHS,
+                  const std::pair<llvm::APSInt, CaseStmt *> &RHS) {
+    return LHS < RHS.first;
+  }
+};
+} // namespace
 
 /// CmpCaseVals - Comparison predicate for sorting case values.
 ///
@@ -1274,7 +1292,7 @@
 }
 
 StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond,
-                                Stmt *Body) {
+                                Stmt *Body, BranchHint Hint) {
   if (Cond.isInvalid())
     return StmtError();
 
@@ -1289,13 +1307,13 @@
     getCurCompoundScope().setHasEmptyLoopBodies();
 
   return WhileStmt::Create(Context, CondVal.first, CondVal.second, Body,
-                           WhileLoc);
+                           WhileLoc, Hint);
 }
 
-StmtResult
-Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
-                  SourceLocation WhileLoc, SourceLocation CondLParen,
-                  Expr *Cond, SourceLocation CondRParen) {
+StmtResult Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
+                             SourceLocation WhileLoc, SourceLocation CondLParen,
+                             Expr *Cond, SourceLocation CondRParen,
+                             BranchHint Hint) {
   assert(Cond && "ActOnDoStmt(): missing expression");
 
   CheckBreakContinueBinding(Cond);
@@ -1314,178 +1332,163 @@
       !Diags.isIgnored(diag::warn_comma_operator, Cond->getExprLoc()))
     CommaVisitor(*this).Visit(Cond);
 
-  return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen);
+  return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen, Hint);
 }
 
 namespace {
-  // Use SetVector since the diagnostic cares about the ordering of the Decl's.
-  using DeclSetVector =
-      llvm::SetVector<VarDecl *, llvm::SmallVector<VarDecl *, 8>,
-                      llvm::SmallPtrSet<VarDecl *, 8>>;
-
-  // This visitor will traverse a conditional statement and store all
-  // the evaluated decls into a vector.  Simple is set to true if none
-  // of the excluded constructs are used.
-  class DeclExtractor : public EvaluatedExprVisitor<DeclExtractor> {
-    DeclSetVector &Decls;
-    SmallVectorImpl<SourceRange> &Ranges;
-    bool Simple;
-  public:
-    typedef EvaluatedExprVisitor<DeclExtractor> Inherited;
-
-    DeclExtractor(Sema &S, DeclSetVector &Decls,
-                  SmallVectorImpl<SourceRange> &Ranges) :
-        Inherited(S.Context),
-        Decls(Decls),
-        Ranges(Ranges),
-        Simple(true) {}
+// Use SetVector since the diagnostic cares about the ordering of the Decl's.
+using DeclSetVector =
+    llvm::SetVector<VarDecl *, llvm::SmallVector<VarDecl *, 8>,
+                    llvm::SmallPtrSet<VarDecl *, 8>>;
+
+// This visitor will traverse a conditional statement and store all
+// the evaluated decls into a vector.  Simple is set to true if none
+// of the excluded constructs are used.
+class DeclExtractor : public EvaluatedExprVisitor<DeclExtractor> {
+  DeclSetVector &Decls;
+  SmallVectorImpl<SourceRange> &Ranges;
+  bool Simple;
 
-    bool isSimple() { return Simple; }
+public:
+  typedef EvaluatedExprVisitor<DeclExtractor> Inherited;
 
-    // Replaces the method in EvaluatedExprVisitor.
-    void VisitMemberExpr(MemberExpr* E) {
-      Simple = false;
-    }
+  DeclExtractor(Sema &S, DeclSetVector &Decls,
+                SmallVectorImpl<SourceRange> &Ranges)
+      : Inherited(S.Context), Decls(Decls), Ranges(Ranges), Simple(true) {}
 
-    // Any Stmt not whitelisted will cause the condition to be marked complex.
-    void VisitStmt(Stmt *S) {
-      Simple = false;
-    }
+  bool isSimple() { return Simple; }
 
-    void VisitBinaryOperator(BinaryOperator *E) {
-      Visit(E->getLHS());
-      Visit(E->getRHS());
-    }
+  // Replaces the method in EvaluatedExprVisitor.
+  void VisitMemberExpr(MemberExpr *E) { Simple = false; }
 
-    void VisitCastExpr(CastExpr *E) {
-      Visit(E->getSubExpr());
-    }
+  // Any Stmt not whitelisted will cause the condition to be marked complex.
+  void VisitStmt(Stmt *S) { Simple = false; }
 
-    void VisitUnaryOperator(UnaryOperator *E) {
-      // Skip checking conditionals with derefernces.
-      if (E->getOpcode() == UO_Deref)
-        Simple = false;
-      else
-        Visit(E->getSubExpr());
-    }
+  void VisitBinaryOperator(BinaryOperator *E) {
+    Visit(E->getLHS());
+    Visit(E->getRHS());
+  }
 
-    void VisitConditionalOperator(ConditionalOperator *E) {
-      Visit(E->getCond());
-      Visit(E->getTrueExpr());
-      Visit(E->getFalseExpr());
-    }
+  void VisitCastExpr(CastExpr *E) { Visit(E->getSubExpr()); }
 
-    void VisitParenExpr(ParenExpr *E) {
+  void VisitUnaryOperator(UnaryOperator *E) {
+    // Skip checking conditionals with derefernces.
+    if (E->getOpcode() == UO_Deref)
+      Simple = false;
+    else
       Visit(E->getSubExpr());
-    }
+  }
 
-    void VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
-      Visit(E->getOpaqueValue()->getSourceExpr());
-      Visit(E->getFalseExpr());
-    }
+  void VisitConditionalOperator(ConditionalOperator *E) {
+    Visit(E->getCond());
+    Visit(E->getTrueExpr());
+    Visit(E->getFalseExpr());
+  }
 
-    void VisitIntegerLiteral(IntegerLiteral *E) { }
-    void VisitFloatingLiteral(FloatingLiteral *E) { }
-    void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { }
-    void VisitCharacterLiteral(CharacterLiteral *E) { }
-    void VisitGNUNullExpr(GNUNullExpr *E) { }
-    void VisitImaginaryLiteral(ImaginaryLiteral *E) { }
-
-    void VisitDeclRefExpr(DeclRefExpr *E) {
-      VarDecl *VD = dyn_cast<VarDecl>(E->getDecl());
-      if (!VD) {
-        // Don't allow unhandled Decl types.
-        Simple = false;
-        return;
-      }
+  void VisitParenExpr(ParenExpr *E) { Visit(E->getSubExpr()); }
 
-      Ranges.push_back(E->getSourceRange());
+  void VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
+    Visit(E->getOpaqueValue()->getSourceExpr());
+    Visit(E->getFalseExpr());
+  }
 
-      Decls.insert(VD);
+  void VisitIntegerLiteral(IntegerLiteral *E) {}
+  void VisitFloatingLiteral(FloatingLiteral *E) {}
+  void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {}
+  void VisitCharacterLiteral(CharacterLiteral *E) {}
+  void VisitGNUNullExpr(GNUNullExpr *E) {}
+  void VisitImaginaryLiteral(ImaginaryLiteral *E) {}
+
+  void VisitDeclRefExpr(DeclRefExpr *E) {
+    VarDecl *VD = dyn_cast<VarDecl>(E->getDecl());
+    if (!VD) {
+      // Don't allow unhandled Decl types.
+      Simple = false;
+      return;
     }
 
-  }; // end class DeclExtractor
+    Ranges.push_back(E->getSourceRange());
 
-  // DeclMatcher checks to see if the decls are used in a non-evaluated
-  // context.
-  class DeclMatcher : public EvaluatedExprVisitor<DeclMatcher> {
-    DeclSetVector &Decls;
-    bool FoundDecl;
+    Decls.insert(VD);
+  }
 
-  public:
-    typedef EvaluatedExprVisitor<DeclMatcher> Inherited;
+}; // end class DeclExtractor
 
-    DeclMatcher(Sema &S, DeclSetVector &Decls, Stmt *Statement) :
-        Inherited(S.Context), Decls(Decls), FoundDecl(false) {
-      if (!Statement) return;
+// DeclMatcher checks to see if the decls are used in a non-evaluated
+// context.
+class DeclMatcher : public EvaluatedExprVisitor<DeclMatcher> {
+  DeclSetVector &Decls;
+  bool FoundDecl;
 
-      Visit(Statement);
-    }
+public:
+  typedef EvaluatedExprVisitor<DeclMatcher> Inherited;
 
-    void VisitReturnStmt(ReturnStmt *S) {
-      FoundDecl = true;
-    }
+  DeclMatcher(Sema &S, DeclSetVector &Decls, Stmt *Statement)
+      : Inherited(S.Context), Decls(Decls), FoundDecl(false) {
+    if (!Statement)
+      return;
 
-    void VisitBreakStmt(BreakStmt *S) {
-      FoundDecl = true;
-    }
+    Visit(Statement);
+  }
 
-    void VisitGotoStmt(GotoStmt *S) {
-      FoundDecl = true;
-    }
+  void VisitReturnStmt(ReturnStmt *S) { FoundDecl = true; }
 
-    void VisitCastExpr(CastExpr *E) {
-      if (E->getCastKind() == CK_LValueToRValue)
-        CheckLValueToRValueCast(E->getSubExpr());
-      else
-        Visit(E->getSubExpr());
-    }
+  void VisitBreakStmt(BreakStmt *S) { FoundDecl = true; }
 
-    void CheckLValueToRValueCast(Expr *E) {
-      E = E->IgnoreParenImpCasts();
+  void VisitGotoStmt(GotoStmt *S) { FoundDecl = true; }
 
-      if (isa<DeclRefExpr>(E)) {
-        return;
-      }
+  void VisitCastExpr(CastExpr *E) {
+    if (E->getCastKind() == CK_LValueToRValue)
+      CheckLValueToRValueCast(E->getSubExpr());
+    else
+      Visit(E->getSubExpr());
+  }
 
-      if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
-        Visit(CO->getCond());
-        CheckLValueToRValueCast(CO->getTrueExpr());
-        CheckLValueToRValueCast(CO->getFalseExpr());
-        return;
-      }
+  void CheckLValueToRValueCast(Expr *E) {
+    E = E->IgnoreParenImpCasts();
 
-      if (BinaryConditionalOperator *BCO =
-              dyn_cast<BinaryConditionalOperator>(E)) {
-        CheckLValueToRValueCast(BCO->getOpaqueValue()->getSourceExpr());
-        CheckLValueToRValueCast(BCO->getFalseExpr());
-        return;
-      }
+    if (isa<DeclRefExpr>(E)) {
+      return;
+    }
 
-      Visit(E);
+    if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
+      Visit(CO->getCond());
+      CheckLValueToRValueCast(CO->getTrueExpr());
+      CheckLValueToRValueCast(CO->getFalseExpr());
+      return;
     }
 
-    void VisitDeclRefExpr(DeclRefExpr *E) {
-      if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()))
-        if (Decls.count(VD))
-          FoundDecl = true;
+    if (BinaryConditionalOperator *BCO =
+            dyn_cast<BinaryConditionalOperator>(E)) {
+      CheckLValueToRValueCast(BCO->getOpaqueValue()->getSourceExpr());
+      CheckLValueToRValueCast(BCO->getFalseExpr());
+      return;
     }
 
-    void VisitPseudoObjectExpr(PseudoObjectExpr *POE) {
-      // Only need to visit the semantics for POE.
-      // SyntaticForm doesn't really use the Decal.
-      for (auto *S : POE->semantics()) {
-        if (auto *OVE = dyn_cast<OpaqueValueExpr>(S))
-          // Look past the OVE into the expression it binds.
-          Visit(OVE->getSourceExpr());
-        else
-          Visit(S);
-      }
+    Visit(E);
+  }
+
+  void VisitDeclRefExpr(DeclRefExpr *E) {
+    if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()))
+      if (Decls.count(VD))
+        FoundDecl = true;
+  }
+
+  void VisitPseudoObjectExpr(PseudoObjectExpr *POE) {
+    // Only need to visit the semantics for POE.
+    // SyntaticForm doesn't really use the Decal.
+    for (auto *S : POE->semantics()) {
+      if (auto *OVE = dyn_cast<OpaqueValueExpr>(S))
+        // Look past the OVE into the expression it binds.
+        Visit(OVE->getSourceExpr());
+      else
+        Visit(S);
     }
+  }
 
-    bool FoundDeclInUse() { return FoundDecl; }
+  bool FoundDeclInUse() { return FoundDecl; }
 
-  };  // end class DeclMatcher
+}; // end class DeclMatcher
 
   void CheckForLoopConditionalStatement(Sema &S, Expr *Second,
                                         Expr *Third, Stmt *Body) {
@@ -1694,170 +1697,171 @@
     if (BreakContinueFinder(S, Body).ContinueFound()) return;
 
     S.Diag(LastDRE->getLocation(), diag::warn_redundant_loop_iteration)
-         << LastDRE->getDecl() << LastIncrement;
+        << LastDRE->getDecl() << LastIncrement;
     S.Diag(LoopDRE->getLocation(), diag::note_loop_iteration_here)
-         << LoopIncrement;
+        << LoopIncrement;
   }
 
-} // end namespace
+  } // end namespace
 
-
-void Sema::CheckBreakContinueBinding(Expr *E) {
-  if (!E || getLangOpts().CPlusPlus)
-    return;
-  BreakContinueFinder BCFinder(*this, E);
-  Scope *BreakParent = CurScope->getBreakParent();
-  if (BCFinder.BreakFound() && BreakParent) {
-    if (BreakParent->getFlags() & Scope::SwitchScope) {
-      Diag(BCFinder.GetBreakLoc(), diag::warn_break_binds_to_switch);
-    } else {
-      Diag(BCFinder.GetBreakLoc(), diag::warn_loop_ctrl_binds_to_inner)
-          << "break";
+  void Sema::CheckBreakContinueBinding(Expr *E) {
+    if (!E || getLangOpts().CPlusPlus)
+      return;
+    BreakContinueFinder BCFinder(*this, E);
+    Scope *BreakParent = CurScope->getBreakParent();
+    if (BCFinder.BreakFound() && BreakParent) {
+      if (BreakParent->getFlags() & Scope::SwitchScope) {
+        Diag(BCFinder.GetBreakLoc(), diag::warn_break_binds_to_switch);
+      } else {
+        Diag(BCFinder.GetBreakLoc(), diag::warn_loop_ctrl_binds_to_inner)
+            << "break";
+      }
+    } else if (BCFinder.ContinueFound() && CurScope->getContinueParent()) {
+      Diag(BCFinder.GetContinueLoc(), diag::warn_loop_ctrl_binds_to_inner)
+          << "continue";
     }
-  } else if (BCFinder.ContinueFound() && CurScope->getContinueParent()) {
-    Diag(BCFinder.GetContinueLoc(), diag::warn_loop_ctrl_binds_to_inner)
-        << "continue";
   }
-}
 
-StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
-                              Stmt *First, ConditionResult Second,
-                              FullExprArg third, SourceLocation RParenLoc,
-                              Stmt *Body) {
-  if (Second.isInvalid())
-    return StmtError();
+  StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
+                                Stmt *First, ConditionResult Second,
+                                FullExprArg third, SourceLocation RParenLoc,
+                                Stmt *Body, BranchHint Hint) {
+    if (Second.isInvalid())
+      return StmtError();
 
-  if (!getLangOpts().CPlusPlus) {
-    if (DeclStmt *DS = dyn_cast_or_null<DeclStmt>(First)) {
-      // C99 6.8.5p3: The declaration part of a 'for' statement shall only
-      // declare identifiers for objects having storage class 'auto' or
-      // 'register'.
-      for (auto *DI : DS->decls()) {
-        VarDecl *VD = dyn_cast<VarDecl>(DI);
-        if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage())
-          VD = nullptr;
-        if (!VD) {
-          Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for);
-          DI->setInvalidDecl();
+    if (!getLangOpts().CPlusPlus) {
+      if (DeclStmt *DS = dyn_cast_or_null<DeclStmt>(First)) {
+        // C99 6.8.5p3: The declaration part of a 'for' statement shall only
+        // declare identifiers for objects having storage class 'auto' or
+        // 'register'.
+        for (auto *DI : DS->decls()) {
+          VarDecl *VD = dyn_cast<VarDecl>(DI);
+          if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage())
+            VD = nullptr;
+          if (!VD) {
+            Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for);
+            DI->setInvalidDecl();
+          }
         }
       }
     }
-  }
 
-  CheckBreakContinueBinding(Second.get().second);
-  CheckBreakContinueBinding(third.get());
+    CheckBreakContinueBinding(Second.get().second);
+    CheckBreakContinueBinding(third.get());
 
-  if (!Second.get().first)
-    CheckForLoopConditionalStatement(*this, Second.get().second, third.get(),
-                                     Body);
-  CheckForRedundantIteration(*this, third.get(), Body);
+    if (!Second.get().first)
+      CheckForLoopConditionalStatement(*this, Second.get().second, third.get(),
+                                       Body);
+    CheckForRedundantIteration(*this, third.get(), Body);
 
-  if (Second.get().second &&
-      !Diags.isIgnored(diag::warn_comma_operator,
-                       Second.get().second->getExprLoc()))
-    CommaVisitor(*this).Visit(Second.get().second);
+    if (Second.get().second &&
+        !Diags.isIgnored(diag::warn_comma_operator,
+                         Second.get().second->getExprLoc()))
+      CommaVisitor(*this).Visit(Second.get().second);
 
-  Expr *Third  = third.release().getAs<Expr>();
-  if (isa<NullStmt>(Body))
-    getCurCompoundScope().setHasEmptyLoopBodies();
+    Expr *Third = third.release().getAs<Expr>();
+    if (isa<NullStmt>(Body))
+      getCurCompoundScope().setHasEmptyLoopBodies();
 
-  return new (Context)
-      ForStmt(Context, First, Second.get().second, Second.get().first, Third,
-              Body, ForLoc, LParenLoc, RParenLoc);
-}
+    return new (Context)
+        ForStmt(Context, First, Second.get().second, Second.get().first, Third,
+                Body, ForLoc, LParenLoc, RParenLoc, Hint);
+  }
 
-/// In an Objective C collection iteration statement:
-///   for (x in y)
-/// x can be an arbitrary l-value expression.  Bind it up as a
-/// full-expression.
-StmtResult Sema::ActOnForEachLValueExpr(Expr *E) {
-  // Reduce placeholder expressions here.  Note that this rejects the
-  // use of pseudo-object l-values in this position.
-  ExprResult result = CheckPlaceholderExpr(E);
-  if (result.isInvalid()) return StmtError();
-  E = result.get();
-
-  ExprResult FullExpr = ActOnFinishFullExpr(E, /*DiscardedValue*/ false);
-  if (FullExpr.isInvalid())
-    return StmtError();
-  return StmtResult(static_cast<Stmt*>(FullExpr.get()));
-}
+  /// In an Objective C collection iteration statement:
+  ///   for (x in y)
+  /// x can be an arbitrary l-value expression.  Bind it up as a
+  /// full-expression.
+  StmtResult Sema::ActOnForEachLValueExpr(Expr *E) {
+    // Reduce placeholder expressions here.  Note that this rejects the
+    // use of pseudo-object l-values in this position.
+    ExprResult result = CheckPlaceholderExpr(E);
+    if (result.isInvalid())
+      return StmtError();
+    E = result.get();
 
-ExprResult
-Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) {
-  if (!collection)
-    return ExprError();
+    ExprResult FullExpr = ActOnFinishFullExpr(E, /*DiscardedValue*/ false);
+    if (FullExpr.isInvalid())
+      return StmtError();
+    return StmtResult(static_cast<Stmt *>(FullExpr.get()));
+  }
 
-  ExprResult result = CorrectDelayedTyposInExpr(collection);
-  if (!result.isUsable())
-    return ExprError();
-  collection = result.get();
+  ExprResult Sema::CheckObjCForCollectionOperand(SourceLocation forLoc,
+                                                 Expr *collection) {
+    if (!collection)
+      return ExprError();
 
-  // Bail out early if we've got a type-dependent expression.
-  if (collection->isTypeDependent()) return collection;
+    ExprResult result = CorrectDelayedTyposInExpr(collection);
+    if (!result.isUsable())
+      return ExprError();
+    collection = result.get();
 
-  // Perform normal l-value conversion.
-  result = DefaultFunctionArrayLvalueConversion(collection);
-  if (result.isInvalid())
-    return ExprError();
-  collection = result.get();
-
-  // The operand needs to have object-pointer type.
-  // TODO: should we do a contextual conversion?
-  const ObjCObjectPointerType *pointerType =
-    collection->getType()->getAs<ObjCObjectPointerType>();
-  if (!pointerType)
-    return Diag(forLoc, diag::err_collection_expr_type)
-             << collection->getType() << collection->getSourceRange();
+    // Bail out early if we've got a type-dependent expression.
+    if (collection->isTypeDependent())
+      return collection;
 
-  // Check that the operand provides
-  //   - countByEnumeratingWithState:objects:count:
-  const ObjCObjectType *objectType = pointerType->getObjectType();
-  ObjCInterfaceDecl *iface = objectType->getInterface();
-
-  // If we have a forward-declared type, we can't do this check.
-  // Under ARC, it is an error not to have a forward-declared class.
-  if (iface &&
-      (getLangOpts().ObjCAutoRefCount
-           ? RequireCompleteType(forLoc, QualType(objectType, 0),
-                                 diag::err_arc_collection_forward, collection)
-           : !isCompleteType(forLoc, QualType(objectType, 0)))) {
-    // Otherwise, if we have any useful type information, check that
-    // the type declares the appropriate method.
-  } else if (iface || !objectType->qual_empty()) {
-    IdentifierInfo *selectorIdents[] = {
-      &Context.Idents.get("countByEnumeratingWithState"),
-      &Context.Idents.get("objects"),
-      &Context.Idents.get("count")
-    };
-    Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]);
+    // Perform normal l-value conversion.
+    result = DefaultFunctionArrayLvalueConversion(collection);
+    if (result.isInvalid())
+      return ExprError();
+    collection = result.get();
+
+    // The operand needs to have object-pointer type.
+    // TODO: should we do a contextual conversion?
+    const ObjCObjectPointerType *pointerType =
+        collection->getType()->getAs<ObjCObjectPointerType>();
+    if (!pointerType)
+      return Diag(forLoc, diag::err_collection_expr_type)
+             << collection->getType() << collection->getSourceRange();
 
-    ObjCMethodDecl *method = nullptr;
+    // Check that the operand provides
+    //   - countByEnumeratingWithState:objects:count:
+    const ObjCObjectType *objectType = pointerType->getObjectType();
+    ObjCInterfaceDecl *iface = objectType->getInterface();
+
+    // If we have a forward-declared type, we can't do this check.
+    // Under ARC, it is an error not to have a forward-declared class.
+    if (iface &&
+        (getLangOpts().ObjCAutoRefCount
+             ? RequireCompleteType(forLoc, QualType(objectType, 0),
+                                   diag::err_arc_collection_forward, collection)
+             : !isCompleteType(forLoc, QualType(objectType, 0)))) {
+      // Otherwise, if we have any useful type information, check that
+      // the type declares the appropriate method.
+    } else if (iface || !objectType->qual_empty()) {
+      IdentifierInfo *selectorIdents[] = {
+          &Context.Idents.get("countByEnumeratingWithState"),
+          &Context.Idents.get("objects"), &Context.Idents.get("count")};
+      Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]);
+
+      ObjCMethodDecl *method = nullptr;
+
+      // If there's an interface, look in both the public and private APIs.
+      if (iface) {
+        method = iface->lookupInstanceMethod(selector);
+        if (!method)
+          method = iface->lookupPrivateMethod(selector);
+      }
 
-    // If there's an interface, look in both the public and private APIs.
-    if (iface) {
-      method = iface->lookupInstanceMethod(selector);
-      if (!method) method = iface->lookupPrivateMethod(selector);
-    }
+      // Also check protocol qualifiers.
+      if (!method)
+        method = LookupMethodInQualifiedType(selector, pointerType,
+                                             /*instance*/ true);
 
-    // Also check protocol qualifiers.
-    if (!method)
-      method = LookupMethodInQualifiedType(selector, pointerType,
-                                           /*instance*/ true);
+      // If we didn't find it anywhere, give up.
+      if (!method) {
+        Diag(forLoc, diag::warn_collection_expr_type)
+            << collection->getType() << selector
+            << collection->getSourceRange();
+      }
 
-    // If we didn't find it anywhere, give up.
-    if (!method) {
-      Diag(forLoc, diag::warn_collection_expr_type)
-        << collection->getType() << selector << collection->getSourceRange();
+      // TODO: check for an incompatible signature?
     }
 
-    // TODO: check for an incompatible signature?
+    // Wrap up any cleanups in the expression.
+    return collection;
   }
 
-  // Wrap up any cleanups in the expression.
-  return collection;
-}
-
 StmtResult
 Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
                                  Stmt *First, Expr *collection,
@@ -2632,8 +2636,8 @@
   return new (Context) CXXForRangeStmt(
       InitStmt, RangeDS, cast_or_null<DeclStmt>(BeginDeclStmt.get()),
       cast_or_null<DeclStmt>(EndDeclStmt.get()), NotEqExpr.get(),
-      IncrExpr.get(), LoopVarDS, /*Body=*/nullptr, ForLoc, CoawaitLoc,
-      ColonLoc, RParenLoc);
+      IncrExpr.get(), LoopVarDS, /*Body=*/nullptr, ForLoc, CoawaitLoc, ColonLoc,
+      RParenLoc, BranchHint::BH_NoHint);
 }
 
 /// FinishObjCForCollectionStmt - Attach the body to a objective-C foreach
@@ -2805,7 +2809,7 @@
 /// This is a separate step from ActOnCXXForRangeStmt because analysis of the
 /// body cannot be performed until after the type of the range variable is
 /// determined.
-StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) {
+StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B, BranchHint Hint) {
   if (!S || !B)
     return StmtError();
 
@@ -2814,6 +2818,7 @@
 
   CXXForRangeStmt *ForStmt = cast<CXXForRangeStmt>(S);
   ForStmt->setBody(B);
+  ForStmt->setBranchHint(Hint);
 
   DiagnoseEmptyStmtBody(ForStmt->getRParenLoc(), B,
                         diag::warn_empty_range_based_for_body);
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -11821,13 +11821,15 @@
   return S.ActOnForStmt(
       Loc, Loc, InitStmt,
       S.ActOnCondition(nullptr, Loc, Comparison, Sema::ConditionKind::Boolean),
-      S.MakeFullDiscardedValueExpr(Increment), Loc, Copy.get());
+      S.MakeFullDiscardedValueExpr(Increment), Loc, Copy.get(),
+      BranchHint::BH_NoHint);
 }
 
-static StmtResult
-buildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
-                      const ExprBuilder &To, const ExprBuilder &From,
-                      bool CopyingBaseSubobject, bool Copying) {
+static StmtResult buildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
+                                        const ExprBuilder &To,
+                                        const ExprBuilder &From,
+                                        bool CopyingBaseSubobject,
+                                        bool Copying) {
   // Maybe we should use a memcpy?
   if (T->isArrayType() && !T.isConstQualified() && !T.isVolatileQualified() &&
       T.isTriviallyCopyableType(S.Context))
Index: clang/lib/Sema/Scope.cpp
===================================================================
--- clang/lib/Sema/Scope.cpp
+++ clang/lib/Sema/Scope.cpp
@@ -87,6 +87,7 @@
 void Scope::Init(Scope *parent, unsigned flags) {
   setFlags(parent, flags);
 
+  BranchLikelihoodAttr = nullptr;
   DeclsInScope.clear();
   UsingDirectives.clear();
   Entity = nullptr;
Index: clang/lib/Parse/ParseStmt.cpp
===================================================================
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -1169,7 +1169,6 @@
   return false;
 }
 
-
 /// ParseIfStatement
 ///       if-statement: [C99 6.8.4.1]
 ///         'if' '(' expression ')' statement
@@ -1259,6 +1258,9 @@
   // Pop the 'if' scope if needed.
   InnerScope.Exit();
 
+  LikelihoodAttr *ThenLikelihoodAttr = getCurScope()->getBranchLikelihoodAttr();
+  getCurScope()->setBranchLikelihoodAttr(nullptr);
+
   // If it has an else, parse it.
   SourceLocation ElseLoc;
   SourceLocation ElseStmtLoc;
@@ -1298,6 +1300,7 @@
   } else if (InnerStatementTrailingElseLoc.isValid()) {
     Diag(InnerStatementTrailingElseLoc, diag::warn_dangling_else);
   }
+  LikelihoodAttr *ElseLikelihoodAttr = getCurScope()->getBranchLikelihoodAttr();
 
   IfScope.Exit();
 
@@ -1317,8 +1320,10 @@
   if (ElseStmt.isInvalid())
     ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
 
-  return Actions.ActOnIfStmt(IfLoc, IsConstexpr, InitStmt.get(), Cond,
-                             ThenStmt.get(), ElseLoc, ElseStmt.get());
+  return Actions.ActOnIfStmt(
+      IfLoc, IsConstexpr, InitStmt.get(), Cond, ThenStmt.get(), ElseLoc,
+      ElseStmt.get(),
+      Actions.HandleIfStmtHint(ThenLikelihoodAttr, ElseLikelihoodAttr));
 }
 
 /// ParseSwitchStatement
@@ -1406,6 +1411,15 @@
   return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get());
 }
 
+/// Converts a potentially null Likelihood attribute in a BranchHint.
+static BranchHint
+getHintFromLikelihoodAttr(LikelihoodAttr *BranchLikelihoodAttr) {
+  if (BranchLikelihoodAttr)
+    return (BranchLikelihoodAttr->isLikely() ? BranchHint::BH_Taken
+                                             : BranchHint::BH_NotTaken);
+  return BranchHint::BH_NoHint;
+}
+
 /// ParseWhileStatement
 ///       while-statement: [C99 6.8.5.1]
 ///         'while' '(' expression ')' statement
@@ -1467,12 +1481,16 @@
 
   // Pop the body scope if needed.
   InnerScope.Exit();
+  LikelihoodAttr *BranchLikelihoodAttr =
+      getCurScope()->getBranchLikelihoodAttr();
   WhileScope.Exit();
 
   if (Cond.isInvalid() || Body.isInvalid())
     return StmtError();
 
-  return Actions.ActOnWhileStmt(WhileLoc, Cond, Body.get());
+  return Actions.ActOnWhileStmt(
+      WhileLoc, Cond, Body.get(),
+      getHintFromLikelihoodAttr(BranchLikelihoodAttr));
 }
 
 /// ParseDoStatement
@@ -1538,13 +1556,16 @@
   if (Cond.isUsable())
     Cond = Actions.CorrectDelayedTyposInExpr(Cond);
   T.consumeClose();
+  LikelihoodAttr *BranchLikelihoodAttr =
+      getCurScope()->getBranchLikelihoodAttr();
   DoScope.Exit();
 
   if (Cond.isInvalid() || Body.isInvalid())
     return StmtError();
 
   return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc, T.getOpenLocation(),
-                             Cond.get(), T.getCloseLocation());
+                             Cond.get(), T.getCloseLocation(),
+                             getHintFromLikelihoodAttr(BranchLikelihoodAttr));
 }
 
 bool Parser::isForRangeIdentifier() {
@@ -1902,6 +1923,8 @@
   // Pop the body scope if needed.
   InnerScope.Exit();
 
+  LikelihoodAttr *BranchLikelihoodAttr =
+      getCurScope()->getBranchLikelihoodAttr();
   // Leave the for-scope.
   ForScope.Exit();
 
@@ -1909,15 +1932,17 @@
     return StmtError();
 
   if (ForEach)
-   return Actions.FinishObjCForCollectionStmt(ForEachStmt.get(),
-                                              Body.get());
+    return Actions.FinishObjCForCollectionStmt(ForEachStmt.get(), Body.get());
 
   if (ForRangeInfo.ParsedForRangeDecl())
-    return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get());
+    return Actions.FinishCXXForRangeStmt(
+        ForRangeStmt.get(), Body.get(),
+        getHintFromLikelihoodAttr(BranchLikelihoodAttr));
 
   return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(),
                               SecondPart, ThirdPart, T.getCloseLocation(),
-                              Body.get());
+                              Body.get(),
+                              getHintFromLikelihoodAttr(BranchLikelihoodAttr));
 }
 
 /// ParseGotoStatement
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2847,10 +2847,12 @@
 
   Address EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false,
                            AggValueSlot AVS = AggValueSlot::ignored());
-  Address EmitCompoundStmtWithoutScope(const CompoundStmt &S,
-                                       bool GetLast = false,
-                                       AggValueSlot AVS =
-                                                AggValueSlot::ignored());
+  Address
+  EmitCompoundStmtWithoutScope(const CompoundStmt &S, bool GetLast = false,
+                               AggValueSlot AVS = AggValueSlot::ignored());
+
+  /// MaybeEmitLikelihoodHint - Emit and llvm.expect if a hint is present.
+  llvm::Value *MaybeEmitLikelihoodHint(llvm::Value *CondV, BranchHint Hint);
 
   /// EmitLabel - Emit the block for the given label. It is legal to call this
   /// function even if there is no current insertion point.
@@ -4037,7 +4039,8 @@
   /// TrueCount should be the number of times we expect the condition to
   /// evaluate to true based on PGO data.
   void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock,
-                            llvm::BasicBlock *FalseBlock, uint64_t TrueCount);
+                            llvm::BasicBlock *FalseBlock, uint64_t TrueCount,
+                            BranchHint hint = BranchHint::BH_NoHint);
 
   /// Given an assignment `*LHS = RHS`, emit a test that checks if \p RHS is
   /// nonnull, if \p LHS is marked _Nonnull.
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1531,7 +1531,8 @@
 void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
                                            llvm::BasicBlock *TrueBlock,
                                            llvm::BasicBlock *FalseBlock,
-                                           uint64_t TrueCount) {
+                                           uint64_t TrueCount,
+                                           BranchHint Hint) {
   Cond = Cond->IgnoreParens();
 
   if (const BinaryOperator *CondBOp = dyn_cast<BinaryOperator>(Cond)) {
@@ -1720,6 +1721,16 @@
     ApplyDebugLocation DL(*this, Cond);
     CondV = EvaluateExprAsBool(Cond);
   }
+
+  if (Hint != BranchHint::BH_NoHint &&
+      CGM.getCodeGenOpts().OptimizationLevel != 0) {
+    llvm::Constant *ExpectedValue =
+        llvm::ConstantInt::get(llvm::Type::getInt1Ty(this->getLLVMContext()),
+                               Hint == BranchHint::BH_Taken);
+    llvm::Function *FnExpect =
+        CGM.getIntrinsic(llvm::Intrinsic::expect, CondV->getType());
+    CondV = Builder.CreateCall(FnExpect, {CondV, ExpectedValue}, "expval");
+  }
   Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable);
 }
 
Index: clang/lib/CodeGen/CGStmt.cpp
===================================================================
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -658,7 +658,7 @@
     ElseBlock = createBasicBlock("if.else");
 
   EmitBranchOnBoolExpr(S.getCond(), ThenBlock, ElseBlock,
-                       getProfileCount(S.getThen()));
+                       getProfileCount(S.getThen()), S.getBranchHint());
 
   // Emit the 'then' code.
   EmitBlock(ThenBlock);
@@ -691,6 +691,20 @@
   EmitBlock(ContBlock, true);
 }
 
+llvm::Value *CodeGenFunction::MaybeEmitLikelihoodHint(llvm::Value *CondV,
+                                                      BranchHint Hint) {
+  if (Hint != BranchHint::BH_NoHint &&
+      CGM.getCodeGenOpts().OptimizationLevel != 0) {
+    llvm::Constant *ExpectedValue =
+        llvm::ConstantInt::get(llvm::Type::getInt1Ty(this->getLLVMContext()),
+                               Hint == BranchHint::BH_Taken);
+    llvm::Function *FnExpect =
+        CGM.getIntrinsic(llvm::Intrinsic::expect, CondV->getType());
+    return Builder.CreateCall(FnExpect, {CondV, ExpectedValue}, "expval");
+  }
+  return CondV;
+}
+
 void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
                                     ArrayRef<const Attr *> WhileAttrs) {
   // Emit the header for the loop, which will also become
@@ -740,6 +754,7 @@
     llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
     if (ConditionScope.requiresCleanups())
       ExitBlock = createBasicBlock("while.exit");
+    BoolCondVal = MaybeEmitLikelihoodHint(BoolCondVal, S.getBranchHint());
     Builder.CreateCondBr(
         BoolCondVal, LoopBody, ExitBlock,
         createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
@@ -825,6 +840,7 @@
   // As long as the condition is true, iterate the loop.
   if (EmitBoolCondBranch) {
     uint64_t BackedgeCount = getProfileCount(S.getBody()) - ParentCount;
+    BoolCondVal = MaybeEmitLikelihoodHint(BoolCondVal, S.getBranchHint());
     Builder.CreateCondBr(
         BoolCondVal, LoopBody, LoopExit.getBlock(),
         createProfileWeightsForLoop(S.getCond(), BackedgeCount));
@@ -895,6 +911,7 @@
     // C99 6.8.5p2/p4: The first substatement is executed if the expression
     // compares unequal to 0.  The condition must be a scalar type.
     llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
+    BoolCondVal = MaybeEmitLikelihoodHint(BoolCondVal, S.getBranchHint());
     Builder.CreateCondBr(
         BoolCondVal, ForBody, ExitBlock,
         createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
@@ -976,6 +993,7 @@
   // The body is executed if the expression, contextually converted
   // to bool, is true.
   llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
+  MaybeEmitLikelihoodHint(BoolCondVal, S.getBranchHint());
   Builder.CreateCondBr(
       BoolCondVal, ForBody, ExitBlock,
       createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
Index: clang/lib/Analysis/CFG.cpp
===================================================================
--- clang/lib/Analysis/CFG.cpp
+++ clang/lib/Analysis/CFG.cpp
@@ -2194,11 +2194,20 @@
 
     case Stmt::WhileStmtClass:
       return VisitWhileStmt(cast<WhileStmt>(S));
-  }
+    }
+}
+
+static bool isLikelyAttributedStmt(Stmt *S) {
+  if (!isa<AttributedStmt>(S))
+    return false;
+  AttributedStmt *Attribute = dyn_cast<AttributedStmt>(S);
+  return std::all_of(
+      Attribute->getAttrs().begin(), Attribute->getAttrs().end(),
+      [](const Attr *Elem) { return isa<LikelihoodAttr>(Elem); });
 }
 
 CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
-  if (asc.alwaysAdd(*this, S)) {
+  if (asc.alwaysAdd(*this, S) && !isLikelyAttributedStmt(S)) {
     autoCreateBlock();
     appendStmt(Block, S);
   }
Index: clang/lib/AST/TextNodeDumper.cpp
===================================================================
--- clang/lib/AST/TextNodeDumper.cpp
+++ clang/lib/AST/TextNodeDumper.cpp
@@ -658,6 +658,9 @@
     OS << " has_var";
   if (Node->hasElseStorage())
     OS << " has_else";
+  if (Node->getBranchHint() != BranchHint::BH_NoHint)
+    OS << ((Node->getBranchHint() == BranchHint::BH_Taken) ? " likely"
+                                                           : " unlikely");
 }
 
 void TextNodeDumper::VisitSwitchStmt(const SwitchStmt *Node) {
@@ -670,6 +673,27 @@
 void TextNodeDumper::VisitWhileStmt(const WhileStmt *Node) {
   if (Node->hasVarStorage())
     OS << " has_var";
+  if (Node->getBranchHint() != BranchHint::BH_NoHint)
+    OS << (Node->getBranchHint() == BranchHint::BH_Taken ? " likely"
+                                                         : " unlikely");
+}
+
+void TextNodeDumper::VisitForStmt(const ForStmt *Node) {
+  if (Node->getBranchHint() != BranchHint::BH_NoHint)
+    OS << (Node->getBranchHint() == BranchHint::BH_Taken ? " likely"
+                                                         : " unlikely");
+}
+
+void TextNodeDumper::VisitDoStmt(const DoStmt *Node) {
+  if (Node->getBranchHint() != BranchHint::BH_NoHint)
+    OS << (Node->getBranchHint() == BranchHint::BH_Taken ? " likely"
+                                                         : " unlikely");
+}
+
+void TextNodeDumper::VisitCXXForRangeStmt(const CXXForRangeStmt *Node) {
+  if (Node->getBranchHint() != BranchHint::BH_NoHint)
+    OS << (Node->getBranchHint() == BranchHint::BH_Taken ? " likely"
+                                                         : " unlikely");
 }
 
 void TextNodeDumper::VisitLabelStmt(const LabelStmt *Node) {
Index: clang/lib/AST/StmtCXX.cpp
===================================================================
--- clang/lib/AST/StmtCXX.cpp
+++ clang/lib/AST/StmtCXX.cpp
@@ -49,7 +49,7 @@
                                  Expr *Cond, Expr *Inc, DeclStmt *LoopVar,
                                  Stmt *Body, SourceLocation FL,
                                  SourceLocation CAL, SourceLocation CL,
-                                 SourceLocation RPL)
+                                 SourceLocation RPL, BranchHint Hint)
     : Stmt(CXXForRangeStmtClass), ForLoc(FL), CoawaitLoc(CAL), ColonLoc(CL),
       RParenLoc(RPL) {
   SubExprs[INIT] = Init;
@@ -60,6 +60,7 @@
   SubExprs[INC] = Inc;
   SubExprs[LOOPVAR] = LoopVar;
   SubExprs[BODY] = Body;
+  setBranchHint(Hint);
 }
 
 Expr *CXXForRangeStmt::getRangeInit() {
Index: clang/lib/AST/Stmt.cpp
===================================================================
--- clang/lib/AST/Stmt.cpp
+++ clang/lib/AST/Stmt.cpp
@@ -798,7 +798,7 @@
 
 IfStmt::IfStmt(const ASTContext &Ctx, SourceLocation IL, bool IsConstexpr,
                Stmt *Init, VarDecl *Var, Expr *Cond, Stmt *Then,
-               SourceLocation EL, Stmt *Else)
+               SourceLocation EL, Stmt *Else, BranchHint Hint)
     : Stmt(IfStmtClass) {
   bool HasElse = Else != nullptr;
   bool HasVar = Var != nullptr;
@@ -806,6 +806,7 @@
   IfStmtBits.HasElse = HasElse;
   IfStmtBits.HasVar = HasVar;
   IfStmtBits.HasInit = HasInit;
+  IfStmtBits.Hint = Hint;
 
   setConstexpr(IsConstexpr);
 
@@ -832,7 +833,8 @@
 
 IfStmt *IfStmt::Create(const ASTContext &Ctx, SourceLocation IL,
                        bool IsConstexpr, Stmt *Init, VarDecl *Var, Expr *Cond,
-                       Stmt *Then, SourceLocation EL, Stmt *Else) {
+                       Stmt *Then, SourceLocation EL, Stmt *Else,
+                       BranchHint Hint) {
   bool HasElse = Else != nullptr;
   bool HasVar = Var != nullptr;
   bool HasInit = Init != nullptr;
@@ -841,7 +843,7 @@
           NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse),
       alignof(IfStmt));
   return new (Mem)
-      IfStmt(Ctx, IL, IsConstexpr, Init, Var, Cond, Then, EL, Else);
+      IfStmt(Ctx, IL, IsConstexpr, Init, Var, Cond, Then, EL, Else, Hint);
 }
 
 IfStmt *IfStmt::CreateEmpty(const ASTContext &Ctx, bool HasElse, bool HasVar,
@@ -880,15 +882,15 @@
 
 ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
                  Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
-                 SourceLocation RP)
-  : Stmt(ForStmtClass), LParenLoc(LP), RParenLoc(RP)
-{
+                 SourceLocation RP, BranchHint Hint)
+    : Stmt(ForStmtClass), LParenLoc(LP), RParenLoc(RP) {
   SubExprs[INIT] = Init;
   setConditionVariable(C, condVar);
   SubExprs[COND] = Cond;
   SubExprs[INC] = Inc;
   SubExprs[BODY] = Body;
   ForStmtBits.ForLoc = FL;
+  ForStmtBits.Hint = Hint;
 }
 
 VarDecl *ForStmt::getConditionVariable() const {
@@ -976,10 +978,11 @@
 }
 
 WhileStmt::WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
-                     Stmt *Body, SourceLocation WL)
+                     Stmt *Body, SourceLocation WL, BranchHint Hint)
     : Stmt(WhileStmtClass) {
   bool HasVar = Var != nullptr;
   WhileStmtBits.HasVar = HasVar;
+  WhileStmtBits.Hint = Hint;
 
   setCond(Cond);
   setBody(Body);
@@ -995,12 +998,12 @@
 }
 
 WhileStmt *WhileStmt::Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
-                             Stmt *Body, SourceLocation WL) {
+                             Stmt *Body, SourceLocation WL, BranchHint Hint) {
   bool HasVar = Var != nullptr;
   void *Mem =
       Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar),
                    alignof(WhileStmt));
-  return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL);
+  return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL, Hint);
 }
 
 WhileStmt *WhileStmt::CreateEmpty(const ASTContext &Ctx, bool HasVar) {
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -5682,7 +5682,7 @@
 
   return IfStmt::Create(Importer.getToContext(), ToIfLoc, S->isConstexpr(),
                         ToInit, ToConditionVariable, ToCond, ToThen, ToElseLoc,
-                        ToElse);
+                        ToElse, S->getBranchHint());
 }
 
 ExpectedStmt ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) {
@@ -5733,7 +5733,7 @@
   std::tie(ToConditionVariable, ToCond, ToBody, ToWhileLoc) = *Imp;
 
   return WhileStmt::Create(Importer.getToContext(), ToConditionVariable, ToCond,
-                           ToBody, ToWhileLoc);
+                           ToBody, ToWhileLoc, S->getBranchHint());
 }
 
 ExpectedStmt ASTNodeImporter::VisitDoStmt(DoStmt *S) {
@@ -5749,7 +5749,7 @@
   std::tie(ToBody, ToCond, ToDoLoc, ToWhileLoc, ToRParenLoc) = *Imp;
 
   return new (Importer.getToContext()) DoStmt(
-      ToBody, ToCond, ToDoLoc, ToWhileLoc, ToRParenLoc);
+      ToBody, ToCond, ToDoLoc, ToWhileLoc, ToRParenLoc, S->getBranchHint());
 }
 
 ExpectedStmt ASTNodeImporter::VisitForStmt(ForStmt *S) {
@@ -5764,14 +5764,12 @@
   VarDecl *ToConditionVariable;
   Stmt *ToBody;
   SourceLocation ToForLoc, ToLParenLoc, ToRParenLoc;
-  std::tie(
-      ToInit, ToCond, ToConditionVariable,  ToInc, ToBody, ToForLoc,
-      ToLParenLoc, ToRParenLoc) = *Imp;
+  std::tie(ToInit, ToCond, ToConditionVariable, ToInc, ToBody, ToForLoc,
+           ToLParenLoc, ToRParenLoc) = *Imp;
 
   return new (Importer.getToContext()) ForStmt(
-      Importer.getToContext(),
-      ToInit, ToCond, ToConditionVariable, ToInc, ToBody, ToForLoc, ToLParenLoc,
-      ToRParenLoc);
+      Importer.getToContext(), ToInit, ToCond, ToConditionVariable, ToInc,
+      ToBody, ToForLoc, ToLParenLoc, ToRParenLoc, S->getBranchHint());
 }
 
 ExpectedStmt ASTNodeImporter::VisitGotoStmt(GotoStmt *S) {
@@ -5886,9 +5884,10 @@
   SourceLocation ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc;
   std::tie(ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc) = *Imp2;
 
-  return new (Importer.getToContext()) CXXForRangeStmt(
-      ToInit, ToRangeStmt, ToBeginStmt, ToEndStmt, ToCond, ToInc, ToLoopVarStmt,
-      ToBody, ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc);
+  return new (Importer.getToContext())
+      CXXForRangeStmt(ToInit, ToRangeStmt, ToBeginStmt, ToEndStmt, ToCond,
+                      ToInc, ToLoopVarStmt, ToBody, ToForLoc, ToCoawaitLoc,
+                      ToColonLoc, ToRParenLoc, S->getBranchHint());
 }
 
 ExpectedStmt
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -3834,32 +3834,33 @@
                                  Stmt *SubStmt);
 
   class ConditionResult;
-  StmtResult ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr,
-                         Stmt *InitStmt,
+  /// Diagnose conflicting attribute and determinate the hint.
+  BranchHint HandleIfStmtHint(LikelihoodAttr *ThenLikelihoodAttr,
+                              LikelihoodAttr *ElseLikelihoodAttr);
+
+  StmtResult ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt,
                          ConditionResult Cond, Stmt *ThenVal,
-                         SourceLocation ElseLoc, Stmt *ElseVal);
-  StmtResult BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
-                         Stmt *InitStmt,
+                         SourceLocation ElseLoc, Stmt *ElseVal,
+                         BranchHint Hint);
+  StmtResult BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt,
                          ConditionResult Cond, Stmt *ThenVal,
-                         SourceLocation ElseLoc, Stmt *ElseVal);
-  StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
-                                    Stmt *InitStmt,
+                         SourceLocation ElseLoc, Stmt *ElseVal,
+                         BranchHint Hint);
+  StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Stmt *InitStmt,
                                     ConditionResult Cond);
-  StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
-                                           Stmt *Switch, Stmt *Body);
+  StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
+                                   Stmt *Body);
   StmtResult ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond,
-                            Stmt *Body);
+                            Stmt *Body, BranchHint Hint);
   StmtResult ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
                          SourceLocation WhileLoc, SourceLocation CondLParen,
-                         Expr *Cond, SourceLocation CondRParen);
-
-  StmtResult ActOnForStmt(SourceLocation ForLoc,
-                          SourceLocation LParenLoc,
-                          Stmt *First,
-                          ConditionResult Second,
-                          FullExprArg Third,
-                          SourceLocation RParenLoc,
-                          Stmt *Body);
+                         Expr *Cond, SourceLocation CondRParen,
+                         BranchHint Hint);
+
+  StmtResult ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
+                          Stmt *First, ConditionResult Second,
+                          FullExprArg Third, SourceLocation RParenLoc,
+                          Stmt *Body, BranchHint Hint);
   ExprResult CheckObjCForCollectionOperand(SourceLocation forLoc,
                                            Expr *collection);
   StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
@@ -3894,14 +3895,12 @@
                                   Stmt *LoopVarDecl,
                                   SourceLocation RParenLoc,
                                   BuildForRangeKind Kind);
-  StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body);
+  StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body, BranchHint Hint);
 
-  StmtResult ActOnGotoStmt(SourceLocation GotoLoc,
-                           SourceLocation LabelLoc,
+  StmtResult ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
                            LabelDecl *TheDecl);
   StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
-                                   SourceLocation StarLoc,
-                                   Expr *DestExp);
+                                   SourceLocation StarLoc, Expr *DestExp);
   StmtResult ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope);
   StmtResult ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope);
 
Index: clang/include/clang/Sema/Scope.h
===================================================================
--- clang/include/clang/Sema/Scope.h
+++ clang/include/clang/Sema/Scope.h
@@ -33,6 +33,7 @@
 class DeclContext;
 class UsingDirectiveDecl;
 class VarDecl;
+class LikelihoodAttr;
 
 /// Scope - A scope is a transient data structure that is used while parsing the
 /// program.  It assists with resolving identifiers to the appropriate
@@ -163,6 +164,10 @@
   /// declared in this scope.
   unsigned short PrototypeIndex;
 
+  /// BranchLikelihoodAttr - This is the Likelihood attribute associated with
+  /// this Branch or a nullptr.
+  LikelihoodAttr *BranchLikelihoodAttr;
+
   /// FnParent - If this scope has a parent scope that is a function body, this
   /// pointer is non-null and points to it.  This is used for label processing.
   Scope *FnParent;
@@ -224,6 +229,17 @@
   /// isBlockScope - Return true if this scope correspond to a closure.
   bool isBlockScope() const { return Flags & BlockScope; }
 
+  /// getBranchLikelihoodAttr - Return the branching attribute associated with
+  /// this scope.
+  const LikelihoodAttr *getBranchLikelihoodAttr() const {
+    return BranchLikelihoodAttr;
+  }
+  LikelihoodAttr *getBranchLikelihoodAttr() { return BranchLikelihoodAttr; }
+
+  void setBranchLikelihoodAttr(LikelihoodAttr *Attribute) {
+    BranchLikelihoodAttr = Attribute;
+  }
+
   /// getParent - Return the scope that this is nested in.
   const Scope *getParent() const { return AnyParent; }
   Scope *getParent() { return AnyParent; }
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7348,6 +7348,8 @@
   "use of the %0 attribute is a C++14 extension">, InGroup<CXX14>;
 def ext_cxx17_attr : Extension<
   "use of the %0 attribute is a C++17 extension">, InGroup<CXX17>;
+def ext_cxx2a_attr : Extension<
+  "use of the %0 attribute is a C++2a extension">, InGroup<CXX2a>;
 
 def warn_unused_comparison : Warning<
   "%select{equality|inequality|relational|three-way}0 comparison result unused">,
@@ -8167,6 +8169,13 @@
   "fallthrough annotation in unreachable code">,
   InGroup<ImplicitFallthrough>, DefaultIgnore;
 
+def warn_likelihood_on_case_outside_switch : Error<
+  "%0 attribute on %1 statement is outside switch statement">;
+def warn_no_likelihood_attr_associated_branch : Warning<
+  "attribute %0 is not associated with a branch and is ignored">, InGroup<IgnoredAttributes>;
+def warn_conflicting_likelihood_attrs : Warning<
+  "attribute %0 conflicts with previous attribute %1">, InGroup<IgnoredAttributes>;
+
 def warn_unreachable_default : Warning<
   "default label in switch which covers all enumeration values">,
   InGroup<CoveredSwitchDefault>, DefaultIgnore;
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -1502,6 +1502,39 @@
   }];
 }
 
+def LikelihoodDocs : Documentation {
+  let Category = DocCatStmt;
+  let Heading = "likely / unlikely";
+  let Content = [{
+
+The ``likely`` or ``unlikely`` attribute is used to annotate that a statement or label is likely or unlikely to executed
+
+Here is an example:
+
+.. code-block:: c++
+
+  void g(int);
+  int f(int n) {
+    if (n > 5) [[unlikely]] {     // n > 5 is considered to be arbitrarily unlikely
+      g(0);
+      return n * 2 + 1;
+    }
+
+    switch (n) {
+    case 1:
+      g(1);
+      [[fallthrough]];
+
+    [[likely]] case 2:            // n == 2 is considered to be arbitrarily more
+      g(2);                       // likely than any other value of n
+      break;
+    }
+    return 3;
+  }
+
+  }];
+}
+
 def ARMInterruptDocs : Documentation {
   let Category = DocCatFunction;
   let Heading = "interrupt (ARM)";
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -1147,6 +1147,23 @@
   let Documentation = [FallthroughDocs];
 }
 
+def Likelihood : StmtAttr {
+  let Spellings = [CXX11<"", "likely", 201803>, Clang<"likely">, CXX11<"", "unlikely", 201803>, Clang<"unlikely">];
+// let Subjects = [Stmt, LabelStmt];
+  let AdditionalMembers = [{
+    bool isLikely() {
+      return getSpelling()[0] == 'l';
+    }
+    bool isUnlikely() {
+      return getSpelling()[0] == 'u';
+    }
+    bool isEqual(LikelihoodAttr* OtherAttr) {
+      return getSpelling()[0] == OtherAttr->getSpelling()[0];
+    }
+  }];
+  let Documentation = [LikelihoodDocs];
+}
+
 def FastCall : DeclOrTypeAttr {
   let Spellings = [GCC<"fastcall">, Keyword<"__fastcall">,
                    Keyword<"_fastcall">];
Index: clang/include/clang/AST/TextNodeDumper.h
===================================================================
--- clang/include/clang/AST/TextNodeDumper.h
+++ clang/include/clang/AST/TextNodeDumper.h
@@ -225,6 +225,9 @@
   void VisitIfStmt(const IfStmt *Node);
   void VisitSwitchStmt(const SwitchStmt *Node);
   void VisitWhileStmt(const WhileStmt *Node);
+  void VisitForStmt(const ForStmt *Node);
+  void VisitDoStmt(const DoStmt *Node);
+  void VisitCXXForRangeStmt(const CXXForRangeStmt *Node);
   void VisitLabelStmt(const LabelStmt *Node);
   void VisitGotoStmt(const GotoStmt *Node);
   void VisitCaseStmt(const CaseStmt *Node);
Index: clang/include/clang/AST/StmtCXX.h
===================================================================
--- clang/include/clang/AST/StmtCXX.h
+++ clang/include/clang/AST/StmtCXX.h
@@ -138,7 +138,7 @@
   CXXForRangeStmt(Stmt *InitStmt, DeclStmt *Range, DeclStmt *Begin,
                   DeclStmt *End, Expr *Cond, Expr *Inc, DeclStmt *LoopVar,
                   Stmt *Body, SourceLocation FL, SourceLocation CAL,
-                  SourceLocation CL, SourceLocation RPL);
+                  SourceLocation CL, SourceLocation RPL, BranchHint Hint);
   CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { }
 
   Stmt *getInit() { return SubExprs[INIT]; }
@@ -160,6 +160,9 @@
   DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); }
   Stmt *getBody() { return SubExprs[BODY]; }
 
+  BranchHint getBranchHint() const { return CXXForRangeStmtBits.Hint; }
+  void setBranchHint(BranchHint Hint) { CXXForRangeStmtBits.Hint = Hint; }
+
   const DeclStmt *getRangeStmt() const {
     return cast<DeclStmt>(SubExprs[RANGE]);
   }
Index: clang/include/clang/AST/Stmt.h
===================================================================
--- clang/include/clang/AST/Stmt.h
+++ clang/include/clang/AST/Stmt.h
@@ -55,6 +55,11 @@
 class StringLiteral;
 class Token;
 class VarDecl;
+class CXXForRangeStmt;
+
+/// BranchHint - This indicate if a conditional statement is expected to be
+/// taken, not taken or no indication.
+enum class BranchHint : unsigned { BH_NoHint, BH_Taken, BH_NotTaken };
 
 //===----------------------------------------------------------------------===//
 // AST classes for statements.
@@ -175,6 +180,9 @@
     /// True if this if statement has storage for an init statement.
     unsigned HasInit : 1;
 
+    /// holds information about likeliness of the branch being taken
+    BranchHint Hint : 2;
+
     /// The location of the "if".
     SourceLocation IfLoc;
   };
@@ -208,6 +216,9 @@
     /// True if the WhileStmt has storage for a condition variable.
     unsigned HasVar : 1;
 
+    /// holds information about likeliness of the branch being taken
+    BranchHint Hint : 2;
+
     /// The location of the "while".
     SourceLocation WhileLoc;
   };
@@ -217,6 +228,9 @@
 
     unsigned : NumStmtBits;
 
+    /// holds information about likeliness of the branch being taken
+    BranchHint Hint : 2;
+
     /// The location of the "do".
     SourceLocation DoLoc;
   };
@@ -226,6 +240,9 @@
 
     unsigned : NumStmtBits;
 
+    /// holds information about likeliness of the branch being taken
+    BranchHint Hint : 2;
+
     /// The location of the "for".
     SourceLocation ForLoc;
   };
@@ -284,6 +301,15 @@
     SourceLocation KeywordLoc;
   };
 
+  class CXXForRangeStmtBitfields {
+    friend class CXXForRangeStmt;
+
+    unsigned : NumStmtBits;
+
+    /// holds information about likeliness of the branch being taken
+    BranchHint Hint : 2;
+  };
+
   //===--- Expression bitfields classes ---===//
 
   class ExprBitfields {
@@ -917,6 +943,9 @@
     ReturnStmtBitfields ReturnStmtBits;
     SwitchCaseBitfields SwitchCaseBits;
 
+    // C++ Statements
+    CXXForRangeStmtBitfields CXXForRangeStmtBits;
+
     // Expressions
     ExprBitfields ExprBits;
     PredefinedExprBitfields PredefinedExprBits;
@@ -1766,7 +1795,8 @@
 
   /// Build an if/then/else statement.
   IfStmt(const ASTContext &Ctx, SourceLocation IL, bool IsConstexpr, Stmt *Init,
-         VarDecl *Var, Expr *Cond, Stmt *Then, SourceLocation EL, Stmt *Else);
+         VarDecl *Var, Expr *Cond, Stmt *Then, SourceLocation EL, Stmt *Else,
+         BranchHint Hint);
 
   /// Build an empty if/then/else statement.
   explicit IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit);
@@ -1776,7 +1806,8 @@
   static IfStmt *Create(const ASTContext &Ctx, SourceLocation IL,
                         bool IsConstexpr, Stmt *Init, VarDecl *Var, Expr *Cond,
                         Stmt *Then, SourceLocation EL = SourceLocation(),
-                        Stmt *Else = nullptr);
+                        Stmt *Else = nullptr,
+                        BranchHint Hint = BranchHint::BH_NoHint);
 
   /// Create an empty IfStmt optionally with storage for an else statement,
   /// condition variable and init expression.
@@ -1792,6 +1823,9 @@
   /// True if this IfStmt has storage for an else statement.
   bool hasElseStorage() const { return IfStmtBits.HasElse; }
 
+  BranchHint getBranchHint() const { return IfStmtBits.Hint; }
+  void setBranchHint(BranchHint Hint) { IfStmtBits.Hint = Hint; }
+
   Expr *getCond() {
     return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[condOffset()]);
   }
@@ -2125,7 +2159,7 @@
 
   /// Build a while statement.
   WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, Stmt *Body,
-            SourceLocation WL);
+            SourceLocation WL, BranchHint Hint);
 
   /// Build an empty while statement.
   explicit WhileStmt(EmptyShell Empty, bool HasVar);
@@ -2133,7 +2167,7 @@
 public:
   /// Create a while statement.
   static WhileStmt *Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
-                           Stmt *Body, SourceLocation WL);
+                           Stmt *Body, SourceLocation WL, BranchHint Hint);
 
   /// Create an empty while statement optionally with storage for
   /// a condition variable.
@@ -2142,6 +2176,9 @@
   /// True if this WhileStmt has storage for a condition variable.
   bool hasVarStorage() const { return WhileStmtBits.HasVar; }
 
+  BranchHint getBranchHint() const { return WhileStmtBits.Hint; }
+  void setBranchHint(BranchHint Hint) { WhileStmtBits.Hint = Hint; }
+
   Expr *getCond() {
     return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[condOffset()]);
   }
@@ -2223,11 +2260,12 @@
 
 public:
   DoStmt(Stmt *Body, Expr *Cond, SourceLocation DL, SourceLocation WL,
-         SourceLocation RP)
+         SourceLocation RP, BranchHint Hint)
       : Stmt(DoStmtClass), WhileLoc(WL), RParenLoc(RP) {
     setCond(Cond);
     setBody(Body);
     setDoLoc(DL);
+    setBranchHint(Hint);
   }
 
   /// Build an empty do-while statement.
@@ -2240,6 +2278,9 @@
 
   void setCond(Expr *Cond) { SubExprs[COND] = reinterpret_cast<Stmt *>(Cond); }
 
+  BranchHint getBranchHint() const { return DoStmtBits.Hint; }
+  void setBranchHint(BranchHint Hint) { DoStmtBits.Hint = Hint; }
+
   Stmt *getBody() { return SubExprs[BODY]; }
   const Stmt *getBody() const { return SubExprs[BODY]; }
   void setBody(Stmt *Body) { SubExprs[BODY] = Body; }
@@ -2275,7 +2316,7 @@
 public:
   ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
           Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
-          SourceLocation RP);
+          SourceLocation RP, BranchHint Hint);
 
   /// Build an empty for statement.
   explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) {}
@@ -2299,6 +2340,9 @@
     return reinterpret_cast<DeclStmt*>(SubExprs[CONDVAR]);
   }
 
+  BranchHint getBranchHint() const { return ForStmtBits.Hint; }
+  void setBranchHint(BranchHint Hint) { ForStmtBits.Hint = Hint; }
+
   Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
   Expr *getInc()  { return reinterpret_cast<Expr*>(SubExprs[INC]); }
   Stmt *getBody() { return SubExprs[BODY]; }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to