ABataev updated this revision to Diff 37854.
ABataev added a comment.

Update after review


http://reviews.llvm.org/D13336

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaPseudoObject.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/CodeGenCXX/ms-property.cpp
  test/SemaCXX/ms-property-error.cpp
  test/SemaCXX/ms-property.cpp

Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -5955,6 +5955,10 @@
     case PREDEF_TYPE_OMP_ARRAY_SECTION:
       T = Context.OMPArraySectionTy;
       break;
+
+    case PREDEF_TYPE_MS_PROPERTY_SUBSCRIPT:
+      T = Context.MSPropertySubscriptTy;
+      break;
     }
 
     assert(!T.isNull() && "Unknown predefined type");
Index: lib/Serialization/ASTCommon.cpp
===================================================================
--- lib/Serialization/ASTCommon.cpp
+++ lib/Serialization/ASTCommon.cpp
@@ -187,6 +187,9 @@
   case BuiltinType::OMPArraySection:
     ID = PREDEF_TYPE_OMP_ARRAY_SECTION;
     break;
+  case BuiltinType::MSPropertySubscript:
+    ID = PREDEF_TYPE_MS_PROPERTY_SUBSCRIPT;
+    break;
   }
 
   return TypeIdx(ID);
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp
+++ lib/AST/Type.cpp
@@ -2597,6 +2597,8 @@
     return "reserve_id_t";
   case OMPArraySection:
     return "<OpenMP array section type>";
+  case MSPropertySubscript:
+    return "<MS declspec property subscript type>";
   }
 
   llvm_unreachable("Invalid builtin type.");
@@ -3554,6 +3556,7 @@
     case BuiltinType::BuiltinFn:
     case BuiltinType::NullPtr:
     case BuiltinType::OMPArraySection:
+    case BuiltinType::MSPropertySubscript:
       return false;
     }
 
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -1055,6 +1055,9 @@
   if (LangOpts.OpenMP)
     InitBuiltinType(OMPArraySectionTy, BuiltinType::OMPArraySection);
 
+  if(LangOpts.MSVCCompat)
+    InitBuiltinType(MSPropertySubscriptTy, BuiltinType::MSPropertySubscript);
+
   // C99 6.2.5p11.
   FloatComplexTy      = getComplexType(FloatTy);
   DoubleComplexTy     = getComplexType(DoubleTy);
Index: lib/AST/TypeLoc.cpp
===================================================================
--- lib/AST/TypeLoc.cpp
+++ lib/AST/TypeLoc.cpp
@@ -353,6 +353,7 @@
   case BuiltinType::OCLReserveID:
   case BuiltinType::BuiltinFn:
   case BuiltinType::OMPArraySection:
+  case BuiltinType::MSPropertySubscript:
     return TST_unspecified;
   }
 
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -3917,7 +3917,21 @@
   // operand might be an overloadable type, in which case the overload
   // resolution for the operator overload should get the first crack
   // at the overload.
-  if (base->getType()->isNonOverloadPlaceholderType()) {
+  // MSDN, property (C++)
+  // https://msdn.microsoft.com/en-us/library/yhfk0thd(v=vs.120).aspx
+  // This attribute can also be used in the declaration of an empty array in a
+  // class or structure definition. For example:
+  // __declspec(property(get=GetX, put=PutX)) int x[];
+  // The above statement indicates that x[] can be used with one or more array
+  // indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b),
+  // and p->x[a][b] = i will be turned into p->PutX(a, b, i);
+  auto *MSProp = dyn_cast<MSPropertyRefExpr>(base->IgnoreParens());
+  bool IsMSPropertySubscript =
+      (MSProp && MSProp->getPropertyDecl()->getType()->isArrayType()) ||
+      base->getType()->isSpecificPlaceholderType(
+          BuiltinType::MSPropertySubscript);
+  if (!IsMSPropertySubscript &&
+      base->getType()->isNonOverloadPlaceholderType()) {
     ExprResult result = CheckPlaceholderExpr(base);
     if (result.isInvalid()) return ExprError();
     base = result.get();
@@ -4093,7 +4107,12 @@
   Expr *RHSExp = Idx;
 
   // Perform default conversions.
-  if (!LHSExp->getType()->getAs<VectorType>()) {
+  auto *MSProp = dyn_cast<MSPropertyRefExpr>(LHSExp->IgnoreParens());
+  bool IsMSPropertySubscript =
+      (MSProp && MSProp->getPropertyDecl()->getType()->isArrayType()) ||
+      LHSExp->getType()->isSpecificPlaceholderType(
+          BuiltinType::MSPropertySubscript);
+  if (!LHSExp->getType()->getAs<VectorType>() && !IsMSPropertySubscript) {
     ExprResult Result = DefaultFunctionArrayLvalueConversion(LHSExp);
     if (Result.isInvalid())
       return ExprError();
@@ -4118,6 +4137,10 @@
     BaseExpr = LHSExp;
     IndexExpr = RHSExp;
     ResultType = Context.DependentTy;
+  } else if (IsMSPropertySubscript) {
+    BaseExpr = LHSExp;
+    IndexExpr = RHSExp;
+    ResultType = Context.MSPropertySubscriptTy;
   } else if (const PointerType *PTy = LHSTy->getAs<PointerType>()) {
     BaseExpr = LHSExp;
     IndexExpr = RHSExp;
@@ -4707,6 +4730,7 @@
     return false;
 
   // Pseudo-objects should be converted as soon as possible.
+  case BuiltinType::MSPropertySubscript:
   case BuiltinType::PseudoObject:
     return true;
 
@@ -4849,7 +4873,8 @@
       return new (Context)
           CallExpr(Context, Fn, None, Context.VoidTy, VK_RValue, RParenLoc);
     }
-    if (Fn->getType() == Context.PseudoObjectTy) {
+    if (Fn->getType() == Context.PseudoObjectTy ||
+        Fn->getType() == Context.MSPropertySubscriptTy) {
       ExprResult result = CheckPlaceholderExpr(Fn);
       if (result.isInvalid()) return ExprError();
       Fn = result.get();
@@ -9355,7 +9380,8 @@
 /// CheckForModifiableLvalue - Verify that E is a modifiable lvalue.  If not,
 /// emit an error and return true.  If so, return false.
 static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
-  assert(!E->hasPlaceholderType(BuiltinType::PseudoObject));
+  assert(!E->hasPlaceholderType(BuiltinType::PseudoObject) &&
+         !E->hasPlaceholderType(BuiltinType::MSPropertySubscript));
   SourceLocation OrigLoc = Loc;
   Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context,
                                                               &Loc);
@@ -9496,7 +9522,8 @@
 QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
                                        SourceLocation Loc,
                                        QualType CompoundType) {
-  assert(!LHSExpr->hasPlaceholderType(BuiltinType::PseudoObject));
+  assert(!LHSExpr->hasPlaceholderType(BuiltinType::PseudoObject) &&
+         !LHSExpr->hasPlaceholderType(BuiltinType::MSPropertySubscript));
 
   // Verify that LHS is a modifiable lvalue, and emit error if not.
   if (CheckForModifiableLvalue(LHSExpr, Loc, *this))
@@ -10678,7 +10705,8 @@
   // Handle pseudo-objects in the LHS.
   if (const BuiltinType *pty = LHSExpr->getType()->getAsPlaceholderType()) {
     // Assignments with a pseudo-object l-value need special analysis.
-    if (pty->getKind() == BuiltinType::PseudoObject &&
+    if ((pty->getKind() == BuiltinType::PseudoObject ||
+         pty->getKind() == BuiltinType::MSPropertySubscript) &&
         BinaryOperator::isAssignmentOp(Opc))
       return checkPseudoObjectAssignment(S, OpLoc, Opc, LHSExpr, RHSExpr);
 
@@ -10968,7 +10996,8 @@
   // overloaded-operator check considers the right type.
   if (const BuiltinType *pty = Input->getType()->getAsPlaceholderType()) {
     // Increment and decrement of pseudo-object references.
-    if (pty->getKind() == BuiltinType::PseudoObject &&
+    if ((pty->getKind() == BuiltinType::PseudoObject ||
+         pty->getKind() == BuiltinType::MSPropertySubscript) &&
         UnaryOperator::isIncrementDecrementOp(Opc))
       return checkPseudoObjectIncDec(S, OpLoc, Opc, Input);
 
@@ -14477,6 +14506,7 @@
     return diagnoseUnknownAnyExpr(*this, E);
 
   // Pseudo-objects.
+  case BuiltinType::MSPropertySubscript:
   case BuiltinType::PseudoObject:
     return checkPseudoObjectRValue(E);
 
Index: lib/Sema/SemaPseudoObject.cpp
===================================================================
--- lib/Sema/SemaPseudoObject.cpp
+++ lib/Sema/SemaPseudoObject.cpp
@@ -121,6 +121,15 @@
                                           rebuiltExpr->isValueDependent());
       }
 
+      if (e->getType()->isSpecificPlaceholderType(
+              BuiltinType::MSPropertySubscript)) {
+        auto *ASE = cast<ArraySubscriptExpr>(e);
+        return new (S.Context) ArraySubscriptExpr(
+            rebuild(ASE->getBase()), ASE->getIdx(), ASE->getType(),
+            ASE->getValueKind(), ASE->getObjectKind(), ASE->getRBracketLoc());
+      }
+
+
       llvm_unreachable("bad expression to rebuild!");
     }
   };
@@ -329,11 +338,26 @@
  class MSPropertyOpBuilder : public PseudoOpBuilder {
    MSPropertyRefExpr *RefExpr;
    OpaqueValueExpr *InstanceBase;
+   SmallVector<Expr *, 4> ArgExprs;
 
  public:
    MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr) :
      PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
      RefExpr(refExpr), InstanceBase(nullptr) {}
+   MSPropertyOpBuilder(Sema &S, Expr *E)
+       : PseudoOpBuilder(S, E->getSourceRange().getBegin()),
+         InstanceBase(nullptr) {
+     assert(E->getType()->isSpecificPlaceholderType(
+         BuiltinType::MSPropertySubscript));
+     auto *Base = E->IgnoreParens();
+     while (Base->getType()->isSpecificPlaceholderType(
+         BuiltinType::MSPropertySubscript)) {
+       auto *ASE = cast<ArraySubscriptExpr>(Base);
+       ArgExprs.insert(ArgExprs.begin(), ASE->getIdx());
+       Base = ASE->getBase()->IgnoreParens();
+     }
+     RefExpr = cast<MSPropertyRefExpr>(Base);
+   }
 
    Expr *rebuildAndCaptureObject(Expr *) override;
    ExprResult buildGet() override;
@@ -1432,7 +1456,6 @@
     return ExprError();
   }
 
-  MultiExprArg ArgExprs;
   return S.ActOnCallExpr(S.getCurScope(), GetterExpr.get(),
                          RefExpr->getSourceRange().getBegin(), ArgExprs,
                          RefExpr->getSourceRange().getEnd());
@@ -1462,7 +1485,6 @@
     return ExprError();
   }
 
-  SmallVector<Expr*, 1> ArgExprs;
   ArgExprs.push_back(op);
   return S.ActOnCallExpr(S.getCurScope(), SetterExpr.get(),
                          RefExpr->getSourceRange().getBegin(), ArgExprs,
@@ -1488,6 +1510,10 @@
              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
     MSPropertyOpBuilder builder(*this, refExpr);
     return builder.buildRValueOperation(E);
+  } else if (E->getType()->isSpecificPlaceholderType(
+                 BuiltinType::MSPropertySubscript)) {
+    MSPropertyOpBuilder builder(*this, E);
+    return builder.buildRValueOperation(E);
   } else {
     llvm_unreachable("unknown pseudo-object kind!");
   }
@@ -1514,6 +1540,10 @@
              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
     MSPropertyOpBuilder builder(*this, refExpr);
     return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
+  } else if (opaqueRef->getType()->isSpecificPlaceholderType(
+                 BuiltinType::MSPropertySubscript)) {
+    MSPropertyOpBuilder builder(*this, opaqueRef);
+    return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
   } else {
     llvm_unreachable("unknown pseudo-object kind!");
   }
@@ -1545,7 +1575,11 @@
     return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
   } else if (MSPropertyRefExpr *refExpr
              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
-    MSPropertyOpBuilder builder(*this, refExpr);
+      MSPropertyOpBuilder builder(*this, refExpr);
+      return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
+  } else if (opaqueRef->getType()->isSpecificPlaceholderType(
+                 BuiltinType::MSPropertySubscript)) {
+    MSPropertyOpBuilder builder(*this, opaqueRef);
     return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
   } else {
     llvm_unreachable("unknown pseudo-object kind!");
@@ -1576,6 +1610,16 @@
              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
     OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr());
     return MSPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
+  } else if (opaqueRef->getType()->isSpecificPlaceholderType(
+                 BuiltinType::MSPropertySubscript)) {
+    while (opaqueRef->getType()->isSpecificPlaceholderType(
+        BuiltinType::MSPropertySubscript)) {
+      opaqueRef =
+          cast<ArraySubscriptExpr>(opaqueRef)->getBase()->IgnoreParens();
+    }
+    auto *BaseOVE = cast<OpaqueValueExpr>(
+        cast<MSPropertyRefExpr>(opaqueRef)->getBaseExpr());
+    return MSPropertyRefRebuilder(S, BaseOVE->getSourceExpr()).rebuild(E);
   } else {
     llvm_unreachable("unknown pseudo-object kind!");
   }
@@ -1613,7 +1657,8 @@
                                         bop->getObjectKind(),
                                         bop->getOperatorLoc(), false);
   } else {
-    assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));
+    assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject) ||
+           syntax->hasPlaceholderType(BuiltinType::MSPropertySubscript));
     return stripOpaqueValuesFromPseudoObjectRef(*this, syntax);
   }
 }
Index: include/clang/Serialization/ASTBitCodes.h
===================================================================
--- include/clang/Serialization/ASTBitCodes.h
+++ include/clang/Serialization/ASTBitCodes.h
@@ -797,7 +797,10 @@
       /// \brief OpenCL reserve_id type.
       PREDEF_TYPE_RESERVE_ID_ID = 54,
       /// \brief The placeholder type for OpenMP array section.
-      PREDEF_TYPE_OMP_ARRAY_SECTION = 55
+      PREDEF_TYPE_OMP_ARRAY_SECTION = 55,
+      /// \brief The placeholder type for MS declspec property subscript pseudo
+      /// expression.
+      PREDEF_TYPE_MS_PROPERTY_SUBSCRIPT = 56,
     };
 
     /// \brief The number of predefined type IDs that are reserved for
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -851,6 +851,7 @@
   CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy;
   CanQualType OCLQueueTy, OCLNDRangeTy, OCLReserveIDTy;
   CanQualType OMPArraySectionTy;
+  CanQualType MSPropertySubscriptTy;
 
   // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
   mutable QualType AutoDeductTy;     // Deduction against 'auto'.
Index: include/clang/AST/BuiltinTypes.def
===================================================================
--- include/clang/AST/BuiltinTypes.def
+++ include/clang/AST/BuiltinTypes.def
@@ -248,8 +248,11 @@
 // A placeholder type for OpenMP array sections.
 PLACEHOLDER_TYPE(OMPArraySection, OMPArraySectionTy)
 
+// A placeholder type for MS property subscript expression.
+PLACEHOLDER_TYPE(MSPropertySubscript, MSPropertySubscriptTy)
+
 #ifdef LAST_BUILTIN_TYPE
-LAST_BUILTIN_TYPE(OMPArraySection)
+LAST_BUILTIN_TYPE(MSPropertySubscript)
 #undef LAST_BUILTIN_TYPE
 #endif
 
Index: test/SemaCXX/ms-property.cpp
===================================================================
--- test/SemaCXX/ms-property.cpp
+++ test/SemaCXX/ms-property.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -ast-print -verify -triple=x86_64-pc-win32 -fms-compatibility %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fms-compatibility -emit-pch -o %t %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fms-compatibility -include-pch %t -verify %s -ast-print -o - | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+class Test1 {
+private:
+  int x_;
+
+public:
+  Test1(int x) : x_(x) {}
+  __declspec(property(get = get_x)) int X;
+  int get_x() const { return x_; }
+  static Test1 *GetTest1() { return new Test1(10); }
+};
+
+class S {
+public:
+  __declspec(property(get=GetX,put=PutX)) int x[];
+  int GetX(int i, int j) { return i+j; }
+  void PutX(int i, int j, int k) { j = i = k; }
+};
+
+template <typename T>
+class St {
+public:
+  __declspec(property(get=GetX,put=PutX)) T x[];
+  T GetX(T i, T j) { return i+j; }
+  void PutX(T i, T j, T k) { j = i = k; }
+  ~St() { x[0][0] = x[1][1]; }
+};
+
+// CHECK: this->x[0][0] = this->x[1][1];
+// CHECK: this->x[0][0] = this->x[1][1];
+
+// CHECK-LABEL: main
+int main(int argc, char **argv) {
+  S *p1 = 0;
+  St<float> *p2 = 0;
+  // CHECK: St<int> a;
+  St<int> a;
+  // CHECK-NEXT: int j = (p1->x)[223][11];
+  int j = (p1->x)[223][11];
+  // CHECK-NEXT: (p1->x[23])[1] = j;
+  (p1->x[23])[1] = j;
+  // CHECK-NEXT: float j1 = (p2->x[223][11]);
+  float j1 = (p2->x[223][11]);
+  // CHECK-NEXT: ((p2->x)[23])[1] = j1;
+  ((p2->x)[23])[1] = j1;
+  // CHECK-NEXT: ++(((p2->x)[23])[1]);
+  ++(((p2->x)[23])[1]);
+  // CHECK-NEXT: return Test1::GetTest1()->X;
+  return Test1::GetTest1()->X;
+}
+#endif // HEADER
Index: test/SemaCXX/ms-property-error.cpp
===================================================================
--- test/SemaCXX/ms-property-error.cpp
+++ test/SemaCXX/ms-property-error.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -verify -fms-compatibility %s -fsyntax-only -o -
+
+class S {
+public:
+  __declspec(property(get=GetX,put=PutX)) int x[];
+  int GetX(int i, int j) { return i+j; } // expected-note {{'GetX' declared here}}
+  void PutX(int i, int j, int k) { j = i = k; } // expected-note {{'PutX' declared here}}
+};
+
+template <typename T>
+class St {
+public:
+  __declspec(property(get=GetX,put=PutX)) T x[];
+  T GetX(T i, T j) { return i+j; } // expected-note 3 {{'GetX' declared here}}
+  void PutX(T i, T j, T k) { j = i = k; }  // expected-note 2 {{'PutX' declared here}}
+  ~St() {
+    x[1] = 0; // expected-error {{too few arguments to function call, expected 3, have 2}}
+    x[2][3] = 4;
+    ++x[2][3];
+    x[1][2] = x[3][4][5]; // expected-error {{too many arguments to function call, expected 2, have 3}}
+  }
+};
+
+// CHECK-LABEL: main
+int main(int argc, char **argv) {
+  S *p1 = 0;
+  St<float> *p2 = 0;
+  St<int> a; // expected-note {{in instantiation of member function 'St<int>::~St' requested here}}
+  int j = (p1->x)[223][11][2]; // expected-error {{too many arguments to function call, expected 2, have 3}}
+  (p1->x[23]) = argc; // expected-error {{too few arguments to function call, expected 3, have 2}}
+  float j1 = (p2->x); // expected-error {{too few arguments to function call, expected 2, have 0}}
+  ((p2->x)[23])[1][2] = *argv; // expected-error {{too many arguments to function call, expected 3, have 4}}
+  return ++(((p2->x)[23])); // expected-error {{too few arguments to function call, expected 2, have 1}}
+}
Index: test/CodeGenCXX/ms-property.cpp
===================================================================
--- test/CodeGenCXX/ms-property.cpp
+++ test/CodeGenCXX/ms-property.cpp
@@ -1,4 +1,10 @@
 // RUN: %clang_cc1 -emit-llvm -triple=x86_64-pc-win32 -fms-compatibility %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fms-compatibility -emit-pch -o %t %s
+// RUN: %clang_cc1 -emit-llvm -triple=x86_64-pc-win32 -fms-compatibility -include-pch %t -verify %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
 
 class Test1 {
 private:
@@ -11,9 +17,42 @@
   static Test1 *GetTest1() { return new Test1(10); }
 };
 
+class S {
+public:
+  __declspec(property(get=GetX,put=PutX)) int x[];
+  int GetX(int i, int j) { return i+j; }
+  void PutX(int i, int j, int k) { j = i = k; }
+};
+
+template <typename T>
+class St {
+public:
+  __declspec(property(get=GetX,put=PutX)) T x[];
+  T GetX(T i, T j) { return i+j; }
+  void PutX(T i, T j, T k) { j = i = k; }
+};
+
 // CHECK-LABEL: main
 int main(int argc, char **argv) {
+  S *p1 = 0;
+  St<float> *p2 = 0;
+  // CHECK: call i32 @"\01?GetX@S@@QEAAHHH@Z"(%class.S* %{{.+}}, i32 223, i32 11)
+  int j = p1->x[223][11];
+  // CHECK: [[J:%.+]] = load i32, i32* %
+  // CHECK-NEXT: call void @"\01?PutX@S@@QEAAXHHH@Z"(%class.S* %{{.+}}, i32 23, i32 1, i32 [[J]])
+  p1->x[23][1] = j;
+  // CHECK: call float @"\01?GetX@?$St@M@@QEAAMMM@Z"(%class.St* %{{.+}}, float 2.230000e+02, float 1.100000e+01)
+  float j1 = p2->x[223][11];
+  // CHECK: [[J1:%.+]] = load float, float* %
+  // CHECK-NEXT: call void @"\01?PutX@?$St@M@@QEAAXMMM@Z"(%class.St* %{{.+}}, float 2.300000e+01, float 1.000000e+00, float [[J1]])
+  p2->x[23][1] = j1;
+  // CHECK: [[GET:%.+]] = call float @"\01?GetX@?$St@M@@QEAAMMM@Z"(%class.St* %6, float 2.300000e+01, float 1.000000e+00)
+  // CHECK-NEXT: [[INC:%.+]] = fadd float [[GET]], 1.000000e+00
+  // CHECK-NEXT: call void @"\01?PutX@?$St@M@@QEAAXMMM@Z"(%class.St* %6, float 2.300000e+01, float 1.000000e+00, float [[INC]])
+  ++p2->x[23][1];
   // CHECK: [[CALL:%.+]] = call %class.Test1* @"\01?GetTest1@Test1@@SAPEAV1@XZ"()
   // CHECK-NEXT: call i32 @"\01?get_x@Test1@@QEBAHXZ"(%class.Test1* [[CALL]])
   return Test1::GetTest1()->X;
 }
+
+#endif //HEADER
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to