[clang] 853df5e - [Concepts] Fix friend duplicate detection when referencing containing Record
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 7 06:14:24 PDT 2022
Author: Erich Keane
Date: 2022-10-07T06:14:11-07:00
New Revision: 853df5e1d63684cbf3bf3da63d3e467003262282
URL: https://github.com/llvm/llvm-project/commit/853df5e1d63684cbf3bf3da63d3e467003262282
DIFF: https://github.com/llvm/llvm-project/commit/853df5e1d63684cbf3bf3da63d3e467003262282.diff
LOG: [Concepts] Fix friend duplicate detection when referencing containing Record
As another regression from the Deferred Concepts Instantiation patch, we
weren't properly detecting that a friend referenced its containing
Record when it referred to it without its template parameters. This
patch makes sure that we do.
Added:
Modified:
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaConcept.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/test/SemaTemplate/concepts-friends.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 37fcfd2940d7..a6acdf6b4952 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3686,8 +3686,10 @@ class Sema final {
// template, or just the current friend function. A 'lower' TemplateDepth in
// the AST refers to a 'containing' template. As the constraint is
// uninstantiated, this is relative to the 'top' of the TU.
- bool ConstraintExpressionDependsOnEnclosingTemplate(unsigned TemplateDepth,
- const Expr *Constraint);
+ bool
+ ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend,
+ unsigned TemplateDepth,
+ const Expr *Constraint);
// Calculates whether the friend function depends on an enclosing template for
// the purposes of [temp.friend] p9.
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index d8dadb38758b..f3301a67d227 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -657,7 +657,7 @@ bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
for (const Expr *Constraint : ACs)
- if (ConstraintExpressionDependsOnEnclosingTemplate(OldTemplateDepth,
+ if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
Constraint))
return true;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e07ad3a72b4b..9fa821ea6bde 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1691,14 +1691,28 @@ namespace {
class ConstraintRefersToContainingTemplateChecker
: public TreeTransform<ConstraintRefersToContainingTemplateChecker> {
bool Result = false;
+ const FunctionDecl *Friend = nullptr;
unsigned TemplateDepth = 0;
+ // Check a record-decl that we've seen to see if it is a lexical parent of the
+ // Friend, likely because it was referred to without its template arguments.
+ void CheckIfContainingRecord(const CXXRecordDecl *CheckingRD) {
+ CheckingRD = CheckingRD->getMostRecentDecl();
+
+ for (const DeclContext *DC = Friend->getLexicalDeclContext();
+ DC && !DC->isFileContext(); DC = DC->getParent())
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(DC))
+ if (CheckingRD == RD->getMostRecentDecl())
+ Result = true;
+ }
+
public:
using inherited = TreeTransform<ConstraintRefersToContainingTemplateChecker>;
ConstraintRefersToContainingTemplateChecker(Sema &SemaRef,
+ const FunctionDecl *Friend,
unsigned TemplateDepth)
- : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
+ : inherited(SemaRef), Friend(Friend), TemplateDepth(TemplateDepth) {}
bool getResult() const { return Result; }
// This should be the only template parm type that we have to deal with.
@@ -1728,6 +1742,8 @@ class ConstraintRefersToContainingTemplateChecker
TransformType(VD->getType());
else if (auto *TD = dyn_cast<TemplateDecl>(D))
TransformTemplateParameterList(TD->getTemplateParameters());
+ else if (auto *RD = dyn_cast<CXXRecordDecl>(D))
+ CheckIfContainingRecord(RD);
else if (isa<NamedDecl>(D)) {
// No direct types to visit here I believe.
} else
@@ -1738,8 +1754,11 @@ class ConstraintRefersToContainingTemplateChecker
} // namespace
bool Sema::ConstraintExpressionDependsOnEnclosingTemplate(
- unsigned TemplateDepth, const Expr *Constraint) {
- ConstraintRefersToContainingTemplateChecker Checker(*this, TemplateDepth);
+ const FunctionDecl *Friend, unsigned TemplateDepth,
+ const Expr *Constraint) {
+ assert(Friend->getFriendObjectKind() && "Only works on a friend");
+ ConstraintRefersToContainingTemplateChecker Checker(*this, Friend,
+ TemplateDepth);
Checker.TransformExpr(const_cast<Expr *>(Constraint));
return Checker.getResult();
}
diff --git a/clang/test/SemaTemplate/concepts-friends.cpp b/clang/test/SemaTemplate/concepts-friends.cpp
index 3db12b560588..6aa461841f9c 100644
--- a/clang/test/SemaTemplate/concepts-friends.cpp
+++ b/clang/test/SemaTemplate/concepts-friends.cpp
@@ -394,3 +394,20 @@ namespace NamedDeclRefs {
// expected-note@#NOREFOUTER{{previous definition is here}}
}
} // namespace NamedDeclRefs
+
+namespace RefersToParentInConstraint {
+ // No diagnostic, these aren't duplicates.
+ template<typename T, typename U>
+ concept similar = true;
+
+ template <typename X>
+ struct S{
+ friend void f(similar<S> auto && self){}
+ friend void f2(similar<S<X>> auto && self){}
+ };
+
+ void use() {
+ S<int> x;
+ S<long> y;
+ }
+} // namespace RefersToParentInConstraint
More information about the cfe-commits
mailing list