diff --git a/docs/ObjectiveCLiterals.rst b/docs/ObjectiveCLiterals.rst
index 8907c1e..e003af0 100644
--- a/docs/ObjectiveCLiterals.rst
+++ b/docs/ObjectiveCLiterals.rst
@@ -120,7 +120,8 @@ Objective-C provides a new syntax for boxing C expressions:
     @( <expression> )
 
 Expressions of scalar (numeric, enumerated, BOOL) and C string pointer
-types are supported:
+types are supported, as well as some NSFoundation C structures 
+(e.g. ``NSPoint``, ``NSRect``, etc.):
 
 .. code-block:: objc
 
@@ -136,6 +137,10 @@ types are supported:
     NSString *path = @(getenv("PATH"));       // [NSString stringWithUTF8String:(getenv("PATH"))]
     NSArray *pathComponents = [path componentsSeparatedByString:@":"];
 
+    // NS structs
+    NSValue *center = @(view.center);         // [NSValue valueWithPoint:view.center]
+    NSValue *frame = @(view.frame);           // [NSValue valueWithRect:view.frame]
+
 Boxed Enums
 -----------
 
@@ -218,6 +223,24 @@ character data is valid. Passing ``NULL`` as the character pointer will
 raise an exception at runtime. When possible, the compiler will reject
 ``NULL`` character pointers used in boxed expressions.
 
+Boxed C Structures
+------------------
+
+Some C structures might be boxed into a NSValue using corresponding class' 
+methods:
+
+.. code-block:: objc
+
+    NSPoint p;
+    NSValue *point = @(p);    // valueWithPoint
+    NSSize s;
+    NSValue *size = @(s);     // valueWithSize
+
+Full list of available types if programmer targets:
+
+  - OSX: ``NSPoint``, ``NSSize``, ``NSRect``, ``NSRange``
+  - iOS: ``CGPoint``, ``CGSize``, ``CGRect``, ``NSRange``
+
 Container Literals
 ==================
 
diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h
index 33fcce2..cc91b94 100644
--- a/include/clang/AST/NSAPI.h
+++ b/include/clang/AST/NSAPI.h
@@ -33,9 +33,10 @@ public:
     ClassId_NSMutableArray,
     ClassId_NSDictionary,
     ClassId_NSMutableDictionary,
-    ClassId_NSNumber
+    ClassId_NSNumber,
+    ClassId_NSValue
   };
-  static const unsigned NumClassIds = 7;
+  static const unsigned NumClassIds = 8;
 
   enum NSStringMethodKind {
     NSStr_stringWithString,
@@ -158,11 +159,26 @@ public:
   };
   static const unsigned NumNSNumberLiteralMethods = 15;
 
+  /// \brief Enumerates the NSValue methods used to generate literals.
+  enum NSValueLiteralMethodKind {
+    NSValueWithPoint,
+    NSValueWithSize,
+    NSValueWithRect,
+    NSValueWithCGPoint,
+    NSValueWithCGSize,
+    NSValueWithCGRect,
+    NSValueWithRange
+  };
+  static const unsigned NumNSValueLiteralMethods = 7;
+  
   /// \brief The Objective-C NSNumber selectors used to create NSNumber literals.
   /// \param Instance if true it will return the selector for the init* method
   /// otherwise it will return the selector for the number* method.
   Selector getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
                                       bool Instance) const;
+  
+  /// \brief The Objective-C NSValue selectors used to create NSValue literals.
+  Selector getNSValueLiteralSelector(NSValueLiteralMethodKind MK) const;
 
   bool isNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
                                  Selector Sel) const {
@@ -178,6 +194,11 @@ public:
   /// literal of the given type.
   Optional<NSNumberLiteralMethodKind>
       getNSNumberFactoryMethodKind(QualType T) const;
+  
+  /// \brief Determine the appropriate NSValue factory method kind for a
+  /// literal of the given type.
+  Optional<NSValueLiteralMethodKind>
+      getNSValueFactoryMethodKind(QualType T) const;
 
   /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
   bool isObjCBOOLType(QualType T) const;
@@ -185,12 +206,27 @@ public:
   bool isObjCNSIntegerType(QualType T) const;
   /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
   bool isObjCNSUIntegerType(QualType T) const;
+  /// \brief Returns true if \param T is a typedef of "NSPoint" in objective-c.
+  bool isObjCNSPointType(QualType T) const;
+  /// \brief Returns true if \param T is a typedef of "NSSize" in objective-c.
+  bool isObjCNSSizeType(QualType T) const;
+  /// \brief Returns true if \param T is a typedef of "NSRect" in objective-c.
+  bool isObjCNSRectType(QualType T) const;
+  /// \brief Returns true if \param T is a typedef of "CGPoint" in objective-c.
+  bool isObjCCGPointType(QualType T) const;
+  /// \brief Returns true if \param T is a typedef of "CGSize" in objective-c.
+  bool isObjCCGSizeType(QualType T) const;
+  /// \brief Returns true if \param T is a typedef of "CGRect" in objective-c.
+  bool isObjCCGRectType(QualType T) const;
+  /// \brief Returns true if \param T is a typedef of "NSRange" in objective-c.
+  bool isObjCNSRangeType(QualType T) const;
   /// \brief Returns one of NSIntegral typedef names if \param T is a typedef
   /// of that name in objective-c.
   StringRef GetNSIntegralKind(QualType T) const;
 
 private:
   bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const;
+  bool isObjCStructure(QualType T, StringRef name) const;
   bool isObjCEnumerator(const Expr *E,
                         StringRef name, IdentifierInfo *&II) const;
   Selector getOrInitSelector(ArrayRef<StringRef> Ids, Selector &Sel) const;
@@ -210,6 +246,9 @@ private:
   /// \brief The Objective-C NSNumber selectors used to create NSNumber literals.
   mutable Selector NSNumberClassSelectors[NumNSNumberLiteralMethods];
   mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods];
+  
+  /// \brief The Objective-C NSValue selectors used to create NSValue literals.
+  mutable Selector NSValueClassSelectors[NumNSValueLiteralMethods];
 
   mutable Selector objectForKeyedSubscriptSel, objectAtIndexedSubscriptSel,
                    setObjectForKeyedSubscriptSel,setObjectAtIndexedSubscriptSel,
@@ -217,6 +256,9 @@ private:
 
   mutable IdentifierInfo *BOOLId, *NSIntegerId, *NSUIntegerId;
   mutable IdentifierInfo *NSASCIIStringEncodingId, *NSUTF8StringEncodingId;
+  mutable IdentifierInfo *NSPointId, *NSSizeId, *NSRectId;
+  mutable IdentifierInfo *CGPointId, *CGSizeId, *CGRectId;
+  mutable IdentifierInfo *NSRangeId;
 };
 
 }  // end namespace clang
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index deb8685..9012e56 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2035,8 +2035,12 @@ def err_attr_objc_ownership_redundant : Error<
   "the type %0 is already explicitly ownership-qualified">;
 def err_undeclared_nsnumber : Error<
   "NSNumber must be available to use Objective-C literals">;
+def err_undeclared_nsvalue : Error<
+  "NSValue must be available to use Objective-C literals">;
 def err_invalid_nsnumber_type : Error<
   "%0 is not a valid literal type for NSNumber">;
+def err_invalid_nsvalue_type : Error<
+  "%0 is not a valid literal type for NSValue">;
 def err_undeclared_nsstring : Error<
   "cannot box a string value because NSString has not been declared">;
 def err_objc_illegal_boxed_expression_type : Error<
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 96dec47..c123c0a 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -661,11 +661,20 @@ public:
   /// \brief The declaration of the Objective-C NSNumber class.
   ObjCInterfaceDecl *NSNumberDecl;
 
+  /// \brief The declaration of the Objective-C NSValue class.
+  ObjCInterfaceDecl *NSValueDecl;
+
   /// \brief Pointer to NSNumber type (NSNumber *).
   QualType NSNumberPointer;
+    
+  /// \brief Pointer to NSValue type (NSValue *).
+  QualType NSValuePointer;
 
   /// \brief The Objective-C NSNumber methods used to create NSNumber literals.
   ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods];
+  
+  /// \brief The Objective-C NSValue methods used to create NSValue literals.
+  ObjCMethodDecl *NSValueLiteralMethods[NSAPI::NumNSValueLiteralMethods];
 
   /// \brief The declaration of the Objective-C NSString class.
   ObjCInterfaceDecl *NSStringDecl;
diff --git a/lib/AST/NSAPI.cpp b/lib/AST/NSAPI.cpp
index 3dc750a..4617d52 100644
--- a/lib/AST/NSAPI.cpp
+++ b/lib/AST/NSAPI.cpp
@@ -17,7 +17,9 @@ using namespace clang;
 NSAPI::NSAPI(ASTContext &ctx)
   : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
     NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
-    NSUTF8StringEncodingId(nullptr) {}
+    NSUTF8StringEncodingId(nullptr), NSPointId(nullptr),
+    NSSizeId(nullptr), NSRectId(nullptr), CGPointId(nullptr),
+    CGSizeId(nullptr), CGRectId(nullptr), NSRangeId(nullptr) {}
 
 IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
   static const char *ClassName[NumClassIds] = {
@@ -27,7 +29,8 @@ IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
     "NSMutableArray",
     "NSDictionary",
     "NSMutableDictionary",
-    "NSNumber"
+    "NSNumber",
+    "NSValue"
   };
 
   if (!ClassIds[K])
@@ -279,6 +282,25 @@ Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
   return Sels[MK];
 }
 
+Selector NSAPI::getNSValueLiteralSelector(NSValueLiteralMethodKind MK) const {
+  static const char *ClassSelectorName[NumNSValueLiteralMethods] = {
+    "valueWithPoint",
+    "valueWithSize",
+    "valueWithRect",
+    "valueWithCGPoint",
+    "valueWithCGSize",
+    "valueWithCGRect",
+    "valueWithRange",
+  };
+  
+  Selector *Sels = NSValueClassSelectors;
+  const char **Names = ClassSelectorName;
+  
+  if (Sels[MK].isNull())
+    Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
+  return Sels[MK];
+}
+
 Optional<NSAPI::NSNumberLiteralMethodKind>
 NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
   for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
@@ -371,6 +393,30 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
   return None;
 }
 
+Optional<NSAPI::NSValueLiteralMethodKind>
+NSAPI::getNSValueFactoryMethodKind(QualType T) const {
+  const RecordType *RT = T->getAsStructureType();
+  if (!RT)
+    return None;
+  
+  if (isObjCNSPointType(T))
+    return NSAPI::NSValueWithPoint;
+  if (isObjCNSSizeType(T))
+    return NSAPI::NSValueWithSize;
+  if (isObjCNSRectType(T))
+    return NSAPI::NSValueWithRect;
+  if (isObjCCGPointType(T))
+    return NSAPI::NSValueWithCGPoint;
+  if (isObjCCGSizeType(T))
+    return NSAPI::NSValueWithCGSize;
+  if (isObjCCGRectType(T))
+    return NSAPI::NSValueWithCGRect;
+  if (isObjCNSRangeType(T))
+    return NSAPI::NSValueWithRange;
+  
+  return None;
+}
+
 /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
 bool NSAPI::isObjCBOOLType(QualType T) const {
   return isObjCTypedef(T, "BOOL", BOOLId);
@@ -384,6 +430,41 @@ bool NSAPI::isObjCNSUIntegerType(QualType T) const {
   return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
 }
 
+/// \brief Returns true if \param T is a typedef of "NSPoint" in objective-c.
+bool NSAPI::isObjCNSPointType(QualType T) const {
+  return isObjCTypedef(T, "NSPoint", NSPointId);
+}
+
+/// \brief Returns true if \param T is a typedef of "NSSize" in objective-c.
+bool NSAPI::isObjCNSSizeType(QualType T) const {
+  return isObjCTypedef(T, "NSSize", NSSizeId);
+}
+
+/// \brief Returns true if \param T is a typedef of "NSRect" in objective-c.
+bool NSAPI::isObjCNSRectType(QualType T) const {
+  return isObjCTypedef(T, "NSRect", NSRectId);
+}
+
+/// \brief Returns true if \param T is a typedef of "CGPoint" in objective-c.
+bool NSAPI::isObjCCGPointType(QualType T) const {
+  return isObjCTypedef(T, "CGPoint", CGPointId);
+}
+
+/// \brief Returns true if \param T is a typedef of "CGSize" in objective-c.
+bool NSAPI::isObjCCGSizeType(QualType T) const {
+  return isObjCTypedef(T, "CGSize", CGSizeId);
+}
+
+/// \brief Returns true if \param T is a typedef of "CGRect" in objective-c.
+bool NSAPI::isObjCCGRectType(QualType T) const {
+  return isObjCTypedef(T, "CGRect", CGRectId);
+}
+
+/// \brief Returns true if \param T is a typedef of "NSRange" in objective-c.
+bool NSAPI::isObjCNSRangeType(QualType T) const {
+  return isObjCTypedef(T, "NSRange", NSRangeId);
+}
+
 StringRef NSAPI::GetNSIntegralKind(QualType T) const {
   if (!Ctx.getLangOpts().ObjC1 || T.isNull())
     return StringRef();
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 7cb3c0a..00b65a7 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -255,6 +255,92 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
   return Method;
 }
 
+/// \brief Retrieve the NSValue factory method that should be used to create
+/// an Objective-C literal for the given type.
+static ObjCMethodDecl *getNSValueFactoryMethod(Sema &S, SourceLocation Loc,
+                                               QualType ValueType,
+                                               bool isLiteral = false,
+                                               SourceRange R = SourceRange()) {
+  Optional<NSAPI::NSValueLiteralMethodKind> Kind =
+  S.NSAPIObj->getNSValueFactoryMethodKind(ValueType);
+  
+  if (!Kind) {
+    if (isLiteral) {
+      S.Diag(Loc, diag::err_invalid_nsvalue_type)
+      << ValueType << R;
+    }
+    return nullptr;
+  }
+  
+  // If we already looked up this method, we're done.
+  if (S.NSValueLiteralMethods[*Kind])
+    return S.NSValueLiteralMethods[*Kind];
+  
+  Selector Sel = S.NSAPIObj->getNSValueLiteralSelector(*Kind);
+  
+  ASTContext &CX = S.Context;
+  
+  // Look up the NSValue class, if we haven't done so already. It's cached
+  // in the Sema instance.
+  if (!S.NSValueDecl) {
+    IdentifierInfo *NSValueId =
+    S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSValue);
+    NamedDecl *IF = S.LookupSingleName(S.TUScope, NSValueId,
+                                       Loc, Sema::LookupOrdinaryName);
+    S.NSValueDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+    if (!S.NSValueDecl) {
+      if (S.getLangOpts().DebuggerObjCLiteral) {
+        // Create a stub definition of NSValue.
+        S.NSValueDecl = ObjCInterfaceDecl::Create(CX,
+                                                  CX.getTranslationUnitDecl(),
+                                                  SourceLocation(), NSValueId,
+                                                  nullptr, SourceLocation());
+      } else {
+        // Otherwise, require a declaration of NSValue.
+        S.Diag(Loc, diag::err_undeclared_nsvalue);
+        return nullptr;
+      }
+    } else if (!S.NSValueDecl->hasDefinition()) {
+      S.Diag(Loc, diag::err_undeclared_nsvalue);
+      return nullptr;
+    }
+    
+    // generate the pointer to NSValue type.
+    QualType NSValueObject = CX.getObjCInterfaceType(S.NSValueDecl);
+    S.NSValuePointer = CX.getObjCObjectPointerType(NSValueObject);
+  }
+  
+  // Look for the appropriate method within NSValue.
+  ObjCMethodDecl *Method = S.NSValueDecl->lookupClassMethod(Sel);
+  if (!Method && S.getLangOpts().DebuggerObjCLiteral) {
+    // create a stub definition this NSValue factory method.
+    TypeSourceInfo *ReturnTInfo = nullptr;
+    Method =
+    ObjCMethodDecl::Create(CX, SourceLocation(), SourceLocation(), Sel,
+                           S.NSValuePointer, ReturnTInfo, S.NSValueDecl,
+                           /*isInstance=*/false, /*isVariadic=*/false,
+                           /*isPropertyAccessor=*/false,
+                           /*isImplicitlyDeclared=*/true,
+                           /*isDefined=*/false, ObjCMethodDecl::Required,
+                           /*HasRelatedResultType=*/false);
+    ParmVarDecl *value = ParmVarDecl::Create(S.Context, Method,
+                                             SourceLocation(), SourceLocation(),
+                                             &CX.Idents.get("value"),
+                                             ValueType, /*TInfo=*/nullptr,
+                                             SC_None, nullptr);
+    Method->setMethodParams(S.Context, value, None);
+  }
+  
+  if (!validateBoxingMethod(S, Loc, S.NSValueDecl, Sel, Method))
+    return nullptr;
+  
+  // Note: if the parameter type is out-of-line, we'll catch it later in the
+  // implicit conversion.
+  
+  S.NSValueLiteralMethods[*Kind] = Method;
+  return Method;
+}
+
 /// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the
 /// numeric literal expression. Type of the expression will be "NSNumber *".
 ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) {
@@ -527,10 +613,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
       BoxedType = NSStringPointer;
     }
   } else if (ValueType->isBuiltinType()) {
-    // The other types we support are numeric, char and BOOL/bool. We could also
-    // provide limited support for structure types, such as NSRange, NSRect, and
-    // NSSize. See NSValue (NSValueGeometryExtensions) in <Foundation/NSGeometry.h>
-    // for more details.
+    // The other types we support are numeric, char and BOOL/bool.
 
     // Check for a top-level character literal.
     if (const CharacterLiteral *Char =
@@ -562,6 +645,15 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
     BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), ValueType);
     BoxedType = NSNumberPointer;
 
+  } else if (ValueType->isStructureType()) {
+    // Limited support for structure types, such as NSRange,
+    // NSRect, and NSSize. See NSValue (NSValueGeometryExtensions)
+    // in <Foundation/NSGeometry.h> for more details.
+      
+    // Look for the appropriate method within NSValue.
+    BoxingMethod = getNSValueFactoryMethod(*this, SR.getBegin(), ValueType);
+    BoxedType = NSValuePointer;
+    
   } else if (const EnumType *ET = ValueType->getAs<EnumType>()) {
     if (!ET->getDecl()->isComplete()) {
       Diag(SR.getBegin(), diag::err_objc_incomplete_boxed_expression_type)
diff --git a/test/SemaObjC/objc-literal-nsvalue.m b/test/SemaObjC/objc-literal-nsvalue.m
new file mode 100644
index 0000000..dd5c781
--- /dev/null
+++ b/test/SemaObjC/objc-literal-nsvalue.m
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1  -fsyntax-only -fblocks -triple x86_64-apple-darwin10 -verify %s
+
+typedef struct _NSPoint {
+  int dummy;
+} NSPoint;
+
+typedef struct _NSSize {
+  int dummy;
+} NSSize;
+
+typedef struct _NSRect {
+  int dummy;
+} NSRect;
+
+typedef struct _CGPoint {
+  int dummy;
+} CGPoint;
+
+typedef struct _CGSize {
+  int dummy;
+} CGSize;
+
+typedef struct _CGRect {
+  int dummy;
+} CGRect;
+
+typedef struct _NSRange {
+  int dummy;
+} NSRange;
+
+typedef struct _SomeStruct {
+  double d;
+} SomeStruct;
+
+@interface NSValue
++ (NSValue *)valueWithPoint:(NSPoint)point;
++ (NSValue *)valueWithSize:(NSSize)size;
++ (NSValue *)valueWithRect:(NSRect)rect;
+
++ (NSValue *)valueWithCGPoint:(CGPoint)point;
++ (NSValue *)valueWithCGSize:(CGSize)size;
++ (NSValue *)valueWithCGRect:(CGRect)rect;
+
++ (NSValue *)valueWithRange:(NSRange)range;
+@end
+
+int main() {
+  NSPoint p;
+  id point = @(p); // no-warning
+
+  NSSize sz;
+  id size = @(sz); // no-warning
+
+  NSRect re;
+  id rect = @(re); // no-warning
+
+  CGPoint cgp;
+  id cgpoint = @(cgp); // no-warning
+
+  CGSize cgsz;
+  id cgsize = @(cgsz); // no-warning
+
+  CGRect cgre;
+  id cgrect = @(cgre); // no-warning
+
+  NSRange rn;
+  id range = @(rn); // no-warning
+
+  SomeStruct s;
+  id err = @(s); // expected-error{{illegal type 'SomeStruct' (aka 'struct _SomeStruct') used in a boxed expression}}
+}
+
