Index: docs/UsersManual.rst =================================================================== --- docs/UsersManual.rst +++ docs/UsersManual.rst @@ -1686,6 +1686,20 @@ Generate complete debug info. +Controlling Macro Debug Info Generation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Debug info for macro 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 complete debug info. This flag is discarded when **-g0** is enabled. + +.. option:: -fno-debug-macro + + Do not generate macro debug info (default). + Controlling Debugger "Tuning" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Index: include/clang/CodeGen/ModuleBuilder.h =================================================================== --- include/clang/CodeGen/ModuleBuilder.h +++ include/clang/CodeGen/ModuleBuilder.h @@ -35,6 +35,7 @@ namespace CodeGen { class CodeGenModule; + class CGDebugInfo; } /// The primary public interface to the Clang code generator. @@ -65,6 +66,9 @@ /// 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. /// Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td +++ include/clang/Driver/CC1Options.td @@ -136,6 +136,8 @@ 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">, Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1212,6 +1212,10 @@ HelpText<"Limit debug information produced to reduce size of debug binary">; def flimit_debug_info : Flag<["-"], "flimit-debug-info">, Flags<[CoreOption]>, Alias; def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Flags<[CoreOption]>, Alias; +def fdebug_macro : Flag<["-"], "fdebug-macro">, Group, Flags<[CoreOption]>, + HelpText<"Emit macro debug information">; +def fno_debug_macro : Flag<["-"], "fno-debug-macro">, Group, Flags<[CoreOption]>, + HelpText<"Do not emit macro debug information">; def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group, Flags<[DriverOption, CoreOption]>; def fstrict_enums : Flag<["-"], "fstrict-enums">, Group, Flags<[CC1Option]>, Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -221,6 +221,9 @@ /// 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) Index: lib/CodeGen/CGDebugInfo.h =================================================================== --- lib/CodeGen/CGDebugInfo.h +++ lib/CodeGen/CGDebugInfo.h @@ -412,6 +412,16 @@ 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, Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -2408,6 +2408,21 @@ 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 { Index: lib/CodeGen/CMakeLists.txt =================================================================== --- lib/CodeGen/CMakeLists.txt +++ lib/CodeGen/CMakeLists.txt @@ -77,6 +77,7 @@ CodeGenTypes.cpp CoverageMappingGen.cpp ItaniumCXXABI.cpp + MacroPPCallbacks.cpp MicrosoftCXXABI.cpp ModuleBuilder.cpp ObjectFilePCHContainerOperations.cpp Index: lib/CodeGen/CodeGenAction.cpp =================================================================== --- lib/CodeGen/CodeGenAction.cpp +++ lib/CodeGen/CodeGenAction.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "CoverageMappingGen.h" +#include "MacroPPCallbacks.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" @@ -99,6 +100,8 @@ I.second.release(); } + CodeGenerator *getCodeGenerator() { return Gen.get(); } + void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override { Gen->HandleCXXStaticMemberVarInstantiation(VD); } @@ -813,6 +816,16 @@ CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile, LinkModules, std::move(OS), *VMContext, CoverageInfo)); BEConsumer = Result.get(); + + // Enable generating macro debug info only in FullDebugInfo mode. + if (CI.getCodeGenOpts().getDebugInfo() != codegenoptions::NoDebugInfo && + CI.getCodeGenOpts().MacroDebugInfo) { + std::unique_ptr Callbacks = + llvm::make_unique(BEConsumer->getCodeGenerator(), + CI.getPreprocessor()); + CI.getPreprocessor().addPPCallbacks(std::move(Callbacks)); + } + return std::move(Result); } Index: lib/CodeGen/MacroPPCallbacks.h =================================================================== --- lib/CodeGen/MacroPPCallbacks.h +++ lib/CodeGen/MacroPPCallbacks.h @@ -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, // and file scopes. + CommandLineIncludeScope, // Included file, from 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 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 Index: lib/CodeGen/MacroPPCallbacks.cpp =================================================================== --- lib/CodeGen/MacroPPCallbacks.cpp +++ lib/CodeGen/MacroPPCallbacks.cpp @@ -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 + - file enter + {Compiler macro definitions} - (Line=0, no scope) + - (Optional) file enter + {Command line macro definitions} - (Line=0, no scope) + - (Optional) file exit + {Command line file includes} - (Line=0, Main file scope) + {macro definitions and file includes} - (Line!=0, Parent scope) + - 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(""); +} + +static bool isCommandLineFile(SourceManager &SM, SourceLocation Loc) { + StringRef Filename(SM.getPresumedLoc(Loc).getFilename()); + return Filename.equals(""); +} + +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(), ""); +} Index: lib/CodeGen/ModuleBuilder.cpp =================================================================== --- lib/CodeGen/ModuleBuilder.cpp +++ lib/CodeGen/ModuleBuilder.cpp @@ -92,6 +92,10 @@ return M.get(); } + CGDebugInfo *getCGDebugInfo() { + return Builder->getModuleDebugInfo(); + } + llvm::Module *ReleaseModule() { return M.release(); } @@ -299,6 +303,10 @@ return static_cast(this)->ReleaseModule(); } +CGDebugInfo *CodeGenerator::getCGDebugInfo() { + return static_cast(this)->getCGDebugInfo(); +} + const Decl *CodeGenerator::GetDeclForMangledName(llvm::StringRef name) { return static_cast(this)->GetDeclForMangledName(name); } Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -4951,6 +4951,11 @@ 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"); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -505,6 +505,7 @@ 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); Index: test/CodeGen/debug-info-macro.c =================================================================== --- test/CodeGen/debug-info-macro.c +++ test/CodeGen/debug-info-macro.c @@ -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") Index: test/CodeGen/include/debug-info-macro.h =================================================================== --- test/CodeGen/include/debug-info-macro.h +++ test/CodeGen/include/debug-info-macro.h @@ -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