Skip to content

Commit

Permalink
Merged master:a03dc8c9fa8 into amd-gfx:5fc05c258fe
Browse files Browse the repository at this point in the history
Local branch amd-gfx 5fc05c2 Merged master:2c7af6dffc0 into amd-gfx:13b4e3c2331
Remote branch master a03dc8c [lldb] Add basic -flimit-debug-info support to expression evaluator
  • Loading branch information
Sw authored and Sw committed Jul 1, 2020
2 parents 5fc05c2 + a03dc8c commit b2bf658
Show file tree
Hide file tree
Showing 20 changed files with 443 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ void InitVariablesCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
varDecl(unless(hasInitializer(anything())), unless(isInstantiated()),
isLocalVarDecl(), unless(isStaticLocal()), isDefinition(),
unless(hasParent(cxxCatchStmt())),
optionally(hasParent(declStmt(hasParent(
cxxForRangeStmt(hasLoopVariable(varDecl().bind(BadDecl))))))),
unless(equalsBoundNode(BadDecl)))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %check_clang_tidy %s cppcoreguidelines-init-variables %t -- -- -fno-delayed-template-parsing
// RUN: %check_clang_tidy %s cppcoreguidelines-init-variables %t -- -- -fno-delayed-template-parsing -fexceptions

// Ensure that function declarations are not changed.
void some_func(int x, double d, bool b, const char *p);
Expand Down Expand Up @@ -84,3 +84,10 @@ void f(RANGE r) {
for (char c : r) {
}
}

void catch_variable_decl() {
// Expect no warning given here.
try {
} catch (int X) {
}
}
28 changes: 28 additions & 0 deletions lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
#include "Plugins/ExpressionParser/Clang/ClangASTSource.h"
#include "Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h"
#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
Expand Down Expand Up @@ -876,6 +877,33 @@ ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) {
}
}

// If we have a forcefully completed type, try to find an actual definition
// for it in other modules.
const ClangASTMetadata *md = m_master.GetDeclMetadata(From);
auto *td = dyn_cast<TagDecl>(From);
if (td && md && md->IsForcefullyCompleted()) {
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
LLDB_LOG(log,
"[ClangASTImporter] Searching for a complete definition of {0} in "
"other modules",
td->getName());
Expected<DeclContext *> dc_or_err = ImportContext(td->getDeclContext());
if (!dc_or_err)
return dc_or_err.takeError();
Expected<DeclarationName> dn_or_err = Import(td->getDeclName());
if (!dn_or_err)
return dn_or_err.takeError();
DeclContext *dc = *dc_or_err;
DeclContext::lookup_result lr = dc->lookup(*dn_or_err);
if (lr.size()) {
clang::Decl *lookup_found = lr.front();
RegisterImportedDecl(From, lookup_found);
m_decls_to_ignore.insert(lookup_found);
return lookup_found;
} else
LLDB_LOG(log, "[ClangASTImporter] Complete definition not found");
}

return ASTImporter::ImportImpl(From);
}

Expand Down
14 changes: 12 additions & 2 deletions lldb/source/Plugins/ExpressionParser/Clang/ClangASTMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ class ClangASTMetadata {
public:
ClangASTMetadata()
: m_user_id(0), m_union_is_user_id(false), m_union_is_isa_ptr(false),
m_has_object_ptr(false), m_is_self(false), m_is_dynamic_cxx(true) {}
m_has_object_ptr(false), m_is_self(false), m_is_dynamic_cxx(true),
m_is_forcefully_completed(false) {}

bool GetIsDynamicCXXType() const { return m_is_dynamic_cxx; }

Expand Down Expand Up @@ -83,6 +84,15 @@ class ClangASTMetadata {

bool HasObjectPtr() const { return m_has_object_ptr; }

/// A type is "forcefully completed" if it was declared complete to satisfy an
/// AST invariant (e.g. base classes must be complete types), but in fact we
/// were not able to find a actual definition for it.
bool IsForcefullyCompleted() const { return m_is_forcefully_completed; }

void SetIsForcefullyCompleted(bool value = true) {
m_is_forcefully_completed = true;
}

void Dump(Stream *s);

private:
Expand All @@ -92,7 +102,7 @@ class ClangASTMetadata {
};

bool m_union_is_user_id : 1, m_union_is_isa_ptr : 1, m_has_object_ptr : 1,
m_is_self : 1, m_is_dynamic_cxx : 1;
m_is_self : 1, m_is_dynamic_cxx : 1, m_is_forcefully_completed : 1;
};

} // namespace lldb_private
Expand Down
25 changes: 9 additions & 16 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2061,26 +2061,19 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
CompilerType base_class_type =
m_ast.GetType(type_source_info->getType());
if (!base_class_type.GetCompleteType()) {
auto module = dwarf->GetObjectFile()->GetModule();
module->ReportError(":: Class '%s' has a base class '%s' which "
"does not have a complete definition.",
die.GetName(),
base_class_type.GetTypeName().GetCString());
if (die.GetCU()->GetProducer() == eProducerClang)
module->ReportError(":: Try compiling the source file with "
"-fstandalone-debug.");

// We have no choice other than to pretend that the base class
// is complete. If we don't do this, clang will crash when we
// call setBases() inside of
// "clang_type.TransferBaseClasses()" below. Since we
// provide layout assistance, all ivars in this class and other
// classes will be fine, this is the best we can do short of
// crashing.
// We mark the class as complete to allow the TransferBaseClasses
// call to succeed. But we make a note of the fact that this class
// is not _really_ complete so we can later search for a definition
// in a different module.
if (TypeSystemClang::StartTagDeclarationDefinition(
base_class_type)) {
TypeSystemClang::CompleteTagDeclarationDefinition(
base_class_type);
const auto *td = TypeSystemClang::GetQualType(
base_class_type.GetOpaqueQualType())
.getTypePtr()
->getAsTagDecl();
m_ast.GetMetadata(td)->SetIsForcefullyCompleted();
}
}
}
Expand Down
27 changes: 27 additions & 0 deletions lldb/test/API/functionalities/limit-debug-info/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
CFLAGS_EXTRAS = $(LIMIT_DEBUG_INFO_FLAGS)
LD_EXTRAS = -L. -lone -ltwo
CXX_SOURCES = main.cpp

ONE_CXXFLAGS = $(LIMIT_DEBUG_INFO_FLAGS)
ifdef STRIP_ONE
ONE_CXXFLAGS += -g0
endif

TWO_CXXFLAGS = $(LIMIT_DEBUG_INFO_FLAGS)
ifdef STRIP_TWO
TWO_CXXFLAGS += -g0
endif

include Makefile.rules

a.out: libone libtwo

libone:
$(MAKE) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=one.cpp DYLIB_NAME=one \
CFLAGS_EXTRAS="$(ONE_CXXFLAGS)"

libtwo: libone
$(MAKE) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=two.cpp DYLIB_NAME=two \
CFLAGS_EXTRAS="$(TWO_CXXFLAGS)" LD_EXTRAS="-L. -lone"
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"""
Test completing types using information from other shared libraries.
"""

import os
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil


class LimitDebugInfoTestCase(TestBase):

mydir = TestBase.compute_mydir(__file__)

def _check_type(self, target, name):
exe = target.FindModule(lldb.SBFileSpec("a.out"))
type_ = exe.FindFirstType(name)
self.trace("type_: %s"%type_)
self.assertTrue(type_)
base = type_.GetDirectBaseClassAtIndex(0).GetType()
self.trace("base:%s"%base)
self.assertTrue(base)
self.assertEquals(base.GetNumberOfFields(), 0)

def _check_debug_info_is_limited(self, target):
# Without other shared libraries we should only see the member declared
# in the derived class. This serves as a sanity check that we are truly
# building with limited debug info.
self._check_type(target, "InheritsFromOne")
self._check_type(target, "InheritsFromTwo")

@skipIf(bugnumber="pr46284", debug_info="gmodules")
def test_one_and_two_debug(self):
self.build()
target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))

self._check_debug_info_is_limited(target)

self.registerSharedLibrariesWithTarget(target, ["one", "two"])

# But when other shared libraries are loaded, we should be able to see
# all members.
self.expect_expr("inherits_from_one.member", result_value="47")
self.expect_expr("inherits_from_one.one", result_value="142")

self.expect_expr("inherits_from_two.member", result_value="47")
self.expect_expr("inherits_from_two.one", result_value="142")
self.expect_expr("inherits_from_two.two", result_value="242")

@skipIf(bugnumber="pr46284", debug_info="gmodules")
def test_two_debug(self):
self.build(dictionary=dict(STRIP_ONE="1"))
target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))

self._check_debug_info_is_limited(target)

self.registerSharedLibrariesWithTarget(target, ["one", "two"])

# This time, we should only see the members from the second library.
self.expect_expr("inherits_from_one.member", result_value="47")
self.expect("expr inherits_from_one.one", error=True,
substrs=["no member named 'one' in 'InheritsFromOne'"])

self.expect_expr("inherits_from_two.member", result_value="47")
self.expect("expr inherits_from_two.one", error=True,
substrs=["no member named 'one' in 'InheritsFromTwo'"])
self.expect_expr("inherits_from_two.two", result_value="242")

@skipIf(bugnumber="pr46284", debug_info="gmodules")
def test_one_debug(self):
self.build(dictionary=dict(STRIP_TWO="1"))
target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))

self._check_debug_info_is_limited(target)

self.registerSharedLibrariesWithTarget(target, ["one", "two"])

# In this case we should only see the members from the second library.
# Note that we cannot see inherits_from_two.one because without debug
# info for "Two", we cannot determine that it in fact inherits from
# "One".
self.expect_expr("inherits_from_one.member", result_value="47")
self.expect_expr("inherits_from_one.one", result_value="142")

self.expect_expr("inherits_from_two.member", result_value="47")
self.expect("expr inherits_from_two.one", error=True,
substrs=["no member named 'one' in 'InheritsFromTwo'"])
self.expect("expr inherits_from_two.two", error=True,
substrs=["no member named 'two' in 'InheritsFromTwo'"])
6 changes: 6 additions & 0 deletions lldb/test/API/functionalities/limit-debug-info/foo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
struct A {
int a = 47;
virtual ~A();
};

A::~A() = default;
13 changes: 13 additions & 0 deletions lldb/test/API/functionalities/limit-debug-info/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "onetwo.h"

struct InheritsFromOne : One {
constexpr InheritsFromOne() = default;
int member = 47;
} inherits_from_one;

struct InheritsFromTwo : Two {
constexpr InheritsFromTwo() = default;
int member = 47;
} inherits_from_two;

int main() { return 0; }
3 changes: 3 additions & 0 deletions lldb/test/API/functionalities/limit-debug-info/one.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include "onetwo.h"

One::~One() = default;
11 changes: 11 additions & 0 deletions lldb/test/API/functionalities/limit-debug-info/onetwo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
struct One {
int one = 142;
constexpr One() = default;
virtual ~One();
};

struct Two : One {
int two = 242;
constexpr Two() = default;
~Two() override;
};
3 changes: 3 additions & 0 deletions lldb/test/API/functionalities/limit-debug-info/two.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include "onetwo.h"

Two::~Two() = default;
6 changes: 3 additions & 3 deletions llvm/include/llvm/IR/DebugInfoMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ class DIEnumerator : public DINode {
friend class MDNode;

APInt Value;
DIEnumerator(LLVMContext &C, StorageType Storage, APInt Value,
DIEnumerator(LLVMContext &C, StorageType Storage, const APInt &Value,
bool IsUnsigned, ArrayRef<Metadata *> Ops)
: DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops),
Value(Value) {
Expand All @@ -371,13 +371,13 @@ class DIEnumerator : public DINode {
Ops) {}
~DIEnumerator() = default;

static DIEnumerator *getImpl(LLVMContext &Context, APInt Value,
static DIEnumerator *getImpl(LLVMContext &Context, const APInt &Value,
bool IsUnsigned, StringRef Name,
StorageType Storage, bool ShouldCreate = true) {
return getImpl(Context, Value, IsUnsigned,
getCanonicalMDString(Context, Name), Storage, ShouldCreate);
}
static DIEnumerator *getImpl(LLVMContext &Context, APInt Value,
static DIEnumerator *getImpl(LLVMContext &Context, const APInt &Value,
bool IsUnsigned, MDString *Name,
StorageType Storage, bool ShouldCreate = true);

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/IR/DebugInfoMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ DISubrange::BoundType DISubrange::getStride() const {
return BoundType();
}

DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, APInt Value,
DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, const APInt &Value,
bool IsUnsigned, MDString *Name,
StorageType Storage, bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString");
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/IR/ModuleSummaryIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ static cl::opt<bool> ImportConstantsWithRefs(
"import-constants-with-refs", cl::init(true), cl::Hidden,
cl::desc("Import constant global variables with references"));

constexpr uint32_t FunctionSummary::ParamAccess::RangeWidth;

FunctionSummary FunctionSummary::ExternalNode =
FunctionSummary::makeDummyFunctionSummary({});

Expand Down
Loading

0 comments on commit b2bf658

Please sign in to comment.