Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
ABataev added a comment. John, thanks a lot for the review! Committed version has a fix according to your last comment. Repository: rL LLVM http://reviews.llvm.org/D13336 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
This revision was automatically updated to reflect the committed changes. Closed by commit rL254067: [MSVC] 'property' with an empty array in array subscript expression. (authored by ABataev). Changed prior to commit: http://reviews.llvm.org/D13336?vs=41018&id=41125#toc Repository: rL LLVM http://reviews.llvm.org/D13336 Files: cfe/trunk/include/clang/AST/ExprCXX.h cfe/trunk/include/clang/AST/RecursiveASTVisitor.h cfe/trunk/include/clang/Basic/StmtNodes.td cfe/trunk/include/clang/Serialization/ASTBitCodes.h cfe/trunk/lib/AST/Expr.cpp cfe/trunk/lib/AST/ExprClassification.cpp cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/lib/AST/ItaniumMangle.cpp cfe/trunk/lib/AST/StmtPrinter.cpp cfe/trunk/lib/AST/StmtProfile.cpp cfe/trunk/lib/Sema/SemaExceptionSpec.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/lib/Sema/SemaPseudoObject.cpp cfe/trunk/lib/Sema/TreeTransform.h cfe/trunk/lib/Serialization/ASTReaderStmt.cpp cfe/trunk/lib/Serialization/ASTWriterStmt.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp cfe/trunk/test/CodeGenCXX/ms-property.cpp cfe/trunk/test/SemaCXX/ms-property-error.cpp cfe/trunk/test/SemaCXX/ms-property.cpp cfe/trunk/tools/libclang/CXCursor.cpp Index: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h === --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h @@ -2112,6 +2112,8 @@ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); }) +DEF_TRAVERSE_STMT(MSPropertySubscriptExpr, {}) + DEF_TRAVERSE_STMT(CXXUuidofExpr, { // The child-iterator will pick up the arg if it's an expression, // but not if it's a type. Index: cfe/trunk/include/clang/AST/ExprCXX.h === --- cfe/trunk/include/clang/AST/ExprCXX.h +++ cfe/trunk/include/clang/AST/ExprCXX.h @@ -677,6 +677,69 @@ friend class ASTStmtReader; }; +/// MS property 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: +/// \code +/// __declspec(property(get=GetX, put=PutX)) int x[]; +/// \endcode +/// 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). +/// This is a syntactic pseudo-object expression. +class MSPropertySubscriptExpr : public Expr { + friend class ASTStmtReader; + enum { BASE_EXPR, IDX_EXPR, NUM_SUBEXPRS = 2 }; + Stmt *SubExprs[NUM_SUBEXPRS]; + SourceLocation RBracketLoc; + + void setBase(Expr *Base) { SubExprs[BASE_EXPR] = Base; } + void setIdx(Expr *Idx) { SubExprs[IDX_EXPR] = Idx; } + +public: + MSPropertySubscriptExpr(Expr *Base, Expr *Idx, QualType Ty, ExprValueKind VK, + ExprObjectKind OK, SourceLocation RBracketLoc) + : Expr(MSPropertySubscriptExprClass, Ty, VK, OK, Idx->isTypeDependent(), + Idx->isValueDependent(), Idx->isInstantiationDependent(), + Idx->containsUnexpandedParameterPack()), +RBracketLoc(RBracketLoc) { +SubExprs[BASE_EXPR] = Base; +SubExprs[IDX_EXPR] = Idx; + } + + /// \brief Create an empty array subscript expression. + explicit MSPropertySubscriptExpr(EmptyShell Shell) + : Expr(MSPropertySubscriptExprClass, Shell) {} + + Expr *getBase() { return cast(SubExprs[BASE_EXPR]); } + const Expr *getBase() const { return cast(SubExprs[BASE_EXPR]); } + + Expr *getIdx() { return cast(SubExprs[IDX_EXPR]); } + const Expr *getIdx() const { return cast(SubExprs[IDX_EXPR]); } + + SourceLocation getLocStart() const LLVM_READONLY { +return getBase()->getLocStart(); + } + SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; } + + SourceLocation getRBracketLoc() const { return RBracketLoc; } + void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } + + SourceLocation getExprLoc() const LLVM_READONLY { +return getBase()->getExprLoc(); + } + + static bool classof(const Stmt *T) { +return T->getStmtClass() == MSPropertySubscriptExprClass; + } + + // Iterators + child_range children() { +return child_range(&SubExprs[0], &SubExprs[0] + NUM_SUBEXPRS); + } +}; + /// A Microsoft C++ @c __uuidof expression, which gets /// the _GUID that corresponds to the supplied type or expression. /// Index: cfe/trunk/include/clang/Basic/StmtNodes.td === --- cfe/trunk/include/clang/Basic/StmtNodes.td +++ cfe/trunk/include/clang/Basic/StmtNodes.td @@ -180,6 +180,7 @@ // Microsoft Extensions. def MSPropertyRefExpr : DStmt; +def MSPropertySubscriptExpr : DStmt; def CXXUuidofExpr : DStmt; def SEHTryStmt : Stmt; def SEHExceptStmt : Stmt; Index: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
rjmccall added a comment. This looks fantastic, thanks for doing all that. Approved with the one minor change. Comment at: lib/Sema/SemaPseudoObject.cpp:175 @@ -145,1 +174,3 @@ +PSE->getType(), PSE->getValueKind(), PSE->getObjectKind(), +PSE->getRBracketLoc()); } One extremely minor tweak: could you organize this like the rest of the pseudo-object expressions, checking for it above and calling a method to rebuild it? http://reviews.llvm.org/D13336 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
ABataev updated this revision to Diff 41018. ABataev added a comment. Update after review http://reviews.llvm.org/D13336 Files: include/clang/AST/ExprCXX.h include/clang/AST/RecursiveASTVisitor.h include/clang/Basic/StmtNodes.td include/clang/Serialization/ASTBitCodes.h lib/AST/Expr.cpp lib/AST/ExprClassification.cpp lib/AST/ExprConstant.cpp lib/AST/ItaniumMangle.cpp lib/AST/StmtPrinter.cpp lib/AST/StmtProfile.cpp lib/Sema/SemaExceptionSpec.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaPseudoObject.cpp lib/Sema/TreeTransform.h lib/Serialization/ASTReaderStmt.cpp lib/Serialization/ASTWriterStmt.cpp lib/StaticAnalyzer/Core/ExprEngine.cpp test/CodeGenCXX/ms-property.cpp test/SemaCXX/ms-property-error.cpp test/SemaCXX/ms-property.cpp tools/libclang/CXCursor.cpp Index: lib/Serialization/ASTWriterStmt.cpp === --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -1689,6 +1689,14 @@ Code = serialization::EXPR_CXX_PROPERTY_REF_EXPR; } +void ASTStmtWriter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *E) { + VisitExpr(E); + Writer.AddStmt(E->getBase()); + Writer.AddStmt(E->getIdx()); + Writer.AddSourceLocation(E->getRBracketLoc(), Record); + Code = serialization::EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR; +} + void ASTStmtWriter::VisitCXXUuidofExpr(CXXUuidofExpr *E) { VisitExpr(E); Writer.AddSourceRange(E->getSourceRange(), Record); Index: lib/Serialization/ASTReaderStmt.cpp === --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -1662,6 +1662,13 @@ E->TheDecl = ReadDeclAs(Record, Idx); } +void ASTStmtReader::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *E) { + VisitExpr(E); + E->setBase(Reader.ReadSubExpr()); + E->setIdx(Reader.ReadSubExpr()); + E->setRBracketLoc(ReadSourceLocation(Record, Idx)); +} + void ASTStmtReader::VisitCXXUuidofExpr(CXXUuidofExpr *E) { VisitExpr(E); E->setSourceRange(ReadSourceRange(Record, Idx)); @@ -3078,6 +3085,9 @@ case EXPR_CXX_PROPERTY_REF_EXPR: S = new (Context) MSPropertyRefExpr(Empty); break; +case EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR: + S = new (Context) MSPropertySubscriptExpr(Empty); + break; case EXPR_CXX_UUIDOF_TYPE: S = new (Context) CXXUuidofExpr(Empty, false); break; Index: lib/StaticAnalyzer/Core/ExprEngine.cpp === --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -755,6 +755,7 @@ case Stmt::CXXUuidofExprClass: case Stmt::CXXFoldExprClass: case Stmt::MSPropertyRefExprClass: +case Stmt::MSPropertySubscriptExprClass: case Stmt::CXXUnresolvedConstructExprClass: case Stmt::DependentScopeDeclRefExprClass: case Stmt::ArrayTypeTraitExprClass: Index: lib/AST/Expr.cpp === --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -3004,6 +3004,7 @@ return true; case MSPropertyRefExprClass: + case MSPropertySubscriptExprClass: case CompoundAssignOperatorClass: case VAArgExprClass: case AtomicExprClass: Index: lib/AST/StmtProfile.cpp === --- lib/AST/StmtProfile.cpp +++ lib/AST/StmtProfile.cpp @@ -1126,6 +1126,11 @@ VisitDecl(S->getPropertyDecl()); } +void StmtProfiler::VisitMSPropertySubscriptExpr( +const MSPropertySubscriptExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitCXXThisExpr(const CXXThisExpr *S) { VisitExpr(S); ID.AddBoolean(S->isImplicit()); Index: lib/AST/StmtPrinter.cpp === --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -1732,6 +1732,13 @@ OS << Node->getPropertyDecl()->getDeclName(); } +void StmtPrinter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *Node) { + PrintExpr(Node->getBase()); + OS << "["; + PrintExpr(Node->getIdx()); + OS << "]"; +} + void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) { switch (Node->getLiteralOperatorKind()) { case UserDefinedLiteral::LOK_Raw: Index: lib/AST/ItaniumMangle.cpp === --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -2811,6 +2811,7 @@ case Expr::ParenListExprClass: case Expr::LambdaExprClass: case Expr::MSPropertyRefExprClass: + case Expr::MSPropertySubscriptExprClass: case Expr::TypoExprClass: // This should no longer exist in the AST by now. case Expr::OMPArraySectionExprClass: llvm_unreachable("unexpected statement kind"); Index: lib/AST/ExprConstant.cpp === --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -8974,6 +8974,7 @@ case Exp
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
rjmccall added inline comments. Comment at: lib/Sema/SemaPseudoObject.cpp:57 @@ +56,3 @@ + // with a base limits the number of cases here. + assert(refExpr->isObjectReceiver()); + Well, it should be okay to call this on something that doesn't have a base; it just doesn't need to do anything and can just return refExpr. Comment at: lib/Sema/SemaPseudoObject.cpp:1591 @@ +1590,3 @@ + return baseOVE->getSourceExpr(); +} else if (ObjCSubscriptRefExpr *refExpr = + dyn_cast(opaqueRef)) { That's what I'm saying, though: the capture process should be building the syntactic MSPropertySubscriptExpr using the captured OVEs for the index expressions as well as the recursively-captured base, and Rebuilder will then need to undo that. We want to consistently replace all the captured sub-trees with their OVEs so that clients can easily recover the relationship between the syntactic and semantic forms. Comment at: lib/Sema/SemaPseudoObject.cpp:1621 @@ -1582,1 +1620,3 @@ + }; + return Rebuilder(S, Callback).rebuild(E); } My hope is that you'll be able to get this whole function down to just this last line and won't need to split out any of the cases here. http://reviews.llvm.org/D13336 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
ABataev updated this revision to Diff 40901. ABataev marked an inline comment as done. http://reviews.llvm.org/D13336 Files: include/clang/AST/DataRecursiveASTVisitor.h include/clang/AST/ExprCXX.h include/clang/AST/RecursiveASTVisitor.h include/clang/Basic/StmtNodes.td include/clang/Serialization/ASTBitCodes.h lib/AST/Expr.cpp lib/AST/ExprClassification.cpp lib/AST/ExprConstant.cpp lib/AST/ItaniumMangle.cpp lib/AST/StmtPrinter.cpp lib/AST/StmtProfile.cpp lib/Sema/SemaExceptionSpec.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaPseudoObject.cpp lib/Sema/TreeTransform.h lib/Serialization/ASTReaderStmt.cpp lib/Serialization/ASTWriterStmt.cpp lib/StaticAnalyzer/Core/ExprEngine.cpp test/CodeGenCXX/ms-property.cpp test/SemaCXX/ms-property-error.cpp test/SemaCXX/ms-property.cpp tools/libclang/CXCursor.cpp Index: lib/Serialization/ASTWriterStmt.cpp === --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -1689,6 +1689,14 @@ Code = serialization::EXPR_CXX_PROPERTY_REF_EXPR; } +void ASTStmtWriter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *E) { + VisitExpr(E); + Writer.AddStmt(E->getBase()); + Writer.AddStmt(E->getIdx()); + Writer.AddSourceLocation(E->getRBracketLoc(), Record); + Code = serialization::EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR; +} + void ASTStmtWriter::VisitCXXUuidofExpr(CXXUuidofExpr *E) { VisitExpr(E); Writer.AddSourceRange(E->getSourceRange(), Record); Index: lib/Serialization/ASTReaderStmt.cpp === --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -1662,6 +1662,13 @@ E->TheDecl = ReadDeclAs(Record, Idx); } +void ASTStmtReader::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *E) { + VisitExpr(E); + E->setBase(Reader.ReadSubExpr()); + E->setIdx(Reader.ReadSubExpr()); + E->setRBracketLoc(ReadSourceLocation(Record, Idx)); +} + void ASTStmtReader::VisitCXXUuidofExpr(CXXUuidofExpr *E) { VisitExpr(E); E->setSourceRange(ReadSourceRange(Record, Idx)); @@ -3078,6 +3085,9 @@ case EXPR_CXX_PROPERTY_REF_EXPR: S = new (Context) MSPropertyRefExpr(Empty); break; +case EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR: + S = new (Context) MSPropertySubscriptExpr(Empty); + break; case EXPR_CXX_UUIDOF_TYPE: S = new (Context) CXXUuidofExpr(Empty, false); break; Index: lib/StaticAnalyzer/Core/ExprEngine.cpp === --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -755,6 +755,7 @@ case Stmt::CXXUuidofExprClass: case Stmt::CXXFoldExprClass: case Stmt::MSPropertyRefExprClass: +case Stmt::MSPropertySubscriptExprClass: case Stmt::CXXUnresolvedConstructExprClass: case Stmt::DependentScopeDeclRefExprClass: case Stmt::ArrayTypeTraitExprClass: Index: lib/AST/Expr.cpp === --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -3004,6 +3004,7 @@ return true; case MSPropertyRefExprClass: + case MSPropertySubscriptExprClass: case CompoundAssignOperatorClass: case VAArgExprClass: case AtomicExprClass: Index: lib/AST/StmtProfile.cpp === --- lib/AST/StmtProfile.cpp +++ lib/AST/StmtProfile.cpp @@ -1126,6 +1126,11 @@ VisitDecl(S->getPropertyDecl()); } +void StmtProfiler::VisitMSPropertySubscriptExpr( +const MSPropertySubscriptExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitCXXThisExpr(const CXXThisExpr *S) { VisitExpr(S); ID.AddBoolean(S->isImplicit()); Index: lib/AST/StmtPrinter.cpp === --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -1732,6 +1732,13 @@ OS << Node->getPropertyDecl()->getDeclName(); } +void StmtPrinter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *Node) { + PrintExpr(Node->getBase()); + OS << "["; + PrintExpr(Node->getIdx()); + OS << "]"; +} + void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) { switch (Node->getLiteralOperatorKind()) { case UserDefinedLiteral::LOK_Raw: Index: lib/AST/ItaniumMangle.cpp === --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -2811,6 +2811,7 @@ case Expr::ParenListExprClass: case Expr::LambdaExprClass: case Expr::MSPropertyRefExprClass: + case Expr::MSPropertySubscriptExprClass: case Expr::TypoExprClass: // This should no longer exist in the AST by now. case Expr::OMPArraySectionExprClass: llvm_unreachable("unexpected statement kind"); Index: lib/AST/ExprConstant.cpp === --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConst
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
ABataev marked an inline comment as done. Comment at: lib/Sema/SemaPseudoObject.cpp:1627 @@ -1579,1 +1626,3 @@ +cast(Base->IgnoreParens())->getBaseExpr()); +return MSPropertyRefRebuilder(S, BaseOVE->getSourceExpr()).rebuild(E); } else { rjmccall wrote: > Hmm. Just like the ObjCSubscriptRefExpr case, this will need to strip the > OVEs off the index expressions, or else you'll end up stacking OVEs and > asserting in IRGen. > > The deeper problem here is that we have too much redundancy in all these > places that have to walk over the different pseudo-object expressions. We > can remove some of that by simplifying the design of Rebuilder, which is > really over-engineered for its task. It should be fine to make it > non-templated, merge all of the rebuildSpecific cases into it (and therefore > remove all of the subclasses), and give it a callback to invoke at all the > capture points in source order. > > I think the callback can just be a llvm::function_ref unsigned)>. The second parameter is the position of the capture point in > source order, so for example in your case the base of the MSPropertyRefExpr > will be 0, the index of the innermost MSPropertySubscriptExpr will be 1, and > so on. That'll be important for callers that care about which capture point > is which. > > The various rebuildAndCaptureObject implementations should use a callback > that returns the appropriate captured expression for the position. > > stripOpaqueValuesFromPseudoObjectRef should use a callback that returns > cast(e)->getSourceExpr(); it shouldn't need to split out the > different cases at all. John, we don't need to strip the OVEs off the index expressions, because index expressions in MSPropertySubscriptExpr are not folded to OVEs. They are folded to OVEs only for CallArgs array. But in rebuilded MSPropertySubscriptExpr only base MSPropertyRefExpr is folded to OVE (we don't need to put indexes in MSPropertySubscriptExpr, because they are not used during codegen and we can keep original expressions). So, the code should work as is. I reworked Rebuilder just like you said. http://reviews.llvm.org/D13336 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
rjmccall added inline comments. Comment at: lib/Sema/SemaPseudoObject.cpp:1627 @@ -1579,1 +1626,3 @@ +cast(Base->IgnoreParens())->getBaseExpr()); +return MSPropertyRefRebuilder(S, BaseOVE->getSourceExpr()).rebuild(E); } else { Hmm. Just like the ObjCSubscriptRefExpr case, this will need to strip the OVEs off the index expressions, or else you'll end up stacking OVEs and asserting in IRGen. The deeper problem here is that we have too much redundancy in all these places that have to walk over the different pseudo-object expressions. We can remove some of that by simplifying the design of Rebuilder, which is really over-engineered for its task. It should be fine to make it non-templated, merge all of the rebuildSpecific cases into it (and therefore remove all of the subclasses), and give it a callback to invoke at all the capture points in source order. I think the callback can just be a llvm::function_ref. The second parameter is the position of the capture point in source order, so for example in your case the base of the MSPropertyRefExpr will be 0, the index of the innermost MSPropertySubscriptExpr will be 1, and so on. That'll be important for callers that care about which capture point is which. The various rebuildAndCaptureObject implementations should use a callback that returns the appropriate captured expression for the position. stripOpaqueValuesFromPseudoObjectRef should use a callback that returns cast(e)->getSourceExpr(); it shouldn't need to split out the different cases at all. http://reviews.llvm.org/D13336 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
ABataev added a comment. John, any comments? http://reviews.llvm.org/D13336 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
ABataev updated this revision to Diff 40253. ABataev marked 3 inline comments as done. ABataev added a comment. Update after review http://reviews.llvm.org/D13336 Files: include/clang/AST/DataRecursiveASTVisitor.h include/clang/AST/ExprCXX.h include/clang/AST/RecursiveASTVisitor.h include/clang/Basic/StmtNodes.td include/clang/Serialization/ASTBitCodes.h lib/AST/Expr.cpp lib/AST/ExprClassification.cpp lib/AST/ExprConstant.cpp lib/AST/ItaniumMangle.cpp lib/AST/StmtPrinter.cpp lib/AST/StmtProfile.cpp lib/Sema/SemaExceptionSpec.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaPseudoObject.cpp lib/Sema/TreeTransform.h lib/Serialization/ASTReaderStmt.cpp lib/Serialization/ASTWriterStmt.cpp lib/StaticAnalyzer/Core/ExprEngine.cpp test/CodeGenCXX/ms-property.cpp test/SemaCXX/ms-property-error.cpp test/SemaCXX/ms-property.cpp tools/libclang/CXCursor.cpp Index: lib/Serialization/ASTWriterStmt.cpp === --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -1668,6 +1668,14 @@ Code = serialization::EXPR_CXX_PROPERTY_REF_EXPR; } +void ASTStmtWriter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *E) { + VisitExpr(E); + Writer.AddStmt(E->getBase()); + Writer.AddStmt(E->getIdx()); + Writer.AddSourceLocation(E->getRBracketLoc(), Record); + Code = serialization::EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR; +} + void ASTStmtWriter::VisitCXXUuidofExpr(CXXUuidofExpr *E) { VisitExpr(E); Writer.AddSourceRange(E->getSourceRange(), Record); Index: lib/Serialization/ASTReaderStmt.cpp === --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -1641,6 +1641,13 @@ E->TheDecl = ReadDeclAs(Record, Idx); } +void ASTStmtReader::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *E) { + VisitExpr(E); + E->setBase(Reader.ReadSubExpr()); + E->setIdx(Reader.ReadSubExpr()); + E->setRBracketLoc(ReadSourceLocation(Record, Idx)); +} + void ASTStmtReader::VisitCXXUuidofExpr(CXXUuidofExpr *E) { VisitExpr(E); E->setSourceRange(ReadSourceRange(Record, Idx)); @@ -3037,6 +3044,9 @@ case EXPR_CXX_PROPERTY_REF_EXPR: S = new (Context) MSPropertyRefExpr(Empty); break; +case EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR: + S = new (Context) MSPropertySubscriptExpr(Empty); + break; case EXPR_CXX_UUIDOF_TYPE: S = new (Context) CXXUuidofExpr(Empty, false); break; Index: lib/StaticAnalyzer/Core/ExprEngine.cpp === --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -754,6 +754,7 @@ case Stmt::CXXUuidofExprClass: case Stmt::CXXFoldExprClass: case Stmt::MSPropertyRefExprClass: +case Stmt::MSPropertySubscriptExprClass: case Stmt::CXXUnresolvedConstructExprClass: case Stmt::DependentScopeDeclRefExprClass: case Stmt::ArrayTypeTraitExprClass: Index: lib/AST/Expr.cpp === --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -2998,6 +2998,7 @@ return true; case MSPropertyRefExprClass: + case MSPropertySubscriptExprClass: case CompoundAssignOperatorClass: case VAArgExprClass: case AtomicExprClass: Index: lib/AST/StmtProfile.cpp === --- lib/AST/StmtProfile.cpp +++ lib/AST/StmtProfile.cpp @@ -1123,6 +1123,11 @@ VisitDecl(S->getPropertyDecl()); } +void StmtProfiler::VisitMSPropertySubscriptExpr( +const MSPropertySubscriptExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitCXXThisExpr(const CXXThisExpr *S) { VisitExpr(S); ID.AddBoolean(S->isImplicit()); Index: lib/AST/StmtPrinter.cpp === --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -1715,6 +1715,13 @@ OS << Node->getPropertyDecl()->getDeclName(); } +void StmtPrinter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *Node) { + PrintExpr(Node->getBase()); + OS << "["; + PrintExpr(Node->getIdx()); + OS << "]"; +} + void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) { switch (Node->getLiteralOperatorKind()) { case UserDefinedLiteral::LOK_Raw: Index: lib/AST/ItaniumMangle.cpp === --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -2809,6 +2809,7 @@ case Expr::ParenListExprClass: case Expr::LambdaExprClass: case Expr::MSPropertyRefExprClass: + case Expr::MSPropertySubscriptExprClass: case Expr::TypoExprClass: // This should no longer exist in the AST by now. case Expr::OMPArraySectionExprClass: llvm_unreachable("unexpected statement kind"); Index: lib/AST/ExprConstant.cpp === ---
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
rjmccall added inline comments. Comment at: include/clang/AST/ExprCXX.h:689 @@ +688,3 @@ +/// 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). +class MSPropertySubscriptExpr : public Expr { Please add to the comment here that this is a syntactic pseudo-object expression. Comment at: lib/Sema/SemaExpr.cpp:3926 @@ -3921,1 +3925,3 @@ + if (base->getType()->isNonOverloadPlaceholderType() && + !IsMSPropertySubscript) { ExprResult result = CheckPlaceholderExpr(base); Please factor this check so that it only does extra work when the base has placeholder type, and please extract a function to compute IsMSPropertySubscript. Comment at: lib/Sema/SemaPseudoObject.cpp:1419 @@ +1418,3 @@ +MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) { + Expr *Base = E->getBase(); + CallArgs.insert(CallArgs.begin(), E->getIdx()); This code will look slightly nicer and be slightly more efficient if you maintain the invariant that parens have been ignored on Base. That is, IgnoreParens here and when assigning in the loop, and then you can remove them from the type-checks. Oh. You also need to capture the index expressions so that they aren't evaluated multiple times when this expression is used as the l-value of an increment, decrement, or compound-assignment. You then need to un-capture them in the Rebuilder. Please add code-generation tests that check that the index expression is only evaluated once in these cases. http://reviews.llvm.org/D13336 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
ABataev updated this revision to Diff 38232. ABataev marked 4 inline comments as done. ABataev added a comment. Update after review http://reviews.llvm.org/D13336 Files: include/clang/AST/DataRecursiveASTVisitor.h include/clang/AST/ExprCXX.h include/clang/AST/RecursiveASTVisitor.h include/clang/Basic/StmtNodes.td include/clang/Serialization/ASTBitCodes.h lib/AST/Expr.cpp lib/AST/ExprClassification.cpp lib/AST/ExprConstant.cpp lib/AST/ItaniumMangle.cpp lib/AST/StmtPrinter.cpp lib/AST/StmtProfile.cpp lib/Sema/SemaExceptionSpec.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaPseudoObject.cpp lib/Sema/TreeTransform.h lib/Serialization/ASTReaderStmt.cpp lib/Serialization/ASTWriterStmt.cpp lib/StaticAnalyzer/Core/ExprEngine.cpp test/CodeGenCXX/ms-property.cpp test/SemaCXX/ms-property-error.cpp test/SemaCXX/ms-property.cpp tools/libclang/CXCursor.cpp Index: lib/Serialization/ASTWriterStmt.cpp === --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -1668,6 +1668,14 @@ Code = serialization::EXPR_CXX_PROPERTY_REF_EXPR; } +void ASTStmtWriter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *E) { + VisitExpr(E); + Writer.AddStmt(E->getBase()); + Writer.AddStmt(E->getIdx()); + Writer.AddSourceLocation(E->getRBracketLoc(), Record); + Code = serialization::EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR; +} + void ASTStmtWriter::VisitCXXUuidofExpr(CXXUuidofExpr *E) { VisitExpr(E); Writer.AddSourceRange(E->getSourceRange(), Record); Index: lib/Serialization/ASTReaderStmt.cpp === --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -1641,6 +1641,13 @@ E->TheDecl = ReadDeclAs(Record, Idx); } +void ASTStmtReader::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *E) { + VisitExpr(E); + E->setBase(Reader.ReadSubExpr()); + E->setIdx(Reader.ReadSubExpr()); + E->setRBracketLoc(ReadSourceLocation(Record, Idx)); +} + void ASTStmtReader::VisitCXXUuidofExpr(CXXUuidofExpr *E) { VisitExpr(E); E->setSourceRange(ReadSourceRange(Record, Idx)); @@ -3037,6 +3044,9 @@ case EXPR_CXX_PROPERTY_REF_EXPR: S = new (Context) MSPropertyRefExpr(Empty); break; +case EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR: + S = new (Context) MSPropertySubscriptExpr(Empty); + break; case EXPR_CXX_UUIDOF_TYPE: S = new (Context) CXXUuidofExpr(Empty, false); break; Index: lib/StaticAnalyzer/Core/ExprEngine.cpp === --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -754,6 +754,7 @@ case Stmt::CXXUuidofExprClass: case Stmt::CXXFoldExprClass: case Stmt::MSPropertyRefExprClass: +case Stmt::MSPropertySubscriptExprClass: case Stmt::CXXUnresolvedConstructExprClass: case Stmt::DependentScopeDeclRefExprClass: case Stmt::ArrayTypeTraitExprClass: Index: lib/AST/Expr.cpp === --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -2998,6 +2998,7 @@ return true; case MSPropertyRefExprClass: + case MSPropertySubscriptExprClass: case CompoundAssignOperatorClass: case VAArgExprClass: case AtomicExprClass: Index: lib/AST/StmtProfile.cpp === --- lib/AST/StmtProfile.cpp +++ lib/AST/StmtProfile.cpp @@ -1123,6 +1123,11 @@ VisitDecl(S->getPropertyDecl()); } +void StmtProfiler::VisitMSPropertySubscriptExpr( +const MSPropertySubscriptExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitCXXThisExpr(const CXXThisExpr *S) { VisitExpr(S); ID.AddBoolean(S->isImplicit()); Index: lib/AST/StmtPrinter.cpp === --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -1715,6 +1715,13 @@ OS << Node->getPropertyDecl()->getDeclName(); } +void StmtPrinter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *Node) { + PrintExpr(Node->getBase()); + OS << "["; + PrintExpr(Node->getIdx()); + OS << "]"; +} + void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) { switch (Node->getLiteralOperatorKind()) { case UserDefinedLiteral::LOK_Raw: Index: lib/AST/ItaniumMangle.cpp === --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -2809,6 +2809,7 @@ case Expr::ParenListExprClass: case Expr::LambdaExprClass: case Expr::MSPropertyRefExprClass: + case Expr::MSPropertySubscriptExprClass: case Expr::TypoExprClass: // This should no longer exist in the AST by now. case Expr::OMPArraySectionExprClass: llvm_unreachable("unexpected statement kind"); Index: lib/AST/ExprConstant.cpp === ---
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
rjmccall added a comment. Needs more tests. 1. Dependent template instantiation. 2. Non-dependent template instantiation. 3. Indexes which are themselves pseudo-objects. 4. Templated getters and setters. 5. Non-POD by-value argument types. Comment at: include/clang/AST/BuiltinTypes.def:253 @@ -251,1 +252,3 @@ +PLACEHOLDER_TYPE(MSPropertySubscript, MSPropertySubscriptTy) + #ifdef LAST_BUILTIN_TYPE Hmm. I don't think you need a new placeholder type. These subscripts are still an ordinary pseudo-object; you can load and store at any point. Instead, you should detect this case by the expression node used, which can either be an ArraySubscriptExpr or a new node if you find it necessary. Comment at: lib/Sema/SemaExpr.cpp:3934 @@ -3921,1 +3933,3 @@ + if (!IsMSPropertySubscript && + base->getType()->isNonOverloadPlaceholderType()) { ExprResult result = CheckPlaceholderExpr(base); I think what you should do here is: 1. Detect whether the base type has pseudo-object type. 2. If so, give the pseudo-object code a chance to work on the expression. In most cases, it will just load; but if the base is an MSPropertyRefExpr of array type, or an ArraySubscriptExpr, it can leave it alone. 3. If the pseudo-object code returned an expression that's still of pseudo-object type, just build an ArraySubscriptExpr of pseudo-object type after you've folded pseudo-objects in the index as well. Comment at: lib/Sema/SemaExpr.cpp:4115 @@ -4097,1 +4114,3 @@ + BuiltinType::MSPropertySubscript); + if (!LHSExp->getType()->getAs() && !IsMSPropertySubscript) { ExprResult Result = DefaultFunctionArrayLvalueConversion(LHSExp); Placeholders should never get here. Comment at: lib/Sema/SemaPseudoObject.cpp:1458 @@ -1433,4 +1457,3 @@ } return S.ActOnCallExpr(S.getCurScope(), GetterExpr.get(), Don't modify ArgExprs in buildGet or buildSet; you might need to build both, e.g. when building a compound assignment or inc/dec. Since you need to copy into a new array anyway, you might as well accumulate them index expressions in stack order and then reverse them when adding them to this array. http://reviews.llvm.org/D13336 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
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 ""; + case MSPropertySubscript: +return ""; } 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(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()) { + auto *MSProp = dyn_cast(LHSExp->IgnoreParens()); + bool IsMSPropertySubscript = + (MSProp && MSProp->getPropertyDecl()->getType()->isArrayType()) || + LHSExp->getType()->isSpecificPlaceholderType( + BuiltinType::MSPropertySubscript); + if (!LHSExp->getType()->getAs() && !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 (cons
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
rjmccall added a comment. I agree with Reid that you should not be adding a DenseMap to Sema for this. Just build a SubscriptExpr for the syntactic form and have it yield an expression of pseudo-object type; or you can make your own AST node for it if that makes things easier. http://reviews.llvm.org/D13336 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
rnk added a subscriber: rnk. rnk added a comment. I spent some time reading through the pseudo-object implementation in clang, but I still don't understand it. We should ask John if he can review this. My gut feeling is that we shouldn't have a global DenseMap in Sema just for this. Should we have some other node, like an ObjCSubscriptRefExpr that describes this instead? We need *some* AST for the as-written syntactic form. Can you send a dump of the AST for the test? Comment at: lib/Sema/SemaExpr.cpp:3986-3987 @@ -3971,1 +3985,4 @@ + if (MSProp && MSProp->getPropertyDecl()->getType()->isArrayType()) +return base; + Will this affect the syntactic form of the expression? Comment at: test/CodeGenCXX/ms-property.cpp:32 @@ +31,3 @@ + // CHECK-NEXT: call void @"\01?PutX@?$St@M@@QEAAXMMM@Z"(%class.St* %{{.+}}, float 2.30e+01, float 1.00e+00, float [[J1]]) + p2->x[23][1] = j1; + return 0; Can you add a ++ test? http://reviews.llvm.org/D13336 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
ABataev added a comment. In http://reviews.llvm.org/D13336#257628, @rnk wrote: > I think fundamentally we are doing too much declspec property lowering in > Sema. We might want to back up and figure out how to do it in IRGen. Right > now we have bugs like this, which are probably more important than new > functionality: > https://llvm.org/bugs/show_bug.cgi?id=24132 Currently declspec property is represented as a member function call and does not keep info about property itself. Array subscripts exprs add arguments to this member function call and it must be built in Sema, so we could use an existing codegen for CallExprs. http://reviews.llvm.org/D13336 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D13336: [MSVC] 'property' with an empty array in array subscript expression.
rnk added a comment. I think fundamentally we are doing too much declspec property lowering in Sema. We might want to back up and figure out how to do it in IRGen. Right now we have bugs like this, which are probably more important than new functionality: https://llvm.org/bugs/show_bug.cgi?id=24132 http://reviews.llvm.org/D13336 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits