<html dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style id="owaParaStyle" type="text/css">
<!--
p
        {margin-top:0;
        margin-bottom:0}
-->
P {margin-top:0;margin-bottom:0;}</style>
</head>
<body ocsi="0" fpstyle="1">
<div style="direction: ltr;font-family: Tahoma;color: #000000;font-size: 10pt;">Hi,<br>
<br>
I have narrowed the issue down to CodeGenModule::GetOrCreateLLVMGlobal()<br>
This I assume is due to the uncertainty of whether a ctor/dtor will need to run on the 'const' data.<br>
<br>
During CodeGenModule::EmitGlobalVarDefinition() the code explicitly checks the ctor/dtor situation:<br>
 // If it is safe to mark the global 'constant', do so now.<br>
  GV->setConstant(!NeedsGlobalCtor && !NeedsGlobalDtor &&<br>
                  isTypeConstant(D->getType(), true));<br>
<br>
However this is only done for definitions and not declarations.<br>
Should declarations be handled in a similar way?<br>
<br>
Dumping the state of the 'VarDecl *D' for the example in the previous emails gives:<br>
<br>
GetOrCreateLLVMGlobal<br>
VarDecl 0x333c230 <test.cpp:5:3, col:23> i 'const int [2]' static<br>
const int identifier[2]<br>
isTypeConstant true<br>
<br>
GetOrCreateLLVMGlobal<br>
VarDecl 0x337eed0 <test.cpp:13:3, col:25> j 'const struct S':'const struct S' static<br>
const struct S identifier<br>
isTypeConstant false<br>
<br>
EmitGlobalVarDefinition<br>
GetOrCreateLLVMGlobal<br>
VarDecl 0x337f7f0 parent 0x337ece0 prev 0x337eed0 <test.cpp:17:1, col:27> j 'const struct S':'const struct S'<br>
`-InitListExpr 0x337f920 <col:23, col:27> 'const struct S':'const struct S'<br>
  |-IntegerLiteral 0x337f890 <col:24> 'int' 1<br>
  `-IntegerLiteral 0x337f8b0 <col:26> 'int' 2<br>
const struct S identifier<br>
NeedsGlobalCtor false<br>
NeedsGlobalDtor false<br>
isTypeConstant true<br>
<br>
GetOrCreateLLVMGlobal<br>
VarDecl 0x337fb80 <test.cpp:21:3, col:25> k 'const struct S':'const struct S' static<br>
const struct S identifier<br>
isTypeConstant false<br>
<br>
<br>
<div style="font-family: Times New Roman; color: #000000; font-size: 16px">
<hr tabindex="-1">
<div style="direction: ltr;" id="divRpF548688"><font color="#000000" face="Tahoma" size="2"><b>From:</b> Robert Lytton<br>
<b>Sent:</b> 06 December 2013 14:41<br>
<b>To:</b> cfe-dev@cs.uiuc.edu<br>
<b>Subject:</b> static const structures declared as "external global %struct.S" instead of "external constant %struct.S"<br>
</font><br>
</div>
<div></div>
<div>
<div style="direction:ltr; font-family:Tahoma; color:#000000; font-size:10pt">Hi,<br>
<br>
I have a problem relating to the way clang handles static const structure declarations in c++ classes.<br>
<br>
If only the declaration is visible:<br>
<font color="black" face="Tahoma" size="2"><span dir="ltr" style="font-size:10pt">    class K {static const struct S k; ...}</span></font><font color="black" face="Tahoma" size="2"><span dir="ltr" style="font-size:10pt"><br>
</span></font>the constness is not emitted in the declaration:<br>
<font color="black" face="Tahoma" size="2"><span dir="ltr" style="font-size:10pt">    @_ZN1K1kE = external global %struct.S<br>
should this not be:</span></font><br>
<font color="black" face="Tahoma" size="2"><span dir="ltr" style="font-size:10pt">    @_ZN1K1kE = external
</span></font><font color="black" face="Tahoma" size="2"><span dir="ltr" style="font-size:10pt"><font color="black" face="Tahoma" size="2"><span dir="ltr" style="font-size:10pt">constant</span></font> %struct.S</span></font><br>
<br>
If the definition is visible too:<br>
<font color="black" face="Tahoma" size="2"><span dir="ltr" style="font-size:10pt">    class J {static const struct S j;...}<br>
    const struct S J::j = {1,2};</span></font><br>
we get a global 'const' definition, viz:<br>
<font color="black" face="Tahoma" size="2"><span dir="ltr" style="font-size:10pt">    @_ZN1J1jE = constant %struct.S { i32 1, i32 2 }, align 4<br>
</span></font><br>
It should be noted that the handling of arrays always uses const - see below.<br>
<br>
Am I correct in believing this is a bug?<br>
Can anyone direct me to where the problem may reside?<br>
<br>
This is a problem on the XCore target as we handle constant and non-constant data in separate areas and hence will emit different assembler instructions.<br>
<br>
Robert<br>
<br>
<br>
<font color="black" face="Tahoma" size="2"><span dir="ltr" style="font-size:10pt">struct S{int s1; int s2;};<br>
<br>
class I {<br>
  static const int i[2];<br>
  static int ii();<br>
};<br>
int I::ii(){return i[0];}<br>
// I::i defined else where - OK<br>
<br>
class J {<br>
  static const struct S j;<br>
  static struct S jj();<br>
};<br>
struct S J::jj(){return j;}<br>
const struct S J::j = {1,2};<br>
<br>
<br>
class K {<br>
  static const struct S k;<br>
  static struct S kk();<br>
};<br>
struct S K::kk(){return k;}<br>
// K::k defined else where - const is lost<br>
<br>
<br>
%struct.S = type { i32, i32 }<br>
@_ZN1I1iE = external constant [2 x i32]<br>
@_ZN1J1jE = constant %struct.S { i32 1, i32 2 }, align 4<br>
@_ZN1K1kE = external global %struct.S<br>
<br>
define i32 @_ZN1I2iiEv() #0 align 2 {<br>
entry:<br>
  %0 = load i32* getelementptr inbounds ([2 x i32]* @_ZN1I1iE, i32 0, i32 0), align 4<br>
  ret i32 %0<br>
}<br>
<br>
define void @_ZN1J2jjEv(%struct.S* noalias sret %agg.result) #0 align 2 {<br>
entry:<br>
  %0 = bitcast %struct.S* %agg.result to i8*<br>
  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* bitcast (%struct.S* @_ZN1J1jE to i8*), i32 8, i32 4, i1 false)<br>
  ret void<br>
}<br>
<br>
define void @_ZN1K2kkEv(%struct.S* noalias sret %agg.result) #0 align 2 {<br>
entry:<br>
  %0 = bitcast %struct.S* %agg.result to i8*<br>
  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* bitcast (%struct.S* @_ZN1K1kE to i8*), i32 8, i32 4, i1 false)<br>
  ret void<br>
}</span></font><br>
<br>
</div>
</div>
</div>
</div>
</body>
</html>