[cfe-commits] Preliminary patch to support MSVC __declspec(property)

Aaron Ballman aaron at aaronballman.com
Thu Jan 10 06:31:04 PST 2013


I was able to apply the patch to ToT cleanly, but it would not build
for me in MSVC 10.  I would get the following error when expanding
StmtNodes.inc:

error C2664: '`anonymous-namespace'::is_good' : cannot convert
parameter 1 from '`anonymous-namespace'::bad' to
'`anonymous-namespace'::good'
C:\llvm\build\tools\clang\include\clang\AST\StmtNodes.inc     485

I think MSPropertyRefExpr doesn't implement some statement node
members as expected, but can't honestly say I've run across this
before.

A few more comments below (mostly nitpicky)...

~Aaron

> diff -ur /home/er91/Downloads/clang-3.2.src/include/clang/AST/Decl.h ./clang/include/clang/AST/Decl.h
> --- /home/er91/Downloads/clang-3.2.src/include/clang/AST/Decl.h 2012-11-10 03:03:35.000000000 +0800
> +++ ./clang/include/clang/AST/Decl.h 2013-01-03 17:51:48.632060006 +0800
> @@ -3053,6 +3053,29 @@
>    static bool classof(const Decl *D) { return classofKind(D->getKind()); }
>    static bool classofKind(Kind K) { return K == FileScopeAsm; }
>  };
> +
> +class MSPropertyDecl : public DeclaratorDecl {
> +  llvm::StringRef GetterName, SetterName;
> +
> +public:
> +  MSPropertyDecl(DeclContext *DC, SourceLocation L,
> +                 DeclarationName N, QualType T, TypeSourceInfo *TInfo,
> +                 SourceLocation StartL, llvm::StringRef Getter,
> +                 llvm::StringRef Setter):
> +  DeclaratorDecl(MSProperty, DC, L, N, T, TInfo, StartL), GetterName(Getter),
> +  SetterName(Setter) {}
> +
> +  static MSPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID);
> +
> +  static bool classof(const Decl *D) { return D->getKind() == MSProperty; }
> +
> +  bool hasGetter() { return !GetterName.empty(); }
> +  llvm::StringRef getGetterName() { return GetterName; }

Both of these can be declared as const methods.

> +  void setGetterName(llvm::StringRef getterName) { GetterName = getterName; }
> +  bool hasSetter() { return !SetterName.empty(); }

This can be a const method as well.

> +  void setSetterName(llvm::StringRef setterName) { SetterName = setterName; }
> +  llvm::StringRef getSetterName() { return SetterName; }

Same here.

> +};
>
>  /// BlockDecl - This represents a block literal declaration, which is like an
>  /// unnamed FunctionDecl.  For example:
> diff -ur /home/er91/Downloads/clang-3.2.src/include/clang/AST/ExprCXX.h ./clang/include/clang/AST/ExprCXX.h
> --- /home/er91/Downloads/clang-3.2.src/include/clang/AST/ExprCXX.h 2012-11-07 08:12:38.000000000 +0800
> +++ ./clang/include/clang/AST/ExprCXX.h 2013-01-03 17:51:48.880060010 +0800
> @@ -546,6 +546,50 @@
>    }
>  };
>
> +class MSPropertyRefExpr : public Expr {
> +  Expr *BaseExpr;
> +  MSPropertyDecl *Decl;
> +  SourceLocation StartLoc, EndLoc, MemberLoc;
> +  bool IsArrow;
> +
> +public:
> +  MSPropertyRefExpr(Expr *baseExpr, MSPropertyDecl *decl, bool isArrow,
> +                    QualType ty, ExprValueKind VK, SourceLocation memberLoc,
> +                    SourceLocation startLoc, SourceLocation endLoc)
> +  : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary,
> +         ty->isDependentType(), ty->isDependentType(),
> +         ty->isInstantiationDependentType(),
> +         ty->containsUnexpandedParameterPack()),
> +  BaseExpr(baseExpr), Decl(decl),
> +  MemberLoc(memberLoc), IsArrow(isArrow) {}
> +
> +  MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {}
> +
> +  SourceRange getSourceRange() const LLVM_READONLY {
> +    return SourceRange(StartLoc, EndLoc);
> +  }
> +  void setSourceRange(SourceRange sr) {
> +    StartLoc = sr.getBegin();
> +    EndLoc = sr.getEnd();
> +  }
> +
> +  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; }
> +  void setBaseExpr(Expr *baseExpr) { BaseExpr = baseExpr; }
> +  MSPropertyDecl* getMSPropertyDecl() const { return Decl; }
> +  void setMSPropertyDecl(MSPropertyDecl *decl) { Decl = decl; }
> +  bool isArrow() const { return IsArrow; }
> +  void setArrow(bool isArrow) { IsArrow = isArrow; }
> +  SourceLocation getMemberLoc() const { return MemberLoc; }
> +  void setMemberLoc(SourceLocation memberLoc) { MemberLoc = memberLoc; }
> +};
> +
>  /// CXXUuidofExpr - A microsoft C++ @c __uuidof expression, which gets
>  /// the _GUID that corresponds to the supplied type or expression.
>  ///
> diff -ur /home/er91/Downloads/clang-3.2.src/include/clang/AST/RecursiveASTVisitor.h ./clang/include/clang/AST/RecursiveASTVisitor.h
> --- /home/er91/Downloads/clang-3.2.src/include/clang/AST/RecursiveASTVisitor.h 2012-09-26 10:36:12.000000000 +0800
> +++ ./clang/include/clang/AST/RecursiveASTVisitor.h 2013-01-03 17:51:48.932060011 +0800
> @@ -1666,6 +1666,9 @@
>    return true;
>  }
>
> +DEF_TRAVERSE_DECL(MSPropertyDecl, {
> +  TRY_TO(TraverseDeclaratorHelper(D));
> +})
>  DEF_TRAVERSE_DECL(FieldDecl, {
>      TRY_TO(TraverseDeclaratorHelper(D));
>      if (D->isBitField())
> @@ -2053,6 +2056,8 @@
>        TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
>    })
>
> +DEF_TRAVERSE_STMT(MSPropertyRefExpr, { })
> +
>  DEF_TRAVERSE_STMT(CXXUuidofExpr, {
>      // The child-iterator will pick up the arg if it's an expression,
>      // but not if it's a type.
> diff -ur /home/er91/Downloads/clang-3.2.src/include/clang/Basic/DeclNodes.td ./clang/include/clang/Basic/DeclNodes.td
> --- /home/er91/Downloads/clang-3.2.src/include/clang/Basic/DeclNodes.td 2012-01-02 05:23:57.000000000 +0800
> +++ ./clang/include/clang/Basic/DeclNodes.td 2013-01-03 17:51:49.276060017 +0800
> @@ -45,6 +45,7 @@
>        def Var : DDecl<Declarator>;
>          def ImplicitParam : DDecl<Var>;
>          def ParmVar : DDecl<Var>;
> +      def MSProperty : DDecl<Declarator>;
>        def NonTypeTemplateParm : DDecl<Declarator>;
>    def Template : DDecl<Named, 1>;
>      def RedeclarableTemplate : DDecl<Template, 1>;
> diff -ur /home/er91/Downloads/clang-3.2.src/include/clang/Basic/DiagnosticParseKinds.td ./clang/include/clang/Basic/DiagnosticParseKinds.td
> --- /home/er91/Downloads/clang-3.2.src/include/clang/Basic/DiagnosticParseKinds.td 2012-11-05 13:32:00.000000000 +0800
> +++ ./clang/include/clang/Basic/DiagnosticParseKinds.td 2013-01-03 17:51:49.332060017 +0800
> @@ -514,6 +514,18 @@
>    "__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_declspec_property_no_getter_or_putter : Error<
> +  "no getter or putter in __declspec(property)">;
> +def err_expected_get_or_put : Error<
> +  "expect 'get' or 'put' in __declspec(property)">;
> +def err_expected_equal : Error<
> +  "expect '=' in __declspec(property)">;
> +def err_duplicate_accessor : Error<
> +  "dupilcate accessor in __declspec(property)">;
> +def err_expected_identifier : Error<
> +  "expected identifier in __declspec(property)">;
> +def err_expected_comma_or_right_paren : Error<
> +  "expected ',' or ')' in __declspec(property)">;
>
>  /// C++ Templates
>  def err_expected_template : Error<"expected template">;
> diff -ur /home/er91/Downloads/clang-3.2.src/include/clang/Basic/DiagnosticSemaKinds.td ./clang/include/clang/Basic/DiagnosticSemaKinds.td
> --- /home/er91/Downloads/clang-3.2.src/include/clang/Basic/DiagnosticSemaKinds.td 2012-11-10 09:18:17.000000000 +0800
> +++ ./clang/include/clang/Basic/DiagnosticSemaKinds.td 2013-01-03 17:51:49.376060018 +0800
> @@ -1712,6 +1712,15 @@
>  def warn_mismatched_section : Warning<
>    "section does not match previous declaration">, InGroup<Section>;
>
> +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<
> diff -ur /home/er91/Downloads/clang-3.2.src/include/clang/Basic/StmtNodes.td ./clang/include/clang/Basic/StmtNodes.td
> --- /home/er91/Downloads/clang-3.2.src/include/clang/Basic/StmtNodes.td 2012-09-12 08:56:43.000000000 +0800
> +++ ./clang/include/clang/Basic/StmtNodes.td 2013-01-03 17:51:49.460060020 +0800
> @@ -163,6 +163,7 @@
>  def OpaqueValueExpr : DStmt<Expr>;
>
>  // Microsoft Extensions.
> +def MSPropertyRefExpr : DStmt<Expr>;
>  def CXXUuidofExpr : DStmt<Expr>;
>  def SEHTryStmt : Stmt;
>  def SEHExceptStmt : Stmt;
> diff -ur /home/er91/Downloads/clang-3.2.src/include/clang/Sema/Sema.h ./clang/include/clang/Sema/Sema.h
> --- /home/er91/Downloads/clang-3.2.src/include/clang/Sema/Sema.h 2012-11-07 08:12:38.000000000 +0800
> +++ ./clang/include/clang/Sema/Sema.h 2013-01-03 17:51:49.960060028 +0800
> @@ -1492,6 +1492,12 @@
>                           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,
> diff -ur /home/er91/Downloads/clang-3.2.src/include/clang/Sema/Template.h ./clang/include/clang/Sema/Template.h
> --- /home/er91/Downloads/clang-3.2.src/include/clang/Sema/Template.h 2012-09-18 12:52:05.000000000 +0800
> +++ ./clang/include/clang/Sema/Template.h 2013-01-03 17:51:49.972060029 +0800
> @@ -391,6 +391,7 @@
>      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);
> diff -ur /home/er91/Downloads/clang-3.2.src/include/clang/Serialization/ASTBitCodes.h ./clang/include/clang/Serialization/ASTBitCodes.h
> --- /home/er91/Downloads/clang-3.2.src/include/clang/Serialization/ASTBitCodes.h 2012-11-01 04:59:50.000000000 +0800
> +++ ./clang/include/clang/Serialization/ASTBitCodes.h 2013-01-03 17:51:49.988060029 +0800
> @@ -906,6 +906,8 @@
>        DECL_OBJC_PROPERTY_IMPL,
>        /// \brief A FieldDecl record.
>        DECL_FIELD,
> +      /// \brief A __delcpec(property) record.
> +      DECL_MS_PROPERTY,
>        /// \brief A VarDecl record.
>        DECL_VAR,
>        /// \brief An ImplicitParamDecl record.
> @@ -1251,6 +1253,7 @@
>        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
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/AST/DeclBase.cpp ./clang/lib/AST/DeclBase.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/AST/DeclBase.cpp 2012-09-11 05:20:09.000000000 +0800
> +++ ./clang/lib/AST/DeclBase.cpp 2013-01-03 17:51:51.812060059 +0800
> @@ -472,6 +472,7 @@
>      case NonTypeTemplateParm:
>      case ObjCMethod:
>      case ObjCProperty:
> +    case MSProperty:
>        return IDNS_Ordinary;
>      case Label:
>        return IDNS_Label;
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/AST/Decl.cpp ./clang/lib/AST/Decl.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/AST/Decl.cpp 2012-11-12 12:10:23.000000000 +0800
> +++ ./clang/lib/AST/Decl.cpp 2013-01-03 17:51:51.800060060 +0800
> @@ -994,7 +994,7 @@
>    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();
> @@ -2918,6 +2918,13 @@
>    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(),
> +                                  llvm::StringRef(), llvm::StringRef());
> +}
> +
>  EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
>                                             SourceLocation L,
>                                             IdentifierInfo *Id, QualType T,
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/AST/ExprClassification.cpp ./clang/lib/AST/ExprClassification.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/AST/ExprClassification.cpp 2012-09-12 08:56:43.000000000 +0800
> +++ ./clang/lib/AST/ExprClassification.cpp 2013-01-03 17:51:51.892060061 +0800
> @@ -135,6 +135,7 @@
>      // 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.
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/AST/ExprConstant.cpp ./clang/lib/AST/ExprConstant.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/AST/ExprConstant.cpp 2012-10-18 07:52:07.000000000 +0800
> +++ ./clang/lib/AST/ExprConstant.cpp 2013-01-03 17:51:51.916060061 +0800
> @@ -6448,6 +6448,7 @@
>    case Expr::CXXDynamicCastExprClass:
>    case Expr::CXXTypeidExprClass:
>    case Expr::CXXUuidofExprClass:
> +  case Expr::MSPropertyRefExprClass:
>    case Expr::CXXNullPtrLiteralExprClass:
>    case Expr::UserDefinedLiteralClass:
>    case Expr::CXXThisExprClass:
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/AST/Expr.cpp ./clang/lib/AST/Expr.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/AST/Expr.cpp 2012-11-09 02:41:43.000000000 +0800
> +++ ./clang/lib/AST/Expr.cpp 2013-01-03 17:51:51.888060061 +0800
> @@ -2764,6 +2764,7 @@
>      return false;
>
>    case CallExprClass:
> +  case MSPropertyRefExprClass:
>    case CompoundAssignOperatorClass:
>    case VAArgExprClass:
>    case AtomicExprClass:
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/AST/ItaniumMangle.cpp ./clang/lib/AST/ItaniumMangle.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/AST/ItaniumMangle.cpp 2012-10-04 12:58:17.000000000 +0800
> +++ ./clang/lib/AST/ItaniumMangle.cpp 2013-01-03 17:51:51.960060062 +0800
> @@ -2367,6 +2367,7 @@
>    case Expr::ImplicitValueInitExprClass:
>    case Expr::ParenListExprClass:
>    case Expr::LambdaExprClass:
> +  case Expr::MSPropertyRefExprClass:
>      llvm_unreachable("unexpected statement kind");
>
>    // FIXME: invent manglings for all these.
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/AST/StmtPrinter.cpp ./clang/lib/AST/StmtPrinter.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/AST/StmtPrinter.cpp 2012-10-24 04:26:57.000000000 +0800
> +++ ./clang/lib/AST/StmtPrinter.cpp 2013-01-03 18:48:29.756117478 +0800
> @@ -1224,6 +1224,15 @@
>    OS << ")";
>  }
>
> +void StmtPrinter::VisitMSPropertyRefExpr(MSPropertyRefExpr *Node) {
> +  PrintExpr(Node->getBaseExpr());
> +  if (Node->isArrow())
> +    OS << "->";
> +  else
> +    OS << ".";
> +  OS << Node->getMSPropertyDecl()->getName();
> +}
> +
>  void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
>    switch (Node->getLiteralOperatorKind()) {
>    case UserDefinedLiteral::LOK_Raw:
> Only in ./clang/lib/AST: StmtPrinter.cpp~
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/AST/StmtProfile.cpp ./clang/lib/AST/StmtProfile.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/AST/StmtProfile.cpp 2012-09-26 10:36:12.000000000 +0800
> +++ ./clang/lib/AST/StmtProfile.cpp 2013-01-03 17:51:52.072060064 +0800
> @@ -766,6 +766,11 @@
>      VisitType(S->getTypeOperand());
>  }
>
> +void StmtProfiler::VisitMSPropertyRefExpr(const MSPropertyRefExpr *S) {
> +  VisitExpr(S);
> +  VisitDecl(S->getMSPropertyDecl());
> +}
> +
>  void StmtProfiler::VisitCXXThisExpr(const CXXThisExpr *S) {
>    VisitExpr(S);
>    ID.AddBoolean(S->isImplicit());
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/CodeGen/CGDecl.cpp ./clang/lib/CodeGen/CGDecl.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/CodeGen/CGDecl.cpp 2012-11-02 06:30:59.000000000 +0800
> +++ ./clang/lib/CodeGen/CGDecl.cpp 2013-01-03 17:51:52.560060072 +0800
> @@ -45,6 +45,7 @@
>    case Decl::CXXDestructor:
>    case Decl::CXXConversion:
>    case Decl::Field:
> +  case Decl::MSProperty:
>    case Decl::IndirectField:
>    case Decl::ObjCIvar:
>    case Decl::ObjCAtDefsField:
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/Parse/ParseDecl.cpp ./clang/lib/Parse/ParseDecl.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/Parse/ParseDecl.cpp 2012-11-07 03:34:54.000000000 +0800
> +++ ./clang/lib/Parse/ParseDecl.cpp 2013-01-03 17:51:54.300060101 +0800
> @@ -363,17 +363,60 @@
>      // 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))
>        return;
> +    unsigned AccessorCount = 0;
> +    llvm::StringRef PrevAccessorType;
> +    IdentifierInfo *GetterName = 0, *SetterName = 0;
> +    while (true) {
> +      if (!Tok.is(tok::identifier) ||
> +          ((Tok.getIdentifierInfo()->getName() != "get")
> +           && (Tok.getIdentifierInfo()->getName() != "put"))) {
> +            Diag(Tok.getLocation(), diag::err_expected_get_or_put);
> +            break;
> +          }
> +      if (PrevAccessorType == Tok.getIdentifierInfo()->getName()) {
> +        Diag(Tok.getLocation(), diag::err_duplicate_accessor);
> +        break;
> +      }
> +      PrevAccessorType = Tok.getIdentifierInfo()->getName();

This may be nit picky, or contrary to someone else's recommendation,
but it strikes me as strange to make this a parser problem instead of
a semantics problem.

Also, this will fail when given input like:

__declspec( property( get=foo, put=bar, get=foobar ) )

> +      ConsumeAnyToken();
> +
> +      if (!Tok.is(tok::equal)) {
> +        Diag(Tok.getLocation(), diag::err_expected_equal);
> +        break;
> +      }
> +      ConsumeAnyToken();
> +
> +      if (!Tok.is(tok::identifier)) {
> +        Diag(Tok.getLocation(), diag::err_expected_identifier);
> +        break;
> +      }
> +      if (PrevAccessorType == "get")
> +        GetterName = Tok.getIdentifierInfo();
> +      else
> +        SetterName = Tok.getIdentifierInfo();
> +      AccessorCount++;
> +      ConsumeAnyToken();
> +
> +      if (Tok.is(tok::comma)) {
> +        ConsumeAnyToken();
> +        continue;
> +      } else if (Tok.is(tok::r_paren)) {
> +        break;
> +      } else {
> +        Diag(Tok.getLocation(), diag::err_expected_comma_or_right_paren);
> +        break;
> +      }
> +    }
> +    if (AccessorCount == 0)
> +      Diag(Loc, diag::err_ms_declspec_property_no_getter_or_putter);
> +    else
> +      // Use "scopeName" to store GetterName and "parmName" to store SetterName
> +      Attrs.addNew(Ident, Loc, GetterName, Loc, SetterName, SourceLocation(),
> +                   0, 0, AttributeList::AS_Declspec);
>      T.skipToEnd();
>    } else {
>      // We don't recognize this as a valid declspec, but instead of creating the
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaDecl.cpp ./clang/lib/Sema/SemaDecl.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaDecl.cpp 2012-11-10 07:03:14.000000000 +0800
> +++ ./clang/lib/Sema/SemaDecl.cpp 2013-01-03 19:13:44.808143078 +0800
> @@ -6512,6 +6512,13 @@
>  /// initialization rather than copy initialization.
>  void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
>                                  bool DirectInit, bool TypeMayContainAuto) {
> +  if (!Init->getType().isNull()
> +      && (Init->getType()->getAsPlaceholderType() != NULL)) {
> +    ExprResult result = CheckPlaceholderExpr(Init);
> +    if  (result.isInvalid()) return;
> +    Init = result.take();
> +  }
> +
>    // If there is no declaration, there was an error parsing it.  Just ignore
>    // the initializer.
>    if (RealDecl == 0 || RealDecl->isInvalidDecl())
> @@ -9542,6 +9549,98 @@
>    return NewFD;
>  }
>
> +/// 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();
> +  SourceLocation Loc = DeclStart;
> +  if (II) 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);
> +
> +  if (D.getDeclSpec().isThreadSpecified())
> +    Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
> +  if (D.getDeclSpec().isConstexprSpecified())
> +    Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
> +    << 2;
> +
> +  // 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;
> +  }
> +  Previous.suppressDiagnostics();
> +
> +  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 *NewFD;
> +  llvm::StringRef GetterName = MSPropertyAttr->getScopeName() ?
> +    MSPropertyAttr->getScopeName()->getName() : StringRef();
> +  llvm::StringRef SetterName = MSPropertyAttr->getParameterName() ?
> +    MSPropertyAttr->getParameterName()->getName() : StringRef();
> +  NewFD = new (Context) MSPropertyDecl(Record, Loc,
> +                                       II, T, TInfo, TSSL,
> +                                       GetterName, SetterName);
> +  NewFD->setAccess(AS);
> +
> +  if (NewFD->isInvalidDecl())
> +    Record->setInvalidDecl();
> +
> +  if (D.getDeclSpec().isModulePrivateSpecified())
> +    NewFD->setModulePrivate();
> +
> +  if (NewFD->isInvalidDecl() && PrevDecl) {
> +    // Don't introduce NewFD into scope; there's already something
> +    // with the same name in the same scope.
> +  } else if (II) {
> +    PushOnScopeChains(NewFD, S);
> +  } else
> +    Record->addDecl(NewFD);
> +
> +  return NewFD;
> +}
> +
>  /// \brief Build a new FieldDecl and check its well-formedness.
>  ///
>  /// This routine builds a new FieldDecl given the fields name, type,
> Only in ./clang/lib/Sema: SemaDecl.cpp~
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaDeclCXX.cpp ./clang/lib/Sema/SemaDeclCXX.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaDeclCXX.cpp 2012-11-10 15:24:09.000000000 +0800
> +++ ./clang/lib/Sema/SemaDeclCXX.cpp 2013-01-03 18:53:55.888122989 +0800
> @@ -1551,6 +1551,13 @@
>    return false;
>  }
>
> +static AttributeList *getMSPropertyAttr(AttributeList *list) {
> +  for (AttributeList* it = list; it != 0; it = it->getNext())
> +    if (it->getName()->getName() == "property")
> +      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
> @@ -1707,8 +1714,15 @@
>        SS.clear();
>      }
>
> -    Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth,
> -                         InitStyle, AS);
> +    AttributeList *MSPropertyAttr = getMSPropertyAttr(D.getDeclSpec().getAttributes().getList());

This line is > 80 characters

> +    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);
> Only in ./clang/lib/Sema: SemaDeclCXX.cpp~
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaExceptionSpec.cpp ./clang/lib/Sema/SemaExceptionSpec.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaExceptionSpec.cpp 2012-10-20 16:26:51.000000000 +0800
> +++ ./clang/lib/Sema/SemaExceptionSpec.cpp 2013-01-03 17:51:54.872060111 +0800
> @@ -976,6 +976,9 @@
>        return CT;
>      return mergeCanThrow(CT, canSubExprsThrow(*this, E));
>    }
> +
> +  case Expr::MSPropertyRefExprClass:
> +    return CT_Can;
>
>      // ObjC message sends are like function calls, but never have exception
>      // specs.
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaExpr.cpp ./clang/lib/Sema/SemaExpr.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaExpr.cpp 2012-11-10 07:55:21.000000000 +0800
> +++ ./clang/lib/Sema/SemaExpr.cpp 2013-01-03 19:43:05.972172839 +0800
> @@ -2544,6 +2544,10 @@
>      case Decl::CXXConstructor:
>        valueKind = VK_RValue;
>        break;
> +
> +    case Decl::MSProperty:
> +      valueKind = VK_LValue;
> +      break;
>      }
>
>      return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS);
> @@ -3309,6 +3313,11 @@
>                                                    RLoc));
>    }
>
> +  if (LHSExp->getType()->getAsPlaceholderType()) {
> +    ExprResult result = CheckPlaceholderExpr(LHSExp);
> +    if (result.isInvalid()) return ExprError();
> +    LHSExp = result.take();
> +  }
>    if (getLangOpts().CPlusPlus &&
>        (LHSExp->getType()->isRecordType() ||
>         LHSExp->getType()->isEnumeralType() ||
> Only in ./clang/lib/Sema: SemaExpr.cpp~
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaExprCXX.cpp ./clang/lib/Sema/SemaExprCXX.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaExprCXX.cpp 2012-11-07 08:12:38.000000000 +0800
> +++ ./clang/lib/Sema/SemaExprCXX.cpp 2013-01-03 19:14:28.520143817 +0800
> @@ -1192,6 +1192,11 @@
>        }
>      } SizeDiagnoser(ArraySize);
>
> +    if (ArraySize->getType()->getAsPlaceholderType()) {
> +      ExprResult result = CheckPlaceholderExpr(ArraySize);
> +      if (result.isInvalid()) return ExprError();
> +      ArraySize = result.take();
> +    }
>      ExprResult ConvertedSize
>        = ConvertToIntegralOrEnumerationType(StartLoc, ArraySize, SizeDiagnoser,
>                                             /*AllowScopedEnumerations*/ false);
> Only in ./clang/lib/Sema: SemaExprCXX.cpp~
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaExprMember.cpp ./clang/lib/Sema/SemaExprMember.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaExprMember.cpp 2012-10-19 03:05:02.000000000 +0800
> +++ ./clang/lib/Sema/SemaExprMember.cpp 2013-01-03 17:51:55.016060113 +0800
> @@ -116,7 +116,8 @@
>      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());
> @@ -788,6 +789,17 @@
>    return Owned(result);
>  }
>
> +static ExprResult
> +BuildMSPropertyRefExpr(ASTContext &Context, Expr *BaseExpr, bool IsArrow,
> +                       SourceLocation StartLoc, SourceLocation EndLoc,
> +                       MSPropertyDecl *PD) {
> +  return new (Context) MSPropertyRefExpr(BaseExpr, PD, IsArrow,
> +                                         Context.PseudoObjectTy, VK_LValue,
> +                                         StartLoc,
> +                                         BaseExpr->getSourceRange().getBegin(),
> +                                         EndLoc);
> +}
> +
>  /// \brief Build a MemberExpr AST node.
>  static MemberExpr *BuildMemberExpr(Sema &SemaRef,
>                                     ASTContext &C, Expr *Base, bool isArrow,
> @@ -944,6 +956,11 @@
>    if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))
>      return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow,
>                                     SS, FD, FoundDecl, MemberNameInfo);
> +
> +  if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl))
> +    return BuildMSPropertyRefExpr(Context, BaseExpr, IsArrow,
> +                                  MemberNameInfo.getLocStart(),
> +                                  MemberNameInfo.getLocEnd(), PD);
>
>    if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))
>      // We may have found a field within an anonymous union or struct
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaPseudoObject.cpp ./clang/lib/Sema/SemaPseudoObject.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaPseudoObject.cpp 2012-11-20 05:01:40.000000000 +0800
> +++ ./clang/lib/Sema/SemaPseudoObject.cpp 2013-01-03 18:43:44.072112650 +0800
> @@ -200,7 +200,7 @@
>      /// Return true if assignments have a non-void result.
>      bool CanCaptureValueOfType(QualType ty) {
>        assert(!ty->isIncompleteType());
> -      assert(!ty->isDependentType());
> +      //assert(!ty->isDependentType());

Why is this commented out?

>
>        if (const CXXRecordDecl *ClassDecl = ty->getAsCXXRecordDecl())
>          return ClassDecl->isTriviallyCopyable();
> @@ -283,6 +283,18 @@
>     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.
> @@ -1327,6 +1339,70 @@
>  }
>
>  //===----------------------------------------------------------------------===//
> +//  MSVC __declspec(property) references
> +//===----------------------------------------------------------------------===//
> +
> +Expr* MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
> +  return syntacticBase;
> +}
> +
> +ExprResult MSPropertyOpBuilder::buildGet() {
> +  if (!RefExpr->getMSPropertyDecl()->hasGetter()) {
> +    S.Diag(RefExpr->getMemberLoc(), diag::err_no_getter_for_property)
> +    << RefExpr->getMSPropertyDecl()->getName();
> +    return ExprError();
> +  }
> +
> +  UnqualifiedId GetterName;
> +  IdentifierInfo *II = S.getPreprocessor().getIdentifierInfo(
> +                                                             RefExpr->getMSPropertyDecl()->getGetterName());
> +  GetterName.setIdentifier(II, SourceLocation());
> +  CXXScopeSpec SS;
> +  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->getMSPropertyDecl()->getName();
> +  }
> +
> +  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->getMSPropertyDecl()->hasSetter()) {
> +    S.Diag(RefExpr->getMemberLoc(), diag::err_no_setter_for_property)
> +    << RefExpr->getMSPropertyDecl()->getName();
> +    return ExprError();
> +  }
> +
> +  UnqualifiedId SetterName;
> +  IdentifierInfo *II = S.getPreprocessor().getIdentifierInfo(
> +                                                             RefExpr->getMSPropertyDecl()->getSetterName());
> +  SetterName.setIdentifier(II, SourceLocation());
> +  CXXScopeSpec SS;
> +  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->getMSPropertyDecl()->getName();
> +  }
> +
> +  SmallVector<Expr*, 1> ArgExprs;
> +  ArgExprs.push_back(op);
> +  return S.ActOnCallExpr(S.getCurScope(), SetterExpr.take(),
> +                         RefExpr->getSourceRange().getBegin(), ArgExprs,
> +                         op->getSourceRange().getEnd());
> +}

Source formatting concerns here as well with line length (check the
all of the new methods).

> +
> +//===----------------------------------------------------------------------===//
>  //  General Sema routines.
>  //===----------------------------------------------------------------------===//
>
> @@ -1341,6 +1417,10 @@
>             = 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!");
>    }
> @@ -1363,6 +1443,10 @@
>    } 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!");
>    }
> @@ -1392,6 +1476,10 @@
>               = 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!");
>    }
> @@ -1417,6 +1505,9 @@
>      OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr());
>      return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(),
>                                       keyOVE->getSourceExpr()).rebuild(E);
> +  } else if (MSPropertyRefExpr *refExpr
> +             = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
> +    return refExpr;
>    } else {
>      llvm_unreachable("unknown pseudo-object kind!");
>    }
> Only in ./clang/lib/Sema: SemaPseudoObject.cpp~
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaTemplateInstantiateDecl.cpp ./clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/Sema/SemaTemplateInstantiateDecl.cpp 2012-10-23 08:32:41.000000000 +0800
> +++ ./clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 2013-01-03 17:51:55.644060124 +0800
> @@ -479,6 +479,54 @@
>    return Field;
>  }
>
> +Decl *TemplateDeclInstantiator::VisitMSPropertyDecl(MSPropertyDecl *D) {
> +  bool Invalid = false;
> +  TypeSourceInfo *DI = D->getTypeSourceInfo();
> +  if (DI->getType()->isInstantiationDependentType() ||
> +      DI->getType()->isVariablyModifiedType())  {
> +    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(), D->getType(), DI,
> +                     D->getLocStart(),
> +                     D->getGetterName(), D->getSetterName());
> +
> +  SemaRef.InstantiateAttrs(TemplateArgs, D, Property, LateAttrs, StartingScope);
> +
> +  if (Invalid)
> +    Property->setInvalidDecl();
> +
> +  if (CXXRecordDecl *Parent= dyn_cast<CXXRecordDecl>(Property->getDeclContext())) {

Line length > 80.

> +    if (Parent->isAnonymousStructOrUnion() &&
> +        Parent->getRedeclContext()->isFunctionOrMethod())
> +      SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Property);
> +  }
> +
> +  Property->setAccess(D->getAccess());
> +  Owner->addDecl(Property);
> +
> +  return Property;
> +}
> +
>  Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
>    NamedDecl **NamedChain =
>      new (SemaRef.Context)NamedDecl*[D->getChainingSize()];
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/Sema/TreeTransform.h ./clang/lib/Sema/TreeTransform.h
> --- /home/er91/Downloads/clang-3.2.src/lib/Sema/TreeTransform.h 2012-11-29 07:44:46.000000000 +0800
> +++ ./clang/lib/Sema/TreeTransform.h 2013-01-03 17:51:55.712060126 +0800
> @@ -5945,6 +5945,20 @@
>                                                     NameInfo,
>                                                     SubStmt.get());
>  }
> +
> +template<typename Derived>
> +ExprResult
> +TreeTransform<Derived>::TransformMSPropertyRefExpr(MSPropertyRefExpr *E) {
> +  ExprResult Base = getDerived().TransformExpr(E->getBaseExpr());
> +  if (Base.isInvalid())
> +    return ExprError();
> +  return new (SemaRef.getASTContext())
> +      MSPropertyRefExpr(Base.get(), E->getMSPropertyDecl(), E->isArrow(),
> +                        SemaRef.getASTContext().PseudoObjectTy, VK_LValue,
> +                        E->getSourceRange().getBegin(),
> +                        E->getMemberLoc(),
> +                        E->getSourceRange().getEnd());
> +}
>
>  template<typename Derived>
>  StmtResult
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/Serialization/ASTReaderDecl.cpp ./clang/lib/Serialization/ASTReaderDecl.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/Serialization/ASTReaderDecl.cpp 2012-11-06 08:35:02.000000000 +0800
> +++ ./clang/lib/Serialization/ASTReaderDecl.cpp 2013-01-03 17:51:55.768060126 +0800
> @@ -251,6 +251,7 @@
>      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);
> @@ -885,6 +886,12 @@
>    }
>  }
>
> +void ASTDeclReader::VisitMSPropertyDecl(MSPropertyDecl *PD) {
> +  VisitDeclaratorDecl(PD);
> +  PD->setGetterName(Reader.ReadString(Record, Idx));
> +  PD->setSetterName(Reader.ReadString(Record, Idx));
> +}
> +
>  void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) {
>    VisitValueDecl(FD);
>
> @@ -2101,6 +2108,9 @@
>    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;
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/Serialization/ASTReaderStmt.cpp ./clang/lib/Serialization/ASTReaderStmt.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/Serialization/ASTReaderStmt.cpp 2012-11-09 02:41:43.000000000 +0800
> +++ ./clang/lib/Serialization/ASTReaderStmt.cpp 2013-01-03 17:51:55.780060126 +0800
> @@ -1493,6 +1493,17 @@
>  //===----------------------------------------------------------------------===//
>  // Microsoft Expressions and Statements
>  //===----------------------------------------------------------------------===//
> +void ASTStmtReader::VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
> +  VisitExpr(E);
> +  E->setArrow(Record[Idx++] != 0);
> +  E->setBaseExpr(Reader.ReadSubExpr());
> +  E->setMemberLoc(ReadSourceLocation(Record, Idx));
> +  SourceLocation StartLoc = ReadSourceLocation(Record, Idx);
> +  SourceLocation EndLoc = ReadSourceLocation(Record, Idx);
> +  E->setSourceRange(SourceRange(StartLoc, EndLoc));
> +  E->setMSPropertyDecl(ReadDeclAs<MSPropertyDecl>(Record, Idx));
> +}
> +
>  void ASTStmtReader::VisitCXXUuidofExpr(CXXUuidofExpr *E) {
>    VisitExpr(E);
>    E->setSourceRange(ReadSourceRange(Record, Idx));
> @@ -2077,6 +2088,9 @@
>      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;
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/Serialization/ASTWriterDecl.cpp ./clang/lib/Serialization/ASTWriterDecl.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/Serialization/ASTWriterDecl.cpp 2012-11-06 08:35:02.000000000 +0800
> +++ ./clang/lib/Serialization/ASTWriterDecl.cpp 2013-01-03 18:50:19.080119325 +0800
> @@ -81,6 +81,7 @@
>      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);
> @@ -655,6 +656,14 @@
>    Code = serialization::DECL_FIELD;
>  }
>
> +void ASTDeclWriter::VisitMSPropertyDecl(MSPropertyDecl *D) {
> +  VisitDeclaratorDecl(D);
> +  Writer.AddString(D->getGetterName(), Record);
> +  Writer.AddString(D->getSetterName(), Record);
> +
> +  Code = serialization::DECL_MS_PROPERTY;
> +}
> +
>  void ASTDeclWriter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
>    VisitValueDecl(D);
>    Record.push_back(D->getChainingSize());
> Only in ./clang/lib/Serialization: ASTWriterDecl.cpp~
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/Serialization/ASTWriterStmt.cpp ./clang/lib/Serialization/ASTWriterStmt.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/Serialization/ASTWriterStmt.cpp 2012-11-09 02:41:43.000000000 +0800
> +++ ./clang/lib/Serialization/ASTWriterStmt.cpp 2013-01-03 17:51:55.812060127 +0800
> @@ -1531,6 +1531,17 @@
>  //===----------------------------------------------------------------------===//
>  // Microsoft Expressions and Statements.
>  //===----------------------------------------------------------------------===//
> +void ASTStmtWriter::VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
> +  VisitExpr(E);
> +  Record.push_back(E->isArrow());
> +  Writer.AddStmt(E->getBaseExpr());
> +  Writer.AddSourceLocation(E->getMemberLoc(), Record);
> +  Writer.AddSourceLocation(E->getSourceRange().getBegin(), Record);
> +  Writer.AddSourceLocation(E->getSourceRange().getEnd(), Record);
> +  Writer.AddDeclRef(E->getMSPropertyDecl(), Record);
> +  Code = serialization::EXPR_CXX_PROPERTY_REF_EXPR;
> +}
> +
>  void ASTStmtWriter::VisitCXXUuidofExpr(CXXUuidofExpr *E) {
>    VisitExpr(E);
>    Writer.AddSourceRange(E->getSourceRange(), Record);
> diff -ur /home/er91/Downloads/clang-3.2.src/lib/StaticAnalyzer/Core/ExprEngine.cpp ./clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
> --- /home/er91/Downloads/clang-3.2.src/lib/StaticAnalyzer/Core/ExprEngine.cpp 2012-11-03 10:54:20.000000000 +0800
> +++ ./clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 2013-01-03 17:51:56.384060137 +0800
> @@ -530,6 +530,7 @@
>      case Stmt::CXXTryStmtClass:
>      case Stmt::CXXTypeidExprClass:
>      case Stmt::CXXUuidofExprClass:
> +    case Stmt::MSPropertyRefExprClass:
>      case Stmt::CXXUnresolvedConstructExprClass:
>      case Stmt::DependentScopeDeclRefExprClass:
>      case Stmt::UnaryTypeTraitExprClass:
> diff -ur /home/er91/Downloads/clang-3.2.src/tools/libclang/IndexBody.cpp ./clang/tools/libclang/IndexBody.cpp
> --- /home/er91/Downloads/clang-3.2.src/tools/libclang/IndexBody.cpp 2012-09-11 06:58:04.000000000 +0800
> +++ ./clang/tools/libclang/IndexBody.cpp 2013-01-03 18:12:31.484081007 +0800
> @@ -89,6 +89,12 @@
>      // be a message expr as part of PseudoObjectExpr.
>      return true;
>    }
> +
> +  bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
> +    IndexCtx.handleReference(E->getMSPropertyDecl(), E->getMemberLoc(), Parent,
> +                             ParentDC, E, CXIdxEntityRef_Direct);
> +    return true;
> +  }
>
>    bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
>      IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
> Only in ./clang/tools/libclang: IndexBody.cpp~
> diff -ur /home/er91/Downloads/clang-3.2.src/tools/libclang/IndexDecl.cpp ./clang/tools/libclang/IndexDecl.cpp
> --- /home/er91/Downloads/clang-3.2.src/tools/libclang/IndexDecl.cpp 2012-10-11 00:42:25.000000000 +0800
> +++ ./clang/tools/libclang/IndexDecl.cpp 2013-01-03 18:05:23.792073780 +0800
> @@ -103,6 +103,11 @@
>        IndexCtx.indexBody(D->getInClassInitializer(), D);
>      return true;
>    }
> +
> +  bool VisitMSPropertyDecl(MSPropertyDecl *D) {
> +    handleDeclarator(D);
> +    return true;
> +  }
>
>    bool VisitEnumConstantDecl(EnumConstantDecl *D) {
>      IndexCtx.handleEnumerator(D);
> Only in ./clang/tools/libclang: IndexDecl.cpp~
> diff -ur /home/er91/Downloads/clang-3.2.src/tools/libclang/IndexingContext.cpp ./clang/tools/libclang/IndexingContext.cpp
> --- /home/er91/Downloads/clang-3.2.src/tools/libclang/IndexingContext.cpp 2012-10-29 14:03:40.000000000 +0800
> +++ ./clang/tools/libclang/IndexingContext.cpp 2013-01-03 18:06:28.048074866 +0800
> @@ -382,6 +382,12 @@
>    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);
> Only in ./clang/tools/libclang: IndexingContext.cpp~
> diff -ur /home/er91/Downloads/clang-3.2.src/tools/libclang/IndexingContext.h ./clang/tools/libclang/IndexingContext.h
> --- /home/er91/Downloads/clang-3.2.src/tools/libclang/IndexingContext.h 2012-10-29 14:02:59.000000000 +0800
> +++ ./clang/tools/libclang/IndexingContext.h 2013-01-03 18:07:12.468075617 +0800
> @@ -403,6 +403,8 @@
>
>    bool handleField(const FieldDecl *D);
>
> +  bool handleMSProperty(const MSPropertyDecl *D);
> +
>    bool handleEnumerator(const EnumConstantDecl *D);
>
>    bool handleTagDecl(const TagDecl *D);
> Only in ./clang/tools/libclang: IndexingContext.h~
> diff -ur /home/er91/Downloads/clang-3.2.src/tools/libclang/RecursiveASTVisitor.h ./clang/tools/libclang/RecursiveASTVisitor.h
> --- /home/er91/Downloads/clang-3.2.src/tools/libclang/RecursiveASTVisitor.h 2012-09-26 10:36:12.000000000 +0800
> +++ ./clang/tools/libclang/RecursiveASTVisitor.h 2013-01-03 18:13:42.716082211 +0800
> @@ -1603,6 +1603,10 @@
>        TRY_TO(TraverseStmt(D->getInClassInitializer()));
>    })
>
> +DEF_TRAVERSE_DECL(MSPropertyDecl, {
> +    TRY_TO(TraverseDeclaratorHelper(D));
> +  })
> +
>  DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, {
>      TRY_TO(TraverseDeclaratorHelper(D));
>      if (D->isBitField())
> @@ -2123,6 +2127,7 @@
>    }
>  })
>
> +DEF_TRAVERSE_STMT(MSPropertyRefExpr, {})
>  DEF_TRAVERSE_STMT(SEHTryStmt, {})
>  DEF_TRAVERSE_STMT(SEHExceptStmt, {})
>  DEF_TRAVERSE_STMT(SEHFinallyStmt,{})
> Only in ./clang/tools/libclang: RecursiveASTVisitor.h~
>

Testcases?  What you've attached is a reasonable start, but it's not
in the proper testcase format (see clang\tests for examples), nor does
it cover as many cases as I'd like to see.

That being said, I think you're getting pretty close!

Thanks!

~Aaron



More information about the cfe-commits mailing list