Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -5373,6 +5373,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() ||
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Sema/SemaOpenCL.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ class SemaOpenCL : public SemaBase {
bool checkBuiltinKernelWorkGroupSize(CallExpr *TheCall);

bool checkBuiltinNDRangeAndBlock(CallExpr *TheCall);

void removeFriendFunctionAddressSpace(FunctionDecl *FD,
TypeSourceInfo *TInfo);
};

} // namespace clang
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -10324,6 +10325,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.
Expand Down
12 changes: 12 additions & 0 deletions clang/lib/Sema/SemaOpenCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 6 additions & 0 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -2825,6 +2826,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();
}
Expand Down
10 changes: 6 additions & 4 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1794,9 +1794,11 @@ bool Sema::CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc) {
}

// Helper to deduce addr space of a pointee type in OpenCL mode.
static QualType deduceOpenCLPointeeAddrSpace(Sema &S, QualType PointeeType) {
static QualType deduceOpenCLPointeeAddrSpace(Sema &S, QualType PointeeType,
bool IsBlock) {
if (!PointeeType->isUndeducedAutoType() && !PointeeType->isDependentType() &&
!PointeeType->isSamplerT() &&
(!PointeeType->isFunctionType() || IsBlock) &&
!PointeeType.hasAddressSpace())
PointeeType = S.getASTContext().getAddrSpaceQualType(
PointeeType, S.getASTContext().getDefaultOpenCLPointeeAddrSpace());
Expand Down Expand Up @@ -1835,7 +1837,7 @@ QualType Sema::BuildPointerType(QualType T,
T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ false);

if (getLangOpts().OpenCL)
T = deduceOpenCLPointeeAddrSpace(*this, T);
T = deduceOpenCLPointeeAddrSpace(*this, T, /*IsBlock*/ false);

// In WebAssembly, pointers to reference types and pointers to tables are
// illegal.
Expand Down Expand Up @@ -1912,7 +1914,7 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ true);

if (getLangOpts().OpenCL)
T = deduceOpenCLPointeeAddrSpace(*this, T);
T = deduceOpenCLPointeeAddrSpace(*this, T, /*IsBlock*/ false);

// In WebAssembly, references to reference types and tables are illegal.
if (getASTContext().getTargetInfo().getTriple().isWasm() &&
Expand Down Expand Up @@ -2767,7 +2769,7 @@ QualType Sema::BuildBlockPointerType(QualType T,
return QualType();

if (getLangOpts().OpenCL)
T = deduceOpenCLPointeeAddrSpace(*this, T);
T = deduceOpenCLPointeeAddrSpace(*this, T, /*IsBlock*/ true);

return Context.getBlockPointerType(T);
}
Expand Down
1 change: 1 addition & 0 deletions clang/test/SemaCXX/friend-template-redecl.cpp
Original file line number Diff line number Diff line change
@@ -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); }

Expand Down
1 change: 1 addition & 0 deletions clang/test/SemaCXX/friend.cpp
Original file line number Diff line number Diff line change
@@ -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}}
Expand Down
11 changes: 6 additions & 5 deletions clang/test/SemaCXX/friend2.cpp
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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.
Expand Down
Loading