ABataev created this revision.
ABataev added a reviewer: rnk.
ABataev added a subscriber: cfe-commits.

MSVC supports 'property' attribute and allows to apply it to 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);

http://reviews.llvm.org/D13336

Files:
  include/clang/Sema/Sema.h
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaPseudoObject.cpp
  test/CodeGenCXX/ms-property.cpp

Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -3958,7 +3958,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());
+  if (MSProp && MSProp->getPropertyDecl()->getType()->isArrayType()) {
+    auto I = MSPropArgsMap.find(MSProp);
+    if (I == MSPropArgsMap.end())
+      I = MSPropArgsMap.insert(std::make_pair(MSProp, MSPropArgsTy())).first;
+    I->second.push_back(idx);
+  } else if (base->getType()->isNonOverloadPlaceholderType()) {
     ExprResult result = CheckPlaceholderExpr(base);
     if (result.isInvalid()) return ExprError();
     base = result.get();
@@ -3969,6 +3983,9 @@
     idx = result.get();
   }
 
+  if (MSProp && MSProp->getPropertyDecl()->getType()->isArrayType())
+    return base;
+
   // Build an unanalyzed expression if either operand is type-dependent.
   if (getLangOpts().CPlusPlus &&
       (base->isTypeDependent() || idx->isTypeDependent())) {
Index: lib/Sema/SemaPseudoObject.cpp
===================================================================
--- lib/Sema/SemaPseudoObject.cpp
+++ lib/Sema/SemaPseudoObject.cpp
@@ -1432,6 +1432,11 @@
   }
 
   MultiExprArg ArgExprs;
+  auto I = S.MSPropArgsMap.find(RefExpr);
+  if (I != S.MSPropArgsMap.end()) {
+    ArgExprs = I->second;
+    S.MSPropArgsMap.erase(I);
+  }
   return S.ActOnCallExpr(S.getCurScope(), GetterExpr.get(),
                          RefExpr->getSourceRange().getBegin(), ArgExprs,
                          RefExpr->getSourceRange().getEnd());
@@ -1461,7 +1466,12 @@
     return ExprError();
   }
 
-  SmallVector<Expr*, 1> ArgExprs;
+  Sema::MSPropArgsTy ArgExprs;
+  auto I = S.MSPropArgsMap.find(RefExpr);
+  if (I != S.MSPropArgsMap.end()) {
+    ArgExprs = I->second;
+    S.MSPropArgsMap.erase(I);
+  }
   ArgExprs.push_back(op);
   return S.ActOnCallExpr(S.getCurScope(), SetterExpr.get(),
                          RefExpr->getSourceRange().getBegin(), ArgExprs,
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -463,6 +463,10 @@
   typedef llvm::SmallVector<DeleteExprLoc, 4> DeleteLocs;
   llvm::MapVector<FieldDecl *, DeleteLocs> DeleteExprs;
 
+  /// \brief Map of additional arguments for ms property calls.
+  typedef llvm::SmallVector<Expr *, 4> MSPropArgsTy;
+  llvm::DenseMap<Expr *, MSPropArgsTy> MSPropArgsMap;
+
   typedef llvm::SmallPtrSet<const CXXRecordDecl*, 8> RecordDeclSetTy;
 
   /// PureVirtualClassDiagSet - a set of class declarations which we have
Index: test/CodeGenCXX/ms-property.cpp
===================================================================
--- test/CodeGenCXX/ms-property.cpp
+++ test/CodeGenCXX/ms-property.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -emit-llvm -triple=x86_64-pc-win32 -fms-compatibility %s -o - | FileCheck %s
+
+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()
+{
+  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;
+  return 0;
+}
+
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to