> On Sep 11, 2015, at 8:27 AM, David Blaikie <dblai...@gmail.com> wrote:
> 
> 
> 
> On Fri, Sep 11, 2015 at 8:18 AM, Adrian Prantl <apra...@apple.com 
> <mailto:apra...@apple.com>> wrote:
> 
>> On Sep 10, 2015, at 6:56 PM, David Blaikie <dblai...@gmail.com 
>> <mailto:dblai...@gmail.com>> wrote:
>> 
>> 
>> 
>> On Thu, Sep 10, 2015 at 6:40 PM, David Blaikie <dblai...@gmail.com 
>> <mailto:dblai...@gmail.com>> wrote:
>> 
>> 
>> On Thu, Sep 10, 2015 at 6:03 PM, Adrian Prantl via cfe-commits 
>> <cfe-commits@lists.llvm.org <mailto:cfe-commits@lists.llvm.org>> wrote:
>> Author: adrian
>> Date: Thu Sep 10 20:03:26 2015
>> New Revision: 247369
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=247369&view=rev 
>> <http://llvm.org/viewvc/llvm-project?rev=247369&view=rev>
>> Log:
>> Module Debugging: Emit forward declarations for types that are defined in
>> clang modules, if -dwarf-ext-refs (DebugTypesExtRefs) is specified.
>> 
>> This change seems to have a lot more code in it than I was expecting... 
>> 
>> I was rather expecting something a lot like the flimit-debug-info support. 
>> Specifically, I would've expected one more conditional added to 
>> CGDebugInfo::shouldOmitDefinition.
>> 
>> Why the extra complexity?
>> 
>> I guess part of it is to be able to omit definitions of things other than 
>> record types - is there much value in that? (especially typedefs - it seems 
>> like a typedef is too small to benefit from a declaration (even if we could 
>> emit one)?)
> 
> The typedef itself is not interesting, but it can be used to anchor template 
> instantiations like std::string. The contract between the debug info in the 
> module and the debug info referencing the module is that all explicit 
> template specializations 
> 
> This I get ^ (though does that case need any special handling, or will the 
> isFromASTFile return true for the location of the explicit specialization 
> declaration/definition?)
>  
> and template instantiations referenced used in a typedef can be expected to 
> exist in the module.
> 
> This I do not get & would imagine it could cause substantial size increase... 
> 
> Might be worth splitting out that change to look at it more carefully. I'd 
> love to see numbers here.
>> Also, we could possibly solve both the problem of "don't emit definitions 
>> for module things when compiling the main source file" and "don't emit 
>> definitions for module things defined in other modules" with the same tool. 
>> If there's a way to say "is this in a foreign AST file" then testing for 
>> that in CGDebugInfo::shouldOmitDefinition would solve both problems, I think 
>> (conditionalized on the appropriate flags, either dwarf-ext-refs or "I'm 
>> building a module here”).
> 
> I believe that this is a good point. Really, getExtRefOrNull is a separate 
> function mostly for evolutionary reasons — it used to do different things 
> like mangling names of ObjC types etc. I will see if I can merge the existing 
> functionality into shouldOmitDefinition().
> 
> From a review perspective it might be easier to revert this & commit a new 
> patch - I haven't reviewed all these changes in detail because they just 
> seemed more complex than necessary, but if you're going to evolve it from 
> here I'll need to dig into the current implementation/be more careful about 
> checking that future changes remove the complexity along with whatever they 
> add.
> 

I just did this in r24743[12].

-- adrian

> - Dave
>  
> 
> -- adrian
> 
>>  
>>  
>> 
>> Added:
>>     cfe/trunk/test/Modules/ExtDebugInfo.cpp
>>     cfe/trunk/test/Modules/ExtDebugInfo.m
>> Modified:
>>     cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
>>     cfe/trunk/lib/CodeGen/CGDebugInfo.h
>> 
>> Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=247369&r1=247368&r2=247369&view=diff
>>  
>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=247369&r1=247368&r2=247369&view=diff>
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Thu Sep 10 20:03:26 2015
>> @@ -148,7 +148,9 @@ void CGDebugInfo::setLocation(SourceLoca
>>  }
>> 
>>  llvm::DIScope *CGDebugInfo::getDeclContextDescriptor(const Decl *D) {
>> -  return getContextDescriptor(cast<Decl>(D->getDeclContext()), TheCU);
>> +  llvm::DIScope *Mod = getParentModuleOrNull(D);
>> +  return getContextDescriptor(cast<Decl>(D->getDeclContext()),
>> +                              Mod ? Mod : TheCU);
>>  }
>> 
>>  llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context,
>> @@ -1448,6 +1450,9 @@ void CGDebugInfo::completeRequiredType(c
>>      if (CXXDecl->isDynamicClass())
>>        return;
>> 
>> +  if (DebugTypeExtRefs && RD->isFromASTFile())
>> +    return;
>> +
>>    QualType Ty = CGM.getContext().getRecordType(RD);
>>    llvm::DIType *T = getTypeOrNull(Ty);
>>    if (T && T->isForwardDecl())
>> @@ -1669,9 +1674,9 @@ CGDebugInfo::getOrCreateModuleRef(Extern
>>        TheCU->getSourceLanguage(), internString(Mod.ModuleName),
>>        internString(Mod.Path), TheCU->getProducer(), true, StringRef(), 0,
>>        internString(Mod.ASTFile), llvm::DIBuilder::FullDebug, Mod.Signature);
>> -  llvm::DIModule *M =
>> -      DIB.createModule(CU, Mod.ModuleName, ConfigMacros, 
>> internString(Mod.Path),
>> -                       internString(CGM.getHeaderSearchOpts().Sysroot));
>> +  llvm::DIModule *M = DIB.createModule(
>> +      CU, Mod.ModuleName, ConfigMacros, internString(Mod.Path),
>> +      internString(CGM.getHeaderSearchOpts().Sysroot));
>>    DIB.finalize();
>>    ModRef.reset(M);
>>    return M;
>> @@ -2081,9 +2086,16 @@ llvm::DIType *CGDebugInfo::getOrCreateTy
>>    if (auto *T = getTypeOrNull(Ty))
>>      return T;
>> 
>> +  llvm::DIType *Res = nullptr;
>> +  if (DebugTypeExtRefs)
>> +    // Make a forward declaration of an external type.
>> +    Res = getTypeExtRefOrNull(Ty, Unit);
>> +
>>    // Otherwise create the type.
>> -  llvm::DIType *Res = CreateTypeNode(Ty, Unit);
>> -  void *TyPtr = Ty.getAsOpaquePtr();
>> +  if (!Res)
>> +    Res = CreateTypeNode(Ty, Unit);
>> +
>> +  void* TyPtr = Ty.getAsOpaquePtr();
>> 
>>    // And update the type cache.
>>    TypeCache[TyPtr].reset(Res);
>> @@ -2115,6 +2127,123 @@ ObjCInterfaceDecl *CGDebugInfo::getObjCI
>>    }
>>  }
>> 
>> +llvm::DIModule *CGDebugInfo::getParentModuleOrNull(const Decl *D) {
>> +  if (!DebugTypeExtRefs || !D || !D->isFromASTFile())
>> +    return nullptr;
>> +
>> +  llvm::DIModule *ModuleRef = nullptr;
>> +  auto *Reader = CGM.getContext().getExternalSource();
>> +  auto Idx = D->getOwningModuleID();
>> +  auto Info = Reader->getSourceDescriptor(Idx);
>> +  if (Info)
>> +    ModuleRef = getOrCreateModuleRef(*Info);
>> +  return ModuleRef;
>> +}
>> +
>> +llvm::DIType *CGDebugInfo::getTypeExtRefOrNull(QualType Ty, llvm::DIFile *F,
>> +                                               bool Anchored) {
>> +  assert(DebugTypeExtRefs && "module debugging only");
>> +  Decl *TyDecl = nullptr;
>> +  StringRef Name;
>> +  SmallString<256> UID;
>> +  unsigned Tag = 0;
>> +
>> +  // Handle all types that have a declaration.
>> +  switch (Ty->getTypeClass()) {
>> +  case Type::Typedef: {
>> +    TyDecl = cast<TypedefType>(Ty)->getDecl();
>> +    if (!TyDecl->isFromASTFile())
>> +      return nullptr;
>> +
>> +    // A typedef will anchor a type in the module.
>> +    if (auto *TD = dyn_cast<TypedefDecl>(TyDecl)) {
>> +      // This is a working around the fact that LLVM does not allow
>> +      // typedefs to be forward declarations.
>> +      QualType Ty = TD->getUnderlyingType();
>> +      Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
>> +      if (auto *AnchoredTy = getTypeExtRefOrNull(Ty, F, /*Anchored=*/true)) 
>> {
>> +        TypeCache[Ty.getAsOpaquePtr()].reset(AnchoredTy);
>> +        SourceLocation Loc = TD->getLocation();
>> +        return DBuilder.createTypedef(AnchoredTy, TD->getName(),
>> +                                      getOrCreateFile(Loc), 
>> getLineNumber(Loc),
>> +                                      getDeclContextDescriptor(TD));
>> +      }
>> +    }
>> +    break;
>> +  }
>> +
>> +  case Type::Record: {
>> +    TyDecl = cast<RecordType>(Ty)->getDecl();
>> +    if (!TyDecl->isFromASTFile())
>> +      return nullptr;
>> +
>> +    if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(TyDecl))
>> +      if (!CTSD->isExplicitInstantiationOrSpecialization() && !Anchored)
>> +        // We may not assume that this type made it into the module.
>> +        return nullptr;
>> +    // C++ classes and template instantiations.
>> +    if (auto *RD = dyn_cast<CXXRecordDecl>(TyDecl)) {
>> +      if (!RD->getDefinition())
>> +        return nullptr;
>> +      Tag = getTagForRecord(RD);
>> +      UID =
>> +          getUniqueTagTypeName(cast<TagType>(RD->getTypeForDecl()), CGM, 
>> TheCU);
>> +      Name = getClassName(RD);
>> +    } else if (auto *RD = dyn_cast<RecordDecl>(TyDecl)) {
>> +      // C-style structs.
>> +      if (!RD->getDefinition())
>> +        return nullptr;
>> +      Tag = getTagForRecord(RD);
>> +      Name = getClassName(RD);
>> +    }
>> +    break;
>> +  }
>> +
>> +  case Type::Enum: {
>> +    TyDecl = cast<EnumType>(Ty)->getDecl();
>> +    if (!TyDecl->isFromASTFile())
>> +      return nullptr;
>> +
>> +    if (auto *ED = dyn_cast<EnumDecl>(TyDecl)) {
>> +      if (!ED->getDefinition())
>> +        return nullptr;
>> +      Tag = llvm::dwarf::DW_TAG_enumeration_type;
>> +      if ((TheCU->getSourceLanguage() == llvm::dwarf::DW_LANG_C_plus_plus) 
>> ||
>> +          (TheCU->getSourceLanguage() == 
>> llvm::dwarf::DW_LANG_ObjC_plus_plus)) {
>> +        UID = getUniqueTagTypeName(cast<TagType>(ED->getTypeForDecl()), CGM,
>> +                                   TheCU);
>> +        Name = ED->getName();
>> +      }
>> +    }
>> +    break;
>> +  }
>> +
>> +  case Type::ObjCInterface: {
>> +    TyDecl = cast<ObjCInterfaceType>(Ty)->getDecl();
>> +    if (!TyDecl->isFromASTFile())
>> +      return nullptr;
>> +
>> +    if (auto *ID = dyn_cast<ObjCInterfaceDecl>(TyDecl)) {
>> +      if (!ID->getDefinition())
>> +        return nullptr;
>> +      Tag = llvm::dwarf::DW_TAG_structure_type;
>> +      Name = ID->getName();
>> +    }
>> +    break;
>> +  }
>> +
>> +  default:
>> +    return nullptr;
>> +  }
>> +
>> +  if (Tag && !Name.empty()) {
>> +    assert(TyDecl);
>> +    auto *Ctx = getDeclContextDescriptor(TyDecl);
>> +    return DBuilder.createForwardDecl(Tag, Name, Ctx, F, 0, 0, 0, 0, UID);
>> +  } else
>> +    return nullptr;
>> +}
>> +
>>  llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
>>    // Handle qualifiers, which recursively handles what they refer to.
>>    if (Ty.hasLocalQualifiers())
>> @@ -2325,8 +2454,10 @@ void CGDebugInfo::collectFunctionDeclPro
>>          dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
>>        FDContext = getOrCreateNameSpace(NSDecl);
>>      else if (const RecordDecl *RDecl =
>> -             dyn_cast_or_null<RecordDecl>(FD->getDeclContext()))
>> -      FDContext = getContextDescriptor(RDecl, TheCU);
>> +             dyn_cast_or_null<RecordDecl>(FD->getDeclContext())) {
>> +      llvm::DIScope *Mod = getParentModuleOrNull(RDecl);
>> +      FDContext = getContextDescriptor(RDecl, Mod ? Mod : TheCU);
>> +    }
>>      // Collect template parameters.
>>      TParamsArray = CollectFunctionTemplateParams(FD, Unit);
>>    }
>> @@ -2374,7 +2505,9 @@ void CGDebugInfo::collectVarDeclProps(co
>>    // outside the class by putting it in the global scope.
>>    if (DC->isRecord())
>>      DC = CGM.getContext().getTranslationUnitDecl();
>> -  VDContext = getContextDescriptor(cast<Decl>(DC), TheCU);
>> +
>> + llvm::DIScope *Mod = getParentModuleOrNull(VD);
>> + VDContext = getContextDescriptor(cast<Decl>(DC), Mod ? Mod : TheCU);
>>  }
>> 
>>  llvm::DISubprogram *
>> @@ -3299,7 +3432,8 @@ void CGDebugInfo::EmitGlobalVariable(con
>>  llvm::DIScope *CGDebugInfo::getCurrentContextDescriptor(const Decl *D) {
>>    if (!LexicalBlockStack.empty())
>>      return LexicalBlockStack.back();
>> -  return getContextDescriptor(D, TheCU);
>> +  llvm::DIScope *Mod = getParentModuleOrNull(D);
>> +  return getContextDescriptor(D, Mod ? Mod : TheCU);
>>  }
>> 
>>  void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) {
>> 
>> Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.h
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=247369&r1=247368&r2=247369&view=diff
>>  
>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=247369&r1=247368&r2=247369&view=diff>
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CGDebugInfo.h (original)
>> +++ cfe/trunk/lib/CodeGen/CGDebugInfo.h Thu Sep 10 20:03:26 2015
>> @@ -397,6 +397,15 @@ private:
>>    llvm::DIModule *
>>    getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod);
>> 
>> +  /// DebugTypeExtRefs: If \p D originated in a clang module, return it.
>> +  llvm::DIModule *getParentModuleOrNull(const Decl *D);
>> +
>> +  /// Return a forward declaration of an external type, if this type
>> +  /// came from a clang module.  If \p Anchored is true, template
>> +  /// types will be assumed to have been instantiated in the module.
>> +  llvm::DIType *getTypeExtRefOrNull(QualType Ty, llvm::DIFile *F,
>> +                                    bool Anchored = false);
>> +
>>    /// Get the type from the cache or create a new partial type if
>>    /// necessary.
>>    llvm::DICompositeType *getOrCreateLimitedType(const RecordType *Ty,
>> 
>> Added: cfe/trunk/test/Modules/ExtDebugInfo.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ExtDebugInfo.cpp?rev=247369&view=auto
>>  
>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ExtDebugInfo.cpp?rev=247369&view=auto>
>> ==============================================================================
>> --- cfe/trunk/test/Modules/ExtDebugInfo.cpp (added)
>> +++ cfe/trunk/test/Modules/ExtDebugInfo.cpp Thu Sep 10 20:03:26 2015
>> @@ -0,0 +1,74 @@
>> +// RUN: rm -rf %t
>> +// Test that only forward declarations are emitted for types dfined in 
>> modules.
>> +
>> +// Modules:
>> +// RUN: %clang_cc1 -x objective-c++ -std=c++11 -g -dwarf-ext-refs -fmodules 
>> \
>> +// RUN:     -fmodule-format=obj -fimplicit-module-maps -DMODULES \
>> +// RUN:     -fmodules-cache-path=%t %s -I %S/Inputs -I %t -emit-llvm -o 
>> %t-mod.ll
>> +// RUN: cat %t-mod.ll |  FileCheck %s
>> +
>> +// PCH:
>> +// RUN: %clang_cc1 -x c++ -std=c++11 -fmodule-format=obj -emit-pch 
>> -I%S/Inputs \
>> +// RUN:     -o %t.pch %S/Inputs/DebugCXX.h
>> +// RUN: %clang_cc1 -std=c++11 -g -dwarf-ext-refs -fmodule-format=obj \
>> +// RUN:     -include-pch %t.pch %s -emit-llvm -o %t-pch.ll %s
>> +// RUN: cat %t-pch.ll |  FileCheck %s
>> +
>> +#ifdef MODULES
>> +@import DebugCXX;
>> +#endif
>> +
>> +using DebugCXX::Struct;
>> +
>> +Struct s;
>> +DebugCXX::Enum e;
>> +DebugCXX::Template<long> implicitTemplate;
>> +DebugCXX::Template<int> explicitTemplate;
>> +DebugCXX::FloatInstatiation typedefTemplate;
>> +int Struct::static_member = -1;
>> +enum {
>> +  e3 = -1
>> +} conflicting_uid = e3;
>> +auto anon_enum = DebugCXX::e2;
>> +char _anchor = anon_enum + conflicting_uid;
>> +
>> +// CHECK: ![[ANON_ENUM:[0-9]+]] = !DICompositeType(tag: 
>> DW_TAG_enumeration_type
>> +// CHECK-SAME:             scope: ![[MOD:[0-9]+]],
>> +// CHECK-SAME: {{.*}}line: 16, {{.*}}, elements: ![[EE:[0-9]+]])
>> +
>> +// CHECK: ![[NS:.*]] = !DINamespace(name: "DebugCXX", scope: 
>> ![[MOD:[0-9]+]],
>> +// CHECK: ![[MOD]] = !DIModule(scope: null, name: {{.*}}DebugCXX
>> +
>> +// CHECK: ![[EE]] = !{![[E2:[0-9]+]]}
>> +// CHECK: ![[E2]] = !DIEnumerator(name: "e2", value: 50)
>> +
>> +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Struct",
>> +// CHECK-SAME:             scope: ![[NS]],
>> +// CHECK-SAME:             flags: DIFlagFwdDecl,
>> +// CHECK-SAME:             identifier: "_ZTSN8DebugCXX6StructE")
>> +
>> +// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum",
>> +// CHECK-SAME:             scope: ![[NS]],
>> +// CHECK-SAME:             flags: DIFlagFwdDecl,
>> +// CHECK-SAME:             identifier:  "_ZTSN8DebugCXX4EnumE")
>> +
>> +// CHECK: !DICompositeType(tag: DW_TAG_class_type,
>> +
>> +// CHECK: !DICompositeType(tag: DW_TAG_class_type,
>> +// CHECK-SAME:             name: "Template<int, DebugCXX::traits<int> >",
>> +// CHECK-SAME:             scope: ![[NS]],
>> +// CHECK-SAME:             flags: DIFlagFwdDecl,
>> +// CHECK-SAME:             identifier: 
>> "_ZTSN8DebugCXX8TemplateIiNS_6traitsIiEEEE")
>> +
>> +// CHECK: !DICompositeType(tag: DW_TAG_class_type,
>> +// CHECK-SAME:             name: "Template<float, DebugCXX::traits<float> 
>> >",
>> +// CHECK-SAME:             scope: ![[NS]],
>> +// CHECK-SAME:             flags: DIFlagFwdDecl,
>> +// CHECK-SAME:             identifier: 
>> "_ZTSN8DebugCXX8TemplateIfNS_6traitsIfEEEE")
>> +
>> +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "static_member",
>> +// CHECK-SAME:           scope: !"_ZTSN8DebugCXX6StructE"
>> +
>> +// CHECK: !DIGlobalVariable(name: "anon_enum", {{.*}}, type: ![[ANON_ENUM]]
>> +
>> +// CHECK: !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !0, 
>> entity: !"_ZTSN8DebugCXX6StructE", line: 21)
>> 
>> Added: cfe/trunk/test/Modules/ExtDebugInfo.m
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ExtDebugInfo.m?rev=247369&view=auto
>>  
>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ExtDebugInfo.m?rev=247369&view=auto>
>> ==============================================================================
>> --- cfe/trunk/test/Modules/ExtDebugInfo.m (added)
>> +++ cfe/trunk/test/Modules/ExtDebugInfo.m Thu Sep 10 20:03:26 2015
>> @@ -0,0 +1,29 @@
>> +// RUN: rm -rf %t
>> +// Test that only forward declarations are emitted for types dfined in 
>> modules.
>> +
>> +// Modules:
>> +// RUN: %clang_cc1 -x objective-c -g -dwarf-ext-refs -fmodules \
>> +// RUN:     -fmodule-format=obj -fimplicit-module-maps -DMODULES \
>> +// RUN:     -fmodules-cache-path=%t %s -I %S/Inputs -I %t -emit-llvm -o 
>> %t-mod.ll
>> +// RUN: cat %t-mod.ll |  FileCheck %s
>> +
>> +// PCH:
>> +// RUN: %clang_cc1 -x objective-c -fmodule-format=obj -emit-pch -I%S/Inputs 
>> \
>> +// RUN:     -o %t.pch %S/Inputs/DebugObjC.h
>> +// RUN: %clang_cc1 -x objective-c -g -dwarf-ext-refs -fmodule-format=obj \
>> +// RUN:     -include-pch %t.pch %s -emit-llvm -o %t-pch.ll %s
>> +// RUN: cat %t-pch.ll |  FileCheck %s
>> +
>> +#ifdef MODULES
>> +@import DebugObjC;
>> +#endif
>> +
>> +int foo(ObjCClass *c) {
>> +  [c instanceMethodWithInt: 0];
>> +  return [c property];
>> +}
>> +
>> +// CHECK: !DICompositeType(tag: DW_TAG_structure_type,
>> +// CHECK-SAME:             scope: ![[MOD:[0-9]+]],
>> +// CHECK-SAME:             flags: DIFlagFwdDecl)
>> +// CHECK: ![[MOD]] = !DIModule(scope: null, name: {{.*}}DebugObjC
>> 
>> 
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits@lists.llvm.org <mailto:cfe-commits@lists.llvm.org>
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits 
>> <http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits>
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to