Commit 7ead0087 authored by Raphael Isemann's avatar Raphael Isemann
Browse files

[lldb] Fix crash in AccessDeclContextSanity when copying FunctionTemplateDecl inside a record.

Summary:
We currently don't set access specifiers for function template declarations. This seems to be fine
as long as the function template is not declared inside any record in which case Clang asserts
with the following once we try to query it's access:
```
Assertion failed: (Access != AS_none && "Access specifier is AS_none inside a record decl"), function AccessDeclContextSanity,
```

This patch just marks these function template declarations as public to make Clang happy.

Reviewers: shafik, teemperor

Reviewed By: teemperor

Subscribers: JDevlieghere, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D71909
parent 136f34fe
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
from lldbsuite.test import lldbinline
from lldbsuite.test import decorators

lldbinline.MakeInlineTest(__file__, globals(), [decorators.skipIf(bugnumber="rdar://53754063")])
lldbinline.MakeInlineTest(__file__, globals(), [])
+0 −0

File moved.

+5 −0
Original line number Diff line number Diff line
@@ -1340,6 +1340,11 @@ clang::FunctionTemplateDecl *ClangASTContext::CreateFunctionTemplateDecl(
    // TODO: verify which decl context we should put template_param_decls into..
    template_param_decls[i]->setDeclContext(func_decl);
  }
  // Function templates inside a record need to have an access specifier.
  // It doesn't matter what access specifier we give the template as LLDB
  // anyway allows accessing everything inside a record.
  if (decl_ctx->isRecord())
    func_tmpl_decl->setAccess(clang::AccessSpecifier::AS_public);

  return func_tmpl_decl;
}
+49 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "TestingSupport/SubsystemRAII.h"
#include "TestingSupport/Symbol/ClangTestUtils.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/ClangASTContext.h"
@@ -471,3 +472,51 @@ TEST_F(TestClangASTContext, TestGetTypeClassNested) {
  QualType t = ctxt.getTypeOfType(t_base);
  EXPECT_EQ(lldb::eTypeClassBuiltin, m_ast->GetTypeClass(t.getAsOpaquePtr()));
}

TEST_F(TestClangASTContext, TestFunctionTemplateConstruction) {
  // Tests creating a function template.

  CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt);
  clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl();

  // Prepare the declarations/types we need for the template.
  CompilerType clang_type =
      m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U);
  FunctionDecl *func =
      m_ast->CreateFunctionDeclaration(TU, "foo", clang_type, 0, false);
  ClangASTContext::TemplateParameterInfos empty_params;

  // Create the actual function template.
  clang::FunctionTemplateDecl *func_template =
      m_ast->CreateFunctionTemplateDecl(TU, func, "foo", empty_params);

  EXPECT_EQ(TU, func_template->getDeclContext());
  EXPECT_EQ("foo", func_template->getName());
  EXPECT_EQ(clang::AccessSpecifier::AS_none, func_template->getAccess());
}

TEST_F(TestClangASTContext, TestFunctionTemplateInRecordConstruction) {
  // Tests creating a function template inside a record.

  CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt);

  // Create a record we can put the function template int.
  CompilerType record_type =
      clang_utils::createRecordWithField(*m_ast, "record", int_type, "field");
  clang::TagDecl *record = ClangUtil::GetAsTagDecl(record_type);

  // Prepare the declarations/types we need for the template.
  CompilerType clang_type =
      m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U);
  FunctionDecl *func =
      m_ast->CreateFunctionDeclaration(record, "foo", clang_type, 0, false);
  ClangASTContext::TemplateParameterInfos empty_params;

  // Create the actual function template.
  clang::FunctionTemplateDecl *func_template =
      m_ast->CreateFunctionTemplateDecl(record, func, "foo", empty_params);

  EXPECT_EQ(record, func_template->getDeclContext());
  EXPECT_EQ("foo", func_template->getName());
  EXPECT_EQ(clang::AccessSpecifier::AS_public, func_template->getAccess());
}