[PATCH] D99983: Provide TreeTransform::TransformAttr the transformed statement; NFC
haberman accepted this revision. haberman added a comment. This revision is now accepted and ready to land. This seems fine to me, but I'll defer to @rsmith for final review. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D99983/new/ https://reviews.llvm.org/D99983 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D99983: Provide TreeTransform::TransformAttr the transformed statement; NFC
aaron.ballman updated this revision to Diff 339319. aaron.ballman added a comment. Now that [[clang::musttail]] has landed, I can show the refactoring I had in mind by implementing it myself. WDYT of this approach? CHANGES SINCE LAST ACTION https://reviews.llvm.org/D99983/new/ https://reviews.llvm.org/D99983 Files: clang/lib/Sema/SemaStmt.cpp clang/lib/Sema/SemaStmtAttr.cpp clang/lib/Sema/SemaTemplateInstantiate.cpp clang/lib/Sema/TreeTransform.h Index: clang/lib/Sema/TreeTransform.h === --- clang/lib/Sema/TreeTransform.h +++ clang/lib/Sema/TreeTransform.h @@ -379,8 +379,14 @@ /// of attribute. Subclasses may override this function to transform /// attributed statements using some other mechanism. /// + /// The \c TransformedStmt parameter points to the substituted statement and + /// is non-const explicitly so that transformations of the attribute that + /// need to set state on the statement they apply to can do so if needed. + /// Note that \c TransformedStmt will be null when transforming type + /// attributes. + /// /// \returns the transformed attribute - const Attr *TransformAttr(const Attr *S); + const Attr *TransformAttr(const Attr *S, Stmt *TransformedStmt); /// Transform the specified attribute. /// @@ -388,10 +394,12 @@ /// spelling to transform expressions stored within the attribute. /// /// \returns the transformed attribute. -#define ATTR(X) -#define PRAGMA_SPELLING_ATTR(X)\ - const X##Attr *Transform##X##Attr(const X##Attr *R) { return R; } +#define ATTR(X)\ + const X##Attr *Transform##X##Attr(const X##Attr *R, Stmt *TransformedStmt) { \ +return R; \ + } #include "clang/Basic/AttrList.inc" +#undef ATTR /// Transform the given expression. /// @@ -6745,7 +6753,8 @@ // oldAttr can be null if we started with a QualType rather than a TypeLoc. const Attr *oldAttr = TL.getAttr(); - const Attr *newAttr = oldAttr ? getDerived().TransformAttr(oldAttr) : nullptr; + const Attr *newAttr = + oldAttr ? getDerived().TransformAttr(oldAttr, nullptr) : nullptr; if (oldAttr && !newAttr) return QualType(); @@ -7298,19 +7307,20 @@ } template -const Attr *TreeTransform::TransformAttr(const Attr *R) { - if (!R) -return R; +const Attr *TreeTransform::TransformAttr(const Attr *A, + Stmt *TransformedStmt) { + if (!A) +return A; - switch (R->getKind()) { + switch (A->getKind()) { // Transform attributes with a pragma spelling by calling TransformXXXAttr. -#define ATTR(X) -#define PRAGMA_SPELLING_ATTR(X)\ +#define ATTR(X)\ case attr::X:\ -return getDerived().Transform##X##Attr(cast(R)); +return getDerived().Transform##X##Attr(cast(A), TransformedStmt); #include "clang/Basic/AttrList.inc" +#undef ATTR default: -return R; +return A; } } @@ -7318,21 +7328,27 @@ StmtResult TreeTransform::TransformAttributedStmt(AttributedStmt *S, StmtDiscardKind SDK) { + // Transform the attributed statement first so that we can pass the + // transformed version in to the attribute handler. This is necessary because + // attributes that need to perform semantic checking are more likely to need + // the transformed statement than statement semantic checking is likely to + // need the transformed attributes. In such a case, the TransformFooAttr() + // function can mutate the non-const transformed statement that it is passed. + StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt(), SDK); + if (SubStmt.isInvalid()) +return StmtError(); + bool AttrsChanged = false; SmallVector Attrs; // Visit attributes and keep track if any are transformed. for (const auto *I : S->getAttrs()) { -const Attr *R = getDerived().TransformAttr(I); +const Attr *R = getDerived().TransformAttr(I, SubStmt.get()); AttrsChanged |= (I != R); if (R) Attrs.push_back(R); } - StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt(), SDK); - if (SubStmt.isInvalid()) -return StmtError(); - if (SubStmt.get() == S->getSubStmt() && !AttrsChanged) return S; Index: clang/lib/Sema/SemaTemplateInstantiate.cpp === --- clang/lib/Sema/SemaTemplateInstantiate.cpp +++ clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1074,7 +1074,10 @@ NamedDecl *FirstQualifierInScope = nullptr, bool AllowInjectedClassName = false); -const LoopHintAttr *Transfor
[PATCH] D99983: Provide TreeTransform::TransformAttr the transformed statement; NFC
aaron.ballman created this revision. aaron.ballman added reviewers: rsmith, haberman. aaron.ballman requested review of this revision. Herald added a project: clang. It is useful statement an attribute is being applied to when performing semantic processing of the attribute during template instantiation. This functionality is not currently needed by existing attributes, but is anticipated to be used by new attributes being worked on. One design choice with this is whether to transform attributes then the attributed statement, or to transform the attributed statement and then the attributes. I elected to transform the attributed statement first because it seems less likely that the statement transformation would require the instanatiated attributes compared to when we transform attributes (those would benefit from knowing the fully instantiated statement). This patch passes a non-`const Stmt *` to `TransformAttr()` in case the attribute instantiation needs to modify the attributed statement for some reason. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D99983 Files: clang/lib/Sema/SemaTemplateInstantiate.cpp clang/lib/Sema/TreeTransform.h Index: clang/lib/Sema/TreeTransform.h === --- clang/lib/Sema/TreeTransform.h +++ clang/lib/Sema/TreeTransform.h @@ -379,8 +379,14 @@ /// of attribute. Subclasses may override this function to transform /// attributed statements using some other mechanism. /// + /// The \c TransformedStmt parameter points to the substituted statement and + /// is non-const explicitly so that transformations of the attribute that + /// need to set state on the statement they apply to can do so if needed. + /// Note that \c TransformedStmt will be null when transforming type + /// attributes. + /// /// \returns the transformed attribute - const Attr *TransformAttr(const Attr *S); + const Attr *TransformAttr(const Attr *A, Stmt *TransformedStmt); /// Transform the specified attribute. /// @@ -390,7 +396,9 @@ /// \returns the transformed attribute. #define ATTR(X) #define PRAGMA_SPELLING_ATTR(X)\ - const X##Attr *Transform##X##Attr(const X##Attr *R) { return R; } + const X##Attr *Transform##X##Attr(const X##Attr *R, Stmt *TransformedStmt) { \ +return R; \ + } #include "clang/Basic/AttrList.inc" /// Transform the given expression. @@ -6734,7 +6742,8 @@ // oldAttr can be null if we started with a QualType rather than a TypeLoc. const Attr *oldAttr = TL.getAttr(); - const Attr *newAttr = oldAttr ? getDerived().TransformAttr(oldAttr) : nullptr; + const Attr *newAttr = + oldAttr ? getDerived().TransformAttr(oldAttr, nullptr) : nullptr; if (oldAttr && !newAttr) return QualType(); @@ -7287,19 +7296,20 @@ } template -const Attr *TreeTransform::TransformAttr(const Attr *R) { - if (!R) -return R; +const Attr *TreeTransform::TransformAttr(const Attr *A, + Stmt *TransformedStmt) { + if (!A) +return A; - switch (R->getKind()) { + switch (A->getKind()) { // Transform attributes with a pragma spelling by calling TransformXXXAttr. #define ATTR(X) #define PRAGMA_SPELLING_ATTR(X)\ case attr::X:\ -return getDerived().Transform##X##Attr(cast(R)); +return getDerived().Transform##X##Attr(cast(A), TransformedStmt); #include "clang/Basic/AttrList.inc" default: -return R; +return A; } } @@ -7307,20 +7317,26 @@ StmtResult TreeTransform::TransformAttributedStmt(AttributedStmt *S, StmtDiscardKind SDK) { + // Transform the attributed statement first so that we can pass the + // transformed version in to the attribute handler. This is necessary because + // attributes that need to perform semantic checking are more likely to need + // the transformed statement than statement semantic checking is likely to + // need the transformed attributes. In such a case, the TransformFooAttr() + // function can mutate the non-const transformed statement that it is passed. + StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt(), SDK); + if (SubStmt.isInvalid()) +return StmtError(); + bool AttrsChanged = false; SmallVector Attrs; // Visit attributes and keep track if any are transformed. for (const auto *I : S->getAttrs()) { -const Attr *R = getDerived().TransformAttr(I); +const Attr *R = getDerived().TransformAttr(I, SubStmt.get()); AttrsChanged |= (I != R); Attrs.push_back(R); } - StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt(), SDK); - if (SubStmt.isInvalid()) -return StmtError(); - if (SubStmt.get() == S->getSubStmt() &