Anastasia marked an inline comment as done.
Anastasia added inline comments.


================
Comment at: lib/Sema/SemaInit.cpp:4539
+  if (InitCategory.isPRValue() || InitCategory.isXValue())
+    T1Quals.removeAddressSpace();
+
----------------
rjmccall wrote:
> ebevhan wrote:
> > rjmccall wrote:
> > > rjmccall wrote:
> > > > I can understand why a pr-value wouldn't have an address space, but an 
> > > > x-value's address space is surely important.
> > > No, wait, I think this is more deeply wrong.  We're initializing a 
> > > reference to type `cv1 T1`, and if we're initializing it with a 
> > > temporary, we're dropping the address space from `cv1`?  That's 
> > > definitely wrong.
> > > 
> > > If we're starting with a pr-value, reference-initialization normally has 
> > > to start by initializing a temporary.  (The exception is it's a class 
> > > type with a conversion operator to a reference type; C++ is abysmally 
> > > complicated.  Let's ignore this for a moment.)  Temporaries are always in 
> > > the default address space (the address space of local variables) because 
> > > the language (neither OpenCL nor Embedded C) does not give us any 
> > > facility for allocating temporary memory anywhere else.  So 
> > > reference-initialization from a pr-value creates a temporary in the 
> > > default address space and then attempts to initialize the destination 
> > > reference type with that temporary.  That initialization should fail if 
> > > there's no conversion from the default address space to the destination 
> > > address space.  For example, consider initializing a `const int __global 
> > > &` from a pr-value: this should clearly not succeed, because we have no 
> > > way of putting a temporary in the global address space.  That reference 
> > > can only be initialized with a gl-value that's already in the `__global` 
> > > address space.
> > > 
> > > On the other hand, we can successfully initialize a `const int &` with a 
> > > gl-value of type `const int __global` not by direct reference 
> > > initialization but by loading from the operand and then materializing the 
> > > result into a new temporary.
> > > 
> > > I think what this means is:
> > > 
> > > - We need to be doing this checking as if pr-values were in `__private`.  
> > > This includes both (1) expressions that were originally pr-values and (2) 
> > > expressions that have been converted to pr-values due to a failure to 
> > > perform direct reference initialization.
> > > 
> > > - We need to make sure that reference compatibility correctly prevents 
> > > references from being bound to gl-values in incompatible address spaces.
> > > On the other hand, we can successfully initialize a `const int &` with a 
> > > gl-value of type `const int __global` not by direct reference 
> > > initialization but by loading from the operand and then materializing the 
> > > result into a new temporary.
> > 
> > Is this the right thing to do? It means that initializing such a reference 
> > would incur a cost under the hood that might be unnoticed/unwanted by the 
> > user. 
> Hmm.  I was going to say that it's consistent with the normal behavior of 
> C++, but looking at the actual rule, it's more complicated than that: C++ 
> will only do this if the types are not reference-related or if the gl-value 
> is a bit-field.  So this would only be allowed if the reference type was e.g. 
> `const long &`.  It's a strange rule, but it's straightforward to stay 
> consistent with it.
> 
> I think we will eventually find ourselves needing a special-case rule for 
> copy-initializing and copy-assigning trivially-copyable types, but we're not 
> there yet.
I need some help to understand what's the right way to fix this problem.

As far as I gathered from this particular example. The issues is caused by the 
following statement of **addrspace-of-this.cl** line 47:
  C c3 = c1 + c2;

If I remove this new `if` statement in **SemaInit.cpp** and disable some 
asserts about the incorrect address space cast the AST that Clang is trying to 
create is as follows:


```
| | |-DeclStmt 0x9d6e70 <line:47:3, col:17>
| | | `-VarDecl 0x9d6b28 <col:3, col:15> col:5 c3 'C' cinit
| | |   `-ExprWithCleanups 0x9d6e58 <col:10, col:15> 'C'
| | |     `-CXXConstructExpr 0x9d6e20 <col:10, col:15> 'C' 'void (__generic C 
&&) __generic' elidable
| | |       `-MaterializeTemporaryExpr 0x9d6e08 <col:10, col:15> '__generic C' 
xvalue
| | |         `-ImplicitCastExpr 0x9d6df0 <col:10, col:15> '__generic C' 
<AddressSpaceConversion>
| | |           `-CXXOperatorCallExpr 0x9d6c90 <col:10, col:15> 'C'
| | |             |-ImplicitCastExpr 0x9d6c78 <col:13> 'C (*)(const __generic C 
&) __generic' <FunctionToPointerDecay>
| | |             | `-DeclRefExpr 0x9d6bf8 <col:13> 'C (const __generic C &) 
__generic' lvalue CXXMethod 0x9d4da0 'operator+' 'C (const __generic C &) 
__generic'
| | |             |-ImplicitCastExpr 0x9d6be0 <col:10> '__generic C' lvalue 
<AddressSpaceConversion>
| | |             | `-DeclRefExpr 0x9d6b88 <col:10> 'C' lvalue Var 0x9d6830 
'c1' 'C'
| | |             `-ImplicitCastExpr 0x9d6bc8 <col:15> 'const __generic C' 
lvalue <AddressSpaceConversion>
| | |               `-DeclRefExpr 0x9d6ba8 <col:15> 'C' lvalue Var 0x9d6928 
'c2' 'C'
```

I feel that this AST (kind of) makes sense? The result of `operator+` returns 
class `C` object but as it's directly used to copy construct `c3` it seems 
logical to cast it to `__generic C`.

Before references with address spaces existed we only had to cast pointers to 
different address spaces... but now in this particular case of initializing a 
reference, casting an address space of non-pointer type seem to make sense?

Do you think the AST is correct and I should just change the address space 
related asserts in casting and teach CodeGen how to generate `addrspacecast` 
for such reference initialization? Or do you think the AST has to be created 
differently?

As a side note: I wish we would have some 'special' AST node to obtain a 
reference to an object just like we are taking an address of an object to 
become a pointer, that we could construct implicitly. It would make our life 
easier for such cases.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56066/new/

https://reviews.llvm.org/D56066



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to