Skip to content

Commit 2145368

Browse files
committed
[OpenCLCpp] Remove address-space from friend declaration
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.
1 parent d49353c commit 2145368

File tree

8 files changed

+41
-5
lines changed

8 files changed

+41
-5
lines changed

clang/include/clang/AST/Type.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5373,6 +5373,12 @@ class FunctionProtoType final
53735373
return Result;
53745374
}
53755375

5376+
ExtProtoInfo withoutAddressSpace() {
5377+
ExtProtoInfo Result(*this);
5378+
Result.TypeQuals = TypeQuals.withoutAddressSpace();
5379+
return Result;
5380+
}
5381+
53765382
bool requiresFunctionProtoTypeExtraBitfields() const {
53775383
return ExceptionSpec.Type == EST_Dynamic ||
53785384
requiresFunctionProtoTypeArmAttributes() ||

clang/include/clang/Sema/SemaOpenCL.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ class SemaOpenCL : public SemaBase {
100100
bool checkBuiltinKernelWorkGroupSize(CallExpr *TheCall);
101101

102102
bool checkBuiltinNDRangeAndBlock(CallExpr *TheCall);
103+
104+
void removeFriendFunctionAddressSpace(FunctionDecl *FD,
105+
TypeSourceInfo *TInfo);
103106
};
104107

105108
} // namespace clang

clang/lib/Sema/SemaDecl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "clang/Sema/SemaInternal.h"
5252
#include "clang/Sema/SemaObjC.h"
5353
#include "clang/Sema/SemaOpenACC.h"
54+
#include "clang/Sema/SemaOpenCL.h"
5455
#include "clang/Sema/SemaOpenMP.h"
5556
#include "clang/Sema/SemaPPC.h"
5657
#include "clang/Sema/SemaRISCV.h"
@@ -10324,6 +10325,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1032410325
}
1032510326
NewFD->setObjectOfFriendDecl();
1032610327
NewFD->setAccess(AS_public);
10328+
// For OpenCLCPlusPlus dialect remove address space from free friend
10329+
// function prototype, since it is non-member and none should be present.
10330+
if (!isa<CXXMethodDecl>(NewFD) && getLangOpts().OpenCLCPlusPlus) {
10331+
OpenCL().removeFriendFunctionAddressSpace(NewFD, TInfo);
10332+
}
1032710333
}
1032810334

1032910335
// If a function is defined as defaulted or deleted, mark it as such now.

clang/lib/Sema/SemaOpenCL.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,4 +576,16 @@ bool SemaOpenCL::checkBuiltinToAddr(unsigned BuiltinID, CallExpr *Call) {
576576
return false;
577577
}
578578

579+
void SemaOpenCL::removeFriendFunctionAddressSpace(FunctionDecl *FD,
580+
TypeSourceInfo *TInfo) {
581+
assert(!isa<CXXMethodDecl>(FD) && "Only free function should be adjusted");
582+
583+
// For generic address space remove __generic, otherwise remove __private
584+
QualType R = TInfo->getType();
585+
const FunctionProtoType *FPT = R->getAs<FunctionProtoType>();
586+
FD->setType(SemaRef.Context.getFunctionType(
587+
FPT->getReturnType(), FPT->getParamTypes(),
588+
FPT->getExtProtoInfo().withoutAddressSpace()));
589+
}
590+
579591
} // namespace clang

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "clang/Sema/SemaCUDA.h"
3030
#include "clang/Sema/SemaHLSL.h"
3131
#include "clang/Sema/SemaObjC.h"
32+
#include "clang/Sema/SemaOpenCL.h"
3233
#include "clang/Sema/SemaOpenMP.h"
3334
#include "clang/Sema/SemaSwift.h"
3435
#include "clang/Sema/Template.h"
@@ -2825,6 +2826,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
28252826

28262827
if (isFriend) {
28272828
Function->setObjectOfFriendDecl();
2829+
// For OpenCLCPlusPlus dialect remove address space (__generic/__private)
2830+
// of dependend or template free friend function instantiation.
2831+
if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
2832+
SemaRef.OpenCL().removeFriendFunctionAddressSpace(Function, TInfo);
2833+
}
28282834
if (FunctionTemplateDecl *FT = Function->getDescribedFunctionTemplate())
28292835
FT->setObjectOfFriendDecl();
28302836
}

clang/test/SemaCXX/friend-template-redecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %clang_cc1 -std=c++17 -verify -emit-llvm-only %s
2+
// RUN: %clang_cc1 -cl-std=clc++2021 -verify -emit-llvm-only %s
23

34
template <class T> void bar(const T &t) { foo(t); }
45

clang/test/SemaCXX/friend.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14
2+
// RUN: %clang_cc1 -fsyntax-only -verify %s -cl-std=clc++2021
23

34
friend class A; // expected-error {{'friend' used outside of class}}
45
void f() { friend class A; } // expected-error {{'friend' used outside of class}}

clang/test/SemaCXX/friend2.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
1+
// RUN: %clang_cc1 -fsyntax-only -verify=expected,expected-noncl %s -std=c++11
2+
// RUN: %clang_cc1 -fsyntax-only -verify=expected,expected-cl %s -cl-std=clc++2021
23

34
// If a friend function is defined in several non-template classes,
45
// it is an error.
@@ -62,16 +63,16 @@ template<typename T> struct C6b {
6263
friend void func6(int) {} // expected-error{{redefinition of 'func6'}}
6364
};
6465
C6a<long> c6a;
65-
C6b<int*> c6b; // expected-note{{in instantiation of template class 'C6b<int *>' requested here}}
66-
66+
C6b<int*> c6b; // expected-noncl-note{{in instantiation of template class 'C6b<int *>' requested here}}
67+
// expected-cl-note@-1{{in instantiation of template class 'C6b<__generic int *>' requested here}}
6768
void func7(int);
6869
template<typename T> struct C7 {
6970
friend void func7(int) {} // expected-error{{redefinition of 'func7'}}
7071
// expected-note@-1{{previous definition is here}}
7172
};
7273
C7<long> c7a;
73-
C7<int*> c7b; // expected-note{{in instantiation of template class 'C7<int *>' requested here}}
74-
74+
C7<int*> c7b; // expected-noncl-note{{in instantiation of template class 'C7<int *>' requested here}}
75+
// expected-cl-note@-1{{in instantiation of template class 'C7<__generic int *>' requested here}}
7576

7677
// Even if clases are not instantiated and hence friend functions defined in them are not
7778
// available, their declarations can be checked.

0 commit comments

Comments
 (0)