Skip to content

Commit f763027

Browse files
committedNov 25, 2015
[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
1 parent 8ade8d2 commit f763027

21 files changed

+469
-113
lines changed
 

‎clang/include/clang/AST/ExprCXX.h

+63
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,69 @@ class MSPropertyRefExpr : public Expr {
677677
friend class ASTStmtReader;
678678
};
679679

680+
/// MS property subscript expression.
681+
/// MSVC supports 'property' attribute and allows to apply it to the
682+
/// declaration of an empty array in a class or structure definition.
683+
/// For example:
684+
/// \code
685+
/// __declspec(property(get=GetX, put=PutX)) int x[];
686+
/// \endcode
687+
/// The above statement indicates that x[] can be used with one or more array
688+
/// indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b), and
689+
/// p->x[a][b] = i will be turned into p->PutX(a, b, i).
690+
/// This is a syntactic pseudo-object expression.
691+
class MSPropertySubscriptExpr : public Expr {
692+
friend class ASTStmtReader;
693+
enum { BASE_EXPR, IDX_EXPR, NUM_SUBEXPRS = 2 };
694+
Stmt *SubExprs[NUM_SUBEXPRS];
695+
SourceLocation RBracketLoc;
696+
697+
void setBase(Expr *Base) { SubExprs[BASE_EXPR] = Base; }
698+
void setIdx(Expr *Idx) { SubExprs[IDX_EXPR] = Idx; }
699+
700+
public:
701+
MSPropertySubscriptExpr(Expr *Base, Expr *Idx, QualType Ty, ExprValueKind VK,
702+
ExprObjectKind OK, SourceLocation RBracketLoc)
703+
: Expr(MSPropertySubscriptExprClass, Ty, VK, OK, Idx->isTypeDependent(),
704+
Idx->isValueDependent(), Idx->isInstantiationDependent(),
705+
Idx->containsUnexpandedParameterPack()),
706+
RBracketLoc(RBracketLoc) {
707+
SubExprs[BASE_EXPR] = Base;
708+
SubExprs[IDX_EXPR] = Idx;
709+
}
710+
711+
/// \brief Create an empty array subscript expression.
712+
explicit MSPropertySubscriptExpr(EmptyShell Shell)
713+
: Expr(MSPropertySubscriptExprClass, Shell) {}
714+
715+
Expr *getBase() { return cast<Expr>(SubExprs[BASE_EXPR]); }
716+
const Expr *getBase() const { return cast<Expr>(SubExprs[BASE_EXPR]); }
717+
718+
Expr *getIdx() { return cast<Expr>(SubExprs[IDX_EXPR]); }
719+
const Expr *getIdx() const { return cast<Expr>(SubExprs[IDX_EXPR]); }
720+
721+
SourceLocation getLocStart() const LLVM_READONLY {
722+
return getBase()->getLocStart();
723+
}
724+
SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; }
725+
726+
SourceLocation getRBracketLoc() const { return RBracketLoc; }
727+
void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
728+
729+
SourceLocation getExprLoc() const LLVM_READONLY {
730+
return getBase()->getExprLoc();
731+
}
732+
733+
static bool classof(const Stmt *T) {
734+
return T->getStmtClass() == MSPropertySubscriptExprClass;
735+
}
736+
737+
// Iterators
738+
child_range children() {
739+
return child_range(&SubExprs[0], &SubExprs[0] + NUM_SUBEXPRS);
740+
}
741+
};
742+
680743
/// A Microsoft C++ @c __uuidof expression, which gets
681744
/// the _GUID that corresponds to the supplied type or expression.
682745
///

‎clang/include/clang/AST/RecursiveASTVisitor.h

+2
Original file line numberDiff line numberDiff line change
@@ -2112,6 +2112,8 @@ DEF_TRAVERSE_STMT(MSPropertyRefExpr, {
21122112
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
21132113
})
21142114

2115+
DEF_TRAVERSE_STMT(MSPropertySubscriptExpr, {})
2116+
21152117
DEF_TRAVERSE_STMT(CXXUuidofExpr, {
21162118
// The child-iterator will pick up the arg if it's an expression,
21172119
// but not if it's a type.

‎clang/include/clang/Basic/StmtNodes.td

+1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ def TypoExpr : DStmt<Expr>;
180180

181181
// Microsoft Extensions.
182182
def MSPropertyRefExpr : DStmt<Expr>;
183+
def MSPropertySubscriptExpr : DStmt<Expr>;
183184
def CXXUuidofExpr : DStmt<Expr>;
184185
def SEHTryStmt : Stmt;
185186
def SEHExceptStmt : Stmt;

‎clang/include/clang/Serialization/ASTBitCodes.h

+1
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,7 @@ namespace clang {
14131413

14141414
// Microsoft
14151415
EXPR_CXX_PROPERTY_REF_EXPR, // MSPropertyRefExpr
1416+
EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR, // MSPropertySubscriptExpr
14161417
EXPR_CXX_UUIDOF_EXPR, // CXXUuidofExpr (of expr).
14171418
EXPR_CXX_UUIDOF_TYPE, // CXXUuidofExpr (of type).
14181419
STMT_SEH_LEAVE, // SEHLeaveStmt

‎clang/lib/AST/Expr.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -3004,6 +3004,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
30043004
return true;
30053005

30063006
case MSPropertyRefExprClass:
3007+
case MSPropertySubscriptExprClass:
30073008
case CompoundAssignOperatorClass:
30083009
case VAArgExprClass:
30093010
case AtomicExprClass:

‎clang/lib/AST/ExprClassification.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
136136
case Expr::ObjCIvarRefExprClass:
137137
case Expr::FunctionParmPackExprClass:
138138
case Expr::MSPropertyRefExprClass:
139+
case Expr::MSPropertySubscriptExprClass:
139140
case Expr::OMPArraySectionExprClass:
140141
return Cl::CL_LValue;
141142

‎clang/lib/AST/ExprConstant.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -8974,6 +8974,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
89748974
case Expr::CXXTypeidExprClass:
89758975
case Expr::CXXUuidofExprClass:
89768976
case Expr::MSPropertyRefExprClass:
8977+
case Expr::MSPropertySubscriptExprClass:
89778978
case Expr::CXXNullPtrLiteralExprClass:
89788979
case Expr::UserDefinedLiteralClass:
89798980
case Expr::CXXThisExprClass:

‎clang/lib/AST/ItaniumMangle.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -2811,6 +2811,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
28112811
case Expr::ParenListExprClass:
28122812
case Expr::LambdaExprClass:
28132813
case Expr::MSPropertyRefExprClass:
2814+
case Expr::MSPropertySubscriptExprClass:
28142815
case Expr::TypoExprClass: // This should no longer exist in the AST by now.
28152816
case Expr::OMPArraySectionExprClass:
28162817
llvm_unreachable("unexpected statement kind");

‎clang/lib/AST/StmtPrinter.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -1738,6 +1738,13 @@ void StmtPrinter::VisitMSPropertyRefExpr(MSPropertyRefExpr *Node) {
17381738
OS << Node->getPropertyDecl()->getDeclName();
17391739
}
17401740

1741+
void StmtPrinter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *Node) {
1742+
PrintExpr(Node->getBase());
1743+
OS << "[";
1744+
PrintExpr(Node->getIdx());
1745+
OS << "]";
1746+
}
1747+
17411748
void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
17421749
switch (Node->getLiteralOperatorKind()) {
17431750
case UserDefinedLiteral::LOK_Raw:

‎clang/lib/AST/StmtProfile.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,11 @@ void StmtProfiler::VisitMSPropertyRefExpr(const MSPropertyRefExpr *S) {
11291129
VisitDecl(S->getPropertyDecl());
11301130
}
11311131

1132+
void StmtProfiler::VisitMSPropertySubscriptExpr(
1133+
const MSPropertySubscriptExpr *S) {
1134+
VisitExpr(S);
1135+
}
1136+
11321137
void StmtProfiler::VisitCXXThisExpr(const CXXThisExpr *S) {
11331138
VisitExpr(S);
11341139
ID.AddBoolean(S->isImplicit());

‎clang/lib/Sema/SemaExceptionSpec.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
11791179
return CT_Cannot;
11801180

11811181
case Expr::MSPropertyRefExprClass:
1182+
case Expr::MSPropertySubscriptExprClass:
11821183
llvm_unreachable("Invalid class for expression");
11831184

11841185
#define STMT(CLASS, PARENT) case Expr::CLASS##Class:

‎clang/lib/Sema/SemaExpr.cpp

+30-3
Original file line numberDiff line numberDiff line change
@@ -3901,6 +3901,13 @@ static bool checkArithmeticOnObjCPointer(Sema &S,
39013901
return true;
39023902
}
39033903

3904+
static bool isMSPropertySubscriptExpr(Sema &S, Expr *Base) {
3905+
auto *BaseNoParens = Base->IgnoreParens();
3906+
if (auto *MSProp = dyn_cast<MSPropertyRefExpr>(BaseNoParens))
3907+
return MSProp->getPropertyDecl()->getType()->isArrayType();
3908+
return isa<MSPropertySubscriptExpr>(BaseNoParens);
3909+
}
3910+
39043911
ExprResult
39053912
Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
39063913
Expr *idx, SourceLocation rbLoc) {
@@ -3921,10 +3928,15 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
39213928
// operand might be an overloadable type, in which case the overload
39223929
// resolution for the operator overload should get the first crack
39233930
// at the overload.
3931+
bool IsMSPropertySubscript = false;
39243932
if (base->getType()->isNonOverloadPlaceholderType()) {
3925-
ExprResult result = CheckPlaceholderExpr(base);
3926-
if (result.isInvalid()) return ExprError();
3927-
base = result.get();
3933+
IsMSPropertySubscript = isMSPropertySubscriptExpr(*this, base);
3934+
if (!IsMSPropertySubscript) {
3935+
ExprResult result = CheckPlaceholderExpr(base);
3936+
if (result.isInvalid())
3937+
return ExprError();
3938+
base = result.get();
3939+
}
39283940
}
39293941
if (idx->getType()->isNonOverloadPlaceholderType()) {
39303942
ExprResult result = CheckPlaceholderExpr(idx);
@@ -3939,6 +3951,21 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
39393951
VK_LValue, OK_Ordinary, rbLoc);
39403952
}
39413953

3954+
// MSDN, property (C++)
3955+
// https://msdn.microsoft.com/en-us/library/yhfk0thd(v=vs.120).aspx
3956+
// This attribute can also be used in the declaration of an empty array in a
3957+
// class or structure definition. For example:
3958+
// __declspec(property(get=GetX, put=PutX)) int x[];
3959+
// The above statement indicates that x[] can be used with one or more array
3960+
// indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b),
3961+
// and p->x[a][b] = i will be turned into p->PutX(a, b, i);
3962+
if (IsMSPropertySubscript) {
3963+
// Build MS property subscript expression if base is MS property reference
3964+
// or MS property subscript.
3965+
return new (Context) MSPropertySubscriptExpr(
3966+
base, idx, Context.PseudoObjectTy, VK_LValue, OK_Ordinary, rbLoc);
3967+
}
3968+
39423969
// Use C++ overloaded-operator rules if either operand has record
39433970
// type. The spec says to do this if either type is *overloadable*,
39443971
// but enum types can't declare subscript operators or conversion

0 commit comments

Comments
 (0)
Please sign in to comment.