-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[OpenCLCpp] Remove address-space from friend declaration #153459
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-clang Author: None (piotrrak) ChangesOpenCL prohibits address-space on function, however it default address-space is implicitly to all member decls. This causes the lookup to fail find correct free function or free function template as it is considered different declaration. This change also makes sure that hidden friend definition doesn't have associated address-space. Without this change friend declaration would cause incorrect diagnostic: 'test/SemaCXX/friend.cpp Line 16: conflicting types for 'f'` in case of prior definition of function f friend declaration was refering to While bit unsatisfactory it was much easier to fix/remove address-space of friend declaration since it is still required for friend of member function decls. This change also enables compilation of some of failing test exposing this defect. It was originally exhibited by 'test/SemaCXX/type-traits.cpp', however this test has currently other issues also related to the __cl_clang_function_pointers extension and address-space inferrence preventing from enabling it by the defaut. Full diff: https://github.com/llvm/llvm-project/pull/153459.diff 8 Files Affected:
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index c4c23c835ebc2..c3c3902a00731 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -5349,6 +5349,12 @@ class FunctionProtoType final
return Result;
}
+ ExtProtoInfo withoutAddressSpace() {
+ ExtProtoInfo Result(*this);
+ Result.TypeQuals = TypeQuals.withoutAddressSpace();
+ return Result;
+ }
+
bool requiresFunctionProtoTypeExtraBitfields() const {
return ExceptionSpec.Type == EST_Dynamic ||
requiresFunctionProtoTypeArmAttributes() ||
diff --git a/clang/include/clang/Sema/SemaOpenCL.h b/clang/include/clang/Sema/SemaOpenCL.h
index 04b2b617fb12f..715b5845f2151 100644
--- a/clang/include/clang/Sema/SemaOpenCL.h
+++ b/clang/include/clang/Sema/SemaOpenCL.h
@@ -100,6 +100,9 @@ class SemaOpenCL : public SemaBase {
bool checkBuiltinKernelWorkGroupSize(CallExpr *TheCall);
bool checkBuiltinNDRangeAndBlock(CallExpr *TheCall);
+
+ void removeFriendFunctionAddressSpace(FunctionDecl *FD,
+ TypeSourceInfo *TInfo);
};
} // namespace clang
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index cb59782b83304..ff641ee033928 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -51,6 +51,7 @@
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaOpenACC.h"
+#include "clang/Sema/SemaOpenCL.h"
#include "clang/Sema/SemaOpenMP.h"
#include "clang/Sema/SemaPPC.h"
#include "clang/Sema/SemaRISCV.h"
@@ -10300,6 +10301,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
NewFD->setObjectOfFriendDecl();
NewFD->setAccess(AS_public);
+ // For OpenCLCPlusPlus dialect remove address space from free friend
+ // function prototype, since it is non-member and none should be present.
+ if (!isa<CXXMethodDecl>(NewFD) && getLangOpts().OpenCLCPlusPlus) {
+ OpenCL().removeFriendFunctionAddressSpace(NewFD, TInfo);
+ }
}
// If a function is defined as defaulted or deleted, mark it as such now.
diff --git a/clang/lib/Sema/SemaOpenCL.cpp b/clang/lib/Sema/SemaOpenCL.cpp
index f11a40e3964ff..c7b6d9d505b26 100644
--- a/clang/lib/Sema/SemaOpenCL.cpp
+++ b/clang/lib/Sema/SemaOpenCL.cpp
@@ -576,4 +576,16 @@ bool SemaOpenCL::checkBuiltinToAddr(unsigned BuiltinID, CallExpr *Call) {
return false;
}
+void SemaOpenCL::removeFriendFunctionAddressSpace(FunctionDecl *FD,
+ TypeSourceInfo *TInfo) {
+ assert(!isa<CXXMethodDecl>(FD) && "Only free function should be adjusted");
+
+ // For generic address space remove __generic, otherwise remove __private
+ QualType R = TInfo->getType();
+ const FunctionProtoType *FPT = R->getAs<FunctionProtoType>();
+ FD->setType(SemaRef.Context.getFunctionType(
+ FPT->getReturnType(), FPT->getParamTypes(),
+ FPT->getExtProtoInfo().withoutAddressSpace()));
+}
+
} // namespace clang
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index f02a295220efb..a925e12786806 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -29,6 +29,7 @@
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaHLSL.h"
#include "clang/Sema/SemaObjC.h"
+#include "clang/Sema/SemaOpenCL.h"
#include "clang/Sema/SemaOpenMP.h"
#include "clang/Sema/SemaSwift.h"
#include "clang/Sema/Template.h"
@@ -2823,6 +2824,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
if (isFriend) {
Function->setObjectOfFriendDecl();
+ // For OpenCLCPlusPlus dialect remove address space (__generic/__private)
+ // of dependend or template free friend function instantiation.
+ if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
+ SemaRef.OpenCL().removeFriendFunctionAddressSpace(Function, TInfo);
+ }
if (FunctionTemplateDecl *FT = Function->getDescribedFunctionTemplate())
FT->setObjectOfFriendDecl();
}
diff --git a/clang/test/SemaCXX/friend-template-redecl.cpp b/clang/test/SemaCXX/friend-template-redecl.cpp
index 4ee03c6f6387f..384291a87b198 100644
--- a/clang/test/SemaCXX/friend-template-redecl.cpp
+++ b/clang/test/SemaCXX/friend-template-redecl.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++17 -verify -emit-llvm-only %s
+// RUN: %clang_cc1 -cl-std=clc++2021 -verify -emit-llvm-only %s
template <class T> void bar(const T &t) { foo(t); }
diff --git a/clang/test/SemaCXX/friend.cpp b/clang/test/SemaCXX/friend.cpp
index 53e6bbfcf42a8..3622b71ee3106 100644
--- a/clang/test/SemaCXX/friend.cpp
+++ b/clang/test/SemaCXX/friend.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14
+// RUN: %clang_cc1 -fsyntax-only -verify %s -cl-std=clc++2021
friend class A; // expected-error {{'friend' used outside of class}}
void f() { friend class A; } // expected-error {{'friend' used outside of class}}
diff --git a/clang/test/SemaCXX/friend2.cpp b/clang/test/SemaCXX/friend2.cpp
index 6d3b545904e48..6c8fe20b7c914 100644
--- a/clang/test/SemaCXX/friend2.cpp
+++ b/clang/test/SemaCXX/friend2.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,expected-noncl %s -std=c++11
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,expected-cl %s -cl-std=clc++2021
// If a friend function is defined in several non-template classes,
// it is an error.
@@ -62,16 +63,16 @@ template<typename T> struct C6b {
friend void func6(int) {} // expected-error{{redefinition of 'func6'}}
};
C6a<long> c6a;
-C6b<int*> c6b; // expected-note{{in instantiation of template class 'C6b<int *>' requested here}}
-
+C6b<int*> c6b; // expected-noncl-note{{in instantiation of template class 'C6b<int *>' requested here}}
+ // expected-cl-note@-1{{in instantiation of template class 'C6b<__generic int *>' requested here}}
void func7(int);
template<typename T> struct C7 {
friend void func7(int) {} // expected-error{{redefinition of 'func7'}}
// expected-note@-1{{previous definition is here}}
};
C7<long> c7a;
-C7<int*> c7b; // expected-note{{in instantiation of template class 'C7<int *>' requested here}}
-
+C7<int*> c7b; // expected-noncl-note{{in instantiation of template class 'C7<int *>' requested here}}
+ // expected-cl-note@-1{{in instantiation of template class 'C7<__generic int *>' requested here}}
// Even if clases are not instantiated and hence friend functions defined in them are not
// available, their declarations can be checked.
|
OpenCL prohibits address-space on function, however it default address-space is implicitly to all member decls. This causes the lookup to fail find correct free function or free function template as it is considered different declaration. This change also makes sure that hidden friend definition doesn't have associated address-space. Without this change friend declaration would cause incorrect diagnostic: 'test/SemaCXX/friend.cpp Line 16: conflicting types for 'f'` in case of prior definition of function f friend declaration was refering to While bit unsatisfactory it was much easier to fix/remove address-space of friend declaration since it is still required for friend of member function decls. This change also enables compilation of some of failing test exposing this defect. It was originally exhibited by 'test/SemaCXX/type-traits.cpp', however this test has currently other issues also related to the __cl_clang_function_pointers extension and address-space inferrence preventing from enabling it by the defaut.
2cc2918
to
4336c58
Compare
An alternative approach to fixing this, would be distinguishing that member is friend declaration in: static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
QualType declSpecType,
TypeSourceInfo *TInfo) Address space is assigned since the check:
in While it'd be great to exclude free function friends there it is much easier to do in |
OpenCL prohibits address-space on function, however it default address-space is implicitly to all member Decls.
This causes the lookup to fail find correct free function or free function template as it is considered different declaration. We make sure that hidden friend definition doesn't have associated address-space.
Without this change friend declaration would cause incorrect diagnostic:
in case of prior definition of function f friend declaration was referring to
While bit unsatisfactory it was much easier to fix/remove address-space of friend declaration since it is still required for friend of member FunctionDecls.
This change also enables compilation of some of failing test exposing this defect.
It was originally exhibited by
test/SemaCXX/type-traits.cpp
, however this test has currently other issues also related to the__cl_clang_function_pointers
extension and address-space inference preventing from enabling it by the default.