Skip to content

Commit

Permalink
[OpenCL] Diagnose conflicting address spaces in templates.
Browse files Browse the repository at this point in the history
Added new diagnostic when templates are instantiated with
different address space from the one provided in its definition.

This also prevents deducing generic address space in pointer
type of templates to allow giving them concrete address space
during instantiation.

Differential Revision: https://reviews.llvm.org/D55127

llvm-svn: 348382
  • Loading branch information
Anastasia Stulova committed Dec 5, 2018
1 parent 4ead99b commit 12e3a8a
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 16 deletions.
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Expand Up @@ -2634,6 +2634,8 @@ def err_field_with_address_space : Error<
"field may not be qualified with an address space">;
def err_compound_literal_with_address_space : Error<
"compound literal in function scope may not be qualified with an address space">;
def err_address_space_mismatch_templ_inst : Error<
"conflicting address space qualifiers are provided between types %0 and %1">;
def err_attr_objc_ownership_redundant : Error<
"the type %0 is already explicitly ownership-qualified">;
def err_invalid_nsnumber_type : Error<
Expand Down
10 changes: 6 additions & 4 deletions clang/lib/Sema/SemaType.cpp
Expand Up @@ -7201,7 +7201,10 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
!IsPointee) ||
// Do not deduce addr space of the void type, e.g. in f(void), otherwise
// it will fail some sema check.
(T->isVoidType() && !IsPointee))
(T->isVoidType() && !IsPointee) ||
// Do not deduce address spaces for dependent types because they might end
// up instantiating to a type with an explicit address space qualifier.
T->isDependentType())
return;

LangAS ImpAddr = LangAS::Default;
Expand All @@ -7226,9 +7229,8 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
if (IsPointee) {
ImpAddr = LangAS::opencl_generic;
} else {
if (D.getContext() == DeclaratorContext::TemplateArgContext ||
T->isDependentType()) {
// Do not deduce address space for non-pointee type in templates.
if (D.getContext() == DeclaratorContext::TemplateArgContext) {
// Do not deduce address space for non-pointee type in template arg.
} else if (D.getContext() == DeclaratorContext::FileContext) {
ImpAddr = LangAS::opencl_global;
} else {
Expand Down
35 changes: 23 additions & 12 deletions clang/lib/Sema/TreeTransform.h
Expand Up @@ -684,15 +684,13 @@ class TreeTransform {
OMPClause *Transform ## Class(Class *S);
#include "clang/Basic/OpenMPKinds.def"

/// Build a new qualified type given its unqualified type and type
/// qualifiers.
/// Build a new qualified type given its unqualified type and type location.
///
/// By default, this routine adds type qualifiers only to types that can
/// have qualifiers, and silently suppresses those qualifiers that are not
/// permitted. Subclasses may override this routine to provide different
/// behavior.
QualType RebuildQualifiedType(QualType T, SourceLocation Loc,
Qualifiers Quals);
QualType RebuildQualifiedType(QualType T, QualifiedTypeLoc TL);

/// Build a new pointer type given its pointee type.
///
Expand Down Expand Up @@ -4228,8 +4226,9 @@ TreeTransform<Derived>::TransformTypeWithDeducedTST(TypeSourceInfo *DI) {
return nullptr;

if (QTL) {
Result = getDerived().RebuildQualifiedType(
Result, QTL.getBeginLoc(), QTL.getType().getLocalQualifiers());
Result = getDerived().RebuildQualifiedType(Result, QTL);
if (Result.isNull())
return nullptr;
TLB.TypeWasModifiedSafely(Result);
}

Expand All @@ -4240,13 +4239,14 @@ template<typename Derived>
QualType
TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
QualifiedTypeLoc T) {
Qualifiers Quals = T.getType().getLocalQualifiers();

QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc());
if (Result.isNull())
return QualType();

Result = getDerived().RebuildQualifiedType(Result, T.getBeginLoc(), Quals);
Result = getDerived().RebuildQualifiedType(Result, T);

if (Result.isNull())
return QualType();

// RebuildQualifiedType might have updated the type, but not in a way
// that invalidates the TypeLoc. (There's no location information for
Expand All @@ -4256,10 +4256,21 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
return Result;
}

template<typename Derived>
template <typename Derived>
QualType TreeTransform<Derived>::RebuildQualifiedType(QualType T,
SourceLocation Loc,
Qualifiers Quals) {
QualifiedTypeLoc TL) {

SourceLocation Loc = TL.getBeginLoc();
Qualifiers Quals = TL.getType().getLocalQualifiers();

if (((T.getAddressSpace() != LangAS::Default &&
Quals.getAddressSpace() != LangAS::Default)) &&
T.getAddressSpace() != Quals.getAddressSpace()) {
SemaRef.Diag(Loc, diag::err_address_space_mismatch_templ_inst)
<< TL.getType() << T;
return QualType();
}

// C++ [dcl.fct]p7:
// [When] adding cv-qualifications on top of the function type [...] the
// cv-qualifiers are ignored.
Expand Down
19 changes: 19 additions & 0 deletions clang/test/SemaOpenCLCXX/address-space-templates.cl
Expand Up @@ -7,6 +7,25 @@ struct S {
void f2(T); // expected-error{{parameter may not be qualified with an address space}}
};

template <typename T>
T foo1(__global T *i) { // expected-note{{candidate template ignored: substitution failure [with T = __local int]: conflicting address space qualifiers are provided between types '__global T' and '__local int'}}
return *i;
}

template <typename T>
T *foo2(T *i) {
return i;
}

template <typename T>
void foo3() {
__private T ii; // expected-error{{conflicting address space qualifiers are provided between types 'T' and '__global int'}}
}

void bar() {
S<const __global int> sintgl; // expected-note{{in instantiation of template class 'S<const __global int>' requested here}}

foo1<__local int>(1); // expected-error{{no matching function for call to 'foo1'}}
foo2<__global int>(0);
foo3<__global int>(); // expected-note{{in instantiation of function template specialization 'foo3<__global int>' requested here}}
}

0 comments on commit 12e3a8a

Please sign in to comment.