Author: adrian Date: Mon Feb 27 15:30:05 2017 New Revision: 296388 URL: http://llvm.org/viewvc/llvm-project?rev=296388&view=rev Log: PR32042: Create inlined debug info for EmitInlinedInheritingCXXConstructorCall.
When clang emits an inheriting C++ constructor it may inline code during the CodeGen phase. This patch ensures that any debug info in this inlined code gets a proper inlined location. Otherwise we can end up with invalid debug info metadata, since all inlined local variables and function arguments would be reparented into the call site. Analogous to ApplyInlineLocation this patch introduces a ApplyInlineDebugLocation scoped helper to facilitate entering an inlined scope and cleaning up afterwards. This fixes one of the issues discovered in PR32042. rdar://problem/30679307 Added: cfe/trunk/test/CodeGenCXX/debug-info-inheriting-constructor.cpp Modified: cfe/trunk/lib/CodeGen/CGClass.cpp cfe/trunk/lib/CodeGen/CGDebugInfo.cpp cfe/trunk/lib/CodeGen/CGDebugInfo.h Modified: cfe/trunk/lib/CodeGen/CGClass.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=296388&r1=296387&r2=296388&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGClass.cpp (original) +++ cfe/trunk/lib/CodeGen/CGClass.cpp Mon Feb 27 15:30:05 2017 @@ -2128,7 +2128,9 @@ void CodeGenFunction::EmitInheritedCXXCo void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall( const CXXConstructorDecl *Ctor, CXXCtorType CtorType, bool ForVirtualBase, bool Delegating, CallArgList &Args) { - InlinedInheritingConstructorScope Scope(*this, GlobalDecl(Ctor, CtorType)); + GlobalDecl GD(Ctor, CtorType); + InlinedInheritingConstructorScope Scope(*this, GD); + ApplyInlineDebugLocation DebugScope(*this, GD); // Save the arguments to be passed to the inherited constructor. CXXInheritedCtorInitExprArgs = Args; Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=296388&r1=296387&r2=296388&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Feb 27 15:30:05 2017 @@ -107,8 +107,8 @@ void ApplyDebugLocation::init(SourceLoca // Construct a location that has a valid scope, but no line info. assert(!DI->LexicalBlockStack.empty()); - CGF->Builder.SetCurrentDebugLocation( - llvm::DebugLoc::get(0, 0, DI->LexicalBlockStack.back())); + CGF->Builder.SetCurrentDebugLocation(llvm::DebugLoc::get( + 0, 0, DI->LexicalBlockStack.back(), DI->getInlinedAt())); } ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF, const Expr *E) @@ -134,6 +134,30 @@ ApplyDebugLocation::~ApplyDebugLocation( CGF->Builder.SetCurrentDebugLocation(std::move(OriginalLocation)); } +ApplyInlineDebugLocation::ApplyInlineDebugLocation(CodeGenFunction &CGF, + GlobalDecl InlinedFn) + : CGF(&CGF) { + if (!CGF.getDebugInfo()) { + this->CGF = nullptr; + return; + } + auto &DI = *CGF.getDebugInfo(); + SavedLocation = DI.getLocation(); + assert((DI.getInlinedAt() == + CGF.Builder.getCurrentDebugLocation()->getInlinedAt()) && + "CGDebugInfo and IRBuilder are out of sync"); + + DI.EmitInlineFunctionStart(CGF.Builder, InlinedFn); +} + +ApplyInlineDebugLocation::~ApplyInlineDebugLocation() { + if (!CGF) + return; + auto &DI = *CGF->getDebugInfo(); + DI.EmitInlineFunctionEnd(CGF->Builder); + DI.EmitLocation(CGF->Builder, SavedLocation); +} + void CGDebugInfo::setLocation(SourceLocation Loc) { // If the new location isn't valid return. if (Loc.isInvalid()) @@ -2871,28 +2895,40 @@ void CGDebugInfo::collectVarDeclProps(co VDContext = getContextDescriptor(cast<Decl>(DC), Mod ? Mod : TheCU); } -llvm::DISubprogram * -CGDebugInfo::getFunctionForwardDeclaration(const FunctionDecl *FD) { +llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD, + bool Stub) { llvm::DINodeArray TParamsArray; StringRef Name, LinkageName; llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; - SourceLocation Loc = FD->getLocation(); + SourceLocation Loc = GD.getDecl()->getLocation(); llvm::DIFile *Unit = getOrCreateFile(Loc); llvm::DIScope *DContext = Unit; unsigned Line = getLineNumber(Loc); - - collectFunctionDeclProps(FD, Unit, Name, LinkageName, DContext, + collectFunctionDeclProps(GD, Unit, Name, LinkageName, DContext, TParamsArray, Flags); + auto *FD = dyn_cast<FunctionDecl>(GD.getDecl()); + // Build function type. SmallVector<QualType, 16> ArgTypes; - for (const ParmVarDecl *Parm: FD->parameters()) - ArgTypes.push_back(Parm->getType()); + if (FD) + for (const ParmVarDecl *Parm : FD->parameters()) + ArgTypes.push_back(Parm->getType()); CallingConv CC = FD->getType()->castAs<FunctionType>()->getCallConv(); QualType FnType = CGM.getContext().getFunctionType( FD->getReturnType(), ArgTypes, FunctionProtoType::ExtProtoInfo(CC)); + if (Stub) { + return DBuilder.createFunction( + DContext, Name, LinkageName, Unit, Line, + getOrCreateFunctionType(GD.getDecl(), FnType, Unit), + !FD->isExternallyVisible(), + /* isDefinition = */ true, 0, Flags, CGM.getLangOpts().Optimize, + TParamsArray.get(), getFunctionDeclaration(FD)); + } + llvm::DISubprogram *SP = DBuilder.createTempFunctionFwdDecl( DContext, Name, LinkageName, Unit, Line, - getOrCreateFunctionType(FD, FnType, Unit), !FD->isExternallyVisible(), + getOrCreateFunctionType(GD.getDecl(), FnType, Unit), + !FD->isExternallyVisible(), /* isDefinition = */ false, 0, Flags, CGM.getLangOpts().Optimize, TParamsArray.get(), getFunctionDeclaration(FD)); const auto *CanonDecl = cast<FunctionDecl>(FD->getCanonicalDecl()); @@ -2902,6 +2938,16 @@ CGDebugInfo::getFunctionForwardDeclarati return SP; } +llvm::DISubprogram * +CGDebugInfo::getFunctionForwardDeclaration(GlobalDecl GD) { + return getFunctionFwdDeclOrStub(GD, /* Stub = */ false); +} + +llvm::DISubprogram * +CGDebugInfo::getFunctionStub(GlobalDecl GD) { + return getFunctionFwdDeclOrStub(GD, /* Stub = */ true); +} + llvm::DIGlobalVariable * CGDebugInfo::getGlobalVariableForwardDeclaration(const VarDecl *VD) { QualType T; @@ -3173,6 +3219,27 @@ void CGDebugInfo::EmitFunctionDecl(Globa TParamsArray.get(), getFunctionDeclaration(D))); } +void CGDebugInfo::EmitInlineFunctionStart(CGBuilderTy &Builder, GlobalDecl GD) { + const auto *FD = cast<FunctionDecl>(GD.getDecl()); + // If there is a subprogram for this function available then use it. + auto FI = SPCache.find(FD->getCanonicalDecl()); + llvm::DISubprogram *SP = nullptr; + if (FI != SPCache.end()) + SP = dyn_cast_or_null<llvm::DISubprogram>(FI->second); + if (!SP) + SP = getFunctionStub(GD); + FnBeginRegionCount.push_back(LexicalBlockStack.size()); + LexicalBlockStack.emplace_back(SP); + setInlinedAt(Builder.getCurrentDebugLocation()); + EmitLocation(Builder, FD->getLocation()); +} + +void CGDebugInfo::EmitInlineFunctionEnd(CGBuilderTy &Builder) { + assert(CurInlinedAt && "unbalanced inline scope stack"); + EmitFunctionEnd(Builder); + setInlinedAt(llvm::DebugLoc(CurInlinedAt).getInlinedAt()); +} + void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) { // Update our current location setLocation(Loc); @@ -3182,7 +3249,7 @@ void CGDebugInfo::EmitLocation(CGBuilder llvm::MDNode *Scope = LexicalBlockStack.back(); Builder.SetCurrentDebugLocation(llvm::DebugLoc::get( - getLineNumber(CurLoc), getColumnNumber(CurLoc), Scope)); + getLineNumber(CurLoc), getColumnNumber(CurLoc), Scope, CurInlinedAt)); } void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) { @@ -3200,8 +3267,9 @@ void CGDebugInfo::EmitLexicalBlockStart( setLocation(Loc); // Emit a line table change for the current location inside the new scope. - Builder.SetCurrentDebugLocation(llvm::DebugLoc::get( - getLineNumber(Loc), getColumnNumber(Loc), LexicalBlockStack.back())); + Builder.SetCurrentDebugLocation( + llvm::DebugLoc::get(getLineNumber(Loc), getColumnNumber(Loc), + LexicalBlockStack.back(), CurInlinedAt)); if (DebugKind <= codegenoptions::DebugLineTablesOnly) return; @@ -3387,9 +3455,10 @@ void CGDebugInfo::EmitDeclare(const VarD Line, Ty, Align); // Insert an llvm.dbg.declare into the current block. - DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr), - llvm::DebugLoc::get(Line, Column, Scope), - Builder.GetInsertBlock()); + DBuilder.insertDeclare( + Storage, D, DBuilder.createExpression(Expr), + llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt), + Builder.GetInsertBlock()); return; } else if (isa<VariableArrayType>(VD->getType())) Expr.push_back(llvm::dwarf::DW_OP_deref); @@ -3420,9 +3489,10 @@ void CGDebugInfo::EmitDeclare(const VarD Flags | llvm::DINode::FlagArtificial, FieldAlign); // Insert an llvm.dbg.declare into the current block. - DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr), - llvm::DebugLoc::get(Line, Column, Scope), - Builder.GetInsertBlock()); + DBuilder.insertDeclare( + Storage, D, DBuilder.createExpression(Expr), + llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt), + Builder.GetInsertBlock()); } } } @@ -3438,7 +3508,7 @@ void CGDebugInfo::EmitDeclare(const VarD // Insert an llvm.dbg.declare into the current block. DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr), - llvm::DebugLoc::get(Line, Column, Scope), + llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt), Builder.GetInsertBlock()); } @@ -3519,7 +3589,8 @@ void CGDebugInfo::EmitDeclareOfBlockDecl Line, Ty, false, llvm::DINode::FlagZero, Align); // Insert an llvm.dbg.declare into the current block. - auto DL = llvm::DebugLoc::get(Line, Column, LexicalBlockStack.back()); + auto DL = + llvm::DebugLoc::get(Line, Column, LexicalBlockStack.back(), CurInlinedAt); if (InsertPoint) DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(addr), DL, InsertPoint); @@ -3687,12 +3758,13 @@ void CGDebugInfo::EmitDeclareOfBlockLite // Insert an llvm.dbg.value into the current block. DBuilder.insertDbgValueIntrinsic( LocalAddr, 0, debugVar, DBuilder.createExpression(), - llvm::DebugLoc::get(line, column, scope), Builder.GetInsertBlock()); + llvm::DebugLoc::get(line, column, scope, CurInlinedAt), + Builder.GetInsertBlock()); } // Insert an llvm.dbg.declare into the current block. DBuilder.insertDeclare(Arg, debugVar, DBuilder.createExpression(), - llvm::DebugLoc::get(line, column, scope), + llvm::DebugLoc::get(line, column, scope, CurInlinedAt), Builder.GetInsertBlock()); } Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=296388&r1=296387&r2=296388&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.h (original) +++ cfe/trunk/lib/CodeGen/CGDebugInfo.h Mon Feb 27 15:30:05 2017 @@ -61,6 +61,7 @@ class CGDebugInfo { ModuleMap *ClangModuleMap = nullptr; ExternalASTSource::ASTSourceDescriptor PCHDescriptor; SourceLocation CurLoc; + llvm::MDNode *CurInlinedAt = nullptr; llvm::DIType *VTablePtrType = nullptr; llvm::DIType *ClassTy = nullptr; llvm::DICompositeType *ObjTy = nullptr; @@ -320,6 +321,17 @@ public: /// ignored. void setLocation(SourceLocation Loc); + /// Return the current source location. This does not necessarily correspond + /// to the IRBuilder's current DebugLoc. + SourceLocation getLocation() const { return CurLoc; } + + /// Update the current inline scope. All subsequent calls to \p EmitLocation + /// will create a location with this inlinedAt field. + void setInlinedAt(llvm::MDNode *InlinedAt) { CurInlinedAt = InlinedAt; } + + /// \return the current inline scope. + llvm::MDNode *getInlinedAt() const { return CurInlinedAt; } + // Converts a SourceLocation to a DebugLoc llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Loc); @@ -336,6 +348,11 @@ public: SourceLocation ScopeLoc, QualType FnType, llvm::Function *Fn, CGBuilderTy &Builder); + /// Start a new scope for an inlined function. + void EmitInlineFunctionStart(CGBuilderTy &Builder, GlobalDecl GD); + /// End an inlined function scope. + void EmitInlineFunctionEnd(CGBuilderTy &Builder); + /// Emit debug info for a function declaration. void EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, QualType FnType); @@ -502,11 +519,18 @@ private: llvm::DIDerivedType * getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D); + /// Helper that either creates a forward declaration or a stub. + llvm::DISubprogram *getFunctionFwdDeclOrStub(GlobalDecl GD, bool Stub); + /// Create a subprogram describing the forward declaration - /// represented in the given FunctionDecl. - llvm::DISubprogram *getFunctionForwardDeclaration(const FunctionDecl *FD); + /// represented in the given FunctionDecl wrapped in a GlobalDecl. + llvm::DISubprogram *getFunctionForwardDeclaration(GlobalDecl GD); + + /// Create a DISubprogram describing the function + /// represented in the given FunctionDecl wrapped in a GlobalDecl. + llvm::DISubprogram *getFunctionStub(GlobalDecl GD); - /// Create a global variable describing the forward decalration + /// Create a global variable describing the forward declaration /// represented in the given VarDecl. llvm::DIGlobalVariable * getGlobalVariableForwardDeclaration(const VarDecl *VD); @@ -633,6 +657,20 @@ public: }; +/// A scoped helper to set the current debug location to an inlined location. +class ApplyInlineDebugLocation { + SourceLocation SavedLocation; + CodeGenFunction *CGF; + +public: + /// Set up the CodeGenFunction's DebugInfo to produce inline locations for the + /// function \p InlinedFn. The current debug location becomes the inlined call + /// site of the inlined function. + ApplyInlineDebugLocation(CodeGenFunction &CGF, GlobalDecl InlinedFn); + /// Restore everything back to the orginial state. + ~ApplyInlineDebugLocation(); +}; + } // namespace CodeGen } // namespace clang Added: cfe/trunk/test/CodeGenCXX/debug-info-inheriting-constructor.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-inheriting-constructor.cpp?rev=296388&view=auto ============================================================================== --- cfe/trunk/test/CodeGenCXX/debug-info-inheriting-constructor.cpp (added) +++ cfe/trunk/test/CodeGenCXX/debug-info-inheriting-constructor.cpp Mon Feb 27 15:30:05 2017 @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -debug-info-kind=standalone -std=c++11 -triple x86_64-darwin -emit-llvm -o - %s | FileCheck %s + +struct A { + A(int, ...); +}; +struct B : A { + using A::A; +}; + +A::A(int i, ...) {} +// CHECK: define void @{{.*}}foo +// CHECK-NOT ret void +// CHECK: call void @llvm.dbg.declare +// CHECK-NOT ret void +// CHECK: call void @llvm.dbg.declare(metadata %{{.*}}** %{{[^,]+}}, +// CHECK-SAME: metadata ![[THIS:[0-9]+]], metadata !{{[0-9]+}}), !dbg ![[LOC:[0-9]+]] +// CHECK: ret void, !dbg ![[NOINL:[0-9]+]] +// CHECK: ![[FOO:.*]] = distinct !DISubprogram(name: "foo" +// CHECK-DAG: ![[A:.*]] = distinct !DISubprogram(name: "A", linkageName: "_ZN1BCI11AEiz" +void foo() { +// CHECK-DAG: ![[LOC]] = !DILocation(line: 0, scope: ![[A]], inlinedAt: ![[INL:[0-9]+]]) +// CHECK-DAG: ![[INL]] = !DILocation(line: [[@LINE+1]], scope: ![[FOO]]) + B b(0); +// CHECK: ![[NOINL]] = !DILocation(line: [[@LINE+1]], scope: !{{[0-9]+}}) +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits