diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 517fd1967fcabe71c97fbc642f966ef12416a2e6..bcd75e5ac47f77f42f7571571e58d82d1cd2cbf7 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -2181,6 +2181,20 @@ def Loopbound : Attr {
   }];
 }
 
+def PlatinaGuard : Attr {
+  // #pragma platina guard <str>
+  let Spellings = [Pragma<"platina", "guard">];
+  let Args = [StringArgument<"GuardExpr">];
+
+  let Documentation = [Undocumented];
+
+  let AdditionalMembers = [{
+    void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
+      OS << guardExpr << "\n";
+    }
+  }];
+}
+
 def CapturedRecord : InheritableAttr {
   // This attribute has no spellings as it is only ever created implicitly.
   let Spellings = [];
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index fbed8c73d6a0f84ca16af0426a660a81517512ff..b267b94c32ddb6b61759c4dcd3ef8d743fe98479 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -990,4 +990,13 @@ def err_pragma_loopbound_malformed : Error<
 def err_pragma_platin_malformed : Error<
   "platin pragma needs to be flowfact: (c1 @x + c2 @y <= c3)">;
 
+// - #pragma platina
+def err_pragma_platinaguard_no_stringliteral : Error<
+  "pragma platina guard is malformed; expecting "
+  "'#pragma platina guard \"expr\"'">;
+def err_pragma_platinaguard_malformed : Error<
+  "pragma platina guard is malformed; "
+  "spurious tokens at end of pragma; expecting "
+  "'#pragma platina guard \"expr\"'">;
+
 } // end of Parser diagnostics
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 97817af35f5a51bf27eb4954759f5638b28ebc7a..0d94e923baa495e225e70705791590ed41e54268 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -662,6 +662,8 @@ def err_pragma_loop_precedes_nonloop : Error<
   "expected a for, while, or do-while loop to follow '%0'">;
 def err_pragma_loopbound_invalid_values : Error<
   "invalid values; expected min >= 0 && max >= 0 && min <= max">;
+def err_pragma_platinaguard_invalid_expr : Error<
+  "invalid Attribute operand; expected a StringLiteral">;
 
 /// Objective-C parser diagnostics
 def err_duplicate_class_def : Error<
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index 02c43053039f95ee0d6bf33424957431d7880cff..1d28620b515f2a5f5b2d9939b8038c4ee0f674c4 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -770,6 +770,11 @@ ANNOTATION(pragma_loop_hint)
 // handles #pragma loopbound ... directives.
 ANNOTATION(pragma_loopbound)
 
+// Annotations for #pragma loopbound
+// The lexer produces these so that they only take effect when the parser
+// handles #pragma loopbound ... directives.
+ANNOTATION(pragma_platinaguard)
+
 // Annotations for platin #pragmas
 ANNOTATION(pragma_platinff)
 ANNOTATION(pragma_platinff_end)
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index d501fdc50835465874ff60092e219cf46e0af7e1..6a7a77538e81f9776b0086490139fe57748fa5d8 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -22,6 +22,7 @@
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/Loopbound.h"
 #include "clang/Sema/LoopHint.h"
+#include "clang/Sema/PlatinaGuard.h"
 #include "clang/Sema/Sema.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Compiler.h"
@@ -167,6 +168,7 @@ class Parser : public CodeCompletionHandler {
   std::unique_ptr<PragmaHandler> MSRuntimeChecks;
   std::unique_ptr<PragmaHandler> OptimizeHandler;
   std::unique_ptr<PragmaHandler> LoopboundHandler;
+  std::unique_ptr<PragmaHandler> PlatinaGuardHandler;
   std::unique_ptr<PragmaHandler> PlatinHandler;
   std::unique_ptr<PragmaHandler> LoopHintHandler;
   std::unique_ptr<PragmaHandler> UnrollHintHandler;
@@ -536,6 +538,10 @@ private:
   /// #pragma loopbound
   void HandlePragmaLoopbound(Loopbound &LB);
 
+  /// \brief Handle the annotation token produced for
+  /// #pragma platina guard
+  void HandlePragmaPlatinaGuard(PlatinaGuard &PG);
+
   /// \brief Handle the annotation token produced for
   /// #pragma clang loop and #pragma unroll.
   bool HandlePragmaLoopHint(LoopHint &Hint);
@@ -1702,6 +1708,10 @@ private:
                                  AllowedContsructsKind Allowed,
                                  SourceLocation *TrailingElseLoc,
                                  ParsedAttributesWithRange &Attrs);
+  StmtResult ParsePragmaPlatinaGuard(StmtVector &Stmts,
+                                     AllowedContsructsKind Allowed,
+                                     SourceLocation *TrailingElseLoc,
+                                     ParsedAttributesWithRange &Attrs);
 
   /// \brief Describes the behavior that should be taken for an __if_exists
   /// block.
diff --git a/include/clang/Sema/PlatinaGuard.h b/include/clang/Sema/PlatinaGuard.h
new file mode 100644
index 0000000000000000000000000000000000000000..7321f2c11f7fab8aa169cc3ccb8960422382c864
--- /dev/null
+++ b/include/clang/Sema/PlatinaGuard.h
@@ -0,0 +1,35 @@
+//===--- PlatinaGuard.h - Types for Loopbound ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_PLATINAGUARD_H
+#define LLVM_CLANG_SEMA_PLATINAGUARD_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/AttributeList.h"
+#include "clang/Sema/Ownership.h"
+
+namespace clang {
+
+/// \brief PlatinaGuard pragmas.
+struct PlatinaGuard {
+  // Source range of the directive.
+  SourceRange Range;
+  // Identifier corresponding to the name of the pragma ("guard")
+  IdentifierLoc *PragmaNameLoc;
+  // String of the guardexpression
+  Expr * GuardExpr;
+
+  PlatinaGuard()
+      : PragmaNameLoc(NULL), GuardExpr(NULL) {}
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_PLATINAGUARD_H
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index f08e3aaa08ed6920bcfdb954ba849768a061eac4..f6f9827399f033f750a1f56aefe98ce793b2d97d 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -487,8 +487,34 @@ void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
   EmitStmt(S.getSubStmt());
 }
 
+
+void CodeGenFunction::EmitPlatinaIntrinsic(const ArrayRef<const Attr*> &Attrs) {
+  using namespace llvm;
+  for (unsigned i = 0; i < Attrs.size(); ++i) {
+    const Attr *A = Attrs[i];
+    const PlatinaGuardAttr *PG = dyn_cast<PlatinaGuardAttr>(A);
+
+    // Skip non PlatinaGuard attributes
+    if (!PG) continue;
+
+    Function *Callee =
+      CGM.getIntrinsic(Intrinsic::platina);
+    CallInst *callsite = Builder.CreateCall(Callee);
+
+    // Attach the guardexpr to the instruction-metadata
+    // We have to store our string in the LLVMContext
+    LLVMContext& C = callsite->getContext();
+    MDNode *meta = MDNode::get(C, MDString::get(C, PG->getGuardExpr()));
+    callsite->setMetadata("platina.guardexpr", meta);
+  }
+}
+
 void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
   const Stmt *SubStmt = S.getSubStmt();
+
+  // We translate the platina expressions to intrinsics, which should happen here
+  EmitPlatinaIntrinsic(S.getAttrs());
+
   switch (SubStmt->getStmtClass()) {
   case Stmt::DoStmtClass:
     EmitDoStmt(cast<DoStmt>(*SubStmt), S.getAttrs());
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 21fc3bd77c893e2a9eb5fc59525361505a1acae2..17118442b399f51069293e689a5a5a8aadf97ce4 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -2142,6 +2142,8 @@ public:
   void EmitHeaderBounds(llvm::BasicBlock *Header,
                         const ArrayRef<const Attr *> &Attrs);
 
+  void EmitPlatinaIntrinsic(const ArrayRef<const Attr*> &Attrs);
+
   void EmitWhileStmt(const WhileStmt &S,
                      ArrayRef<const Attr *> Attrs = None);
   void EmitDoStmt(const DoStmt &S, ArrayRef<const Attr *> Attrs = None);
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index 85db7610fe9b34f4e8f7127efcac3ff4c89555e8..1705cce40e148791dab50049a6da56eb7d65da95 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -19,8 +19,10 @@
 #include "clang/Parse/Parser.h"
 #include "clang/Sema/Loopbound.h"
 #include "clang/Sema/LoopHint.h"
+#include "clang/Sema/PlatinaGuard.h"
 #include "clang/Sema/Scope.h"
 #include "llvm/ADT/StringSwitch.h"
+#include <iostream>
 using namespace clang;
 
 namespace {
@@ -151,6 +153,12 @@ struct PragmaLoopboundHandler : public PragmaHandler {
                     Token &FirstToken) override;
 };
 
+struct PragmaPlatinaGuardHandler : public PragmaHandler {
+  PragmaPlatinaGuardHandler() : PragmaHandler("guard") {}
+  void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+                    Token &FirstToken) override;
+};
+
 struct PragmaPlatinHandler : public PragmaHandler {
   PragmaPlatinHandler() : PragmaHandler("platin") { }
   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
@@ -249,6 +257,9 @@ void Parser::initializePragmaHandlers() {
   LoopboundHandler.reset(new PragmaLoopboundHandler());
   PP.AddPragmaHandler(LoopboundHandler.get());
 
+  PlatinaGuardHandler.reset(new PragmaPlatinaGuardHandler());
+  PP.AddPragmaHandler("platina", PlatinaGuardHandler.get());
+
   PlatinHandler.reset(new PragmaPlatinHandler());
   PP.AddPragmaHandler(PlatinHandler.get());
 
@@ -329,6 +340,9 @@ void Parser::resetPragmaHandlers() {
   PP.RemovePragmaHandler(LoopboundHandler.get());
   LoopboundHandler.reset();
 
+  PP.RemovePragmaHandler("platina", PlatinaGuardHandler.get());
+  PlatinaGuardHandler.reset();
+
   PP.RemovePragmaHandler("clang", LoopHintHandler.get());
   LoopHintHandler.reset();
 
@@ -1956,7 +1970,7 @@ void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
     return;
   }
   PP.Lex(Tok);
-  
+
   if (Tok.isNot(tok::eod)) {
     PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
       << PP.getSpelling(Tok);
@@ -2023,6 +2037,72 @@ void PragmaLoopboundHandler::HandlePragma(Preprocessor &PP,
                       /*OwnsTokens=*/true);
 }
 
+namespace {
+struct PragmaPlatinaGuardInfo {
+  Token PragmaName;
+  Token GuardExpr;
+};
+} // end anonymous namespace
+
+// #pragma platina guard "expr"
+void PragmaPlatinaGuardHandler::HandlePragma(Preprocessor &PP,
+                                             PragmaIntroducerKind Introducer,
+                                             Token &FirstTok) {
+
+  Token Tok;
+
+  // Get the next token, we do not want to expand it, as guardexpr
+  // is a language of its own
+  PP.LexUnexpandedToken(Tok);
+
+  if (Tok.isNot(tok::string_literal)) {
+    PP.Diag(Tok.getLocation(), diag::err_pragma_platinaguard_no_stringliteral);
+    return;
+  }
+
+  PragmaPlatinaGuardInfo *Info =
+    new (PP.getPreprocessorAllocator()) PragmaPlatinaGuardInfo;
+
+  Info->PragmaName = FirstTok;
+  Info->GuardExpr  = Tok;
+
+  // Lex the next token
+  PP.Lex(Tok);
+  if (Tok.isNot(tok::eod)) {
+    PP.Diag(Tok.getLocation(), diag::err_pragma_platinaguard_malformed);
+    return;
+  }
+
+  Token out;
+  out.startToken();
+  out.setKind(tok::annot_pragma_platinaguard);
+  out.setLocation(FirstTok.getLocation());
+  out.setAnnotationValue(static_cast<void *>(Info));
+  PP.EnterToken(out);
+}
+
+void Parser::HandlePragmaPlatinaGuard(PlatinaGuard &PG) {
+  assert(Tok.is(tok::annot_pragma_platinaguard));
+
+  PragmaPlatinaGuardInfo *Info =
+      static_cast<PragmaPlatinaGuardInfo *>(Tok.getAnnotationValue());
+  ConsumeToken(); // The annotation token.
+
+  PG.PragmaNameLoc = IdentifierLoc::create(
+      Actions.Context,
+      Info->PragmaName.getLocation(),
+      Info->PragmaName.getIdentifierInfo()
+      );
+
+  Token toks[1];
+  toks[0] = Info->GuardExpr;
+  PG.GuardExpr = Actions.ActOnStringLiteral(toks, nullptr).get();
+
+  // Determine which token ends our pragms:
+  PG.Range =
+        SourceRange(Info->PragmaName.getLocation(), Info->GuardExpr.getLocation());
+}
+
 void
 PragmaPlatinHandler::HandlePragma(Preprocessor &PP,
                                   PragmaIntroducerKind Introducer,
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 3993b51573b46ee15235e33fd7c4a271df9d3fce..7bbb3b5cb43e5a97dc5f433342c87743a9236f67 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -377,6 +377,10 @@ Retry:
     ProhibitAttributes(Attrs);
     return ParsePlatinPragma();
 
+  case tok::annot_pragma_platinaguard:
+    ProhibitAttributes(Attrs);
+    return ParsePragmaPlatinaGuard(Stmts, Allowed, TrailingElseLoc, Attrs);
+
   case tok::annot_pragma_loop_hint:
     ProhibitAttributes(Attrs);
     return ParsePragmaLoopHint(Stmts, Allowed, TrailingElseLoc, Attrs);
@@ -1944,6 +1948,34 @@ StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts,
   return S;
 }
 
+StmtResult Parser::ParsePragmaPlatinaGuard(StmtVector &Stmts,
+                                           AllowedContsructsKind Allowed,
+                                           SourceLocation *TrailingElseLoc,
+                                           ParsedAttributesWithRange &Attrs) {
+  // Create temporary attribute list.
+  ParsedAttributesWithRange TempAttrs(AttrFactory);
+
+  // Get loop hints and consume annotated token.
+  while (Tok.is(tok::annot_pragma_platinaguard)) {
+    PlatinaGuard guard;
+    HandlePragmaPlatinaGuard(guard);
+
+    ArgsUnion ArgPG[] = {ArgsUnion(guard.GuardExpr)};
+    TempAttrs.addNew(guard.PragmaNameLoc->Ident, guard.Range, nullptr,
+                       guard.PragmaNameLoc->Loc, ArgPG, 4,
+                       AttributeList::AS_Pragma);
+  }
+
+  // Get the next statement.
+  MaybeParseCXX11Attributes(Attrs);
+
+  StmtResult S = ParseStatementOrDeclarationAfterAttributes(
+      Stmts, Allowed, TrailingElseLoc, Attrs);
+
+  Attrs.takeAllFrom(TempAttrs);
+  return S;
+}
+
 Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) {
   assert(Tok.is(tok::l_brace));
   SourceLocation LBraceLoc = Tok.getLocation();
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index 52e19fa3546ad1e15bbfa5d5a698034b83011f09..7315f1519bb5637985dcc06ff272496c80d3167d 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -160,6 +160,24 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
                                       ValueExpr, A.getRange());
 }
 
+static Attr *handlePlatinaGuardAttr(Sema &S, Stmt *St, const AttributeList &A,
+                                    SourceRange Range) {
+  Expr *Expr = A.getArgAsExpr(0);
+
+  assert(Expr != NULL);
+
+  if (!StringLiteral::classof(Expr)) {
+    S.Diag(A.getLoc(), diag::err_pragma_platinaguard_invalid_expr);
+	return nullptr;
+  }
+
+  StringLiteral *str = cast<StringLiteral>(Expr);
+  StringRef val = str->getString();
+
+  return ::new (S.Context) PlatinaGuardAttr(A.getRange(), S.Context,
+      val, A.getAttributeSpellingListIndex());
+}
+
 static void
 CheckForIncompatibleAttributes(Sema &S,
                                const SmallVectorImpl<const Attr *> &Attrs) {
@@ -250,6 +268,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
     return handleLoopboundAttr(S, St, A, Range);
   case AttributeList::AT_LoopHint:
     return handleLoopHintAttr(S, St, A, Range);
+  case AttributeList::AT_PlatinaGuard:
+    return handlePlatinaGuardAttr(S, St, A, Range);
   default:
     // if we're here, then we parsed a known attribute, but didn't recognize
     // it as a statement attribute => it is declaration attribute