forked from OSchip/llvm-project
[DebugInfo] Added support to Clang FE for generating debug info for preprocessor macros.
Added "-fdebug-macro" flag (and "-fno-debug-macro" flag) to enable (and to disable) emitting macro debug info. Added CC1 "-debug-info-macro" flag that enables emitting macro debug info. Differential Revision: https://reviews.llvm.org/D16135 llvm-svn: 294637
This commit is contained in:
parent
ef089bdb4b
commit
546bc1103b
|
@ -1696,6 +1696,22 @@ below. If multiple flags are present, the last one is used.
|
|||
|
||||
Generate complete debug info.
|
||||
|
||||
Controlling Macro Debug Info Generation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Debug info for C preprocessor macros increases the size of debug information in
|
||||
the binary. Macro debug info generated by Clang can be controlled by the flags
|
||||
listed below.
|
||||
|
||||
.. option:: -fdebug-macro
|
||||
|
||||
Generate debug info for preprocessor macros. This flag is discarded when
|
||||
**-g0** is enabled.
|
||||
|
||||
.. option:: -fno-debug-macro
|
||||
|
||||
Do not generate debug info for preprocessor macros (default).
|
||||
|
||||
Controlling Debugger "Tuning"
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace clang {
|
|||
|
||||
namespace CodeGen {
|
||||
class CodeGenModule;
|
||||
class CGDebugInfo;
|
||||
}
|
||||
|
||||
/// The primary public interface to the Clang code generator.
|
||||
|
@ -65,6 +66,9 @@ public:
|
|||
/// CodeGenerator after releasing its module.
|
||||
llvm::Module *ReleaseModule();
|
||||
|
||||
/// Return debug info code generator.
|
||||
CodeGen::CGDebugInfo *getCGDebugInfo();
|
||||
|
||||
/// Given a mangled name, return a declaration which mangles that way
|
||||
/// which has been added to this code generator via a Handle method.
|
||||
///
|
||||
|
|
|
@ -136,6 +136,8 @@ def migrator_no_finalize_removal : Flag<["-"], "no-finalize-removal">,
|
|||
let Flags = [CC1Option, CC1AsOption, NoDriverOption] in {
|
||||
|
||||
def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">;
|
||||
def debug_info_macro : Flag<["-"], "debug-info-macro">,
|
||||
HelpText<"Emit macro debug information">;
|
||||
def dwarf_version_EQ : Joined<["-"], "dwarf-version=">;
|
||||
def debugger_tuning_EQ : Joined<["-"], "debugger-tuning=">;
|
||||
def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">,
|
||||
|
|
|
@ -1322,6 +1322,10 @@ def fno_standalone_debug : Flag<["-"], "fno-standalone-debug">, Group<f_Group>,
|
|||
HelpText<"Limit debug information produced to reduce size of debug binary">;
|
||||
def flimit_debug_info : Flag<["-"], "flimit-debug-info">, Flags<[CoreOption]>, Alias<fno_standalone_debug>;
|
||||
def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Flags<[CoreOption]>, Alias<fstandalone_debug>;
|
||||
def fdebug_macro : Flag<["-"], "fdebug-macro">, Group<f_Group>, Flags<[CoreOption]>,
|
||||
HelpText<"Emit macro debug information">;
|
||||
def fno_debug_macro : Flag<["-"], "fno-debug-macro">, Group<f_Group>, Flags<[CoreOption]>,
|
||||
HelpText<"Do not emit macro debug information">;
|
||||
def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group<f_Group>,
|
||||
Flags<[DriverOption, CoreOption]>;
|
||||
def fstrict_enums : Flag<["-"], "fstrict-enums">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
|
|
|
@ -224,6 +224,9 @@ VALUE_CODEGENOPT(SSPBufferSize, 32, 0)
|
|||
/// The kind of generated debug info.
|
||||
ENUM_CODEGENOPT(DebugInfo, codegenoptions::DebugInfoKind, 3, codegenoptions::NoDebugInfo)
|
||||
|
||||
/// Whether to generate macro debug info.
|
||||
CODEGENOPT(MacroDebugInfo, 1, 0)
|
||||
|
||||
/// Tune the debug info for this debugger.
|
||||
ENUM_CODEGENOPT(DebuggerTuning, llvm::DebuggerKind, 2,
|
||||
llvm::DebuggerKind::Default)
|
||||
|
|
|
@ -2419,6 +2419,21 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) {
|
|||
FullName);
|
||||
}
|
||||
|
||||
llvm::DIMacro *CGDebugInfo::CreateMacro(llvm::DIMacroFile *Parent,
|
||||
unsigned MType, SourceLocation LineLoc,
|
||||
StringRef Name, StringRef Value) {
|
||||
unsigned Line = LineLoc.isInvalid() ? 0 : getLineNumber(LineLoc);
|
||||
return DBuilder.createMacro(Parent, Line, MType, Name, Value);
|
||||
}
|
||||
|
||||
llvm::DIMacroFile *CGDebugInfo::CreateTempMacroFile(llvm::DIMacroFile *Parent,
|
||||
SourceLocation LineLoc,
|
||||
SourceLocation FileLoc) {
|
||||
llvm::DIFile *FName = getOrCreateFile(FileLoc);
|
||||
unsigned Line = LineLoc.isInvalid() ? 0 : getLineNumber(LineLoc);
|
||||
return DBuilder.createTempMacroFile(Parent, Line, FName);
|
||||
}
|
||||
|
||||
static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
|
||||
Qualifiers Quals;
|
||||
do {
|
||||
|
|
|
@ -413,6 +413,16 @@ public:
|
|||
|
||||
void completeTemplateDefinition(const ClassTemplateSpecializationDecl &SD);
|
||||
|
||||
/// Create debug info for a macro defined by a #define directive or a macro
|
||||
/// undefined by a #undef directive.
|
||||
llvm::DIMacro *CreateMacro(llvm::DIMacroFile *Parent, unsigned MType,
|
||||
SourceLocation LineLoc, StringRef Name,
|
||||
StringRef Value);
|
||||
|
||||
/// Create debug info for a file referenced by an #include directive.
|
||||
llvm::DIMacroFile *CreateTempMacroFile(llvm::DIMacroFile *Parent,
|
||||
SourceLocation LineLoc,
|
||||
SourceLocation FileLoc);
|
||||
private:
|
||||
/// Emit call to llvm.dbg.declare for a variable declaration.
|
||||
void EmitDeclare(const VarDecl *decl, llvm::Value *AI,
|
||||
|
|
|
@ -77,6 +77,7 @@ add_clang_library(clangCodeGen
|
|||
CodeGenTypes.cpp
|
||||
CoverageMappingGen.cpp
|
||||
ItaniumCXXABI.cpp
|
||||
MacroPPCallbacks.cpp
|
||||
MicrosoftCXXABI.cpp
|
||||
ModuleBuilder.cpp
|
||||
ObjectFilePCHContainerOperations.cpp
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "clang/CodeGen/CodeGenAction.h"
|
||||
#include "CodeGenModule.h"
|
||||
#include "CoverageMappingGen.h"
|
||||
#include "MacroPPCallbacks.h"
|
||||
#include "clang/AST/ASTConsumer.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
|
@ -97,6 +98,8 @@ namespace clang {
|
|||
return std::unique_ptr<llvm::Module>(Gen->ReleaseModule());
|
||||
}
|
||||
|
||||
CodeGenerator *getCodeGenerator() { return Gen.get(); }
|
||||
|
||||
void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override {
|
||||
Gen->HandleCXXStaticMemberVarInstantiation(VD);
|
||||
}
|
||||
|
@ -830,6 +833,17 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
|
|||
CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile,
|
||||
std::move(LinkModules), std::move(OS), *VMContext, CoverageInfo));
|
||||
BEConsumer = Result.get();
|
||||
|
||||
// Enable generating macro debug info only when debug info is not disabled and
|
||||
// also macro debug info is enabled.
|
||||
if (CI.getCodeGenOpts().getDebugInfo() != codegenoptions::NoDebugInfo &&
|
||||
CI.getCodeGenOpts().MacroDebugInfo) {
|
||||
std::unique_ptr<PPCallbacks> Callbacks =
|
||||
llvm::make_unique<MacroPPCallbacks>(BEConsumer->getCodeGenerator(),
|
||||
CI.getPreprocessor());
|
||||
CI.getPreprocessor().addPPCallbacks(std::move(Callbacks));
|
||||
}
|
||||
|
||||
return std::move(Result);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
//===--- MacroPPCallbacks.cpp ---------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains implementation for the macro preprocessors callbacks.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MacroPPCallbacks.h"
|
||||
#include "CGDebugInfo.h"
|
||||
#include "clang/CodeGen/ModuleBuilder.h"
|
||||
#include "clang/Parse/Parser.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
void MacroPPCallbacks::writeMacroDefinition(const IdentifierInfo &II,
|
||||
const MacroInfo &MI,
|
||||
Preprocessor &PP, raw_ostream &Name,
|
||||
raw_ostream &Value) {
|
||||
Name << II.getName();
|
||||
|
||||
if (MI.isFunctionLike()) {
|
||||
Name << '(';
|
||||
if (!MI.arg_empty()) {
|
||||
MacroInfo::arg_iterator AI = MI.arg_begin(), E = MI.arg_end();
|
||||
for (; AI + 1 != E; ++AI) {
|
||||
Name << (*AI)->getName();
|
||||
Name << ',';
|
||||
}
|
||||
|
||||
// Last argument.
|
||||
if ((*AI)->getName() == "__VA_ARGS__")
|
||||
Name << "...";
|
||||
else
|
||||
Name << (*AI)->getName();
|
||||
}
|
||||
|
||||
if (MI.isGNUVarargs())
|
||||
// #define foo(x...)
|
||||
Name << "...";
|
||||
|
||||
Name << ')';
|
||||
}
|
||||
|
||||
SmallString<128> SpellingBuffer;
|
||||
bool First = true;
|
||||
for (const auto &T : MI.tokens()) {
|
||||
if (!First && T.hasLeadingSpace())
|
||||
Value << ' ';
|
||||
|
||||
Value << PP.getSpelling(T, SpellingBuffer);
|
||||
First = false;
|
||||
}
|
||||
}
|
||||
|
||||
MacroPPCallbacks::MacroPPCallbacks(CodeGenerator *Gen, Preprocessor &PP)
|
||||
: Gen(Gen), PP(PP), Status(NoScope) {}
|
||||
|
||||
/*
|
||||
This is the expected flow of enter/exit compiler and user files:
|
||||
- Main File Enter
|
||||
- <built-in> file enter
|
||||
{Compiler macro definitions} - (Line=0, no scope)
|
||||
- (Optional) <command line> file enter
|
||||
{Command line macro definitions} - (Line=0, no scope)
|
||||
- (Optional) <command line> file exit
|
||||
{Command line file includes} - (Line=0, Main file scope)
|
||||
{macro definitions and file includes} - (Line!=0, Parent scope)
|
||||
- <built-in> file exit
|
||||
{User code macro definitions and file includes} - (Line!=0, Parent scope)
|
||||
*/
|
||||
|
||||
llvm::DIMacroFile *MacroPPCallbacks::getCurrentScope() {
|
||||
if (Status == MainFileScope || Status == CommandLineIncludeScope)
|
||||
return Scopes.back();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SourceLocation MacroPPCallbacks::getCorrectLocation(SourceLocation Loc) {
|
||||
if (Status == MainFileScope || EnteredCommandLineIncludeFiles)
|
||||
return Loc;
|
||||
|
||||
// While parsing skipped files, location of macros is invalid.
|
||||
// Invalid location represents line zero.
|
||||
return SourceLocation();
|
||||
}
|
||||
|
||||
static bool isBuiltinFile(SourceManager &SM, SourceLocation Loc) {
|
||||
StringRef Filename(SM.getPresumedLoc(Loc).getFilename());
|
||||
return Filename.equals("<built-in>");
|
||||
}
|
||||
|
||||
static bool isCommandLineFile(SourceManager &SM, SourceLocation Loc) {
|
||||
StringRef Filename(SM.getPresumedLoc(Loc).getFilename());
|
||||
return Filename.equals("<command line>");
|
||||
}
|
||||
|
||||
void MacroPPCallbacks::updateStatusToNextScope() {
|
||||
switch (Status) {
|
||||
case NoScope:
|
||||
Status = InitializedScope;
|
||||
break;
|
||||
case InitializedScope:
|
||||
Status = BuiltinScope;
|
||||
break;
|
||||
case BuiltinScope:
|
||||
Status = CommandLineIncludeScope;
|
||||
break;
|
||||
case CommandLineIncludeScope:
|
||||
Status = MainFileScope;
|
||||
break;
|
||||
case MainFileScope:
|
||||
llvm_unreachable("There is no next scope, already in the final scope");
|
||||
}
|
||||
}
|
||||
|
||||
void MacroPPCallbacks::FileEntered(SourceLocation Loc) {
|
||||
SourceLocation LineLoc = getCorrectLocation(LastHashLoc);
|
||||
switch (Status) {
|
||||
default:
|
||||
llvm_unreachable("Do not expect to enter a file from current scope");
|
||||
case NoScope:
|
||||
updateStatusToNextScope();
|
||||
break;
|
||||
case InitializedScope:
|
||||
updateStatusToNextScope();
|
||||
return;
|
||||
case BuiltinScope:
|
||||
if (isCommandLineFile(PP.getSourceManager(), Loc))
|
||||
return;
|
||||
updateStatusToNextScope();
|
||||
LLVM_FALLTHROUGH;
|
||||
case CommandLineIncludeScope:
|
||||
EnteredCommandLineIncludeFiles++;
|
||||
break;
|
||||
case MainFileScope:
|
||||
break;
|
||||
}
|
||||
|
||||
Scopes.push_back(Gen->getCGDebugInfo()->CreateTempMacroFile(getCurrentScope(),
|
||||
LineLoc, Loc));
|
||||
}
|
||||
|
||||
void MacroPPCallbacks::FileExited(SourceLocation Loc) {
|
||||
switch (Status) {
|
||||
default:
|
||||
llvm_unreachable("Do not expect to exit a file from current scope");
|
||||
case BuiltinScope:
|
||||
if (!isBuiltinFile(PP.getSourceManager(), Loc))
|
||||
// Skip next scope and change status to MainFileScope.
|
||||
Status = MainFileScope;
|
||||
return;
|
||||
case CommandLineIncludeScope:
|
||||
if (!EnteredCommandLineIncludeFiles) {
|
||||
updateStatusToNextScope();
|
||||
return;
|
||||
}
|
||||
EnteredCommandLineIncludeFiles--;
|
||||
break;
|
||||
case MainFileScope:
|
||||
break;
|
||||
}
|
||||
|
||||
Scopes.pop_back();
|
||||
}
|
||||
|
||||
void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason,
|
||||
SrcMgr::CharacteristicKind FileType,
|
||||
FileID PrevFID) {
|
||||
// Only care about enter file or exit file changes.
|
||||
if (Reason == EnterFile)
|
||||
FileEntered(Loc);
|
||||
else if (Reason == ExitFile)
|
||||
FileExited(Loc);
|
||||
}
|
||||
|
||||
void MacroPPCallbacks::InclusionDirective(
|
||||
SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
|
||||
bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
|
||||
StringRef SearchPath, StringRef RelativePath, const Module *Imported) {
|
||||
|
||||
// Record the line location of the current included file.
|
||||
LastHashLoc = HashLoc;
|
||||
}
|
||||
|
||||
void MacroPPCallbacks::MacroDefined(const Token &MacroNameTok,
|
||||
const MacroDirective *MD) {
|
||||
IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();
|
||||
SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());
|
||||
std::string NameBuffer, ValueBuffer;
|
||||
llvm::raw_string_ostream Name(NameBuffer);
|
||||
llvm::raw_string_ostream Value(ValueBuffer);
|
||||
writeMacroDefinition(*Id, *MD->getMacroInfo(), PP, Name, Value);
|
||||
Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),
|
||||
llvm::dwarf::DW_MACINFO_define, location,
|
||||
Name.str(), Value.str());
|
||||
}
|
||||
|
||||
void MacroPPCallbacks::MacroUndefined(const Token &MacroNameTok,
|
||||
const MacroDefinition &MD) {
|
||||
IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();
|
||||
SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());
|
||||
Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),
|
||||
llvm::dwarf::DW_MACINFO_undef, location,
|
||||
Id->getName(), "");
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
//===--- MacroPPCallbacks.h -------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines implementation for the macro preprocessors callbacks.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Lex/PPCallbacks.h"
|
||||
|
||||
namespace llvm {
|
||||
class DIMacroFile;
|
||||
class DIMacroNode;
|
||||
}
|
||||
namespace clang {
|
||||
class Preprocessor;
|
||||
class MacroInfo;
|
||||
class CodeGenerator;
|
||||
|
||||
class MacroPPCallbacks : public PPCallbacks {
|
||||
/// A pointer to code generator, where debug info generator can be found.
|
||||
CodeGenerator *Gen;
|
||||
|
||||
/// Preprocessor.
|
||||
Preprocessor &PP;
|
||||
|
||||
/// Location of recent included file, used for line number.
|
||||
SourceLocation LastHashLoc;
|
||||
|
||||
/// Counts current number of command line included files, which were entered
|
||||
/// and were not exited yet.
|
||||
int EnteredCommandLineIncludeFiles = 0;
|
||||
|
||||
enum FileScopeStatus {
|
||||
NoScope = 0, // Scope is not initialized yet.
|
||||
InitializedScope, // Main file scope is initialized but not set yet.
|
||||
BuiltinScope, // <built-in> and <command line> file scopes.
|
||||
CommandLineIncludeScope, // Included file, from <command line> file, scope.
|
||||
MainFileScope // Main file scope.
|
||||
};
|
||||
FileScopeStatus Status;
|
||||
|
||||
/// Parent contains all entered files that were not exited yet according to
|
||||
/// the inclusion order.
|
||||
llvm::SmallVector<llvm::DIMacroFile *, 4> Scopes;
|
||||
|
||||
/// Get current DIMacroFile scope.
|
||||
/// \return current DIMacroFile scope or nullptr if there is no such scope.
|
||||
llvm::DIMacroFile *getCurrentScope();
|
||||
|
||||
/// Get current line location or invalid location.
|
||||
/// \param Loc current line location.
|
||||
/// \return current line location \p `Loc`, or invalid location if it's in a
|
||||
/// skipped file scope.
|
||||
SourceLocation getCorrectLocation(SourceLocation Loc);
|
||||
|
||||
/// Use the passed preprocessor to write the macro name and value from the
|
||||
/// given macro info and identifier info into the given \p `Name` and \p
|
||||
/// `Value` output streams.
|
||||
///
|
||||
/// \param II Identifier info, used to get the Macro name.
|
||||
/// \param MI Macro info, used to get the Macro argumets and values.
|
||||
/// \param PP Preprocessor.
|
||||
/// \param [out] Name Place holder for returned macro name and arguments.
|
||||
/// \param [out] Value Place holder for returned macro value.
|
||||
static void writeMacroDefinition(const IdentifierInfo &II,
|
||||
const MacroInfo &MI, Preprocessor &PP,
|
||||
raw_ostream &Name, raw_ostream &Value);
|
||||
|
||||
/// Update current file scope status to next file scope.
|
||||
void updateStatusToNextScope();
|
||||
|
||||
/// Handle the case when entering a file.
|
||||
///
|
||||
/// \param Loc Indicates the new location.
|
||||
/// \Return true if file scope status should be updated.
|
||||
void FileEntered(SourceLocation Loc);
|
||||
|
||||
/// Handle the case when exiting a file.
|
||||
///
|
||||
/// \Return true if file scope status should be updated.
|
||||
void FileExited(SourceLocation Loc);
|
||||
|
||||
public:
|
||||
MacroPPCallbacks(CodeGenerator *Gen, Preprocessor &PP);
|
||||
|
||||
/// Callback invoked whenever a source file is entered or exited.
|
||||
///
|
||||
/// \param Loc Indicates the new location.
|
||||
/// \param PrevFID the file that was exited if \p Reason is ExitFile.
|
||||
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
|
||||
SrcMgr::CharacteristicKind FileType,
|
||||
FileID PrevFID = FileID()) override;
|
||||
|
||||
/// Callback invoked whenever a directive (#xxx) is processed.
|
||||
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
|
||||
StringRef FileName, bool IsAngled,
|
||||
CharSourceRange FilenameRange, const FileEntry *File,
|
||||
StringRef SearchPath, StringRef RelativePath,
|
||||
const Module *Imported) override;
|
||||
|
||||
/// Hook called whenever a macro definition is seen.
|
||||
void MacroDefined(const Token &MacroNameTok,
|
||||
const MacroDirective *MD) override;
|
||||
|
||||
/// Hook called whenever a macro \#undef is seen.
|
||||
///
|
||||
/// MD is released immediately following this callback.
|
||||
void MacroUndefined(const Token &MacroNameTok,
|
||||
const MacroDefinition &MD) override;
|
||||
};
|
||||
|
||||
} // end namespace clang
|
|
@ -92,6 +92,10 @@ namespace {
|
|||
return M.get();
|
||||
}
|
||||
|
||||
CGDebugInfo *getCGDebugInfo() {
|
||||
return Builder->getModuleDebugInfo();
|
||||
}
|
||||
|
||||
llvm::Module *ReleaseModule() {
|
||||
return M.release();
|
||||
}
|
||||
|
@ -299,6 +303,10 @@ llvm::Module *CodeGenerator::ReleaseModule() {
|
|||
return static_cast<CodeGeneratorImpl*>(this)->ReleaseModule();
|
||||
}
|
||||
|
||||
CGDebugInfo *CodeGenerator::getCGDebugInfo() {
|
||||
return static_cast<CodeGeneratorImpl*>(this)->getCGDebugInfo();
|
||||
}
|
||||
|
||||
const Decl *CodeGenerator::GetDeclForMangledName(llvm::StringRef name) {
|
||||
return static_cast<CodeGeneratorImpl*>(this)->GetDeclForMangledName(name);
|
||||
}
|
||||
|
|
|
@ -5013,6 +5013,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DwarfVersion,
|
||||
DebuggerTuning);
|
||||
|
||||
// -fdebug-macro turns on macro debug info generation.
|
||||
if (Args.hasFlag(options::OPT_fdebug_macro, options::OPT_fno_debug_macro,
|
||||
false))
|
||||
CmdArgs.push_back("-debug-info-macro");
|
||||
|
||||
// -ggnu-pubnames turns on gnu style pubnames in the backend.
|
||||
if (Args.hasArg(options::OPT_ggnu_pubnames)) {
|
||||
CmdArgs.push_back("-backend-option");
|
||||
|
|
|
@ -505,6 +505,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
|
|||
Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 0, Diags);
|
||||
Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info);
|
||||
Opts.EmitCodeView = Args.hasArg(OPT_gcodeview);
|
||||
Opts.MacroDebugInfo = Args.hasArg(OPT_debug_info_macro);
|
||||
Opts.WholeProgramVTables = Args.hasArg(OPT_fwhole_program_vtables);
|
||||
Opts.LTOVisibilityPublicStd = Args.hasArg(OPT_flto_visibility_public_std);
|
||||
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
// RUN: %clang_cc1 -emit-llvm -debug-info-kind=line-tables-only -debug-info-macro %s -o - "-DC1(x)=( x + 5 )" -DA -include %S/include/debug-info-macro.h -UC1 | FileCheck -check-prefixes=CHECK,NO_PCH %s
|
||||
// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -debug-info-macro %s -o - "-DC1(x)=( x + 5 )" -DA -include %S/include/debug-info-macro.h -UC1 | FileCheck -check-prefixes=CHECK,NO_PCH %s
|
||||
// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -debug-info-macro %s -o - "-DC1(x)=( x + 5 )" -DA -include %S/include/debug-info-macro.h -UC1 | FileCheck -check-prefixes=CHECK,NO_PCH %s
|
||||
// RUN: %clang_cc1 -emit-llvm -debug-info-macro %s -o - "-DC1(x)=( x + 5 )" -DA -include %S/include/debug-info-macro.h -UC1 | FileCheck -check-prefixes=NO_MACRO %s
|
||||
|
||||
// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -debug-info-macro %S/include/debug-info-macro.h -emit-pch -o %t.pch -DC3
|
||||
// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -debug-info-macro %s -o - -include-pch %t.pch "-DC1(x)=( x + 5 )" -DA -include %S/include/debug-info-macro.h -UC1 | FileCheck -check-prefixes=CHECK,PCH %s
|
||||
|
||||
// This test checks that macro Debug info is correctly generated.
|
||||
|
||||
// TODO: Check for an following entry once support macros defined in pch files.
|
||||
// -PCH: !DIMacro(type: DW_MACINFO_define, name: "C3", value: "1")>
|
||||
|
||||
#line 15
|
||||
/*Line 15*/ #define D1 1
|
||||
/*Line 16*/ #include "include/debug-info-macro.h"
|
||||
/*Line 17*/ #undef D1
|
||||
/*Line 18*/ #define D2 2
|
||||
/*Line 19*/ #include "include/debug-info-macro.h"
|
||||
/*Line 20*/ #undef D2
|
||||
|
||||
// NO_MACRO-NOT: macros
|
||||
// NO_MACRO-NOT: DIMacro
|
||||
// NO_MACRO-NOT: DIMacroFile
|
||||
|
||||
// CHECK: !DICompileUnit({{.*}} macros: [[Macros:![0-9]+]])
|
||||
// CHECK: [[EmptyMD:![0-9]+]] = !{}
|
||||
|
||||
// NO_PCH: [[Macros]] = !{[[MainMacroFile:![0-9]+]], [[BuiltinMacro:![0-9]+]], {{.*}}, [[DefineC1:![0-9]+]], [[DefineA:![0-9]+]], [[UndefC1:![0-9]+]]}
|
||||
// PCH: [[Macros]] = !{[[MainMacroFile:![0-9]+]], [[DefineC1:![0-9]+]], [[DefineA:![0-9]+]], [[UndefC1:![0-9]+]]}
|
||||
|
||||
// CHECK: [[MainMacroFile]] = !DIMacroFile(file: [[MainFile:![0-9]+]], nodes: [[N1:![0-9]+]])
|
||||
// CHECK: [[MainFile]] = !DIFile(filename: "{{.*}}debug-info-macro.c"
|
||||
// CHECK: [[N1]] = !{[[CommandLineInclude:![0-9]+]], [[DefineD1:![0-9]+]], [[FileInclude1:![0-9]+]], [[UndefD1:![0-9]+]], [[DefineD2:![0-9]+]], [[FileInclude2:![0-9]+]], [[UndefD2:![0-9]+]]}
|
||||
|
||||
// CHECK: [[CommandLineInclude]] = !DIMacroFile(file: [[HeaderFile:![0-9]+]], nodes: [[N2:![0-9]+]])
|
||||
// CHECK: [[HeaderFile]] = !DIFile(filename: "{{.*}}debug-info-macro.h"
|
||||
// CHECK: [[N2]] = !{[[UndefA:![0-9]+]]}
|
||||
// CHECK: [[UndefA]] = !DIMacro(type: DW_MACINFO_undef, line: 11, name: "A")
|
||||
|
||||
// CHECK: [[DefineD1]] = !DIMacro(type: DW_MACINFO_define, line: 15, name: "D1", value: "1")
|
||||
// CHECK: [[FileInclude1]] = !DIMacroFile(line: 16, file: [[HeaderFile]], nodes: [[N3:![0-9]+]])
|
||||
// CHECK: [[N3]] = !{[[DefineAx:![0-9]+]], [[UndefA]]}
|
||||
// CHECK: [[DefineAx]] = !DIMacro(type: DW_MACINFO_define, line: 3, name: "A(x,y,z)", value: "(x)")
|
||||
// CHECK: [[UndefD1]] = !DIMacro(type: DW_MACINFO_undef, line: 17, name: "D1")
|
||||
|
||||
// CHECK: [[DefineD2]] = !DIMacro(type: DW_MACINFO_define, line: 18, name: "D2", value: "2")
|
||||
// CHECK: [[FileInclude2]] = !DIMacroFile(line: 19, file: [[HeaderFile]], nodes: [[N4:![0-9]+]])
|
||||
// CHECK: [[N4]] = !{[[DefineAy:![0-9]+]], [[UndefA]]}
|
||||
// CHECK: [[DefineAy]] = !DIMacro(type: DW_MACINFO_define, line: 7, name: "A(x,y,z)", value: "(y)")
|
||||
// CHECK: [[UndefD2]] = !DIMacro(type: DW_MACINFO_undef, line: 20, name: "D2")
|
||||
|
||||
// NO_PCH: [[BuiltinMacro]] = !DIMacro(type: DW_MACINFO_define, name: "__llvm__", value: "1")
|
||||
|
||||
// CHECK: [[DefineC1]] = !DIMacro(type: DW_MACINFO_define, name: "C1(x)", value: "( x + 5 )")
|
||||
// CHECK: [[DefineA]] = !DIMacro(type: DW_MACINFO_define, name: "A", value: "1")
|
||||
// CHECK: [[UndefC1]] = !DIMacro(type: DW_MACINFO_undef, name: "C1")
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
#ifdef D1
|
||||
/*Line 3*/ #define A(x, y, z) (x)
|
||||
#endif
|
||||
|
||||
#ifdef D2
|
||||
/*Line 7*/ #define A(x, y, z) (y)
|
||||
#endif
|
||||
|
||||
#ifdef A
|
||||
/*Line 11*/ #undef A
|
||||
#endif
|
|
@ -214,3 +214,9 @@
|
|||
// BADSTRING1: error: invalid value 'watkind' in '-debug-info-kind=watkind'
|
||||
// RUN: not %clang -cc1 -debugger-tuning=gmodal 2>&1 | FileCheck -check-prefix=BADSTRING2 %s
|
||||
// BADSTRING2: error: invalid value 'gmodal' in '-debugger-tuning=gmodal'
|
||||
|
||||
// RUN: %clang -### -fdebug-macro %s 2>&1 | FileCheck -check-prefix=MACRO %s
|
||||
// RUN: %clang -### -fno-debug-macro %s 2>&1 | FileCheck -check-prefix=NOMACRO %s
|
||||
// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=NOMACRO %s
|
||||
// MACRO: "-debug-info-macro"
|
||||
// NOMACRO-NOT: "-debug-info-macro"
|
||||
|
|
Loading…
Reference in New Issue