r179585 - Basic support for Microsoft property declarations and

John McCall rjmccall at apple.com
Tue Apr 16 00:28:32 PDT 2013


Author: rjmccall
Date: Tue Apr 16 02:28:30 2013
New Revision: 179585

URL: http://llvm.org/viewvc/llvm-project?rev=179585&view=rev
Log:
Basic support for Microsoft property declarations and
references thereto.

Patch by Tong Shen!

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/DeclNodes.td
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/StmtNodes.td
    cfe/trunk/include/clang/Sema/AttributeList.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Sema/Template.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprClassification.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtProfile.cpp
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Sema/AttributeList.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaExprMember.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaPseudoObject.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTCommon.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/test/Parser/MicrosoftExtensions.cpp
    cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp
    cfe/trunk/test/SemaObjC/property-user-setter.m
    cfe/trunk/tools/libclang/CIndex.cpp
    cfe/trunk/tools/libclang/CXCursor.cpp
    cfe/trunk/tools/libclang/IndexBody.cpp
    cfe/trunk/tools/libclang/IndexDecl.cpp
    cfe/trunk/tools/libclang/IndexingContext.cpp
    cfe/trunk/tools/libclang/IndexingContext.h
    cfe/trunk/tools/libclang/RecursiveASTVisitor.h

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Apr 16 02:28:30 2013
@@ -2984,6 +2984,56 @@ public:
   friend class ASTDeclReader;
 };
 
+/// An instance of this class represents the declaration of a property
+/// member.  This is a Microsoft extension to C++, first introduced in
+/// Visual Studio .NET 2003 as a parallel to similar features in C#
+/// and Managed C++.
+///
+/// A property must always be a non-static class member.
+///
+/// A property member superficially resembles a non-static data
+/// member, except preceded by a property attribute:
+///   __declspec(property(get=GetX, put=PutX)) int x;
+/// Either (but not both) of the 'get' and 'put' names may be omitted.
+///
+/// A reference to a property is always an lvalue.  If the lvalue
+/// undergoes lvalue-to-rvalue conversion, then a getter name is
+/// required, and that member is called with no arguments.
+/// If the lvalue is assigned into, then a setter name is required,
+/// and that member is called with one argument, the value assigned.
+/// Both operations are potentially overloaded.  Compound assignments
+/// are permitted, as are the increment and decrement operators.
+///
+/// The getter and putter methods are permitted to be overloaded,
+/// although their return and parameter types are subject to certain
+/// restrictions according to the type of the property.
+///
+/// A property declared using an incomplete array type may
+/// additionally be subscripted, adding extra parameters to the getter
+/// and putter methods.
+class MSPropertyDecl : public DeclaratorDecl {
+  IdentifierInfo *GetterId, *SetterId;
+
+public:
+  MSPropertyDecl(DeclContext *DC, SourceLocation L,
+                 DeclarationName N, QualType T, TypeSourceInfo *TInfo,
+                 SourceLocation StartL, IdentifierInfo *Getter,
+                 IdentifierInfo *Setter):
+  DeclaratorDecl(MSProperty, DC, L, N, T, TInfo, StartL), GetterId(Getter),
+  SetterId(Setter) {}
+
+  static MSPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+  static bool classof(const Decl *D) { return D->getKind() == MSProperty; }
+
+  bool hasGetter() const { return GetterId != NULL; }
+  IdentifierInfo* getGetterId() const { return GetterId; }
+  bool hasSetter() const { return SetterId != NULL; }
+  IdentifierInfo* getSetterId() const { return SetterId; }
+
+  friend class ASTDeclReader;
+};
+
 /// Insertion operator for diagnostics.  This allows sending an AccessSpecifier
 /// into a diagnostic with <<.
 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Tue Apr 16 02:28:30 2013
@@ -29,6 +29,7 @@ class CXXConstructorDecl;
 class CXXDestructorDecl;
 class CXXMethodDecl;
 class CXXTemporary;
+class MSPropertyDecl;
 class TemplateArgumentListInfo;
 class UuidAttr;
 
@@ -560,6 +561,64 @@ public:
   }
 };
 
+/// A member reference to an MSPropertyDecl.  This expression always
+/// has pseudo-object type, and therefore it is typically not
+/// encountered in a fully-typechecked expression except within the
+/// syntactic form of a PseudoObjectExpr.
+class MSPropertyRefExpr : public Expr {
+  Expr *BaseExpr;
+  MSPropertyDecl *TheDecl;
+  SourceLocation MemberLoc;
+  bool IsArrow;
+  NestedNameSpecifierLoc QualifierLoc;
+
+public:
+  MSPropertyRefExpr(Expr *baseExpr, MSPropertyDecl *decl, bool isArrow,
+                    QualType ty, ExprValueKind VK,
+                    NestedNameSpecifierLoc qualifierLoc,
+                    SourceLocation nameLoc)
+  : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary,
+         /*type-dependent*/ false, baseExpr->isValueDependent(),
+         baseExpr->isInstantiationDependent(),
+         baseExpr->containsUnexpandedParameterPack()),
+    BaseExpr(baseExpr), TheDecl(decl),
+    MemberLoc(nameLoc), IsArrow(isArrow),
+    QualifierLoc(qualifierLoc) {}
+
+  MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {}
+
+  SourceRange getSourceRange() const LLVM_READONLY {
+    return SourceRange(getLocStart(), getLocEnd());
+  }
+  bool isImplicitAccess() const {
+    return getBaseExpr() && getBaseExpr()->isImplicitCXXThis();
+  }
+  SourceLocation getLocStart() const {
+    if (!isImplicitAccess())
+      return BaseExpr->getLocStart();
+    else if (QualifierLoc)
+      return QualifierLoc.getBeginLoc();
+    else
+        return MemberLoc;
+  }
+  SourceLocation getLocEnd() const { return getMemberLoc(); }
+
+  child_range children() {
+    return child_range((Stmt**)&BaseExpr, (Stmt**)&BaseExpr + 1);
+  }
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == MSPropertyRefExprClass;
+  }
+
+  Expr *getBaseExpr() const { return BaseExpr; }
+  MSPropertyDecl *getPropertyDecl() const { return TheDecl; }
+  bool isArrow() const { return IsArrow; }
+  SourceLocation getMemberLoc() const { return MemberLoc; }
+  NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+  friend class ASTStmtReader;
+};
+
 /// CXXUuidofExpr - A microsoft C++ @c __uuidof expression, which gets
 /// the _GUID that corresponds to the supplied type or expression.
 ///

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Apr 16 02:28:30 2013
@@ -1671,6 +1671,10 @@ bool RecursiveASTVisitor<Derived>::Trave
   return true;
 }
 
+DEF_TRAVERSE_DECL(MSPropertyDecl, {
+    TRY_TO(TraverseDeclaratorHelper(D));
+  })
+
 DEF_TRAVERSE_DECL(FieldDecl, {
     TRY_TO(TraverseDeclaratorHelper(D));
     if (D->isBitField())
@@ -2058,6 +2062,10 @@ DEF_TRAVERSE_STMT(CXXTypeidExpr, {
       TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
   })
 
+DEF_TRAVERSE_STMT(MSPropertyRefExpr, {
+  TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+})
+
 DEF_TRAVERSE_STMT(CXXUuidofExpr, {
     // The child-iterator will pick up the arg if it's an expression,
     // but not if it's a type.

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Tue Apr 16 02:28:30 2013
@@ -928,6 +928,10 @@ def TypeTagForDatatype : InheritableAttr
 
 // Microsoft-related attributes
 
+def MsProperty : Attr {
+  let Spellings = [Declspec<"property">];
+}
+
 def MsStruct : InheritableAttr {
   let Spellings = [Declspec<"ms_struct">];
 }

Modified: cfe/trunk/include/clang/Basic/DeclNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DeclNodes.td?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DeclNodes.td (original)
+++ cfe/trunk/include/clang/Basic/DeclNodes.td Tue Apr 16 02:28:30 2013
@@ -34,14 +34,15 @@ def Named : Decl<1>;
     def UnresolvedUsingValue : DDecl<Value>;
     def IndirectField : DDecl<Value>;
     def Declarator : DDecl<Value, 1>;
+      def Field : DDecl<Declarator>;
+        def ObjCIvar : DDecl<Field>;
+        def ObjCAtDefsField : DDecl<Field>;
+      def MSProperty : DDecl<Declarator>;
       def Function : DDecl<Declarator>, DeclContext;
         def CXXMethod : DDecl<Function>;
           def CXXConstructor : DDecl<CXXMethod>;
           def CXXDestructor : DDecl<CXXMethod>;
           def CXXConversion : DDecl<CXXMethod>;
-      def Field : DDecl<Declarator>;
-        def ObjCIvar : DDecl<Field>;
-        def ObjCAtDefsField : DDecl<Field>;
       def Var : DDecl<Declarator>;
         def ImplicitParam : DDecl<Var>;
         def ParmVar : DDecl<Var>;

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Tue Apr 16 02:28:30 2013
@@ -527,6 +527,22 @@ def err_ms_declspec_type : Error<
   "__declspec attributes must be an identifier or string literal">;
 def warn_ms_declspec_unknown : Warning<
   "unknown __declspec attribute %0 ignored">, InGroup<UnknownAttributes>;
+def err_ms_property_no_getter_or_putter : Error<
+  "property does not specify a getter or a putter">;
+def err_ms_property_unknown_accessor : Error<
+  "expected 'get' or 'put' in property declaration">;
+def err_ms_property_has_set_accessor : Error<
+  "putter for property must be specified as 'put', not 'set'">;
+def err_ms_property_missing_accessor_kind : Error<
+  "missing 'get=' or 'put='">;
+def err_ms_property_expected_equal : Error<
+  "expected '=' after '%0'">;
+def err_ms_property_duplicate_accessor : Error<
+  "property declaration specifies '%0' accessor twice">;
+def err_ms_property_expected_accessor_name : Error<
+  "expected name of accessor method">;
+def err_ms_property_expected_comma_or_rparen : Error<
+  "expected ',' or ')' at end of property accessor list">;
 
 /// C++ Templates
 def err_expected_template : Error<"expected template">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Apr 16 02:28:30 2013
@@ -1810,6 +1810,19 @@ def err_attribute_section_local_variable
 def warn_mismatched_section : Warning<
   "section does not match previous declaration">, InGroup<Section>;
 
+def err_anonymous_property: Error<
+  "anonymous property is not supported">;
+def err_property_is_variably_modified: Error<
+  "property '%0' has a variably modified type">;
+def err_no_getter_for_property : Error<
+  "no getter defined for property '%0'">;
+def err_no_setter_for_property : Error<
+  "no setter defined for property '%0'">;
+def error_cannot_find_suitable_getter : Error<
+  "cannot find suitable getter for property '%0'">;
+def error_cannot_find_suitable_setter : Error<
+  "cannot find suitable setter for property '%0'">;
+
 def err_attribute_aligned_not_power_of_two : Error<
   "requested alignment is not a power of 2">;
 def err_attribute_aligned_greater_than_8192 : Error<

Modified: cfe/trunk/include/clang/Basic/StmtNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/StmtNodes.td (original)
+++ cfe/trunk/include/clang/Basic/StmtNodes.td Tue Apr 16 02:28:30 2013
@@ -163,6 +163,7 @@ def BlockExpr : DStmt<Expr>;
 def OpaqueValueExpr : DStmt<Expr>;
 
 // Microsoft Extensions.
+def MSPropertyRefExpr : DStmt<Expr>;
 def CXXUuidofExpr : DStmt<Expr>; 
 def SEHTryStmt : Stmt;
 def SEHExceptStmt : Stmt;

Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Tue Apr 16 02:28:30 2013
@@ -96,6 +96,10 @@ private:
   /// type_tag_for_datatype attribute.
   unsigned IsTypeTagForDatatype : 1;
 
+  /// True if this has extra information associated with a
+  /// Microsoft __delcspec(property) attribute.
+  unsigned IsProperty : 1;
+
   unsigned AttrKind : 8;
 
   /// \brief The location of the 'unavailable' keyword in an
@@ -134,6 +138,11 @@ public:
     unsigned LayoutCompatible : 1;
     unsigned MustBeNull : 1;
   };
+  struct PropertyData {
+    IdentifierInfo *GetterId, *SetterId;
+    PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId)
+    : GetterId(getterId), SetterId(setterId) {}
+  };
 
 private:
   TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
@@ -152,6 +161,16 @@ private:
     return *reinterpret_cast<const ParsedType *>(this + 1);
   }
 
+  PropertyData &getPropertyDataBuffer() {
+    assert(IsProperty);
+    return *reinterpret_cast<PropertyData*>(this + 1);
+  }
+
+  const PropertyData &getPropertyDataBuffer() const {
+    assert(IsProperty);
+    return *reinterpret_cast<const PropertyData*>(this + 1);
+  }
+
   AttributeList(const AttributeList &) LLVM_DELETED_FUNCTION;
   void operator=(const AttributeList &) LLVM_DELETED_FUNCTION;
   void operator delete(void *) LLVM_DELETED_FUNCTION;
@@ -169,7 +188,8 @@ private:
       AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
       EllipsisLoc(ellipsisLoc), NumArgs(numArgs), SyntaxUsed(syntaxUsed),
       Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
-      IsTypeTagForDatatype(false), NextInPosition(0), NextInPool(0) {
+      IsTypeTagForDatatype(false), IsProperty(false), NextInPosition(0),
+      NextInPool(0) {
     if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*));
     AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
   }
@@ -188,7 +208,7 @@ private:
       AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), EllipsisLoc(),
       NumArgs(0), SyntaxUsed(syntaxUsed),
       Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
-      IsTypeTagForDatatype(false),
+      IsTypeTagForDatatype(false), IsProperty(false),
       UnavailableLoc(unavailable), MessageExpr(messageExpr),
       NextInPosition(0), NextInPool(0) {
     new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
@@ -208,7 +228,8 @@ private:
       AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(argumentKindLoc),
       EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
       Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
-      IsTypeTagForDatatype(true), NextInPosition(NULL), NextInPool(NULL) {
+      IsTypeTagForDatatype(true), IsProperty(false), NextInPosition(NULL),
+      NextInPool(NULL) {
     TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
     new (&ExtraData.MatchingCType) ParsedType(matchingCType);
     ExtraData.LayoutCompatible = layoutCompatible;
@@ -225,11 +246,28 @@ private:
         AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
         EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
         UsedAsTypeAttr(false), IsAvailability(false),
-        IsTypeTagForDatatype(false), NextInPosition(0), NextInPool(0) {
+        IsTypeTagForDatatype(false), IsProperty(false), NextInPosition(0),
+        NextInPool(0) {
     new (&getTypeBuffer()) ParsedType(typeArg);
     AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
   }
 
+  /// Constructor for microsoft __declspec(property) attribute.
+  AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
+                IdentifierInfo *scopeName, SourceLocation scopeLoc,
+                IdentifierInfo *parmName, SourceLocation parmLoc,
+                IdentifierInfo *getterId, IdentifierInfo *setterId,
+                Syntax syntaxUsed)
+    : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
+      AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
+      SyntaxUsed(syntaxUsed),
+      Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
+      IsTypeTagForDatatype(false), IsProperty(true), NextInPosition(0),
+      NextInPool(0) {
+    new (&getPropertyDataBuffer()) PropertyData(getterId, setterId);
+    AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+  }
+
   friend class AttributePool;
   friend class AttributeFactory;
 
@@ -253,6 +291,11 @@ public:
   IdentifierInfo *getParameterName() const { return ParmName; }
   SourceLocation getParameterLoc() const { return ParmLoc; }
 
+  /// Is this the Microsoft __declspec(property) attribute?
+  bool isDeclspecPropertyAttribute() const  {
+    return IsProperty;
+  }
+
   bool isAlignasAttribute() const {
     // FIXME: Use a better mechanism to determine this.
     return getKind() == AT_Aligned && SyntaxUsed == AS_Keyword;
@@ -379,6 +422,11 @@ public:
     return getTypeBuffer();
   }
 
+  const PropertyData &getPropertyData() const {
+    assert(isDeclspecPropertyAttribute() && "Not a __delcspec(property) attribute");
+    return getPropertyDataBuffer();
+  }
+
   /// \brief Get an index into the attribute spelling list
   /// defined in Attr.td. This index is used by an attribute
   /// to pretty print itself.
@@ -402,6 +450,10 @@ public:
     TypeTagForDatatypeAllocSize =
       sizeof(AttributeList)
       + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) - 1)
+        / sizeof(void*) * sizeof(void*),
+    PropertyAllocSize =
+      sizeof(AttributeList)
+      + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1)
         / sizeof(void*) * sizeof(void*)
   };
 
@@ -548,6 +600,20 @@ public:
                                           parmName, parmLoc,
                                           typeArg, syntaxUsed));
   }
+
+  AttributeList *createPropertyAttribute(
+                    IdentifierInfo *attrName, SourceRange attrRange,
+                    IdentifierInfo *scopeName, SourceLocation scopeLoc,
+                    IdentifierInfo *parmName, SourceLocation parmLoc,
+                    IdentifierInfo *getterId, IdentifierInfo *setterId,
+                    AttributeList::Syntax syntaxUsed) {
+    void *memory = allocate(AttributeFactory::PropertyAllocSize);
+    return add(new (memory) AttributeList(attrName, attrRange,
+                                          scopeName, scopeLoc,
+                                          parmName, parmLoc,
+                                          getterId, setterId,
+                                          syntaxUsed));
+  }
 };
 
 /// addAttributeLists - Add two AttributeLists together
@@ -702,6 +768,21 @@ public:
     add(attr);
     return attr;
   }
+
+  /// Add microsoft __delspec(property) attribute.
+  AttributeList *
+  addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange,
+                 IdentifierInfo *scopeName, SourceLocation scopeLoc,
+                 IdentifierInfo *parmName, SourceLocation parmLoc,
+                 IdentifierInfo *getterId, IdentifierInfo *setterId,
+                 AttributeList::Syntax syntaxUsed) {
+    AttributeList *attr =
+        pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc,
+                                     parmName, parmLoc, getterId, setterId,
+                                     syntaxUsed);
+    add(attr);
+    return attr;
+  }
 
   AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name,
                                SourceLocation loc, int arg) {

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Apr 16 02:28:30 2013
@@ -1586,6 +1586,12 @@ public:
                          Declarator &D, Expr *BitfieldWidth,
                          InClassInitStyle InitStyle,
                          AccessSpecifier AS);
+  MSPropertyDecl *HandleMSProperty(Scope *S, RecordDecl *TagD,
+                                   SourceLocation DeclStart,
+                                   Declarator &D, Expr *BitfieldWidth,
+                                   InClassInitStyle InitStyle,
+                                   AccessSpecifier AS,
+                                   AttributeList *MSPropertyAttr);
 
   FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T,
                             TypeSourceInfo *TInfo,

Modified: cfe/trunk/include/clang/Sema/Template.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Template.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Template.h (original)
+++ cfe/trunk/include/clang/Sema/Template.h Tue Apr 16 02:28:30 2013
@@ -401,6 +401,7 @@ namespace clang {
     Decl *VisitVarDecl(VarDecl *D);
     Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
     Decl *VisitFieldDecl(FieldDecl *D);
+    Decl *VisitMSPropertyDecl(MSPropertyDecl *D);
     Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D);
     Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
     Decl *VisitEnumDecl(EnumDecl *D);

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Apr 16 02:28:30 2013
@@ -951,6 +951,8 @@ namespace clang {
       DECL_OBJC_PROPERTY_IMPL,
       /// \brief A FieldDecl record.
       DECL_FIELD,
+      /// \brief A MSPropertyDecl record.
+      DECL_MS_PROPERTY,
       /// \brief A VarDecl record.
       DECL_VAR,
       /// \brief An ImplicitParamDecl record.
@@ -1300,6 +1302,7 @@ namespace clang {
       EXPR_ASTYPE,                 // AsTypeExpr
 
       // Microsoft
+      EXPR_CXX_PROPERTY_REF_EXPR, // MSPropertyRefExpr
       EXPR_CXX_UUIDOF_EXPR,       // CXXUuidofExpr (of expr).
       EXPR_CXX_UUIDOF_TYPE,       // CXXUuidofExpr (of type).
       STMT_SEH_EXCEPT,            // SEHExceptStmt

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Tue Apr 16 02:28:30 2013
@@ -1293,7 +1293,7 @@ bool NamedDecl::isCXXInstanceMember() co
   if (isa<UsingShadowDecl>(D))
     D = cast<UsingShadowDecl>(D)->getTargetDecl();
 
-  if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D))
+  if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<MSPropertyDecl>(D))
     return true;
   if (isa<CXXMethodDecl>(D))
     return cast<CXXMethodDecl>(D)->isInstance();
@@ -3226,6 +3226,14 @@ BlockDecl *BlockDecl::CreateDeserialized
   return new (Mem) BlockDecl(0, SourceLocation());
 }
 
+MSPropertyDecl *MSPropertyDecl::CreateDeserialized(ASTContext &C,
+                                                   unsigned ID) {
+  void *Mem = AllocateDeserializedDecl(C, ID, sizeof(MSPropertyDecl));
+  return new (Mem) MSPropertyDecl(0, SourceLocation(), DeclarationName(),
+                                  QualType(), 0, SourceLocation(),
+                                  0, 0);
+}
+
 EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
                                            SourceLocation L,
                                            IdentifierInfo *Id, QualType T,

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Tue Apr 16 02:28:30 2013
@@ -493,6 +493,7 @@ unsigned Decl::getIdentifierNamespaceFor
     case NonTypeTemplateParm:
     case ObjCMethod:
     case ObjCProperty:
+    case MSProperty:
       return IDNS_Ordinary;
     case Label:
       return IDNS_Label;

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Tue Apr 16 02:28:30 2013
@@ -2789,6 +2789,7 @@ bool Expr::HasSideEffects(const ASTConte
     return false;
 
   case CallExprClass:
+  case MSPropertyRefExprClass:
   case CompoundAssignOperatorClass:
   case VAArgExprClass:
   case AtomicExprClass:

Modified: cfe/trunk/lib/AST/ExprClassification.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprClassification.cpp (original)
+++ cfe/trunk/lib/AST/ExprClassification.cpp Tue Apr 16 02:28:30 2013
@@ -134,6 +134,7 @@ static Cl::Kinds ClassifyInternal(ASTCon
     // FIXME: ObjC++0x might have different rules
   case Expr::ObjCIvarRefExprClass:
   case Expr::FunctionParmPackExprClass:
+  case Expr::MSPropertyRefExprClass:
     return Cl::CL_LValue;
 
     // C99 6.5.2.5p5 says that compound literals are lvalues.

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Apr 16 02:28:30 2013
@@ -6488,6 +6488,7 @@ static ICEDiag CheckICE(const Expr* E, A
   case Expr::CXXDynamicCastExprClass:
   case Expr::CXXTypeidExprClass:
   case Expr::CXXUuidofExprClass:
+  case Expr::MSPropertyRefExprClass:
   case Expr::CXXNullPtrLiteralExprClass:
   case Expr::UserDefinedLiteralClass:
   case Expr::CXXThisExprClass:

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue Apr 16 02:28:30 2013
@@ -2394,6 +2394,7 @@ recurse:
   case Expr::ImplicitValueInitExprClass:
   case Expr::ParenListExprClass:
   case Expr::LambdaExprClass:
+  case Expr::MSPropertyRefExprClass:
     llvm_unreachable("unexpected statement kind");
 
   // FIXME: invent manglings for all these.

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Tue Apr 16 02:28:30 2013
@@ -1238,6 +1238,18 @@ void StmtPrinter::VisitCXXUuidofExpr(CXX
   OS << ")";
 }
 
+void StmtPrinter::VisitMSPropertyRefExpr(MSPropertyRefExpr *Node) {
+  PrintExpr(Node->getBaseExpr());
+  if (Node->isArrow())
+    OS << "->";
+  else
+    OS << ".";
+  if (NestedNameSpecifier *Qualifier =
+      Node->getQualifierLoc().getNestedNameSpecifier())
+    Qualifier->print(OS, Policy);
+  OS << Node->getPropertyDecl()->getDeclName();
+}
+
 void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
   switch (Node->getLiteralOperatorKind()) {
   case UserDefinedLiteral::LOK_Raw:

Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Tue Apr 16 02:28:30 2013
@@ -766,6 +766,11 @@ void StmtProfiler::VisitCXXUuidofExpr(co
     VisitType(S->getTypeOperand());
 }
 
+void StmtProfiler::VisitMSPropertyRefExpr(const MSPropertyRefExpr *S) {
+  VisitExpr(S);
+  VisitDecl(S->getPropertyDecl());
+}
+
 void StmtProfiler::VisitCXXThisExpr(const CXXThisExpr *S) {
   VisitExpr(S);
   ID.AddBoolean(S->isImplicit());

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Tue Apr 16 02:28:30 2013
@@ -45,6 +45,7 @@ void CodeGenFunction::EmitDecl(const Dec
   case Decl::CXXDestructor:
   case Decl::CXXConversion:
   case Decl::Field:
+  case Decl::MSProperty:
   case Decl::IndirectField:
   case Decl::ObjCIvar:
   case Decl::ObjCAtDefsField:

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Apr 16 02:28:30 2013
@@ -394,17 +394,119 @@ void Parser::ParseComplexMicrosoftDeclSp
     // The property declspec is more complex in that it can take one or two
     // assignment expressions as a parameter, but the lhs of the assignment
     // must be named get or put.
-    //
-    // For right now, we will just skip to the closing right paren of the
-    // property expression.
-    //
-    // FIXME: we should deal with __declspec(property) at some point because it
-    // is used in the platform SDK headers for the Parallel Patterns Library
-    // and ATL.
-    BalancedDelimiterTracker T(*this, tok::l_paren);
-    if (T.expectAndConsume(diag::err_expected_lparen_after,
-                           Ident->getNameStart(), tok::r_paren))
+    if (Tok.isNot(tok::l_paren)) {
+      Diag(Tok.getLocation(), diag::err_expected_lparen_after)
+        << Ident->getNameStart();
       return;
+    }
+    BalancedDelimiterTracker T(*this, tok::l_paren);
+    T.expectAndConsume(diag::err_expected_lparen_after,
+                       Ident->getNameStart(), tok::r_paren);
+
+    enum AccessorKind {
+      AK_Invalid = -1,
+      AK_Put = 0, AK_Get = 1 // indices into AccessorNames
+    };
+    IdentifierInfo *AccessorNames[] = { 0, 0 };
+    bool HasInvalidAccessor = false;
+
+    // Parse the accessor specifications.
+    while (true) {
+      // Stop if this doesn't look like an accessor spec.
+      if (!Tok.is(tok::identifier)) {
+        // If the user wrote a completely empty list, use a special diagnostic.
+        if (Tok.is(tok::r_paren) && !HasInvalidAccessor &&
+            AccessorNames[AK_Put] == 0 && AccessorNames[AK_Get] == 0) {
+          Diag(Loc, diag::err_ms_property_no_getter_or_putter);
+          break;
+        }
+
+        Diag(Tok.getLocation(), diag::err_ms_property_unknown_accessor);
+        break;
+      }
+
+      AccessorKind Kind;
+      SourceLocation KindLoc = Tok.getLocation();
+      StringRef KindStr = Tok.getIdentifierInfo()->getName();
+      if (KindStr == "get") {
+        Kind = AK_Get;
+      } else if (KindStr == "put") {
+        Kind = AK_Put;
+
+      // Recover from the common mistake of using 'set' instead of 'put'.
+      } else if (KindStr == "set") {
+        Diag(KindLoc, diag::err_ms_property_has_set_accessor)
+          << FixItHint::CreateReplacement(KindLoc, "put");
+        Kind = AK_Put;
+
+      // Handle the mistake of forgetting the accessor kind by skipping
+      // this accessor.
+      } else if (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)) {
+        Diag(KindLoc, diag::err_ms_property_missing_accessor_kind);
+        ConsumeToken();
+        HasInvalidAccessor = true;
+        goto next_property_accessor;
+
+      // Otherwise, complain about the unknown accessor kind.
+      } else {
+        Diag(KindLoc, diag::err_ms_property_unknown_accessor);
+        HasInvalidAccessor = true;
+        Kind = AK_Invalid;
+
+        // Try to keep parsing unless it doesn't look like an accessor spec.
+        if (!NextToken().is(tok::equal)) break;
+      }
+
+      // Consume the identifier.
+      ConsumeToken();
+
+      // Consume the '='.
+      if (Tok.is(tok::equal)) {
+        ConsumeToken();
+      } else {
+        Diag(Tok.getLocation(), diag::err_ms_property_expected_equal)
+          << KindStr;
+        break;
+      }
+
+      // Expect the method name.
+      if (!Tok.is(tok::identifier)) {
+        Diag(Tok.getLocation(), diag::err_ms_property_expected_accessor_name);
+        break;
+      }
+
+      if (Kind == AK_Invalid) {
+        // Just drop invalid accessors.
+      } else if (AccessorNames[Kind] != NULL) {
+        // Complain about the repeated accessor, ignore it, and keep parsing.
+        Diag(KindLoc, diag::err_ms_property_duplicate_accessor) << KindStr;
+      } else {
+        AccessorNames[Kind] = Tok.getIdentifierInfo();
+      }
+      ConsumeToken();
+
+    next_property_accessor:
+      // Keep processing accessors until we run out.
+      if (Tok.is(tok::comma)) {
+        ConsumeAnyToken();
+        continue;
+
+      // If we run into the ')', stop without consuming it.
+      } else if (Tok.is(tok::r_paren)) {
+        break;
+      } else {
+        Diag(Tok.getLocation(), diag::err_ms_property_expected_comma_or_rparen);
+        break;
+      }
+    }
+
+    // Only add the property attribute if it was well-formed.
+    if (!HasInvalidAccessor) {
+      Attrs.addNewPropertyAttr(Ident, Loc, 0, SourceLocation(), 0,
+                               SourceLocation(),
+                               AccessorNames[AK_Get], AccessorNames[AK_Put],
+                               AttributeList::AS_Declspec);
+    }
     T.skipToEnd();
   } else {
     // We don't recognize this as a valid declspec, but instead of creating the

Modified: cfe/trunk/lib/Sema/AttributeList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AttributeList.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AttributeList.cpp (original)
+++ cfe/trunk/lib/Sema/AttributeList.cpp Tue Apr 16 02:28:30 2013
@@ -23,6 +23,8 @@ size_t AttributeList::allocated_size() c
   if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
   else if (IsTypeTagForDatatype)
     return AttributeFactory::TypeTagForDatatypeAllocSize;
+  else if (IsProperty)
+    return AttributeFactory::PropertyAllocSize;
   return (sizeof(AttributeList) + NumArgs * sizeof(Expr*));
 }
 

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Tue Apr 16 02:28:30 2013
@@ -4889,6 +4889,7 @@ static void ProcessInheritableDeclAttr(S
     break;
 
   // Microsoft attributes:
+  case AttributeList::AT_MsProperty: break;
   case AttributeList::AT_MsStruct:
     handleMsStructAttr(S, D, Attr);
     break;

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Apr 16 02:28:30 2013
@@ -1603,6 +1603,13 @@ static bool InitializationHasSideEffects
   return false;
 }
 
+static AttributeList *getMSPropertyAttr(AttributeList *list) {
+  for (AttributeList* it = list; it != 0; it = it->getNext())
+    if (it->isDeclspecPropertyAttribute())
+      return it;
+  return 0;
+}
+
 /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
 /// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the
 /// bitfield width if there is one, 'InitExpr' specifies the initializer if
@@ -1782,8 +1789,16 @@ Sema::ActOnCXXMemberDeclarator(Scope *S,
       SS.clear();
     }
 
-    Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth,
-                         InitStyle, AS);
+    AttributeList *MSPropertyAttr =
+      getMSPropertyAttr(D.getDeclSpec().getAttributes().getList());
+    if (MSPropertyAttr) {
+      Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D,
+                                BitWidth, InitStyle, AS, MSPropertyAttr);
+      isInstField = false;
+    } else {
+      Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D,
+                                BitWidth, InitStyle, AS);
+    }
     assert(Member && "HandleField never returns null");
   } else {
     assert(InitStyle == ICIS_NoInit || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static);
@@ -12096,3 +12111,94 @@ bool Sema::CheckCUDATarget(CUDAFunctionT
 
   return false;
 }
+
+/// HandleMSProperty - Analyze a __delcspec(property) field of a C++ class.
+///
+MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
+                                       SourceLocation DeclStart,
+                                       Declarator &D, Expr *BitWidth,
+                                       InClassInitStyle InitStyle,
+                                       AccessSpecifier AS,
+                                       AttributeList *MSPropertyAttr) {
+  IdentifierInfo *II = D.getIdentifier();
+  if (!II) {
+    Diag(DeclStart, diag::err_anonymous_property);
+    return NULL;
+  }
+  SourceLocation Loc = D.getIdentifierLoc();
+
+  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+  QualType T = TInfo->getType();
+  if (getLangOpts().CPlusPlus) {
+    CheckExtraCXXDefaultArguments(D);
+
+    if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
+                                        UPPC_DataMemberType)) {
+      D.setInvalidType();
+      T = Context.IntTy;
+      TInfo = Context.getTrivialTypeSourceInfo(T, Loc);
+    }
+  }
+
+  DiagnoseFunctionSpecifiers(D.getDeclSpec());
+
+  if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec())
+    Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+         diag::err_invalid_thread)
+      << DeclSpec::getSpecifierName(TSCS);
+
+  // Check to see if this name was declared as a member previously
+  NamedDecl *PrevDecl = 0;
+  LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
+  LookupName(Previous, S);
+  switch (Previous.getResultKind()) {
+  case LookupResult::Found:
+  case LookupResult::FoundUnresolvedValue:
+    PrevDecl = Previous.getAsSingle<NamedDecl>();
+    break;
+
+  case LookupResult::FoundOverloaded:
+    PrevDecl = Previous.getRepresentativeDecl();
+    break;
+
+  case LookupResult::NotFound:
+  case LookupResult::NotFoundInCurrentInstantiation:
+  case LookupResult::Ambiguous:
+    break;
+  }
+
+  if (PrevDecl && PrevDecl->isTemplateParameter()) {
+    // Maybe we will complain about the shadowed template parameter.
+    DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+    // Just pretend that we didn't see the previous declaration.
+    PrevDecl = 0;
+  }
+
+  if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
+    PrevDecl = 0;
+
+  SourceLocation TSSL = D.getLocStart();
+  MSPropertyDecl *NewPD;
+  const AttributeList::PropertyData &Data = MSPropertyAttr->getPropertyData();
+  NewPD = new (Context) MSPropertyDecl(Record, Loc,
+                                       II, T, TInfo, TSSL,
+                                       Data.GetterId, Data.SetterId);
+  ProcessDeclAttributes(TUScope, NewPD, D);
+  NewPD->setAccess(AS);
+
+  if (NewPD->isInvalidDecl())
+    Record->setInvalidDecl();
+
+  if (D.getDeclSpec().isModulePrivateSpecified())
+    NewPD->setModulePrivate();
+
+  if (NewPD->isInvalidDecl() && PrevDecl) {
+    // Don't introduce NewFD into scope; there's already something
+    // with the same name in the same scope.
+  } else if (II) {
+    PushOnScopeChains(NewPD, S);
+  } else
+    Record->addDecl(NewPD);
+
+  return NewPD;
+}

Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Tue Apr 16 02:28:30 2013
@@ -1111,6 +1111,9 @@ CanThrowResult Sema::canThrow(const Expr
     // These expressions can never throw.
     return CT_Cannot;
 
+  case Expr::MSPropertyRefExprClass:
+    llvm_unreachable("Invalid class for expression");
+
 #define STMT(CLASS, PARENT) case Expr::CLASS##Class:
 #define STMT_RANGE(Base, First, Last)
 #define LAST_STMT_RANGE(BASE, FIRST, LAST)

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Apr 16 02:28:30 2013
@@ -2636,6 +2636,10 @@ Sema::BuildDeclarationNameExpr(const CXX
       break;
     }
 
+    case Decl::MSProperty:
+      valueKind = VK_LValue;
+      break;
+
     case Decl::CXXMethod:
       // If we're referring to a method with an __unknown_anytype
       // result type, make the entire expression __unknown_anytype.
@@ -4023,6 +4027,63 @@ Sema::CheckStaticArrayArgument(SourceLoc
 /// to have a function type.
 static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn);
 
+/// Is the given type a placeholder that we need to lower out
+/// immediately during argument processing?
+static bool isPlaceholderToRemoveAsArg(QualType type) {
+  // Placeholders are never sugared.
+  const BuiltinType *placeholder = dyn_cast<BuiltinType>(type);
+  if (!placeholder) return false;
+
+  switch (placeholder->getKind()) {
+  // Ignore all the non-placeholder types.
+#define PLACEHOLDER_TYPE(ID, SINGLETON_ID)
+#define BUILTIN_TYPE(ID, SINGLETON_ID) case BuiltinType::ID:
+#include "clang/AST/BuiltinTypes.def"
+    return false;
+
+  // We cannot lower out overload sets; they might validly be resolved
+  // by the call machinery.
+  case BuiltinType::Overload:
+    return false;
+
+  // Unbridged casts in ARC can be handled in some call positions and
+  // should be left in place.
+  case BuiltinType::ARCUnbridgedCast:
+    return false;
+
+  // Pseudo-objects should be converted as soon as possible.
+  case BuiltinType::PseudoObject:
+    return true;
+
+  // The debugger mode could theoretically but currently does not try
+  // to resolve unknown-typed arguments based on known parameter types.
+  case BuiltinType::UnknownAny:
+    return true;
+
+  // These are always invalid as call arguments and should be reported.
+  case BuiltinType::BoundMember:
+  case BuiltinType::BuiltinFn:
+    return true;
+  }
+  llvm_unreachable("bad builtin type kind");
+}
+
+/// Check an argument list for placeholders that we won't try to
+/// handle later.
+static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args) {
+  // Apply this processing to all the arguments at once instead of
+  // dying at the first failure.
+  bool hasInvalid = false;
+  for (size_t i = 0, e = args.size(); i != e; i++) {
+    if (isPlaceholderToRemoveAsArg(args[i]->getType())) {
+      ExprResult result = S.CheckPlaceholderExpr(args[i]);
+      if (result.isInvalid()) hasInvalid = true;
+      else args[i] = result.take();
+    }
+  }
+  return hasInvalid;
+}
+
 /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
 /// This provides the location of the left/right parens and a list of comma
 /// locations.
@@ -4035,6 +4096,9 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn,
   if (Result.isInvalid()) return ExprError();
   Fn = Result.take();
 
+  if (checkArgsForPlaceholders(*this, ArgExprs))
+    return ExprError();
+
   if (getLangOpts().CPlusPlus) {
     // If this is a pseudo-destructor expression, build the call immediately.
     if (isa<CXXPseudoDestructorExpr>(Fn)) {
@@ -4050,6 +4114,11 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn,
                                           Context.VoidTy, VK_RValue,
                                           RParenLoc));
     }
+    if (Fn->getType() == Context.PseudoObjectTy) {
+      ExprResult result = CheckPlaceholderExpr(Fn);
+      if (result.isInvalid()) return ExprError();
+      Fn = result.take();
+    }
 
     // Determine whether this is a dependent call inside a C++ template,
     // in which case we won't do any semantic analysis now.

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Apr 16 02:28:30 2013
@@ -1170,6 +1170,11 @@ Sema::BuildCXXNew(SourceRange Range, boo
 
   QualType ResultType = Context.getPointerType(AllocType);
     
+  if (ArraySize && ArraySize->getType()->isNonOverloadPlaceholderType()) {
+    ExprResult result = CheckPlaceholderExpr(ArraySize);
+    if (result.isInvalid()) return ExprError();
+    ArraySize = result.take();
+  }
   // C++98 5.3.4p6: "The expression in a direct-new-declarator shall have
   //   integral or enumeration type with a non-negative value."
   // C++11 [expr.new]p6: The expression [...] shall be of integral or unscoped

Modified: cfe/trunk/lib/Sema/SemaExprMember.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprMember.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprMember.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprMember.cpp Tue Apr 16 02:28:30 2013
@@ -105,7 +105,8 @@ static IMAKind ClassifyImplicitMemberAcc
     NamedDecl *D = *I;
 
     if (D->isCXXInstanceMember()) {
-      if (dyn_cast<FieldDecl>(D) || dyn_cast<IndirectFieldDecl>(D))
+      if (dyn_cast<FieldDecl>(D) || dyn_cast<MSPropertyDecl>(D)
+          || dyn_cast<IndirectFieldDecl>(D))
         isField = true;
 
       CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
@@ -778,6 +779,19 @@ Sema::BuildAnonymousStructUnionMemberRef
   return Owned(result);
 }
 
+static ExprResult
+BuildMSPropertyRefExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
+                       const CXXScopeSpec &SS,
+                       MSPropertyDecl *PD,
+                       const DeclarationNameInfo &NameInfo) {
+  // Property names are always simple identifiers and therefore never
+  // require any interesting additional storage.
+  return new (S.Context) MSPropertyRefExpr(BaseExpr, PD, IsArrow,
+                                           S.Context.PseudoObjectTy, VK_LValue,
+                                           SS.getWithLocInContext(S.Context),
+                                           NameInfo.getLoc());
+}
+
 /// \brief Build a MemberExpr AST node.
 static MemberExpr *BuildMemberExpr(Sema &SemaRef,
                                    ASTContext &C, Expr *Base, bool isArrow,
@@ -935,6 +949,10 @@ Sema::BuildMemberReferenceExpr(Expr *Bas
     return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow,
                                    SS, FD, FoundDecl, MemberNameInfo);
 
+  if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl))
+    return BuildMSPropertyRefExpr(*this, BaseExpr, IsArrow, SS, PD,
+                                  MemberNameInfo);
+
   if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))
     // We may have found a field within an anonymous union or struct
     // (C++ [class.union]).

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Apr 16 02:28:30 2013
@@ -4136,6 +4136,21 @@ InitializationSequence::InitializationSe
     : FailedCandidateSet(Kind.getLocation()) {
   ASTContext &Context = S.Context;
 
+  // Eliminate non-overload placeholder types in the arguments.  We
+  // need to do this before checking whether types are dependent
+  // because lowering a pseudo-object expression might well give us
+  // something of dependent type.
+  for (unsigned I = 0; I != NumArgs; ++I)
+    if (Args[I]->getType()->isNonOverloadPlaceholderType()) {
+      // FIXME: should we be doing this here?
+      ExprResult result = S.CheckPlaceholderExpr(Args[I]);
+      if (result.isInvalid()) {
+        SetFailed(FK_PlaceholderType);
+        return;
+      }
+      Args[I] = result.take();
+    }
+
   // C++0x [dcl.init]p16:
   //   The semantics of initializers are as follows. The destination type is
   //   the type of the object or reference being initialized and the source
@@ -4153,18 +4168,6 @@ InitializationSequence::InitializationSe
   // Almost everything is a normal sequence.
   setSequenceKind(NormalSequence);
 
-  for (unsigned I = 0; I != NumArgs; ++I)
-    if (Args[I]->getType()->isNonOverloadPlaceholderType()) {
-      // FIXME: should we be doing this here?
-      ExprResult result = S.CheckPlaceholderExpr(Args[I]);
-      if (result.isInvalid()) {
-        SetFailed(FK_PlaceholderType);
-        return;
-      }
-      Args[I] = result.take();
-    }
-
-
   QualType SourceType;
   Expr *Initializer = 0;
   if (NumArgs == 1) {

Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original)
+++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Tue Apr 16 02:28:30 2013
@@ -153,6 +153,23 @@ namespace {
                              refExpr->getRBracket());
     }
   };
+
+  struct MSPropertyRefRebuilder : Rebuilder<MSPropertyRefRebuilder> {
+    Expr *NewBase;
+    MSPropertyRefRebuilder(Sema &S, Expr *newBase)
+    : Rebuilder<MSPropertyRefRebuilder>(S), NewBase(newBase) {}
+
+    typedef MSPropertyRefExpr specific_type;
+    Expr *rebuildSpecific(MSPropertyRefExpr *refExpr) {
+      assert(refExpr->getBaseExpr());
+
+      return new (S.Context)
+        MSPropertyRefExpr(NewBase, refExpr->getPropertyDecl(),
+                       refExpr->isArrow(), refExpr->getType(),
+                       refExpr->getValueKind(), refExpr->getQualifierLoc(),
+                       refExpr->getMemberLoc());
+    }
+  };
   
   class PseudoOpBuilder {
   public:
@@ -284,6 +301,18 @@ namespace {
    ExprResult buildSet(Expr *op, SourceLocation, bool);
  };
 
+ class MSPropertyOpBuilder : public PseudoOpBuilder {
+   MSPropertyRefExpr *RefExpr;
+
+ public:
+   MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr) :
+     PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
+     RefExpr(refExpr) {}
+
+   Expr *rebuildAndCaptureObject(Expr *);
+   ExprResult buildGet();
+   ExprResult buildSet(Expr *op, SourceLocation, bool);
+ };
 }
 
 /// Capture the given expression in an OpaqueValueExpr.
@@ -1324,6 +1353,77 @@ ExprResult ObjCSubscriptOpBuilder::build
 }
 
 //===----------------------------------------------------------------------===//
+//  MSVC __declspec(property) references
+//===----------------------------------------------------------------------===//
+
+Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
+  Expr *NewBase = capture(RefExpr->getBaseExpr());
+
+  syntacticBase =
+    MSPropertyRefRebuilder(S, NewBase).rebuild(syntacticBase);
+
+  return syntacticBase;
+}
+
+ExprResult MSPropertyOpBuilder::buildGet() {
+  if (!RefExpr->getPropertyDecl()->hasGetter()) {
+    S.Diag(RefExpr->getMemberLoc(), diag::err_no_getter_for_property)
+      << RefExpr->getPropertyDecl()->getName();
+    return ExprError();
+  }
+
+  UnqualifiedId GetterName;
+  IdentifierInfo *II = RefExpr->getPropertyDecl()->getGetterId();
+  GetterName.setIdentifier(II, RefExpr->getMemberLoc());
+  CXXScopeSpec SS;
+  SS.Adopt(RefExpr->getQualifierLoc());
+  ExprResult GetterExpr = S.ActOnMemberAccessExpr(
+    S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(),
+    RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
+    GetterName, 0, true);
+  if (GetterExpr.isInvalid()) {
+    S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_getter)
+      << RefExpr->getPropertyDecl()->getName();
+    return ExprError();
+  }
+
+  MultiExprArg ArgExprs;
+  return S.ActOnCallExpr(S.getCurScope(), GetterExpr.take(),
+                         RefExpr->getSourceRange().getBegin(), ArgExprs,
+                         RefExpr->getSourceRange().getEnd());
+}
+
+ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
+                                         bool captureSetValueAsResult) {
+  if (!RefExpr->getPropertyDecl()->hasSetter()) {
+    S.Diag(RefExpr->getMemberLoc(), diag::err_no_setter_for_property)
+      << RefExpr->getPropertyDecl()->getName();
+    return ExprError();
+  }
+
+  UnqualifiedId SetterName;
+  IdentifierInfo *II = RefExpr->getPropertyDecl()->getSetterId();
+  SetterName.setIdentifier(II, RefExpr->getMemberLoc());
+  CXXScopeSpec SS;
+  SS.Adopt(RefExpr->getQualifierLoc());
+  ExprResult SetterExpr = S.ActOnMemberAccessExpr(
+    S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(),
+    RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
+    SetterName, 0, true);
+  if (SetterExpr.isInvalid()) {
+    S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_setter)
+      << RefExpr->getPropertyDecl()->getName();
+    return ExprError();
+  }
+
+  SmallVector<Expr*, 1> ArgExprs;
+  ArgExprs.push_back(op);
+  return S.ActOnCallExpr(S.getCurScope(), SetterExpr.take(),
+                         RefExpr->getSourceRange().getBegin(), ArgExprs,
+                         op->getSourceRange().getEnd());
+}
+
+//===----------------------------------------------------------------------===//
 //  General Sema routines.
 //===----------------------------------------------------------------------===//
 
@@ -1338,6 +1438,10 @@ ExprResult Sema::checkPseudoObjectRValue
            = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
     ObjCSubscriptOpBuilder builder(*this, refExpr);
     return builder.buildRValueOperation(E);
+  } else if (MSPropertyRefExpr *refExpr
+             = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
+    MSPropertyOpBuilder builder(*this, refExpr);
+    return builder.buildRValueOperation(E);
   } else {
     llvm_unreachable("unknown pseudo-object kind!");
   }
@@ -1360,6 +1464,10 @@ ExprResult Sema::checkPseudoObjectIncDec
   } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
     Diag(opcLoc, diag::err_illegal_container_subscripting_op);
     return ExprError();
+  } else if (MSPropertyRefExpr *refExpr
+             = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
+    MSPropertyOpBuilder builder(*this, refExpr);
+    return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
   } else {
     llvm_unreachable("unknown pseudo-object kind!");
   }
@@ -1389,6 +1497,10 @@ ExprResult Sema::checkPseudoObjectAssign
              = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
     ObjCSubscriptOpBuilder builder(*this, refExpr);
     return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
+  } else if (MSPropertyRefExpr *refExpr
+             = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
+    MSPropertyOpBuilder builder(*this, refExpr);
+    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
   } else {
     llvm_unreachable("unknown pseudo-object kind!");
   }
@@ -1414,6 +1526,10 @@ static Expr *stripOpaqueValuesFromPseudo
     OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr());
     return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(), 
                                      keyOVE->getSourceExpr()).rebuild(E);
+  } else if (MSPropertyRefExpr *refExpr
+             = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
+    OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr());
+    return MSPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
   } else {
     llvm_unreachable("unknown pseudo-object kind!");
   }

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Apr 16 02:28:30 2013
@@ -525,6 +525,53 @@ Decl *TemplateDeclInstantiator::VisitFie
   return Field;
 }
 
+Decl *TemplateDeclInstantiator::VisitMSPropertyDecl(MSPropertyDecl *D) {
+  bool Invalid = false;
+  TypeSourceInfo *DI = D->getTypeSourceInfo();
+
+  if (DI->getType()->isVariablyModifiedType()) {
+    SemaRef.Diag(D->getLocation(), diag::err_property_is_variably_modified)
+    << D->getName();
+    Invalid = true;
+  } else if (DI->getType()->isInstantiationDependentType())  {
+    DI = SemaRef.SubstType(DI, TemplateArgs,
+                           D->getLocation(), D->getDeclName());
+    if (!DI) {
+      DI = D->getTypeSourceInfo();
+      Invalid = true;
+    } else if (DI->getType()->isFunctionType()) {
+      // C++ [temp.arg.type]p3:
+      //   If a declaration acquires a function type through a type
+      //   dependent on a template-parameter and this causes a
+      //   declaration that does not use the syntactic form of a
+      //   function declarator to have function type, the program is
+      //   ill-formed.
+      SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function)
+      << DI->getType();
+      Invalid = true;
+    }
+  } else {
+    SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType());
+  }
+
+  MSPropertyDecl *Property = new (SemaRef.Context)
+      MSPropertyDecl(Owner, D->getLocation(),
+                     D->getDeclName(), DI->getType(), DI,
+                     D->getLocStart(),
+                     D->getGetterId(), D->getSetterId());
+
+  SemaRef.InstantiateAttrs(TemplateArgs, D, Property, LateAttrs,
+                           StartingScope);
+
+  if (Invalid)
+    Property->setInvalidDecl();
+
+  Property->setAccess(D->getAccess());
+  Owner->addDecl(Property);
+
+  return Property;
+}
+
 Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
   NamedDecl **NamedChain =
     new (SemaRef.Context)NamedDecl*[D->getChainingSize()];

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Apr 16 02:28:30 2013
@@ -6029,6 +6029,32 @@ TreeTransform<Derived>::TransformMSDepen
 }
 
 template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformMSPropertyRefExpr(MSPropertyRefExpr *E) {
+  NestedNameSpecifierLoc QualifierLoc;
+  if (E->getQualifierLoc()) {
+    QualifierLoc
+    = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc());
+    if (!QualifierLoc)
+      return ExprError();
+  }
+
+  MSPropertyDecl *PD = cast_or_null<MSPropertyDecl>(
+    getDerived().TransformDecl(E->getMemberLoc(), E->getPropertyDecl()));
+  if (!PD)
+    return ExprError();
+
+  ExprResult Base = getDerived().TransformExpr(E->getBaseExpr());
+  if (Base.isInvalid())
+    return ExprError();
+
+  return new (SemaRef.getASTContext())
+      MSPropertyRefExpr(Base.get(), PD, E->isArrow(),
+                        SemaRef.getASTContext().PseudoObjectTy, VK_LValue,
+                        QualifierLoc, E->getMemberLoc());
+}
+
+template<typename Derived>
 StmtResult
 TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) {
   StmtResult TryBlock; //  = getDerived().TransformCompoundStmt(S->getTryBlock());

Modified: cfe/trunk/lib/Serialization/ASTCommon.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTCommon.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTCommon.cpp Tue Apr 16 02:28:30 2013
@@ -180,6 +180,7 @@ bool serialization::isRedeclarableDeclKi
   case Decl::UnresolvedUsingValue:
   case Decl::IndirectField:
   case Decl::Field:
+  case Decl::MSProperty:
   case Decl::ObjCIvar:
   case Decl::ObjCAtDefsField:
   case Decl::ImplicitParam:

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Apr 16 02:28:30 2013
@@ -244,6 +244,7 @@ namespace clang {
     void VisitCXXDestructorDecl(CXXDestructorDecl *D);
     void VisitCXXConversionDecl(CXXConversionDecl *D);
     void VisitFieldDecl(FieldDecl *FD);
+    void VisitMSPropertyDecl(MSPropertyDecl *FD);
     void VisitIndirectFieldDecl(IndirectFieldDecl *FD);
     void VisitVarDecl(VarDecl *VD);
     void VisitImplicitParamDecl(ImplicitParamDecl *PD);
@@ -879,6 +880,12 @@ void ASTDeclReader::VisitFieldDecl(Field
   }
 }
 
+void ASTDeclReader::VisitMSPropertyDecl(MSPropertyDecl *PD) {
+  VisitDeclaratorDecl(PD);
+  PD->GetterId = Reader.GetIdentifierInfo(F, Record, Idx);
+  PD->SetterId = Reader.GetIdentifierInfo(F, Record, Idx);
+}
+
 void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) {
   VisitValueDecl(FD);
 
@@ -2136,6 +2143,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID I
   case DECL_BLOCK:
     D = BlockDecl::CreateDeserialized(Context, ID);
     break;
+  case DECL_MS_PROPERTY:
+    D = MSPropertyDecl::CreateDeserialized(Context, ID);
+    break;
   case DECL_CXX_BASE_SPECIFIERS:
     Error("attempt to read a C++ base-specifier record as a declaration");
     return 0;

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Tue Apr 16 02:28:30 2013
@@ -1498,6 +1498,15 @@ void ASTStmtReader::VisitOpaqueValueExpr
 //===----------------------------------------------------------------------===//
 // Microsoft Expressions and Statements
 //===----------------------------------------------------------------------===//
+void ASTStmtReader::VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
+  VisitExpr(E);
+  E->IsArrow = (Record[Idx++] != 0);
+  E->BaseExpr = Reader.ReadSubExpr();
+  E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
+  E->MemberLoc = ReadSourceLocation(Record, Idx);
+  E->TheDecl = ReadDeclAs<MSPropertyDecl>(Record, Idx);
+}
+
 void ASTStmtReader::VisitCXXUuidofExpr(CXXUuidofExpr *E) {
   VisitExpr(E);
   E->setSourceRange(ReadSourceRange(Record, Idx));
@@ -2073,6 +2082,9 @@ Stmt *ASTReader::ReadStmtFromStream(Modu
     case EXPR_CXX_UUIDOF_EXPR:
       S = new (Context) CXXUuidofExpr(Empty, true);
       break;
+    case EXPR_CXX_PROPERTY_REF_EXPR:
+      S = new (Context) MSPropertyRefExpr(Empty);
+      break;
     case EXPR_CXX_UUIDOF_TYPE:
       S = new (Context) CXXUuidofExpr(Empty, false);
       break;

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Apr 16 02:28:30 2013
@@ -907,6 +907,7 @@ void ASTWriter::WriteBlockInfoBlock() {
   RECORD(DECL_OBJC_PROPERTY);
   RECORD(DECL_OBJC_PROPERTY_IMPL);
   RECORD(DECL_FIELD);
+  RECORD(DECL_MS_PROPERTY);
   RECORD(DECL_VAR);
   RECORD(DECL_IMPLICIT_PARAM);
   RECORD(DECL_PARM_VAR);

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Tue Apr 16 02:28:30 2013
@@ -81,6 +81,7 @@ namespace clang {
     void VisitCXXDestructorDecl(CXXDestructorDecl *D);
     void VisitCXXConversionDecl(CXXConversionDecl *D);
     void VisitFieldDecl(FieldDecl *D);
+    void VisitMSPropertyDecl(MSPropertyDecl *D);
     void VisitIndirectFieldDecl(IndirectFieldDecl *D);
     void VisitVarDecl(VarDecl *D);
     void VisitImplicitParamDecl(ImplicitParamDecl *D);
@@ -662,6 +663,13 @@ void ASTDeclWriter::VisitFieldDecl(Field
   Code = serialization::DECL_FIELD;
 }
 
+void ASTDeclWriter::VisitMSPropertyDecl(MSPropertyDecl *D) {
+  VisitDeclaratorDecl(D);
+  Writer.AddIdentifierRef(D->getGetterId(), Record);
+  Writer.AddIdentifierRef(D->getSetterId(), Record);
+  Code = serialization::DECL_MS_PROPERTY;
+}
+
 void ASTDeclWriter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
   VisitValueDecl(D);
   Record.push_back(D->getChainingSize());

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Tue Apr 16 02:28:30 2013
@@ -1534,6 +1534,16 @@ void ASTStmtWriter::VisitAsTypeExpr(AsTy
 //===----------------------------------------------------------------------===//
 // Microsoft Expressions and Statements.
 //===----------------------------------------------------------------------===//
+void ASTStmtWriter::VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
+  VisitExpr(E);
+  Record.push_back(E->isArrow());
+  Writer.AddStmt(E->getBaseExpr());
+  Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record);
+  Writer.AddSourceLocation(E->getMemberLoc(), Record);
+  Writer.AddDeclRef(E->getPropertyDecl(), Record);
+  Code = serialization::EXPR_CXX_PROPERTY_REF_EXPR;
+}
+
 void ASTStmtWriter::VisitCXXUuidofExpr(CXXUuidofExpr *E) {
   VisitExpr(E);
   Writer.AddSourceRange(E->getSourceRange(), Record);

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Tue Apr 16 02:28:30 2013
@@ -609,6 +609,7 @@ void ExprEngine::Visit(const Stmt *S, Ex
     case Stmt::CXXTryStmtClass:
     case Stmt::CXXTypeidExprClass:
     case Stmt::CXXUuidofExprClass:
+    case Stmt::MSPropertyRefExprClass:
     case Stmt::CXXUnresolvedConstructExprClass:
     case Stmt::DependentScopeDeclRefExprClass:
     case Stmt::UnaryTypeTraitExprClass:

Modified: cfe/trunk/test/Parser/MicrosoftExtensions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/MicrosoftExtensions.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/test/Parser/MicrosoftExtensions.cpp (original)
+++ cfe/trunk/test/Parser/MicrosoftExtensions.cpp Tue Apr 16 02:28:30 2013
@@ -331,3 +331,32 @@ namespace Inheritance {
   class __multiple_inheritance B;
   class __virtual_inheritance C;
 }
+
+struct StructWithProperty {
+  __declspec(property) int V0; // expected-error {{expected '(' after 'property'}}
+  __declspec(property()) int V1; // expected-error {{property does not specify a getter or a putter}}
+  __declspec(property(set)) int V2; // expected-error {{putter for property must be specified as 'put', not 'set'}} expected-error {{expected '=' after 'set'}}
+  __declspec(property(ptu)) int V3; // expected-error {{missing 'get=' or 'put='}}
+  __declspec(property(ptu=PutV)) int V4; // expected-error {{expected 'get' or 'put' in property declaration}}
+  __declspec(property(get)) int V5; // expected-error {{expected '=' after 'get'}}
+  __declspec(property(get&)) int V6; // expected-error {{expected '=' after 'get'}}
+  __declspec(property(get=)) int V7; // expected-error {{expected name of accessor method}}
+  __declspec(property(get=GetV)) int V8; // no-warning
+  __declspec(property(get=GetV=)) int V9; // expected-error {{expected ',' or ')' at end of property accessor list}}
+  __declspec(property(get=GetV,)) int V10; // expected-error {{expected 'get' or 'put' in property declaration}}
+  __declspec(property(get=GetV,put=SetV)) int V11; // no-warning
+  __declspec(property(get=GetV,put=SetV,get=GetV)) int V12; // expected-error {{property declaration specifies 'get' accessor twice}}
+
+  int GetV() { return 123; }
+  void SetV(int v) {}
+};
+void TestProperty() {
+  StructWithProperty sp;
+  sp.V8;
+  sp.V8 = 0; // expected-error {{no setter defined for property 'V8'}}
+  int i = sp.V11;
+  sp.V11 = i++;
+  sp.V11 += 8;
+  sp.V11++;
+  ++sp.V11;
+}

Modified: cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp (original)
+++ cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp Tue Apr 16 02:28:30 2013
@@ -208,3 +208,127 @@ void ::f(); // expected-warning{{extra q
 class C {
   C::C(); // expected-warning{{extra qualification on member 'C'}}
 };
+
+struct StructWithProperty {
+  __declspec(property(get=GetV)) int V1;
+  __declspec(property(put=SetV)) int V2;
+  __declspec(property(get=GetV, put=SetV_NotExist)) int V3;
+  __declspec(property(get=GetV_NotExist, put=SetV)) int V4;
+  __declspec(property(get=GetV, put=SetV)) int V5;
+
+  int GetV() { return 123; }
+  void SetV(int i) {}
+};
+void TestProperty() {
+  StructWithProperty sp;
+  int i = sp.V2; // expected-error{{no getter defined for property 'V2'}}
+  sp.V1 = 12; // expected-error{{no setter defined for property 'V1'}}
+  int j = sp.V4; // expected-error{{no member named 'GetV_NotExist' in 'StructWithProperty'}} expected-error{{cannot find suitable getter for property 'V4'}}
+  sp.V3 = 14; // expected-error{{no member named 'SetV_NotExist' in 'StructWithProperty'}} expected-error{{cannot find suitable setter for property 'V3'}}
+  int k = sp.V5;
+  sp.V5 = k++;
+}
+
+/* 4 tests for PseudoObject, begin */
+struct SP1
+{
+  bool operator()() { return true; }
+};
+struct SP2
+{
+  __declspec(property(get=GetV)) SP1 V;
+  SP1 GetV() { return SP1(); }
+};
+void TestSP2() {
+  SP2 sp2;
+  bool b = sp2.V();
+}
+
+struct SP3 {
+  template <class T>
+  void f(T t) {}
+};
+template <class T>
+struct SP4
+{
+  __declspec(property(get=GetV)) int V;
+  int GetV() { return 123; }
+  void f() { SP3 s2; s2.f(V); }
+};
+void TestSP4() {
+  SP4<int> s;
+  s.f();
+}
+
+template <class T>
+struct SP5
+{
+  __declspec(property(get=GetV)) T V;
+  int GetV() { return 123; }
+  void f() { int *p = new int[V]; }
+};
+
+template <class T>
+struct SP6
+{
+public:
+  __declspec(property(get=GetV)) T V;
+  T GetV() { return 123; }
+  void f() { int t = V; }
+};
+void TestSP6() {
+  SP6<int> c;
+  c.f();
+}
+/* 4 tests for PseudoObject, end */
+
+// Property access: explicit, implicit, with Qualifier
+struct SP7 {
+  __declspec(property(get=GetV, put=SetV)) int V;
+  int GetV() { return 123; }
+  void SetV(int v) {}
+
+  void ImplicitAccess() { int i = V; V = i; }
+  void ExplicitAccess() { int i = this->V; this->V = i; }
+};
+struct SP8: public SP7 {
+  void AccessWithQualifier() { int i = SP7::V; SP7::V = i; }
+};
+
+// Property usage
+template <class T>
+struct SP9 {
+  __declspec(property(get=GetV, put=SetV)) T V;
+  T GetV() { return 0; }
+  void SetV(T v) {}
+  void f() { V = this->V; V < this->V; }
+  //void g() { V++; }
+  //void h() { V*=2; }
+};
+struct SP10 {
+  SP10(int v) {}
+  bool operator<(const SP10& v) { return true; }
+  SP10 operator*(int v) { return *this; }
+  SP10& operator=(const SP10& v) { return *this; }
+};
+void TestSP9() {
+  SP9<int> c;
+  int i = c.V; // Decl initializer
+  i = c.V; // Binary op operand
+  c.SetV(c.V); // CallExpr arg
+  int *p = new int[c.V + 1]; // Array size
+  p[c.V] = 1; // Array index
+
+  c.V = 123; // Setter
+
+  c.V++; // Unary op operand
+  c.V *= 2; // Unary op operand
+
+  SP9<int*> c2;
+  c2.V[0] = 123; // Array
+
+  SP9<SP10> c3;
+  c3.f(); // Overloaded binary op operand
+  //c3.g(); // Overloaded incdec op operand
+  //c3.h(); // Overloaded unary op operand
+}

Modified: cfe/trunk/test/SemaObjC/property-user-setter.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-user-setter.m?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/property-user-setter.m (original)
+++ cfe/trunk/test/SemaObjC/property-user-setter.m Tue Apr 16 02:28:30 2013
@@ -85,7 +85,7 @@ static int g_val;
 - (void)setFoo:(int)value;
 @end
 
-void g(int); // expected-note {{passing argument to parameter here}}
+void g(int);
 
 void f(C *c) {
     c.Foo = 17; // OK 

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Tue Apr 16 02:28:30 2013
@@ -4458,6 +4458,7 @@ CXCursor clang_getCursorDefinition(CXCur
   case Decl::TemplateTypeParm:
   case Decl::EnumConstant:
   case Decl::Field:
+  case Decl::MSProperty:
   case Decl::IndirectField:
   case Decl::ObjCIvar:
   case Decl::ObjCAtDefsField:

Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Tue Apr 16 02:28:30 2013
@@ -442,6 +442,7 @@ CXCursor cxcursor::MakeCXCursor(const St
   case Stmt::CXXDependentScopeMemberExprClass:
   case Stmt::CXXPseudoDestructorExprClass:
   case Stmt::MemberExprClass:            
+  case Stmt::MSPropertyRefExprClass:
   case Stmt::ObjCIsaExprClass:
   case Stmt::ObjCIvarRefExprClass:    
   case Stmt::ObjCPropertyRefExprClass: 

Modified: cfe/trunk/tools/libclang/IndexBody.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexBody.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/IndexBody.cpp (original)
+++ cfe/trunk/tools/libclang/IndexBody.cpp Tue Apr 16 02:28:30 2013
@@ -89,6 +89,12 @@ public:
     return true;
   }
 
+  bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
+    IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), Parent,
+                             ParentDC, E, CXIdxEntityRef_Direct);
+    return true;
+  }
+
   bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
     IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
                              Parent, ParentDC, E, CXIdxEntityRef_Direct);

Modified: cfe/trunk/tools/libclang/IndexDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexDecl.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/IndexDecl.cpp (original)
+++ cfe/trunk/tools/libclang/IndexDecl.cpp Tue Apr 16 02:28:30 2013
@@ -105,6 +105,11 @@ public:
     return true;
   }
 
+  bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
+    handleDeclarator(D);
+    return true;
+  }
+
   bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
     IndexCtx.handleEnumerator(D);
     IndexCtx.indexBody(D->getInitExpr(), D);

Modified: cfe/trunk/tools/libclang/IndexingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexingContext.cpp?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/IndexingContext.cpp (original)
+++ cfe/trunk/tools/libclang/IndexingContext.cpp Tue Apr 16 02:28:30 2013
@@ -396,6 +396,12 @@ bool IndexingContext::handleField(const
   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
 }
 
+bool IndexingContext::handleMSProperty(const MSPropertyDecl *D) {
+  DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
+                 /*isContainer=*/false);
+  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+}
+
 bool IndexingContext::handleEnumerator(const EnumConstantDecl *D) {
   DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
                  /*isContainer=*/false);

Modified: cfe/trunk/tools/libclang/IndexingContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexingContext.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/IndexingContext.h (original)
+++ cfe/trunk/tools/libclang/IndexingContext.h Tue Apr 16 02:28:30 2013
@@ -16,6 +16,7 @@
 
 namespace clang {
   class FileEntry;
+  class MSPropertyDecl;
   class ObjCPropertyDecl;
   class ClassTemplateDecl;
   class FunctionTemplateDecl;
@@ -404,6 +405,8 @@ public:
 
   bool handleField(const FieldDecl *D);
 
+  bool handleMSProperty(const MSPropertyDecl *D);
+
   bool handleEnumerator(const EnumConstantDecl *D);
 
   bool handleTagDecl(const TagDecl *D);

Modified: cfe/trunk/tools/libclang/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/RecursiveASTVisitor.h?rev=179585&r1=179584&r2=179585&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/RecursiveASTVisitor.h (original)
+++ cfe/trunk/tools/libclang/RecursiveASTVisitor.h Tue Apr 16 02:28:30 2013
@@ -1614,6 +1614,10 @@ DEF_TRAVERSE_DECL(FieldDecl, {
       TRY_TO(TraverseStmt(D->getInClassInitializer()));
   })
 
+DEF_TRAVERSE_DECL(MSPropertyDecl, {
+    TRY_TO(TraverseDeclaratorHelper(D));
+  })
+
 DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, {
     TRY_TO(TraverseDeclaratorHelper(D));
     if (D->isBitField())
@@ -2133,6 +2137,7 @@ DEF_TRAVERSE_STMT(UnresolvedMemberExpr,
   }
 })
 
+DEF_TRAVERSE_STMT(MSPropertyRefExpr, {})
 DEF_TRAVERSE_STMT(SEHTryStmt, {})
 DEF_TRAVERSE_STMT(SEHExceptStmt, {})
 DEF_TRAVERSE_STMT(SEHFinallyStmt,{})





More information about the cfe-commits mailing list