[PATCH] D129068: [AST] Accept identical TypeConstraint referring to other template parameters.
Chuanqi Xu via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Sun Jul 10 20:23:20 PDT 2022
ChuanqiXu added a comment.
In D129068#3640249 <https://reviews.llvm.org/D129068#3640249>, @vsapsai wrote:
> Thanks for the changes, they look good! While I was looking how we handle "requires" constraints in other cases, I've noticed that they are suspiciously similar. That's why I offer the following change to unify comparison of the constraint expressions
>
> diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
> index 92293622cc3d..555669f027a7 100644
> --- a/clang/include/clang/AST/ASTContext.h
> +++ b/clang/include/clang/AST/ASTContext.h
> @@ -2664,6 +2664,11 @@ public:
> /// that they may be used in declarations of the same template.
> bool isSameTemplateParameter(const NamedDecl *X, const NamedDecl *Y) const;
>
> + /// Determine whether two 'requires' expressions are similar enough.
> + /// Use of 'requires' isn't mandatory, works with constraints expressed in
> + /// other ways too.
> + bool isSameConstraintExpr(const Expr *XCE, const Expr *YCE) const;
> +
> /// Retrieve the "canonical" template argument.
> ///
> /// The canonical template argument is the simplest template argument
> diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
> index aced0ab39ace..f3937d6304f9 100644
> --- a/clang/lib/AST/ASTContext.cpp
> +++ b/clang/lib/AST/ASTContext.cpp
> @@ -6245,14 +6245,10 @@ bool ASTContext::isSameTemplateParameter(const NamedDecl *X,
> auto *TYTCArgs = TYTC->getTemplateArgsAsWritten();
> if (TXTCArgs->NumTemplateArgs != TYTCArgs->NumTemplateArgs)
> return false;
> - llvm::FoldingSetNodeID XID, YID;
> - for (auto &ArgLoc : TXTCArgs->arguments())
> - ArgLoc.getArgument().Profile(XID, X->getASTContext());
> - for (auto &ArgLoc : TYTCArgs->arguments())
> - ArgLoc.getArgument().Profile(YID, Y->getASTContext());
> - if (XID != YID)
> - return false;
> }
> + if (!isSameConstraintExpr(TXTC->getImmediatelyDeclaredConstraint(),
> + TYTC->getImmediatelyDeclaredConstraint()))
> + return false;
> }
> return true;
> }
> @@ -6279,15 +6275,20 @@ bool ASTContext::isSameTemplateParameterList(
> if (!isSameTemplateParameter(X->getParam(I), Y->getParam(I)))
> return false;
>
> - const Expr *XRC = X->getRequiresClause();
> - const Expr *YRC = Y->getRequiresClause();
> - if (!XRC != !YRC)
> + if (!isSameConstraintExpr(X->getRequiresClause(), Y->getRequiresClause()))
> return false;
> - if (XRC) {
> - llvm::FoldingSetNodeID XRCID, YRCID;
> - XRC->Profile(XRCID, *this, /*Canonical=*/true);
> - YRC->Profile(YRCID, *this, /*Canonical=*/true);
> - if (XRCID != YRCID)
> +
> + return true;
> +}
> +
> +bool ASTContext::isSameConstraintExpr(const Expr *XCE, const Expr *YCE) const {
> + if (!XCE != !YCE)
> + return false;
> + if (XCE) {
> + llvm::FoldingSetNodeID XCEID, YCEID;
> + XCE->Profile(XCEID, *this, /*Canonical=*/true);
> + YCE->Profile(YCEID, *this, /*Canonical=*/true);
> + if (XCEID != YCEID)
> return false;
> }
>
> @@ -6450,17 +6451,9 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const {
> return false;
> }
>
> - const Expr *XRC = FuncX->getTrailingRequiresClause();
> - const Expr *YRC = FuncY->getTrailingRequiresClause();
> - if (!XRC != !YRC)
> + if (!isSameConstraintExpr(FuncX->getTrailingRequiresClause(),
> + FuncY->getTrailingRequiresClause()))
> return false;
> - if (XRC) {
> - llvm::FoldingSetNodeID XRCID, YRCID;
> - XRC->Profile(XRCID, *this, /*Canonical=*/true);
> - YRC->Profile(YRCID, *this, /*Canonical=*/true);
> - if (XRCID != YRCID)
> - return false;
> - }
>
> auto GetTypeAsWritten = [](const FunctionDecl *FD) {
> // Map to the first declaration that we've already merged into this one.
>
> In `ASTContext::isSameTemplateParameter` it is exactly the same change as yours modulo comments.
Thanks for the detailed suggestion! Done!
================
Comment at: clang/test/Modules/concept.cppm:38
+ template <__integer_like _Tp, C<_Tp> Sentinel>
+ constexpr _Tp operator()(_Tp &&__t, Sentinel &&last) const {
+ return __t;
----------------
vsapsai wrote:
> In what cases `operator()` is critical for the test? I was thinking about replacing with something like "funcA", "funcB", "funcC", so that diagnostic verification is easier because it is tricky to understand which method "__fn::operator()" refers to.
The `operator()` is not critical for the test. It is reduced from the actual testing. But I prefer to remain `operator()` here. Since tests are rarely read and the current style could improve the diversity. Diversity is good for tests (to me).
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D129068/new/
https://reviews.llvm.org/D129068
More information about the cfe-commits
mailing list