From: David Blaikie Date: Tue, 11 Nov 2014 20:44:45 +0000 (+0000) Subject: PR16091 continued: Debug Info for member functions with undeduced return types. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=42edade9d91bc568e90b6bc3fb7a2fb9dd25c680;p=platform%2Fupstream%2Fllvm.git PR16091 continued: Debug Info for member functions with undeduced return types. So DWARF5 specs out auto deduced return types as DW_TAG_unspecified_type with DW_AT_name "auto", and GCC implements this somewhat, but it presents a few problems to do this with Clang. GCC's implementation only applies to member functions where the auto return type isn't deduced immediately (ie: member functions of templates or member functions defined out of line). In the common case of an inline deduced return type function, GCC emits the DW_AT_type as the deduced return type. Currently GDB doesn't seem to behave too well with this debug info - it treats the return type as 'void', even though the definition of the function has the correctly deduced return type (I guess it sees the return type the declaration has, doesn't understand it, and assumes void). This means the function's ABI might be broken (non-trivial return types, etc), etc. Clang, on the other hand doesn't track this particular case of a deducable return type that is deduced immediately versus one that is deduced 'later'. So if we implement the DWARF5 representation, all deducible return type functions would get adverse GDB behavior (including deduced return type lambda functions, inline deduced return type functions, etc). Also, we can't just do this for auto types that are not deduced - because Clang marks even the declaration's return type as deduced (& provides the underlying type) once a definition is seen that allows the deduction. So we have to ignore even deduced types - but we can't do that for auto variables (because this representation only applies to function declarations - variables and function definitions need the real type so the function can be called, etc) so we'd need to add an extra flag to the type unwrapping/creation code to indicate when we want to see through deduced types and when we don't. It's also not as simple as just checking at the top level when building a function type (for one thing, we reuse the function type building for building function pointer types which might also have 'auto' in them - but be the type of a variable instead) because the auto might be arbitrarily deeply nested ("auto &", "auto (*)()", etc...) So, with all that said, let's do the simple thing that works in existing debuggers for now and treat these functions the same way we do function templates and implicit special members: omit them from the member list, since they can't be correctly called anyway (without knowing the return type the ABI isn't know and a function call could put the arguments in the wrong place) so they're not much use to the user. At some point in the future, when GDB understands the DWARF5 representation better it might be worth plumbing through the extra type builder handling to avoid looking through AutoType for some callers, etc... llvm-svn: 221704 --- diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index e655f05..f2a5d27 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1175,6 +1175,10 @@ void CGDebugInfo::CollectCXXMemberFunctions( // referenced) if (!Method || Method->isImplicit()) continue; + + if (Method->getType()->getAs()->getContainedAutoType()) + continue; + // Reuse the existing member function declaration if it exists. // It may be associated with the declaration of the type & should be // reused as we're building the definition. @@ -2013,8 +2017,7 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { break; case Type::Auto: QualType DT = cast(T)->getDeducedType(); - if (DT.isNull()) - return T; + assert(!DT.isNull() && "Undeduced types shouldn't reach here."); T = DT; break; } @@ -2106,8 +2109,6 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) { if (Ty.hasLocalQualifiers()) return CreateQualifiedType(Ty, Unit); - const char *Diag = nullptr; - // Work out details of type. switch (Ty->getTypeClass()) { #define TYPE(Class, Base) @@ -2167,6 +2168,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) { case Type::TemplateSpecialization: return CreateType(cast(Ty), Unit); + case Type::Auto: case Type::Attributed: case Type::Elaborated: case Type::Paren: @@ -2176,18 +2178,10 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) { case Type::Decltype: case Type::UnaryTransform: case Type::PackExpansion: - llvm_unreachable("type should have been unwrapped!"); - case Type::Auto: - Diag = "auto"; break; } - assert(Diag && "Fall through without a diagnostic?"); - unsigned DiagID = CGM.getDiags().getCustomDiagID( - DiagnosticsEngine::Error, - "debug information for %0 is not yet supported"); - CGM.getDiags().Report(DiagID) << Diag; - return llvm::DIType(); + llvm_unreachable("type should have been unwrapped!"); } /// getOrCreateLimitedType - Get the type from the cache or create a new diff --git a/clang/test/CodeGenCXX/debug-info-cxx1y.cpp b/clang/test/CodeGenCXX/debug-info-cxx1y.cpp index 3cb7e45..c1879c9 100644 --- a/clang/test/CodeGenCXX/debug-info-cxx1y.cpp +++ b/clang/test/CodeGenCXX/debug-info-cxx1y.cpp @@ -1,7 +1,20 @@ -// RUN: not %clang_cc1 -emit-llvm-only -std=c++1y -g %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm-only -std=c++14 -emit-llvm -g %s -o - | FileCheck %s + +// CHECK: [[EMPTY:![0-9]*]] = metadata !{} +// CHECK: \00foo\00{{.*}}, metadata [[EMPTY]], {{.*}}} ; [ DW_TAG_structure_type ] +// FIXME: The context of this definition should be the CU/file scope, not the class. +// CHECK: metadata !"_ZTS3foo", metadata [[SUBROUTINE_TYPE:![0-9]*]], {{.*}}, metadata [[FUNC_DECL:![0-9]*]], metadata {{![0-9]*}}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func] +// CHECK: [[SUBROUTINE_TYPE]] = {{.*}}, metadata [[TYPE_LIST:![0-9]*]], +// CHECK: [[TYPE_LIST]] = metadata !{metadata [[INT:![0-9]*]]} +// CHECK: [[INT]] = {{.*}} ; [ DW_TAG_base_type ] [int] +// CHECK: [[FUNC_DECL]] = {{.*}}, metadata !"_ZTS3foo", metadata [[SUBROUTINE_TYPE]], {{.*}}} ; [ DW_TAG_subprogram ] {{.*}} [func] struct foo { - auto func(); // CHECK: error: debug information for auto is not yet supported + static auto func(); }; foo f; + +auto foo::func() { + return 1; +}