[cfe-dev] Problem with address spaces and 'CWG2352: Allow qualification conversions during reference binding.'

Jeroen Dobbelaere via cfe-dev cfe-dev at lists.llvm.org
Fri Jan 10 06:20:26 PST 2020

Hi Richard,

I have found some issues with following patch: 
   346de9b67228f42eb9b55fa3b426b5dedfdb1d40   CWG2352: Allow qualification conversions during reference binding.

There are two unwanted effects that we observe now (see testcase below):
1) It has effect on the implicit promotions of 'pointers pointing to an address space'. Code that would (should) give an error is now silently accepted. 

2) Code that worked, now triggers an internal assertion error.
clang-10: /..../llvm-project/llvm/include/llvm/IR/Instructions.h:2656: void llvm::PHINode::setIncomingValue(unsigned int, llvm::Value*): Assertion `getType() == V->getType() && "All operands to PHI node must be the same type as the PHI node!"' failed.                                                                                                                                                                                                                                                 

about the 'FIXME: Does "superset" also imply the representation of a pointer is the same?' comment in the patch:
    -> no, even if an address space is a superset of another, their representations can differ. It is only after converting
        the clang AS to the target AS that you have some more information about the representation:
        for example, for x86, the different opencl address spaces (__global, __private, __generic, ...) seem to map onto the
        same pointer type (target AS 0). For amdgcn, this is not the case.

NOTE: I added Anastasia, as she is also interested in everything related to address spaces.


Jeroen Dobbelaere

----- test.c -----
// use an amdgcn target as that has separate target address spaces
// clang  -target amdgcn-unknown-amdhsa -x cl -cl-std=clc++ -O3 -S -emit-llvm -Xclang -disable-llvm-passes -o - test.c
#define SUP __generic 
#define SUB __global 

#if 1
  extern void foo(int SUP*&);
  int test_should_give_error(int SUB*p) {
    foo(p); // ISSUE1: int SUB* cannot be passes as a 'int SUP* &'  -> should give an error
    return *p;

  extern void foo_constant(int SUP* const &);
  int test_pass_constant(int SUB*p) {
    foo_constant(p); // int SUB* is first converted into a local int SUP*, and then passed as a 'int SUP* const&' -> ok
    return *p;

int test6(int c, int SUB* a, int SUP* b) {
    return *(c ? a : b); // ISSUE2: internal error -> should return something like: '*(c ? (int SUP*)a : b)'
----- test.c --

More information about the cfe-dev mailing list