[MSVC] 'property' with an empty array in array subscript expression.
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);
Differential Revision: http://reviews.llvm.org/D13336

llvm-svn: 254067
diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp
index 8998a7e..f94fb17 100644
--- a/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/clang/lib/Sema/SemaPseudoObject.cpp
@@ -44,17 +44,76 @@
 
 namespace {
   // Basically just a very focused copy of TreeTransform.
-  template <class T> struct Rebuilder {
+  struct Rebuilder {
     Sema &S;
-    Rebuilder(Sema &S) : S(S) {}
+    unsigned MSPropertySubscriptCount;
+    typedef llvm::function_ref<Expr *(Expr *, unsigned)> SpecificRebuilderRefTy;
+    const SpecificRebuilderRefTy &SpecificCallback;
+    Rebuilder(Sema &S, const SpecificRebuilderRefTy &SpecificCallback)
+        : S(S), MSPropertySubscriptCount(0),
+          SpecificCallback(SpecificCallback) {}
 
-    T &getDerived() { return static_cast<T&>(*this); }
+    Expr *rebuildObjCPropertyRefExpr(ObjCPropertyRefExpr *refExpr) {
+      // Fortunately, the constraint that we're rebuilding something
+      // with a base limits the number of cases here.
+      if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
+        return refExpr;
+
+      if (refExpr->isExplicitProperty()) {
+        return new (S.Context) ObjCPropertyRefExpr(
+            refExpr->getExplicitProperty(), refExpr->getType(),
+            refExpr->getValueKind(), refExpr->getObjectKind(),
+            refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));
+      }
+      return new (S.Context) ObjCPropertyRefExpr(
+          refExpr->getImplicitPropertyGetter(),
+          refExpr->getImplicitPropertySetter(), refExpr->getType(),
+          refExpr->getValueKind(), refExpr->getObjectKind(),
+          refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));
+    }
+    Expr *rebuildObjCSubscriptRefExpr(ObjCSubscriptRefExpr *refExpr) {
+      assert(refExpr->getBaseExpr());
+      assert(refExpr->getKeyExpr());
+
+      return new (S.Context) ObjCSubscriptRefExpr(
+          SpecificCallback(refExpr->getBaseExpr(), 0),
+          SpecificCallback(refExpr->getKeyExpr(), 1), refExpr->getType(),
+          refExpr->getValueKind(), refExpr->getObjectKind(),
+          refExpr->getAtIndexMethodDecl(), refExpr->setAtIndexMethodDecl(),
+          refExpr->getRBracket());
+    }
+    Expr *rebuildMSPropertyRefExpr(MSPropertyRefExpr *refExpr) {
+      assert(refExpr->getBaseExpr());
+
+      return new (S.Context) MSPropertyRefExpr(
+          SpecificCallback(refExpr->getBaseExpr(), 0),
+          refExpr->getPropertyDecl(), refExpr->isArrow(), refExpr->getType(),
+          refExpr->getValueKind(), refExpr->getQualifierLoc(),
+          refExpr->getMemberLoc());
+    }
+    Expr *rebuildMSPropertySubscriptExpr(MSPropertySubscriptExpr *refExpr) {
+      assert(refExpr->getBase());
+      assert(refExpr->getIdx());
+
+      auto *NewBase = rebuild(refExpr->getBase());
+      ++MSPropertySubscriptCount;
+      return new (S.Context) MSPropertySubscriptExpr(
+          NewBase,
+          SpecificCallback(refExpr->getIdx(), MSPropertySubscriptCount),
+          refExpr->getType(), refExpr->getValueKind(), refExpr->getObjectKind(),
+          refExpr->getRBracketLoc());
+    }
 
     Expr *rebuild(Expr *e) {
       // Fast path: nothing to look through.
-      if (typename T::specific_type *specific
-            = dyn_cast<typename T::specific_type>(e))
-        return getDerived().rebuildSpecific(specific);
+      if (auto *PRE = dyn_cast<ObjCPropertyRefExpr>(e))
+        return rebuildObjCPropertyRefExpr(PRE);
+      if (auto *SRE = dyn_cast<ObjCSubscriptRefExpr>(e))
+        return rebuildObjCSubscriptRefExpr(SRE);
+      if (auto *MSPRE = dyn_cast<MSPropertyRefExpr>(e))
+        return rebuildMSPropertyRefExpr(MSPRE);
+      if (auto *MSPSE = dyn_cast<MSPropertySubscriptExpr>(e))
+        return rebuildMSPropertySubscriptExpr(MSPSE);
 
       // Otherwise, we should look through and rebuild anything that
       // IgnoreParens would.
@@ -125,72 +184,6 @@
     }
   };
 
-  struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> {
-    Expr *NewBase;
-    ObjCPropertyRefRebuilder(Sema &S, Expr *newBase)
-      : Rebuilder<ObjCPropertyRefRebuilder>(S), NewBase(newBase) {}
-
-    typedef ObjCPropertyRefExpr specific_type;
-    Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) {
-      // Fortunately, the constraint that we're rebuilding something
-      // with a base limits the number of cases here.
-      assert(refExpr->isObjectReceiver());
-
-      if (refExpr->isExplicitProperty()) {
-        return new (S.Context)
-          ObjCPropertyRefExpr(refExpr->getExplicitProperty(),
-                              refExpr->getType(), refExpr->getValueKind(),
-                              refExpr->getObjectKind(), refExpr->getLocation(),
-                              NewBase);
-      }
-      return new (S.Context)
-        ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(),
-                            refExpr->getImplicitPropertySetter(),
-                            refExpr->getType(), refExpr->getValueKind(),
-                            refExpr->getObjectKind(),refExpr->getLocation(),
-                            NewBase);
-    }
-  };
-
-  struct ObjCSubscriptRefRebuilder : Rebuilder<ObjCSubscriptRefRebuilder> {
-    Expr *NewBase;
-    Expr *NewKeyExpr;
-    ObjCSubscriptRefRebuilder(Sema &S, Expr *newBase, Expr *newKeyExpr)
-    : Rebuilder<ObjCSubscriptRefRebuilder>(S), 
-      NewBase(newBase), NewKeyExpr(newKeyExpr) {}
-    
-    typedef ObjCSubscriptRefExpr specific_type;
-    Expr *rebuildSpecific(ObjCSubscriptRefExpr *refExpr) {
-      assert(refExpr->getBaseExpr());
-      assert(refExpr->getKeyExpr());
-      
-      return new (S.Context)
-        ObjCSubscriptRefExpr(NewBase,
-                             NewKeyExpr,
-                             refExpr->getType(), refExpr->getValueKind(),
-                             refExpr->getObjectKind(),refExpr->getAtIndexMethodDecl(),
-                             refExpr->setAtIndexMethodDecl(),
-                             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:
     Sema &S;
@@ -329,11 +322,19 @@
  class MSPropertyOpBuilder : public PseudoOpBuilder {
    MSPropertyRefExpr *RefExpr;
    OpaqueValueExpr *InstanceBase;
+   SmallVector<Expr *, 4> CallArgs;
+
+   MSPropertyRefExpr *getBaseMSProperty(MSPropertySubscriptExpr *E);
 
  public:
    MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr) :
      PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
      RefExpr(refExpr), InstanceBase(nullptr) {}
+   MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr)
+       : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
+         InstanceBase(nullptr) {
+     RefExpr = getBaseMSProperty(refExpr);
+   }
 
    Expr *rebuildAndCaptureObject(Expr *) override;
    ExprResult buildGet() override;
@@ -674,9 +675,9 @@
   // form to use the OVE as its base.
   if (RefExpr->isObjectReceiver()) {
     InstanceReceiver = capture(RefExpr->getBase());
-
-    syntacticBase =
-      ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase);
+    syntacticBase = Rebuilder(S, [=](Expr *, unsigned) -> Expr * {
+                      return InstanceReceiver;
+                    }).rebuild(syntacticBase);
   }
 
   if (ObjCPropertyRefExpr *
@@ -994,11 +995,19 @@
   // form to use the OVE as its base expression.
   InstanceBase = capture(RefExpr->getBaseExpr());
   InstanceKey = capture(RefExpr->getKeyExpr());
-    
+
   syntacticBase =
-    ObjCSubscriptRefRebuilder(S, InstanceBase, 
-                              InstanceKey).rebuild(syntacticBase);
-  
+      Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {
+        switch (Idx) {
+        case 0:
+          return InstanceBase;
+        case 1:
+          return InstanceKey;
+        default:
+          llvm_unreachable("Unexpected index for ObjCSubscriptExpr");
+        }
+      }).rebuild(syntacticBase);
+
   return syntacticBase;
 }
 
@@ -1400,11 +1409,30 @@
 //  MSVC __declspec(property) references
 //===----------------------------------------------------------------------===//
 
+MSPropertyRefExpr *
+MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) {
+  CallArgs.insert(CallArgs.begin(), E->getIdx());
+  Expr *Base = E->getBase()->IgnoreParens();
+  while (auto *MSPropSubscript = dyn_cast<MSPropertySubscriptExpr>(Base)) {
+    CallArgs.insert(CallArgs.begin(), MSPropSubscript->getIdx());
+    Base = MSPropSubscript->getBase()->IgnoreParens();
+  }
+  return cast<MSPropertyRefExpr>(Base);
+}
+
 Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
   InstanceBase = capture(RefExpr->getBaseExpr());
-
-  syntacticBase =
-    MSPropertyRefRebuilder(S, InstanceBase).rebuild(syntacticBase);
+  std::for_each(CallArgs.begin(), CallArgs.end(),
+                [this](Expr *&Arg) { Arg = capture(Arg); });
+  syntacticBase = Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {
+                    switch (Idx) {
+                    case 0:
+                      return InstanceBase;
+                    default:
+                      assert(Idx <= CallArgs.size());
+                      return CallArgs[Idx - 1];
+                    }
+                  }).rebuild(syntacticBase);
 
   return syntacticBase;
 }
@@ -1432,9 +1460,8 @@
     return ExprError();
   }
 
-  MultiExprArg ArgExprs;
   return S.ActOnCallExpr(S.getCurScope(), GetterExpr.get(),
-                         RefExpr->getSourceRange().getBegin(), ArgExprs,
+                         RefExpr->getSourceRange().getBegin(), CallArgs,
                          RefExpr->getSourceRange().getEnd());
 }
 
@@ -1462,7 +1489,8 @@
     return ExprError();
   }
 
-  SmallVector<Expr*, 1> ArgExprs;
+  SmallVector<Expr*, 4> ArgExprs;
+  ArgExprs.append(CallArgs.begin(), CallArgs.end());
   ArgExprs.push_back(op);
   return S.ActOnCallExpr(S.getCurScope(), SetterExpr.get(),
                          RefExpr->getSourceRange().getBegin(), ArgExprs,
@@ -1488,6 +1516,10 @@
              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
     MSPropertyOpBuilder builder(*this, refExpr);
     return builder.buildRValueOperation(E);
+  } else if (MSPropertySubscriptExpr *RefExpr =
+                 dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
+    MSPropertyOpBuilder Builder(*this, RefExpr);
+    return Builder.buildRValueOperation(E);
   } else {
     llvm_unreachable("unknown pseudo-object kind!");
   }
@@ -1514,6 +1546,10 @@
              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
     MSPropertyOpBuilder builder(*this, refExpr);
     return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
+  } else if (MSPropertySubscriptExpr *RefExpr
+             = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
+    MSPropertyOpBuilder Builder(*this, RefExpr);
+    return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
   } else {
     llvm_unreachable("unknown pseudo-object kind!");
   }
@@ -1545,8 +1581,12 @@
     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);
+      MSPropertyOpBuilder builder(*this, refExpr);
+      return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
+  } else if (MSPropertySubscriptExpr *RefExpr
+             = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
+      MSPropertyOpBuilder Builder(*this, RefExpr);
+      return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
   } else {
     llvm_unreachable("unknown pseudo-object kind!");
   }
@@ -1556,29 +1596,11 @@
 /// values.  Basically, undo the behavior of rebuildAndCaptureObject.
 /// This should never operate in-place.
 static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {
-  Expr *opaqueRef = E->IgnoreParens();
-  if (ObjCPropertyRefExpr *refExpr
-        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
-    // Class and super property references don't have opaque values in them.
-    if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
-      return E;
-    
-    assert(refExpr->isObjectReceiver() && "Unknown receiver kind?");
-    OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase());
-    return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
-  } else if (ObjCSubscriptRefExpr *refExpr
-               = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
-    OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr());
-    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!");
-  }
+  return Rebuilder(S,
+                   [=](Expr *E, unsigned) -> Expr * {
+                     return cast<OpaqueValueExpr>(E)->getSourceExpr();
+                   })
+      .rebuild(E);
 }
 
 /// Given a pseudo-object expression, recreate what it looks like