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

endlessroad1991 at gmail.com endlessroad1991 at gmail.com
Mon Dec 17 06:51:05 PST 2012


Here's a try to summarize implementation detail about __decpspec(property):
1. Add a MSPropertyDecl, because:
    - Property can be private, as long as getter/setter is public. This is
different from regular members.
    - Type of property can be imcomplete, like return type of a member
function. This is different from regular members.
    - We can use it to store how many parameters should be used for
getter/setter
2. Add a MSPropertyRefExpr, like ObjCPropertyRefExpr. Preserve all
(index) parameters for getter/setter calls in ast. This is necessary
because (a.v)[1][2] and (a.v[1])[2] are both legal.
3. Lookup actual getter/setter, and generate CallExpr in PseudoObject
related routines.

And a complete test, covering all that I can think of now.


#include <iostream>
#include <vector>
class C
{
 // property can be private, as long as getter/setter is public.
 __declspec(property(get=GetA, put=SetA)) int A[123][321];
public:
 // We choose getter/setter like regular overloaded functions.
 int GetA() { std::cout << "Get 0\n"; return 0; }
 int GetA(double i) { std::cout << "Get 1\n"; return 0; }
 int GetA(int i) { std::cout << "Get 1i\n"; return 0; }
 int GetA(double i, double j) { std::cout << "Get 2\n"; return 0; }
 void SetA(int value) { std::cout << "Set 0\n"; }
 void SetA(double i, double value) { std::cout << "Set 1\n"; }
 void SetA(double i, double j, int value) { std::cout << "Set 2\n"; }
 // Property type can be reference.
 __declspec(property(get=GetA2, put=SetA2)) int& A2;
 int& GetA2() { std::cout << "GetA2\n"; return ri; }
 void SetA2(int& v) { std::cout << "SetA2\n"; ri = v; }
 // "[]" can be filled with a integer number, which is legal, but useless.
 // And "[]" that appear in typedef will also be treated as placeholder for
parameter.
 typedef int int_arr[10][10];
 __declspec(property(get=GetA3, put=SetA3)) int_arr A3;
 int GetA3() { std::cout << "GetA3 0\n"; return 0; }
 int GetA3(double i) { std::cout << "GetA3 1\n"; return 0; }
 int GetA3(double i, double j) { std::cout << "GetA3 2\n"; return 0; } //
We can only leave this getter.
 // If property type is pointer, only getter/setter with NO parameters will
be picked.
 __declspec(property(get=GetA4, put=SetA4)) int ***A4;
 int*** GetA4() { std::cout << "GetA4 0\n"; return ppp; }
 int*** GetA4(int i) { std::cout << "GetA4 1\n"; return ppp; }
 int*** GetA4(int i, int j) { std::cout << "GetA4 2\n"; return ppp; }
 void SetA4(int ***v) { std::cout << "SetA4 0\n"; }
 void SetA4(int i, int ***v) { std::cout << "SetA4 1\n"; }
 void SetA4(int i, int j, int ***v) { std::cout << "SetA4 2\n"; }
 // Even if property type can be subscripted, we cannot directly subsrcipt
it by appending "[]".
 __declspec(property(get=GetA5)) std::vector<int> A5[];
 std::vector<int> GetA5(int i) { std::cout << "GetA5 1\n"; return v; }
 std::vector<int> GetA5(int i, int j) { std::cout << "GetA5 2\n"; return v;
}
 std::vector<int> v;
 int i;
 int &ri;
 int *p;
 int **pp;
 int ***ppp;
 C(int &ri_): ri(ri_) { p = &i, pp = &p, ppp = &pp; }
};
int main()
{
 int ri = 5445;
 C c(ri);
 int i = c.A; // Get 0
 int j = c.A[1.0f]; // Get 1
 int j2 = c.A[1]; // Get 1i
 int k = c.A[1.0f][2.0f]; // Get 2
 int k1 = (c.A)[1.0f][2.0f]; // Get 2
 int k2 = (c.A[1.0f])[2.0f]; // Get 2
 int& ir = c.A2; // GetA2
 std::cout << ir << "\n"; // 5445
 int ai = 4;
 c.A2 = ai; // SetA2 // SetA2 must exist!
 std::cout << c.A2 << "\n"; // GetA2 // 4
 ai = 3;
 std::cout << c.A2 << "\n"; // GetA2 // 4
 int ii = c.A3; // GetA3 0
 int jj = c.A3[1.0]; // GetA3 1
 int kk = c.A3[1.0][2.0]; // GetA3 2
 int ll = c.A3[1]; // GetA3 1
 int ***a1 = c.A4; // GetA4 0
 int **b1 = c.A4[0]; // GetA4 0
 int *c1 = c.A4[0][0]; // GetA4 0
 int d1 = c.A4[0][0][0]; // GetA4 0
 // int d2 = c.A4[0][0][0][0]; // Doesn't compile
 c.A4 = 0; // SetA4 0
 c.A4[0] = c.pp; // GetA4 0
 c.A4[0][0] = c.p; // GetA4 0
 c.A4[0][0][0] = 0; // GetA4 0
 std::vector<int> v = c.A5[0]; // GetA5 1
 v = c.A5[0][0]; // GetA5 2
 //int v2 = c.A5[0][0]; // Doesn't compile, "Cannot convert vector<int> to
int"
 //int v3 = c.A5[0][0][0]; // Doesn't compile, "Cannot convert vector<int>
to int"
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20121217/3ab5f34c/attachment.html>


More information about the cfe-dev mailing list