Index: include/clang/AST/ASTConsumer.h =================================================================== --- include/clang/AST/ASTConsumer.h +++ include/clang/AST/ASTConsumer.h @@ -25,6 +25,7 @@ class ASTDeserializationListener; // layering violation because void* is ugly class SemaConsumer; // layering violation required for safe SemaConsumer class TagDecl; + class EnumConstantDecl; class VarDecl; class FunctionDecl; class ImportDecl; @@ -75,6 +76,8 @@ /// be complete. virtual void HandleTagDeclRequiredDefinition(const TagDecl *D) {} + virtual void HandleEnumDeclReferenced(const EnumConstantDecl *ED) {} + /// \brief Invoked when a function is implicitly instantiated. /// Note that at this point point it does not have a body, its body is /// instantiated at the end of the translation unit and passed to Index: lib/CodeGen/CGDebugInfo.h =================================================================== --- lib/CodeGen/CGDebugInfo.h +++ lib/CodeGen/CGDebugInfo.h @@ -299,6 +299,7 @@ void completeType(const EnumDecl *ED); void completeType(const RecordDecl *RD); void completeRequiredType(const RecordDecl *RD); + void completeRequiredType(const EnumConstantDecl *ED); void completeClassData(const RecordDecl *RD); void completeTemplateDefinition(const ClassTemplateSpecializationDecl &SD); Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -3212,22 +3212,27 @@ Var->hasInternalLinkage(), Var); } +void CGDebugInfo::completeRequiredType(const EnumConstantDecl *ECD) { + const EnumDecl *ED = cast(ECD->getDeclContext()); + const EnumType *Ty = cast(ED->getTypeForDecl()); + if (Ty->isDependentType()) + return; + if (!ED->getDefinition()) + return; + llvm::DIFile Unit = getOrCreateFile(ED->getLocation()); + getOrCreateType(QualType(Ty, 0), Unit); +} + /// EmitGlobalVariable - Emit global variable's debug info. void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, llvm::Constant *Init) { assert(DebugKind >= CodeGenOptions::LimitedDebugInfo); + assert(!isa(VD)); // Create the descriptor for the variable. llvm::DIFile Unit = getOrCreateFile(VD->getLocation()); StringRef Name = VD->getName(); llvm::DIType Ty = getOrCreateType(VD->getType(), Unit); - if (const EnumConstantDecl *ECD = dyn_cast(VD)) { - const EnumDecl *ED = cast(ECD->getDeclContext()); - assert(isa(ED->getTypeForDecl()) && "Enum without EnumType?"); - Ty = getOrCreateType(QualType(ED->getTypeForDecl(), 0), Unit); - } - // Do not use DIGlobalVariable for enums. - if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type) - return; + assert(Ty.getTag() != llvm::dwarf::DW_TAG_enumeration_type); // Do not emit separate definitions for function local const/statics. if (isa(VD->getDeclContext())) return; Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -973,14 +973,8 @@ // Make sure we emit a debug reference to the global variable. // This should probably fire even for - if (isa(value)) { - if (!getContext().DeclMustBeEmitted(cast(value))) - EmitDeclRefExprDbgValue(refExpr, C); - } else { - assert(isa(value)); + if (isa(value) && !getContext().DeclMustBeEmitted(cast(value))) EmitDeclRefExprDbgValue(refExpr, C); - } - // If we emitted a reference constant, we need to dereference that. if (resultIsReference) return ConstantEmission::forReference(C); Index: lib/CodeGen/CodeGenAction.cpp =================================================================== --- lib/CodeGen/CodeGenAction.cpp +++ lib/CodeGen/CodeGenAction.cpp @@ -173,6 +173,10 @@ Gen->HandleTagDeclDefinition(D); } + void HandleEnumDeclReferenced(const EnumConstantDecl *ED) override { + Gen->HandleEnumDeclReferenced(ED); + } + void HandleTagDeclRequiredDefinition(const TagDecl *D) override { Gen->HandleTagDeclRequiredDefinition(D); } Index: lib/CodeGen/ModuleBuilder.cpp =================================================================== --- lib/CodeGen/ModuleBuilder.cpp +++ lib/CodeGen/ModuleBuilder.cpp @@ -103,6 +103,14 @@ } } + void HandleEnumDeclReferenced(const EnumConstantDecl *ED) override { + if (Diags.hasErrorOccurred()) + return; + + if (CodeGen::CGDebugInfo *DI = Builder->getModuleDebugInfo()) + DI->completeRequiredType(ED); + } + void HandleTagDeclRequiredDefinition(const TagDecl *D) override { if (Diags.hasErrorOccurred()) return; Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -12381,6 +12381,10 @@ return; } } + + if (const EnumConstantDecl *ED = dyn_cast(D)) + Consumer.HandleEnumDeclReferenced(ED); + D->setReferenced(); } Index: test/CodeGenCXX/debug-info-enum.cpp =================================================================== --- test/CodeGenCXX/debug-info-enum.cpp +++ test/CodeGenCXX/debug-info-enum.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -g %s -o - | FileCheck %s // CHECK: [[ENUMS:![0-9]*]], {{[^,]*}}, {{[^,]*}}, {{[^,]*}}, {{[^,]*}}, {{[^,]*}}} ; [ DW_TAG_compile_unit ] -// CHECK: [[ENUMS]] = metadata !{metadata [[E1:![0-9]*]], metadata [[E2:![0-9]*]], metadata [[E3:![0-9]*]]} +// CHECK: [[ENUMS]] = metadata !{metadata [[E1:![0-9]*]], metadata [[E2:![0-9]*]], metadata [[E3:![0-9]*]], metadata [[E5:![0-9]*]]} namespace test1 { // CHECK: [[E1]] = metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST1:![0-9]*]], {{.*}}, metadata [[TEST1_ENUMS:![0-9]*]], {{[^,]*}}, null, null, metadata !"_ZTSN5test11eE"} ; [ DW_TAG_enumeration_type ] [e] @@ -43,3 +43,10 @@ enum e { E = T::v }; }; } + +namespace test5 { +// CHECK: [[E5]] = metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST5:![0-9]*]], {{.*}}, metadata [[TEST1_ENUMS]], {{[^,]*}}, null, null, metadata !"_ZTSN5test51eE"} ; [ DW_TAG_enumeration_type ] [e] +// CHECK: [[TEST5]] = {{.*}} ; [ DW_TAG_namespace ] [test5] +enum e { E }; +int i = E; +}