<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;}</style>
</head>
<body ocsi="0" fpstyle="1">
<div style="direction: ltr;font-family: Tahoma;color: #000000;font-size: 10pt;">Hi Richard,<br>
<br>
Thank you for the review.<br>
<br>
I'll change the metadata numbers to use filecheck variables.<br>
<br>
In regard to using <span dir="ltr">getMostRecentDecl, is the problem that I am using it too soon or the way I use it?<br>
Indeed, if I was to add a pass, would </span><span dir="ltr"><span dir="ltr">it </span>
be needed at all - maybe the pass should handle multiple list entries of a symbol.<br>
<br>
I agree, building a target specific list and adding a pass seems good.<br>
Should I handle all global declarations in this way or only those I can't compute?<br>
I need to understand the best places to discover/add-to-list the global declarations.<br>
</span><span dir="ltr"><span dir="ltr">getTargetCodeGenInfo()::SetTargetAttributes only receives definitions (and their typestrings could be emitted).<br>
Is there another target hook which receives all declarations rather than only definitions?<br>
I'll look through the code again regarding how </span></span><span dir="ltr"><span dir="ltr"><span dir="ltr"><span dir="ltr">'MangledDeclNames' is built up to try to gain insight.<br>
<br>
Any guidance most welcome!<br>
<br>
Robert</span></span></span></span><span dir="ltr"><br>
</span><br>
<div style="font-family: Times New Roman; color: #000000; font-size: 16px">
<hr tabindex="-1">
<div style="direction: ltr;" id="divRpF650847"><font color="#000000" face="Tahoma" size="2"><b>From:</b> metafoo@gmail.com [metafoo@gmail.com] on behalf of Richard Smith [richard@metafoo.co.uk]<br>
<b>Sent:</b> 16 July 2014 04:07<br>
<b>To:</b> Robert Lytton<br>
<b>Cc:</b> cfe commits<br>
<b>Subject:</b> Re: r212263 - Move the calling of emitTargetMD() later.<br>
</font><br>
</div>
<div></div>
<div>
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">On Thu, Jul 3, 2014 at 2:30 AM, Robert Lytton <span dir="ltr">
<<a href="mailto:robert@xmos.com" target="_blank">robert@xmos.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex; border-left-width:1px; border-left-color:rgb(204,204,204); border-left-style:solid; padding-left:1ex">
Author: rlytton<br>
Date: Thu Jul  3 04:30:33 2014<br>
New Revision: 212263<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=212263&view=rev" target="_blank">
http://llvm.org/viewvc/llvm-project?rev=212263&view=rev</a><br>
Log:<br>
Move the calling of emitTargetMD() later.<br>
<br>
Summary:<br>
Because a global created by GetOrCreateLLVMGlobal() is not finalised until later viz:<br>
  extern char a[];<br>
  char f(){ return a[5];}<br>
  char a[10];<br>
<br>
Change MangledDeclNames to use a MapVector rather than a DenseMap so that the<br>
Metadata is output in order of original declaration, so to make deterministic<br>
and improve human readablity.<br>
</blockquote>
<div><br>
</div>
<div>Sorry for not reviewing this before. I think this is completely the wrong approach. Please just keep a list of those variables for which you couldn't compute the type string when they are emitted (within XCoreTargetCodeGenInfo), and perform another pass
 at the end of IR generation to fix up those ones. That will have much better locality, and will avoid the target metadata emission loop that is redundant on almost all targets.</div>
<div><br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex; border-left-width:1px; border-left-color:rgb(204,204,204); border-left-style:solid; padding-left:1ex">
Differential Revision: <a href="http://reviews.llvm.org/D4176" target="_blank">http://reviews.llvm.org/D4176</a><br>
<br>
Modified:<br>
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp<br>
    cfe/trunk/lib/CodeGen/CodeGenModule.h<br>
    cfe/trunk/test/CodeGen/xcore-stringtype.c<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=212263&r1=212262&r2=212263&view=diff" target="_blank">
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=212263&r1=212262&r2=212263&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Thu Jul  3 04:30:33 2014<br>
@@ -393,6 +393,8 @@ void CodeGenModule::Release() {<br>
     DebugInfo->finalize();<br>
<br>
   EmitVersionIdentMetadata();<br>
+<br>
+  EmitTargetMetadata();<br>
 }<br>
<br>
 void CodeGenModule::UpdateCompletedType(const TagDecl *TD) {<br>
@@ -1534,8 +1536,6 @@ CodeGenModule::GetOrCreateLLVMFunction(S<br>
     }<br>
   }<br>
<br>
-  getTargetCodeGenInfo().emitTargetMD(D, F, *this);<br>
-<br>
   // Make sure the result is of the requested type.<br>
   if (!IsIncompleteFunction) {<br>
     assert(F->getType()->getElementType() == Ty);<br>
@@ -1685,8 +1685,6 @@ CodeGenModule::GetOrCreateLLVMGlobal(Str<br>
   if (AddrSpace != Ty->getAddressSpace())<br>
     return llvm::ConstantExpr::getAddrSpaceCast(GV, Ty);<br>
<br>
-  getTargetCodeGenInfo().emitTargetMD(D, GV, *this);<br>
-<br>
   return GV;<br>
 }<br>
<br>
@@ -3340,6 +3338,14 @@ void CodeGenModule::EmitVersionIdentMeta<br>
   IdentMetadata->addOperand(llvm::MDNode::get(Ctx, IdentNode));<br>
 }<br>
<br>
+void CodeGenModule::EmitTargetMetadata() {<br>
+  for (auto &I : MangledDeclNames) {<br>
+    const Decl *D = I.first.getDecl()->getMostRecentDecl();<br>
</blockquote>
<div><br>
</div>
<div>This has introduced an iterator invalidation bug that breaks most modules builds: getMostRecentDecl can result in lazy deserialization, and thus in MangledDeclNames having entries added to it.</div>
<div> </div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex; border-left-width:1px; border-left-color:rgb(204,204,204); border-left-style:solid; padding-left:1ex">
+    llvm::GlobalValue *GV = GetGlobalValue(I.second);<br>
+    getTargetCodeGenInfo().emitTargetMD(D, GV, *this);<br>
+  }<br>
+}<br>
+<br>
 void CodeGenModule::EmitCoverageFile() {<br>
   if (!getCodeGenOpts().CoverageFile.empty()) {<br>
     if (llvm::NamedMDNode *CUNode = TheModule.getNamedMetadata("<a href="http://llvm.dbg.cu" target="_blank">llvm.dbg.cu</a>")) {<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=212263&r1=212262&r2=212263&view=diff" target="_blank">
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=212263&r1=212262&r2=212263&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Thu Jul  3 04:30:33 2014<br>
@@ -349,8 +349,8 @@ class CodeGenModule : public CodeGenType<br>
   /// emitted when the translation unit is complete.<br>
   CtorList GlobalDtors;<br>
<br>
-  /// A map of canonical GlobalDecls to their mangled names.<br>
-  llvm::DenseMap<GlobalDecl, StringRef> MangledDeclNames;<br>
+  /// An ordered map of canonical GlobalDecls to their mangled names.<br>
+  llvm::MapVector<GlobalDecl, StringRef> MangledDeclNames;<br>
   llvm::StringMap<GlobalDecl, llvm::BumpPtrAllocator> Manglings;<br>
<br>
   /// Global annotations.<br>
@@ -1146,6 +1146,9 @@ private:<br>
   /// \brief Emit the Clang version as llvm.ident metadata.<br>
   void EmitVersionIdentMetadata();<br>
<br>
+  /// Emits target specific Metadata for global declarations.<br>
+  void EmitTargetMetadata();<br>
+<br>
   /// Emit the llvm.gcov metadata used to tell LLVM where to emit the .gcno and<br>
   /// .gcda files in a way that persists in .bc files.<br>
   void EmitCoverageFile();<br>
<br>
Modified: cfe/trunk/test/CodeGen/xcore-stringtype.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/xcore-stringtype.c?rev=212263&r1=212262&r2=212263&view=diff" target="_blank">
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/xcore-stringtype.c?rev=212263&r1=212262&r2=212263&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGen/xcore-stringtype.c (original)<br>
+++ cfe/trunk/test/CodeGen/xcore-stringtype.c Thu Jul  3 04:30:33 2014<br>
@@ -9,13 +9,13 @@<br>
 // Please see 'Tools Development Guide' section 2.16.2 for format details:<br>
 // <<a href="https://www.xmos.com/download/public/Tools-Development-Guide%28X9114A%29.pdf" target="_blank">https://www.xmos.com/download/public/Tools-Development-Guide%28X9114A%29.pdf</a>><br>
<br>
-// CHECK: !xcore.typestrings = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10,<br>
-// CHECK: !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23,<br>
-// CHECK: !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34}<br>
+// CHECK: !xcore.typestrings = !{!1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11,<br>
+// CHECK: !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25,<br>
+// CHECK: !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38}<br>
</blockquote>
<div><br>
</div>
<div>Please fix this test to not hardcode metadata numbers; these are extremely fragile, and will break if we start emitting more metadata for any reason. Instead, use FileCheck variables (<a href="http://llvm.org/docs/CommandGuide/FileCheck.html#filecheck-variables" target="_blank">http://llvm.org/docs/CommandGuide/FileCheck.html#filecheck-variables</a>).</div>
<div> </div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex; border-left-width:1px; border-left-color:rgb(204,204,204); border-left-style:solid; padding-left:1ex">
 // test BuiltinType<br>
-// CHECK: !0 = metadata !{void (i1, i8, i8, i8, i16, i16, i16, i32, i32, i32,<br>
+// CHECK: !1 = metadata !{void (i1, i8, i8, i8, i16, i16, i16, i32, i32, i32,<br>
 // CHECK:      i32, i32, i32, i64, i64, i64, float, double, double)*<br>
 // CHECK:      @builtinType, metadata !"f{0}(b,uc,uc,sc,ss,us,ss,si,ui,si,sl,<br>
 // CHECK:      ul,sl,sll,ull,sll,ft,d,ld)"}<br>
@@ -28,14 +28,14 @@ double _Complex Complex; // not supporte<br>
<br>
<br>
 // test FunctionType & Qualifiers<br>
-// CHECK: !1 = metadata !{void ()* @gI, metadata !"f{0}()"}<br>
-// CHECK: !2 = metadata !{void (...)* @eI, metadata !"f{0}()"}<br>
-// CHECK: !3 = metadata !{void ()* @gV, metadata !"f{0}(0)"}<br>
-// CHECK: !4 = metadata !{void ()* @eV, metadata !"f{0}(0)"}<br>
-// CHECK: !5 = metadata !{void (i32, ...)* @gVA, metadata !"f{0}(si,va)"}<br>
-// CHECK: !6 = metadata !{void (i32, ...)* @eVA, metadata !"f{0}(si,va)"}<br>
-// CHECK: !7 = metadata !{i32* (i32*)* @gQ, metadata !"f{crv:p(cv:si)}(p(cv:si))"}<br>
-// CHECK: !8 = metadata !{i32* (i32*)* @eQ, metadata !"f{crv:p(cv:si)}(p(cv:si))"}<br>
+// CHECK: !2 = metadata !{void ()* @gI, metadata !"f{0}()"}<br>
+// CHECK: !3 = metadata !{void (...)* @eI, metadata !"f{0}()"}<br>
+// CHECK: !4 = metadata !{void ()* @gV, metadata !"f{0}(0)"}<br>
+// CHECK: !5 = metadata !{void ()* @eV, metadata !"f{0}(0)"}<br>
+// CHECK: !6 = metadata !{void (i32, ...)* @gVA, metadata !"f{0}(si,va)"}<br>
+// CHECK: !7 = metadata !{void (i32, ...)* @eVA, metadata !"f{0}(si,va)"}<br>
+// CHECK: !8 = metadata !{i32* (i32*)* @gQ, metadata !"f{crv:p(cv:si)}(p(cv:si))"}<br>
+// CHECK: !9 = metadata !{i32* (i32*)* @eQ, metadata !"f{crv:p(cv:si)}(p(cv:si))"}<br>
 extern void eI();<br>
 void gI() {eI();};<br>
 extern void eV(void);<br>
@@ -49,10 +49,10 @@ const volatile int* volatile restrict co<br>
<br>
<br>
 // test PointerType<br>
-// CHECK: !9 = metadata !{i32* (i32*, i32* (i32*)*)*<br>
-// CHECK:      @pointerType, metadata !"f{p(si)}(p(si),p(f{p(si)}(p(si))))"}<br>
-// CHECK: !10 = metadata !{i32** @EP, metadata !"p(si)"}<br>
-// CHECK: !11 = metadata !{i32** @GP, metadata !"p(si)"}<br>
+// CHECK: !10 = metadata !{i32* (i32*, i32* (i32*)*)*<br>
+// CHECK:       @pointerType, metadata !"f{p(si)}(p(si),p(f{p(si)}(p(si))))"}<br>
+// CHECK: !11 = metadata !{i32** @EP, metadata !"p(si)"}<br>
+// CHECK: !12 = metadata !{i32** @GP, metadata !"p(si)"}<br>
 extern int* EP;<br>
 int* GP;<br>
 int* pointerType(int *I, int * (*FP)(int *)) {<br>
@@ -60,25 +60,25 @@ int* pointerType(int *I, int * (*FP)(int<br>
 }<br>
<br>
 // test ArrayType<br>
-// CHECK: !12 = metadata !{[2 x i32]* (i32*, i32*, [2 x i32]*, [2 x i32]*, i32*)*<br>
+// CHECK: !13 = metadata !{[2 x i32]* (i32*, i32*, [2 x i32]*, [2 x i32]*, i32*)*<br>
 // CHECK:       @arrayType, metadata !"f{p(a(2:si))}(p(si),p(cv:si),p(a(2:si)),<br>
 // CHECK:       p(a(2:si)),p(si))"}<br>
-// CHECK: !13 = metadata !{[0 x i32]* @EA1, metadata !"a(*:cv:si)"}<br>
-// CHECK: !14 = metadata !{[2 x i32]* @EA2, metadata !"a(2:si)"}<br>
-// CHECK: !15 = metadata !{[0 x [2 x i32]]* @EA3, metadata !"a(*:a(2:si))"}<br>
-// CHECK: !16 = metadata !{[3 x [2 x i32]]* @EA4, metadata !"a(3:a(2:si))"}<br>
-// CHECK: !17 = metadata !{[2 x i32]* @GA1, metadata !"a(2:cv:si)"}<br>
-// CHECK: !18 = metadata !{void ([2 x i32]*)* @arrayTypeVariable1,<br>
+// CHECK: !14 = metadata !{[0 x i32]* @EA1, metadata !"a(*:cv:si)"}<br>
+// CHECK: !15 = metadata !{[2 x i32]* @EA2, metadata !"a(2:si)"}<br>
+// CHECK: !16 = metadata !{[0 x [2 x i32]]* @EA3, metadata !"a(*:a(2:si))"}<br>
+// CHECK: !17 = metadata !{[3 x [2 x i32]]* @EA4, metadata !"a(3:a(2:si))"}<br>
+// CHECK: !18 = metadata !{[2 x i32]* @GA1, metadata !"a(2:cv:si)"}<br>
+// CHECK: !19 = metadata !{void ([2 x i32]*)* @arrayTypeVariable1,<br>
 // CHECK:       metadata !"f{0}(p(a(2:si)))"}<br>
-// CHECK: !19 = metadata !{void (void ([2 x i32]*)*)* @arrayTypeVariable2,<br>
+// CHECK: !20 = metadata !{void (void ([2 x i32]*)*)* @arrayTypeVariable2,<br>
 // CHECK:       metadata !"f{0}(p(f{0}(p(a(2:si)))))"}<br>
-// CHECK: !20 = metadata !{[3 x [2 x i32]]* @GA2, metadata !"a(3:a(2:si))"}<br>
+// CHECK: !21 = metadata !{[3 x [2 x i32]]* @GA2, metadata !"a(3:a(2:si))"}<br>
+extern int GA2[3][2];<br>
 extern const volatile int EA1[];<br>
 extern int EA2[2];<br>
 extern int EA3[][2];<br>
 extern int EA4[3][2];<br>
 const volatile int GA1[2];<br>
-int GA2[3][2];<br>
 extern void arrayTypeVariable1(int[*][2]);<br>
 extern void arrayTypeVariable2( void(*fp)(int[*][2]) );<br>
 extern void arrayTypeVariable3(int[3][*]);                // not supported<br>
@@ -100,16 +100,16 @@ RetType* arrayType(int A1[], int const v<br>
<br>
<br>
 // test StructureType<br>
-// CHECK: !21 = metadata !{void (%struct.S1*)* @structureType1, metadata<br>
+// CHECK: !22 = metadata !{void (%struct.S1*)* @structureType1, metadata<br>
 // CHECK:       !"f{0}(s(S1){m(ps2){p(s(S2){m(ps3){p(s(S3){m(s1){s(S1){}}})}})}})"}<br>
-// CHECK: !22 = metadata !{void (%struct.S2*)* @structureType2, metadata<br>
+// CHECK: !23 = metadata !{void (%struct.S2*)* @structureType2, metadata<br>
 // CHECK:       !"f{0}(s(S2){m(ps3){p(s(S3){m(s1){s(S1){m(ps2){p(s(S2){})}}}})}})"}<br>
-// CHECK: !23 = metadata !{void (%struct.S3*)* @structureType3, metadata<br>
+// CHECK: !24 = metadata !{void (%struct.S3*)* @structureType3, metadata<br>
 // CHECK:       !"f{0}(s(S3){m(s1){s(S1){m(ps2){p(s(S2){m(ps3){p(s(S3){})}})}}}})"}<br>
-// CHECK: !24 = metadata !{void (%struct.S4*)* @structureType4, metadata<br>
+// CHECK: !25 = metadata !{void (%struct.S4*)* @structureType4, metadata<br>
 // CHECK:       !"f{0}(s(S4){m(s1){s(S1){m(ps2){p(s(S2){m(ps3){p(s(S3){m(s1){s(S1){}}})}})}}}})"}<br>
-// CHECK: !25 = metadata !{%struct.anon* @StructAnon, metadata !"s(){m(A){si}}"}<br>
-// CHECK: !26 = metadata !{i32 (%struct.SB*)* @structureTypeB, metadata<br>
+// CHECK: !26 = metadata !{%struct.anon* @StructAnon, metadata !"s(){m(A){si}}"}<br>
+// CHECK: !27 = metadata !{i32 (%struct.SB*)* @structureTypeB, metadata<br>
 // CHECK:       !"f{si}(s(SB){m(){b(4:si)},m(){b(2:si)},m(N4){b(4:si)},<br>
 // CHECK:       m(N2){b(2:si)},m(){b(4:ui)},m(){b(4:si)},m(){b(4:c:si)},<br>
 // CHECK:       m(){b(4:c:si)},m(){b(4:cv:si)}})"}<br>
@@ -130,16 +130,16 @@ int structureTypeB(struct SB sb){return<br>
<br>
<br>
 // test UnionType<br>
-// CHECK: !27 = metadata !{void (%union.U1*)* @unionType1, metadata<br>
+// CHECK: !28 = metadata !{void (%union.U1*)* @unionType1, metadata<br>
 // CHECK:       !"f{0}(u(U1){m(pu2){p(u(U2){m(pu3){p(u(U3){m(u1){u(U1){}}})}})}})"}<br>
-// CHECK: !28 = metadata !{void (%union.U2*)* @unionType2, metadata<br>
+// CHECK: !29 = metadata !{void (%union.U2*)* @unionType2, metadata<br>
 // CHECK:       !"f{0}(u(U2){m(pu3){p(u(U3){m(u1){u(U1){m(pu2){p(u(U2){})}}}})}})"}<br>
-// CHECK: !29 = metadata !{void (%union.U3*)* @unionType3, metadata<br>
+// CHECK: !30 = metadata !{void (%union.U3*)* @unionType3, metadata<br>
 // CHECK:       !"f{0}(u(U3){m(u1){u(U1){m(pu2){p(u(U2){m(pu3){p(u(U3){})}})}}}})"}<br>
-// CHECK: !30 = metadata !{void (%union.U4*)* @unionType4, metadata<br>
+// CHECK: !31 = metadata !{void (%union.U4*)* @unionType4, metadata<br>
 // CHECK:       !"f{0}(u(U4){m(u1){u(U1){m(pu2){p(u(U2){m(pu3){p(u(U3){m(u1){u(U1){}}})}})}}}})"}<br>
-// CHECK: !31 = metadata !{%union.anon* @UnionAnon, metadata !"u(){m(A){si}}"}<br>
-// CHECK: !32 = metadata !{i32 (%union.UB*)* @unionTypeB, metadata<br>
+// CHECK: !32 = metadata !{%union.anon* @UnionAnon, metadata !"u(){m(A){si}}"}<br>
+// CHECK: !33 = metadata !{i32 (%union.UB*)* @unionTypeB, metadata<br>
 // CHECK:       !"f{si}(u(UB){m(N2){b(2:si)},m(N4){b(4:si)},m(){b(2:si)},<br>
 // CHECK:       m(){b(4:c:si)},m(){b(4:c:si)},m(){b(4:cv:si)},m(){b(4:si)},<br>
 // CHECK:       m(){b(4:si)},m(){b(4:ui)}})"}<br>
@@ -160,9 +160,20 @@ int unionTypeB(union UB ub) {return Unio<br>
<br>
<br>
 // test EnumType<br>
-// CHECK: !33 = metadata !{i32* @EnumAnon, metadata !"e(){m(EA){3}}"}<br>
-// CHECK: !34 = metadata !{i32 (i32)* @enumType, metadata<br>
+// CHECK: !34 = metadata !{i32* @EnumAnon, metadata !"e(){m(EA){3}}"}<br>
+// CHECK: !35 = metadata !{i32 (i32)* @enumType, metadata<br>
 // CHECK:       !"f{si}(e(E){m(A){7},m(B){6},m(C){5},m(D){0}})"}<br>
 enum E {D, C=5, B, A};<br>
 enum {EA=3} EnumAnon = EA;<br>
 int enumType(enum E e) {return EnumAnon;}<br>
+<br>
+<br>
+// CHECK: !36 = metadata !{i32 ()* @testReDecl, metadata !"f{si}()"}<br>
+// CHECK: !37 = metadata !{[10 x i32]* @After, metadata !"a(10:si)"}<br>
+// CHECK: !38 = metadata !{[10 x i32]* @Before, metadata !"a(10:si)"}<br>
+extern int After[];<br>
+extern int Before[10];<br>
+int testReDecl() {return After[0] + Before[0];}<br>
+int After[10];<br>
+int Before[];<br>
+<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote>
</div>
<br>
</div>
</div>
</div>
</div>
</div>
</body>
</html>