[clang] c4c35d9 - [Clang] [Sema] Handle `this` in `__restrict`-qualified member functions properly (#83187)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 29 08:43:04 PST 2024
Author: Sirraide
Date: 2024-02-29T17:43:01+01:00
New Revision: c4c35d9522d19a0a511ee2cc011a21661e69f3c0
URL: https://github.com/llvm/llvm-project/commit/c4c35d9522d19a0a511ee2cc011a21661e69f3c0
DIFF: https://github.com/llvm/llvm-project/commit/c4c35d9522d19a0a511ee2cc011a21661e69f3c0.diff
LOG: [Clang] [Sema] Handle `this` in `__restrict`-qualified member functions properly (#83187)
When resolving the type of `this` inside a member function, we were
attaching all qualifiers present on the member function to the class
type and then making it a pointer; however, `__restrict`, unlike `const`
and `volatile`, needs to be attached to the pointer type rather than the
pointee type.
This fixes #82941, #42411, and #18121.
Added:
clang/test/SemaCXX/restrict-this.cpp
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/AST/DeclCXX.cpp
clang/lib/Sema/SemaExprCXX.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a5c6b80c4e99e1..f44fef28b9f17f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -293,6 +293,11 @@ Bug Fixes to C++ Support
lookup searches the bases of an incomplete class.
- Fix a crash when an unresolved overload set is encountered on the RHS of a ``.*`` operator.
(`#53815 <https://github.com/llvm/llvm-project/issues/53815>`_)
+- In ``__restrict``-qualified member functions, attach ``__restrict`` to the pointer type of
+ ``this`` rather than the pointee type.
+ Fixes (`#82941 <https://github.com/llvm/llvm-project/issues/82941>`_),
+ (`#42411 <https://github.com/llvm/llvm-project/issues/42411>`_), and
+ (`#18121 <https://github.com/llvm/llvm-project/issues/18121>`_).
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 117e802dae2d9d..b4f2327d9c560a 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -2543,8 +2543,19 @@ QualType CXXMethodDecl::getThisType(const FunctionProtoType *FPT,
const CXXRecordDecl *Decl) {
ASTContext &C = Decl->getASTContext();
QualType ObjectTy = ::getThisObjectType(C, FPT, Decl);
- return C.getLangOpts().HLSL ? C.getLValueReferenceType(ObjectTy)
- : C.getPointerType(ObjectTy);
+
+ // Unlike 'const' and 'volatile', a '__restrict' qualifier must be
+ // attached to the pointer type, not the pointee.
+ bool Restrict = FPT->getMethodQuals().hasRestrict();
+ if (Restrict)
+ ObjectTy.removeLocalRestrict();
+
+ ObjectTy = C.getLangOpts().HLSL ? C.getLValueReferenceType(ObjectTy)
+ : C.getPointerType(ObjectTy);
+
+ if (Restrict)
+ ObjectTy.addRestrict();
+ return ObjectTy;
}
QualType CXXMethodDecl::getThisType() const {
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 59758d3bd6d1a3..c4750ce78fa9c1 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1220,7 +1220,7 @@ static QualType adjustCVQualifiersForCXXThisWithinLambda(
: nullptr;
}
}
- return ASTCtx.getPointerType(ClassType);
+ return ThisTy;
}
QualType Sema::getCurrentThisType() {
diff --git a/clang/test/SemaCXX/restrict-this.cpp b/clang/test/SemaCXX/restrict-this.cpp
new file mode 100644
index 00000000000000..e78c8e0d56e2f8
--- /dev/null
+++ b/clang/test/SemaCXX/restrict-this.cpp
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s
+// expected-no-diagnostics
+
+struct C {
+ void f() __restrict {
+ static_assert(__is_same(decltype(this), C *__restrict));
+ (void) [this]() {
+ static_assert(__is_same(decltype(this), C *__restrict));
+ (void) [this]() { static_assert(__is_same(decltype(this), C *__restrict)); };
+
+ // By-value capture means 'this' is now a
diff erent object; do not
+ // make it __restrict.
+ (void) [*this]() { static_assert(__is_same(decltype(this), const C *)); };
+ (void) [*this]() mutable { static_assert(__is_same(decltype(this), C *)); };
+ };
+ }
+};
+
+template <typename T> struct TC {
+ void f() __restrict {
+ static_assert(__is_same(decltype(this), TC<int> *__restrict));
+ (void) [this]() {
+ static_assert(__is_same(decltype(this), TC<int> *__restrict));
+ (void) [this]() { static_assert(__is_same(decltype(this), TC<int> *__restrict)); };
+
+ // By-value capture means 'this' is now a
diff erent object; do not
+ // make it __restrict.
+ (void) [*this]() { static_assert(__is_same(decltype(this), const TC<int> *)); };
+ (void) [*this]() mutable { static_assert(__is_same(decltype(this), TC<int> *)); };
+ };
+ }
+};
+
+void f() {
+ TC<int>{}.f();
+}
+
+namespace gh18121 {
+struct Foo {
+ void member() __restrict {
+ Foo *__restrict This = this;
+ }
+};
+}
+
+namespace gh42411 {
+struct foo {
+ int v;
+ void f() const __restrict {
+ static_assert(__is_same(decltype((v)), const int&));
+ (void) [this]() { static_assert(__is_same(decltype((v)), const int&)); };
+ }
+};
+}
+
+namespace gh82941 {
+void f(int& x) {
+ (void)x;
+}
+
+class C {
+ int x;
+ void g() __restrict;
+};
+
+void C::g() __restrict {
+ f(this->x);
+}
+}
More information about the cfe-commits
mailing list