Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 93 additions & 30 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,68 @@ StringRef CGDebugInfo::getCurrentDirname() {
return CGM.getCodeGenOpts().DebugCompilationDir;
}

static llvm::dwarf::SourceLanguage GetSourceLanguage(const CodeGenModule &CGM) {
const CodeGenOptions &CGO = CGM.getCodeGenOpts();
const LangOptions &LO = CGM.getLangOpts();

assert(CGO.DwarfVersion <= 5);

llvm::dwarf::SourceLanguage LangTag;
if (LO.CPlusPlus) {
if (LO.ObjC)
LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
else if (CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)
LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
else if (LO.CPlusPlus14)
LangTag = llvm::dwarf::DW_LANG_C_plus_plus_14;
else if (LO.CPlusPlus11)
LangTag = llvm::dwarf::DW_LANG_C_plus_plus_11;
else
LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
} else if (LO.ObjC) {
LangTag = llvm::dwarf::DW_LANG_ObjC;
} else if (LO.OpenCL && (!CGO.DebugStrictDwarf || CGO.DwarfVersion >= 5)) {
LangTag = llvm::dwarf::DW_LANG_OpenCL;
} else if (LO.C11 && !(CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)) {
LangTag = llvm::dwarf::DW_LANG_C11;
} else if (LO.C99) {
LangTag = llvm::dwarf::DW_LANG_C99;
} else {
LangTag = llvm::dwarf::DW_LANG_C89;
}

return LangTag;
}

static llvm::DISourceLanguageName
GetDISourceLanguageName(const CodeGenModule &CGM) {
// Emit pre-DWARFv6 language codes.
if (CGM.getCodeGenOpts().DwarfVersion < 6)
return llvm::DISourceLanguageName(GetSourceLanguage(CGM));

const LangOptions &LO = CGM.getLangOpts();

uint32_t LangVersion = 0;
llvm::dwarf::SourceLanguageName LangTag;
if (LO.CPlusPlus) {
if (LO.ObjC) {
LangTag = llvm::dwarf::DW_LNAME_ObjC_plus_plus;
} else {
LangTag = llvm::dwarf::DW_LNAME_C_plus_plus;
LangVersion = LO.getCPlusPlusLangStd().value_or(0);
}
} else if (LO.ObjC) {
LangTag = llvm::dwarf::DW_LNAME_ObjC;
} else if (LO.OpenCL) {
LangTag = llvm::dwarf::DW_LNAME_OpenCL_C;
} else {
LangTag = llvm::dwarf::DW_LNAME_C;
LangVersion = LO.getCLangStd().value_or(0);
}

return llvm::DISourceLanguageName(LangTag, LangVersion);
}

void CGDebugInfo::CreateCompileUnit() {
SmallString<64> Checksum;
std::optional<llvm::DIFile::ChecksumKind> CSKind;
Expand Down Expand Up @@ -702,31 +764,6 @@ void CGDebugInfo::CreateCompileUnit() {
}
}

llvm::dwarf::SourceLanguage LangTag;
if (LO.CPlusPlus) {
if (LO.ObjC)
LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
else if (CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)
LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
else if (LO.CPlusPlus14)
LangTag = llvm::dwarf::DW_LANG_C_plus_plus_14;
else if (LO.CPlusPlus11)
LangTag = llvm::dwarf::DW_LANG_C_plus_plus_11;
else
LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
} else if (LO.ObjC) {
LangTag = llvm::dwarf::DW_LANG_ObjC;
} else if (LO.OpenCL && (!CGM.getCodeGenOpts().DebugStrictDwarf ||
CGM.getCodeGenOpts().DwarfVersion >= 5)) {
LangTag = llvm::dwarf::DW_LANG_OpenCL;
} else if (LO.C11 && !(CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)) {
LangTag = llvm::dwarf::DW_LANG_C11;
} else if (LO.C99) {
LangTag = llvm::dwarf::DW_LANG_C99;
} else {
LangTag = llvm::dwarf::DW_LANG_C89;
}

std::string Producer = getClangFullVersion();

// Figure out which version of the ObjC runtime we have.
Expand Down Expand Up @@ -787,7 +824,7 @@ void CGDebugInfo::CreateCompileUnit() {

// Create new compile unit.
TheCU = DBuilder.createCompileUnit(
llvm::DISourceLanguageName(LangTag), CUFile,
GetDISourceLanguageName(CGM), CUFile,
CGOpts.EmitVersionIdentMetadata ? Producer : "",
CGOpts.OptimizationLevel != 0 || CGOpts.PrepareForLTO ||
CGOpts.PrepareForThinLTO,
Expand Down Expand Up @@ -1234,20 +1271,46 @@ llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty,
Ty->getPointeeType(), Unit);
}

/// \return whether a C++ mangling exists for the type defined by TD.
static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) {
switch (TheCU->getSourceLanguage().getUnversionedName()) {
static bool hasCXXMangling(llvm::dwarf::SourceLanguage Lang, bool IsTagDecl) {
switch (Lang) {
case llvm::dwarf::DW_LANG_C_plus_plus:
case llvm::dwarf::DW_LANG_C_plus_plus_11:
case llvm::dwarf::DW_LANG_C_plus_plus_14:
return true;
case llvm::dwarf::DW_LANG_ObjC_plus_plus:
return isa<CXXRecordDecl>(TD) || isa<EnumDecl>(TD);
return IsTagDecl;
default:
return false;
}
}

static bool hasCXXMangling(llvm::dwarf::SourceLanguageName Lang,
bool IsTagDecl) {
switch (Lang) {
case llvm::dwarf::DW_LNAME_C_plus_plus:
return true;
case llvm::dwarf::DW_LNAME_ObjC_plus_plus:
return IsTagDecl;
default:
return false;
}
}

/// \return whether a C++ mangling exists for the type defined by TD.
static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) {
const bool IsTagDecl = isa<CXXRecordDecl>(TD) || isa<EnumDecl>(TD);

if (llvm::DISourceLanguageName SourceLang = TheCU->getSourceLanguage();
SourceLang.hasVersionedName())
return hasCXXMangling(
static_cast<llvm::dwarf::SourceLanguageName>(SourceLang.getName()),
IsTagDecl);
else
return hasCXXMangling(
static_cast<llvm::dwarf::SourceLanguage>(SourceLang.getName()),
IsTagDecl);
}

// Determines if the debug info for this tag declaration needs a type
// identifier. The purpose of the unique identifier is to deduplicate type
// information for identical types across TUs. Because of the C++ one definition
Expand Down
23 changes: 23 additions & 0 deletions clang/test/DebugInfo/CXX/versioned-language.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=5 -std=c++98 \
// RUN: | FileCheck %s --implicit-check-not "sourceLanguageName" --implicit-check-not "sourceLanguageVersion"
//
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++98 | FileCheck %s --check-prefix=CHECK-CPP98
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++03 | FileCheck %s --check-prefix=CHECK-CPP03
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++11 | FileCheck %s --check-prefix=CHECK-CPP11
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++14 | FileCheck %s --check-prefix=CHECK-CPP14
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++17 | FileCheck %s --check-prefix=CHECK-CPP17
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++20 | FileCheck %s --check-prefix=CHECK-CPP20
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++23 | FileCheck %s --check-prefix=CHECK-CPP23
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++2c | FileCheck %s --check-prefix=CHECK-CPP2C

struct Foo {} globalVar;

// CHECK-CPP98: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 199711
// FIXME: C++03 technically has no official standard version code. From Clang's point of view C++03 and C++98 are interchangable.
// CHECK-CPP03: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 199711
// CHECK-CPP11: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 201103
// CHECK-CPP14: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 201402
// CHECK-CPP17: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 201703
// CHECK-CPP20: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 202002
// CHECK-CPP23: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 202302
// CHECK-CPP2C: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 202400
17 changes: 17 additions & 0 deletions clang/test/DebugInfo/Generic/versioned-language.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=5 -std=c99 \
// RUN: | FileCheck %s --implicit-check-not "sourceLanguageName" --implicit-check-not "sourceLanguageVersion"
//
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c89 | FileCheck %s --check-prefix=CHECK-C89 --implicit-check-not "sourceLanguageVersion"
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c99 | FileCheck %s --check-prefix=CHECK-C99
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c17 | FileCheck %s --check-prefix=CHECK-C17
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c23 | FileCheck %s --check-prefix=CHECK-C23
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c2y | FileCheck %s --check-prefix=CHECK-C2Y

int globalVar = 10;

// CHECK-C89: !DICompileUnit(sourceLanguageName: DW_LNAME_C,
// CHECK-C99: !DICompileUnit(sourceLanguageName: DW_LNAME_C, sourceLanguageVersion: 199901
// CHECK-C11: !DICompileUnit(sourceLanguageName: DW_LNAME_C, sourceLanguageVersion: 201112
// CHECK-C17: !DICompileUnit(sourceLanguageName: DW_LNAME_C, sourceLanguageVersion: 201710
// CHECK-C23: !DICompileUnit(sourceLanguageName: DW_LNAME_C, sourceLanguageVersion: 202311
// CHECK-C2Y: !DICompileUnit(sourceLanguageName: DW_LNAME_C, sourceLanguageVersion: 202400
9 changes: 9 additions & 0 deletions clang/test/DebugInfo/ObjC/versioned-language.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=5 \
// RUN: | FileCheck %s --implicit-check-not "sourceLanguageName" --implicit-check-not "sourceLanguageVersion"
//
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 \
// RUN: | FileCheck %s --implicit-check-not "sourceLanguageVersion" --check-prefix=CHECK-OBJC

int globalVar = 10;

// CHECK-OBJC: !DICompileUnit(sourceLanguageName: DW_LNAME_ObjC,
9 changes: 9 additions & 0 deletions clang/test/DebugInfo/ObjCXX/versioned-language.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=5 \
// RUN: | FileCheck %s --implicit-check-not "sourceLanguageName" --implicit-check-not "sourceLanguageVersion"
//
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 \
// RUN: | FileCheck %s --implicit-check-not "sourceLanguageVersion" --check-prefix=CHECK-OBJCXX

int globalVar = 10;

// CHECK-OBJCXX: !DICompileUnit(sourceLanguageName: DW_LNAME_ObjC_plus_plus,