alexander-shaposhnikov created this revision. alexander-shaposhnikov added a reviewer: erichkeane. alexander-shaposhnikov created this object with visibility "All Users". Herald added a project: All. alexander-shaposhnikov requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Substitute constraints only for declarations with different lexical contexts. This results in avoiding the substitution of constraints during the redeclaration check inside a class (and by product caching the wrong substitution result). Test plan: ninja check-all Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D150730 Files: clang/lib/Sema/SemaConcept.cpp clang/test/SemaTemplate/concepts-no-early-substitution.cpp Index: clang/test/SemaTemplate/concepts-no-early-substitution.cpp =================================================================== --- /dev/null +++ clang/test/SemaTemplate/concepts-no-early-substitution.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -std=c++20 -x c++ %s -verify -fsyntax-only +// expected-no-diagnostics + +template <typename T0> +concept HasMemberBegin = requires(T0 t) { t.begin(); }; + +struct GetBegin { + template <HasMemberBegin T1> + void operator()(T1); +}; + +GetBegin begin; + +template <typename T2> +concept Concept = requires(T2 t) { begin(t); }; + +struct Subrange; + +template <typename T3> +struct View { + Subrange &getSubrange(); + + operator bool() + requires true; + + operator bool() + requires requires { begin(getSubrange()); }; + + void begin(); +}; + +struct Subrange : View<void> {}; +static_assert(Concept<Subrange>); Index: clang/lib/Sema/SemaConcept.cpp =================================================================== --- clang/lib/Sema/SemaConcept.cpp +++ clang/lib/Sema/SemaConcept.cpp @@ -780,7 +780,8 @@ const Expr *NewConstr) { if (OldConstr == NewConstr) return true; - if (Old && New && Old != New) { + if (Old && New && Old != New && + Old->getLexicalDeclContext() != New->getLexicalDeclContext()) { if (const Expr *SubstConstr = SubstituteConstraintExpression(*this, Old, OldConstr)) OldConstr = SubstConstr;
Index: clang/test/SemaTemplate/concepts-no-early-substitution.cpp =================================================================== --- /dev/null +++ clang/test/SemaTemplate/concepts-no-early-substitution.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -std=c++20 -x c++ %s -verify -fsyntax-only +// expected-no-diagnostics + +template <typename T0> +concept HasMemberBegin = requires(T0 t) { t.begin(); }; + +struct GetBegin { + template <HasMemberBegin T1> + void operator()(T1); +}; + +GetBegin begin; + +template <typename T2> +concept Concept = requires(T2 t) { begin(t); }; + +struct Subrange; + +template <typename T3> +struct View { + Subrange &getSubrange(); + + operator bool() + requires true; + + operator bool() + requires requires { begin(getSubrange()); }; + + void begin(); +}; + +struct Subrange : View<void> {}; +static_assert(Concept<Subrange>); Index: clang/lib/Sema/SemaConcept.cpp =================================================================== --- clang/lib/Sema/SemaConcept.cpp +++ clang/lib/Sema/SemaConcept.cpp @@ -780,7 +780,8 @@ const Expr *NewConstr) { if (OldConstr == NewConstr) return true; - if (Old && New && Old != New) { + if (Old && New && Old != New && + Old->getLexicalDeclContext() != New->getLexicalDeclContext()) { if (const Expr *SubstConstr = SubstituteConstraintExpression(*this, Old, OldConstr)) OldConstr = SubstConstr;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits