diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2766,6 +2766,20 @@
   let Documentation = [TypeTagForDatatypeDocs];
 }
 
+def Owner : InheritableAttr {
+  let Spellings = [CXX11<"gsl", "Owner">];
+  let Subjects = SubjectList<[CXXRecord]>;
+  let Args = [TypeArgument<"DerefType">];
+  let Documentation = [LifetimeOwnerDocs];
+}
+
+def Pointer : InheritableAttr {
+  let Subjects = SubjectList<[CXXRecord]>;
+  let Spellings = [CXX11<"gsl", "Pointer">];
+  let Args = [TypeArgument<"DerefType">];
+  let Documentation = [LifetimePointerDocs];
+}
+
 // Microsoft-related attributes
 
 def MSNoVTable : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -4157,3 +4157,29 @@
 ``__attribute__((malloc))``.
 }];
 }
+
+def LifetimeOwnerDocs : Documentation {
+  let Category = DocCatFunction;
+  let Content = [{
+When annotating a class ``O`` with ``[[gsl::Owner(T)]]``, then each function
+that returns cv-qualified ``T&`` or ``T*`` is assumed to return a
+pointer/reference to the data owned by ``O``. The owned data is assumed to end
+its lifetime once the owning object's lifetime end.
+
+This attribute may be used by analysis tools but will not have effect on code
+generation.
+}];
+}
+
+def LifetimePointerDocs : Documentation {
+  let Category = DocCatFunction;
+  let Content = [{
+When annotating a class ``P`` with ``[[gsl::Pointer(T)]]``, it assumed to be a
+non-owning type whose objects can point to ``T`` type objects or dangle.
+This attribute may be used by analysis tools but will not have effect on code
+generation.
+
+For example ``std::vector<int>::iterator`` might be annotated
+``[[gsl::Pointer(int)]]``.
+}];
+}
\ No newline at end of file
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2513,6 +2513,8 @@
   "'NSObject' attribute is for pointer types only">;
 def err_attributes_are_not_compatible : Error<
   "%0 and %1 attributes are not compatible">;
+def err_attribute_invalid_argument : Error<
+  "%0 is an invalid argument to attribute %1">;
 def err_attribute_wrong_number_arguments : Error<
   "%0 attribute %plural{0:takes no arguments|1:takes one argument|"
   ":requires exactly %1 arguments}1">;
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -331,6 +331,15 @@
     IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
     ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
     SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
+
+  if (attributeIsTypeArgAttr(*AttrName)) {
+    ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
+                              ScopeLoc, Syntax);
+    // FIXME: when attributeIsTypeArgAttr() is true, assumes that the attribute
+    // takes a single parameter.
+    return 1;
+  }
+
   // Ignore the left paren location for now.
   ConsumeParen();
 
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2614,6 +2614,11 @@
       // C's _Noreturn is allowed to be added to a function after it is defined.
       ++I;
       continue;
+    } else if (isa<OwnerAttr>(NewAttribute) || isa<PointerAttr>(NewAttribute)) {
+      // gsl::Owner and gsl::Pointer are allowed to be added to a class after it
+      // is defined.
+      ++I;
+      continue;
     } else if (const AlignedAttr *AA = dyn_cast<AlignedAttr>(NewAttribute)) {
       if (AA->isAlignas()) {
         // C++11 [dcl.align]p6:
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4533,6 +4533,49 @@
       DiagnosticIdentifiers.size(), AL.getAttributeSpellingListIndex()));
 }
 
+static void handleLifetimeCategoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  if (!AL.hasParsedType()) {
+    S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
+    return;
+  }
+
+  TypeSourceInfo *DerefTypeLoc = nullptr;
+  QualType ParmType = S.GetTypeFromParser(AL.getTypeArg(), &DerefTypeLoc);
+  assert(DerefTypeLoc && "no type source info for attribute argument");
+
+  if (ParmType->isVoidType()) {
+    S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument) << "'void'" << AL;
+    return;
+  }
+
+  // To check if earlier decl attributes do not conflict the newly parsed ones
+  // we always add (and check) the attribute to the cannonical decl.
+  D = D->getCanonicalDecl();
+  if(AL.getKind() ==  ParsedAttr::AT_Owner) {
+    if (checkAttrMutualExclusion<PointerAttr>(S, D, AL))
+      return;
+    if (const auto *Attr = D->getAttr<OwnerAttr>()) {
+      if (Attr->getDerefType().getTypePtr() != ParmType.getTypePtr()) {
+        S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << Attr;
+        S.Diag(Attr->getLocation(), diag::note_conflicting_attribute);
+      }
+    }
+    D->addAttr(::new (S.Context) OwnerAttr(
+      AL.getRange(), S.Context, DerefTypeLoc, AL.getAttributeSpellingListIndex()));
+  } else {
+    if (checkAttrMutualExclusion<OwnerAttr>(S, D, AL))
+      return;
+    if (const auto *Attr = D->getAttr<PointerAttr>()) {
+      if (Attr->getDerefType().getTypePtr() != ParmType.getTypePtr()) {
+        S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << Attr;
+        S.Diag(Attr->getLocation(), diag::note_conflicting_attribute);
+      }
+    }
+    D->addAttr(::new (S.Context) PointerAttr(
+      AL.getRange(), S.Context, DerefTypeLoc, AL.getAttributeSpellingListIndex()));
+  }
+}
+
 bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
                                 const FunctionDecl *FD) {
   if (Attrs.isInvalid())
@@ -7110,6 +7153,10 @@
   case ParsedAttr::AT_Suppress:
     handleSuppressAttr(S, D, AL);
     break;
+  case ParsedAttr::AT_Owner:
+  case ParsedAttr::AT_Pointer:
+    handleLifetimeCategoryAttr(S, D, AL);
+    break;
   case ParsedAttr::AT_OpenCLKernel:
     handleSimpleAttribute<OpenCLKernelAttr>(S, D, AL);
     break;
diff --git a/clang/test/AST/ast-dump-attr.cpp b/clang/test/AST/ast-dump-attr.cpp
--- a/clang/test/AST/ast-dump-attr.cpp
+++ b/clang/test/AST/ast-dump-attr.cpp
@@ -211,6 +211,15 @@
     }
 }
 
+namespace TestLifetimeCategories {
+  class [[gsl::Owner(int)]] AOwner {};
+  // CHECK: CXXRecordDecl{{.*}} class AOwner
+  // CHECK: OwnerAttr {{.*}} int
+  class [[gsl::Pointer(int)]] APointer {};
+  // CHECK: CXXRecordDecl{{.*}} class APointer
+  // CHECK: PointerAttr {{.*}} int
+}
+
 // Verify the order of attributes in the Ast. It must reflect the order
 // in the parsed source.
 int mergeAttrTest() __attribute__((deprecated)) __attribute__((warn_unused_result));
diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -116,8 +116,10 @@
 // CHECK-NEXT: OpenCLNoSVM (SubjectMatchRule_variable)
 // CHECK-NEXT: OptimizeNone (SubjectMatchRule_function, SubjectMatchRule_objc_method)
 // CHECK-NEXT: Overloadable (SubjectMatchRule_function)
+// CHECK-NEXT: Owner (SubjectMatchRule_record)
 // CHECK-NEXT: ParamTypestate (SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter)
+// CHECK-NEXT: Pointer (SubjectMatchRule_record)
 // CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function)
 // CHECK-NEXT: ReqdWorkGroupSize (SubjectMatchRule_function)
 // CHECK-NEXT: RequireConstantInit (SubjectMatchRule_variable_is_global)
diff --git a/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp b/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp
new file mode 100644
--- /dev/null
+++ b/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp
@@ -0,0 +1,60 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int [[gsl::Owner]] i;
+// expected-error@-1 {{'Owner' attribute cannot be applied to types}}
+void [[gsl::Owner]] f();
+// expected-error@-1 {{'Owner' attribute cannot be applied to types}}
+
+[[gsl::Owner]] void f();
+ // expected-warning@-1 {{'Owner' attribute only applies to classes}}
+
+struct S {
+};
+
+S [[gsl::Owner]] Instance;
+// expected-error@-1 {{'Owner' attribute cannot be applied to types}}
+
+class [[gsl::Owner]] OwnerMissingParameter {};
+// expected-error@-1 {{'Owner' attribute takes one argument}}
+class [[gsl::Pointer]] PointerMissingParameter {};
+// expected-error@-1 {{'Pointer' attribute takes one argument}}
+
+class [[gsl::Owner(7)]] OwnerDerefNoType {};
+// expected-error@-1 {{expected a type}} expected-error@-1 {{expected ')'}}
+// expected-note@-2 {{to match this '('}}
+
+class [[gsl::Pointer("int")]] PointerDerefNoType {};
+// expected-error@-1 {{expected a type}} expected-error@-1 {{expected ')'}}
+// expected-note@-2 {{to match this '('}}
+
+class [[gsl::Owner(int)]] [[gsl::Pointer(int)]] BothOwnerPointer {};
+// expected-error@-1 {{'Pointer' and 'Owner' attributes are not compatible}}
+// expected-note@-2 {{conflicting attribute is here}}
+
+class [[gsl::Owner(int)]] [[gsl::Owner(int)]] DuplicateOwner {};
+
+class [[gsl::Pointer(int)]] [[gsl::Pointer(int)]] DuplicatePointer {};
+
+class [[gsl::Owner(void)]] OwnerVoidDerefType {};
+// expected-error@-1 {{'void' is an invalid argument to attribute 'Owner'}}
+class [[gsl::Pointer(void)]] PointerVoidDerefType {};
+// expected-error@-1 {{'void' is an invalid argument to attribute 'Pointer'}}
+
+class [[gsl::Owner(int)]] AnOwner {};
+class [[gsl::Pointer(S)]] APointer {};
+
+class AddOwnerLater {};
+class [[gsl::Owner(int)]] AddOwnerLater;
+
+class [[gsl::Pointer(int)]] AddConflictLater {};
+class [[gsl::Owner(int)]] AddConflictLater;
+// expected-error@-1 {{'Owner' and 'Pointer' attributes are not compatible}}
+// expected-note@-3 {{conflicting attribute is here}}
+
+class [[gsl::Owner(int)]] AddConflictLater2 {};
+class [[gsl::Owner(float)]] AddConflictLater2;
+// expected-error@-1 {{'Owner' and 'Owner' attributes are not compatible}}
+// expected-note@-3 {{conflicting attribute is here}}
+
+class [[gsl::Owner(int)]] AddTheSameLater {};
+class [[gsl::Owner(int)]] AddTheSameLater;
\ No newline at end of file