[Lldb-commits] [lldb] 60eb06b - [lldb][TypeSystemClang] Honor DW_AT_rvalue_reference when creating C++ FunctionPrototypes
Michael Buch via lldb-commits
lldb-commits at lists.llvm.org
Tue Sep 27 10:04:09 PDT 2022
Author: Michael Buch
Date: 2022-09-27T18:03:23+01:00
New Revision: 60eb06be6d23e3c5fd80113143784aac0d962965
URL: https://github.com/llvm/llvm-project/commit/60eb06be6d23e3c5fd80113143784aac0d962965
DIFF: https://github.com/llvm/llvm-project/commit/60eb06be6d23e3c5fd80113143784aac0d962965.diff
LOG: [lldb][TypeSystemClang] Honor DW_AT_rvalue_reference when creating C++ FunctionPrototypes
Currently funciton lookup in the expression evaluator
fails to disambiguate member functions the are overloaded
on lvalue/rvalue reference-qualifiers. This happens because
we unconditionally set a `FunctionPrototype`s
`ExtProtoInfo::RefQualifier` to `RQ_None`. We lose
the ref-qualifiers in the synthesized AST and `clang::Sema`
fails to pick a correct overload candidate.
DWARF emits information about a function's ref-qualifiers
in the form of a boolean `DW_AT_rvalue_reference` (for rvalues)
and `DW_AT_reference` (for lvalues).
This patch sets the `FunctionPrototype::ExtProtoInfo::RefQualifier`
based on the DWARF attributes above.
**Testing**
* Added API test
llvm/llvm-project issue #57866
Differential Revision: https://reviews.llvm.org/D134661
Added:
lldb/test/API/lang/cpp/function-ref-qualifiers/Makefile
lldb/test/API/lang/cpp/function-ref-qualifiers/TestCppFunctionQualifiers.py
lldb/test/API/lang/cpp/function-ref-qualifiers/main.cpp
Modified:
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
Removed:
################################################################################
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 9fe9b2e25a2f8..25f2a37cbab5d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -36,12 +36,12 @@
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
-#include "llvm/Demangle/Demangle.h"
-
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Type.h"
+#include "llvm/Demangle/Demangle.h"
#include <map>
#include <memory>
@@ -412,6 +412,12 @@ ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) {
case DW_AT_export_symbols:
exports_symbols = form_value.Boolean();
break;
+ case DW_AT_rvalue_reference:
+ ref_qual = clang::RQ_RValue;
+ break;
+ case DW_AT_reference:
+ ref_qual = clang::RQ_LValue;
+ break;
}
}
}
@@ -974,9 +980,10 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
// clang_type will get the function prototype clang type after this
// call
- CompilerType clang_type = m_ast.CreateFunctionType(
- return_clang_type, function_param_types.data(),
- function_param_types.size(), is_variadic, type_quals, calling_convention);
+ CompilerType clang_type =
+ m_ast.CreateFunctionType(return_clang_type, function_param_types.data(),
+ function_param_types.size(), is_variadic,
+ type_quals, calling_convention, attrs.ref_qual);
if (attrs.name) {
bool type_handled = false;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index 735665328fd50..a8640b4a56938 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -10,6 +10,7 @@
#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFASTPARSERCLANG_H
#include "clang/AST/CharUnits.h"
+#include "clang/AST/Type.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
@@ -303,6 +304,10 @@ struct ParsedDWARFTypeAttributes {
uint32_t bit_stride = 0;
uint32_t byte_stride = 0;
uint32_t encoding = 0;
+ clang::RefQualifierKind ref_qual =
+ clang::RQ_None; ///< Indicates ref-qualifier of
+ ///< C++ member function if present.
+ ///< Is RQ_None otherwise.
};
#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFASTPARSERCLANG_H
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 6164b978f2f24..7e0a19c6b8bf1 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -2168,11 +2168,10 @@ FunctionDecl *TypeSystemClang::CreateFunctionDeclaration(
return func_decl;
}
-CompilerType
-TypeSystemClang::CreateFunctionType(const CompilerType &result_type,
- const CompilerType *args, unsigned num_args,
- bool is_variadic, unsigned type_quals,
- clang::CallingConv cc) {
+CompilerType TypeSystemClang::CreateFunctionType(
+ const CompilerType &result_type, const CompilerType *args,
+ unsigned num_args, bool is_variadic, unsigned type_quals,
+ clang::CallingConv cc, clang::RefQualifierKind ref_qual) {
if (!result_type || !ClangUtil::IsClangType(result_type))
return CompilerType(); // invalid return type
@@ -2201,7 +2200,7 @@ TypeSystemClang::CreateFunctionType(const CompilerType &result_type,
proto_info.Variadic = is_variadic;
proto_info.ExceptionSpec = EST_None;
proto_info.TypeQuals = clang::Qualifiers::fromFastMask(type_quals);
- proto_info.RefQualifier = RQ_None;
+ proto_info.RefQualifier = ref_qual;
return GetType(getASTContext().getFunctionType(
ClangUtil::GetQualType(result_type), qual_type_args, proto_info));
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index 7f25a6df548fb..ff8e12e821d12 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -23,6 +23,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTFwd.h"
#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallVector.h"
@@ -398,10 +399,11 @@ class TypeSystemClang : public TypeSystem {
llvm::StringRef name, const CompilerType &function_Type,
clang::StorageClass storage, bool is_inline);
- CompilerType CreateFunctionType(const CompilerType &result_type,
- const CompilerType *args, unsigned num_args,
- bool is_variadic, unsigned type_quals,
- clang::CallingConv cc = clang::CC_C);
+ CompilerType
+ CreateFunctionType(const CompilerType &result_type, const CompilerType *args,
+ unsigned num_args, bool is_variadic, unsigned type_quals,
+ clang::CallingConv cc = clang::CC_C,
+ clang::RefQualifierKind ref_qual = clang::RQ_None);
clang::ParmVarDecl *
CreateParameterDeclaration(clang::DeclContext *decl_ctx,
diff --git a/lldb/test/API/lang/cpp/function-ref-qualifiers/Makefile b/lldb/test/API/lang/cpp/function-ref-qualifiers/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/lang/cpp/function-ref-qualifiers/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/lang/cpp/function-ref-qualifiers/TestCppFunctionQualifiers.py b/lldb/test/API/lang/cpp/function-ref-qualifiers/TestCppFunctionQualifiers.py
new file mode 100644
index 0000000000000..0016ede4937e2
--- /dev/null
+++ b/lldb/test/API/lang/cpp/function-ref-qualifiers/TestCppFunctionQualifiers.py
@@ -0,0 +1,39 @@
+"""
+Tests that C++ expression evaluation can
+disambiguate between rvalue and lvalue
+reference-qualified functions.
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestCase(TestBase):
+
+ def test(self):
+ self.build()
+ lldbutil.run_to_source_breakpoint(self, "Break here", lldb.SBFileSpec("main.cpp"))
+
+ # const lvalue
+ self.expect_expr("const_foo.func()", result_type="uint32_t", result_value="0")
+
+ # const rvalue
+ self.expect_expr("static_cast<Foo const&&>(Foo{}).func()",
+ result_type="int64_t", result_value="1")
+
+ # non-const lvalue
+ self.expect_expr("foo.func()", result_type="uint32_t", result_value="2")
+
+ # non-const rvalue
+ self.expect_expr("Foo{}.func()", result_type="int64_t", result_value="3")
+
+ self.filecheck("target modules dump ast", __file__)
+ # CHECK: |-CXXMethodDecl {{.*}} func 'uint32_t () const &'
+ # CHECK-NEXT: | `-AsmLabelAttr {{.*}}
+ # CHECK-NEXT: |-CXXMethodDecl {{.*}} func 'int64_t () const &&'
+ # CHECK-NEXT: | `-AsmLabelAttr {{.*}}
+ # CHECK-NEXT: |-CXXMethodDecl {{.*}} func 'uint32_t () &'
+ # CHECK-NEXT: | `-AsmLabelAttr {{.*}}
+ # CHECK-NEXT: `-CXXMethodDecl {{.*}} func 'int64_t () &&'
+ # CHECK-NEXT: `-AsmLabelAttr {{.*}}
diff --git a/lldb/test/API/lang/cpp/function-ref-qualifiers/main.cpp b/lldb/test/API/lang/cpp/function-ref-qualifiers/main.cpp
new file mode 100644
index 0000000000000..70f3a63eb9e64
--- /dev/null
+++ b/lldb/test/API/lang/cpp/function-ref-qualifiers/main.cpp
@@ -0,0 +1,19 @@
+#include <cstdint>
+#include <cstdio>
+
+struct Foo {
+ uint32_t func() const & { return 0; }
+ int64_t func() const && { return 1; }
+ uint32_t func() & { return 2; }
+ int64_t func() && { return 3; }
+};
+
+int main() {
+ Foo foo;
+ const Foo const_foo;
+ auto res = foo.func() + const_foo.func() + Foo{}.func() +
+ static_cast<Foo const &&>(Foo{}).func();
+
+ std::puts("Break here");
+ return res;
+}
More information about the lldb-commits
mailing list