From: Adrian Prantl Date: Thu, 10 Apr 2014 23:21:53 +0000 (+0000) Subject: Debug info: (Bugfix) Make sure artificial functions like _GLOBAL__I_a X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9a7c2b4dfae18c6826c6e8caed450f39efdf3ab3;p=clang Debug info: (Bugfix) Make sure artificial functions like _GLOBAL__I_a are not associated with any source lines. Previously, if the Location of a Decl was empty, EmitFunctionStart would just keep using CurLoc, which would sometimes be correct (e.g., thunks) but in other cases would just point to a hilariously random location. This patch fixes this by completely eliminating all uses of CurLoc from EmitFunctionStart and rather have clients explicitly pass in a SourceLocation for the function header and the function body. rdar://problem/14985269 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@205999 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 15b08d476c..c1cbfde4b5 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -1135,6 +1135,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, // Begin generating the function. StartFunction(blockDecl, fnType->getReturnType(), fn, fnInfo, args, + blockDecl->getLocation(), blockInfo.getBlockExpr()->getBody()->getLocStart()); // Okay. Undo some of what StartFunction did. @@ -1306,7 +1307,7 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { false); // Create a scope with an artificial location for the body of this function. ArtificialLocation AL(*this, Builder); - StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); + StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation(), SourceLocation()); AL.Emit(); llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); @@ -1476,7 +1477,7 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { false, false); // Create a scope with an artificial location for the body of this function. ArtificialLocation AL(*this, Builder); - StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); + StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation(), SourceLocation()); AL.Emit(); llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); @@ -1765,7 +1766,7 @@ generateByrefCopyHelper(CodeGenFunction &CGF, SC_Static, false, false); - CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation()); + CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation(), SourceLocation()); if (byrefInfo.needsCopy()) { llvm::Type *byrefPtrType = byrefType.getPointerTo(0); @@ -1834,7 +1835,7 @@ generateByrefDisposeHelper(CodeGenFunction &CGF, SourceLocation(), II, R, 0, SC_Static, false, false); - CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation()); + CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation(), SourceLocation()); if (byrefInfo.needsDispose()) { llvm::Value *V = CGF.GetAddrOfLocalVar(&src); diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 45c78064aa..8e06bbd34b 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -2504,7 +2504,10 @@ llvm::DICompositeType CGDebugInfo::getOrCreateFunctionType(const Decl *D, } /// EmitFunctionStart - Constructs the debug code for entering a function. -void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, +void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, + SourceLocation Loc, + SourceLocation ScopeLoc, + QualType FnType, llvm::Function *Fn, CGBuilderTy &Builder) { @@ -2514,24 +2517,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, FnBeginRegionCount.push_back(LexicalBlockStack.size()); const Decl *D = GD.getDecl(); - - // Use the location of the start of the function to determine where - // the function definition is located. By default use the location - // of the declaration as the location for the subprogram. A function - // may lack a declaration in the source code if it is created by code - // gen. (examples: _GLOBAL__I_a, __cxx_global_array_dtor, thunk). bool HasDecl = (D != 0); - SourceLocation Loc; - if (HasDecl) { - Loc = D->getLocation(); - - // If this is a function specialization then use the pattern body - // as the location for the function. - if (const FunctionDecl *FD = dyn_cast(D)) - if (const FunctionDecl *SpecDecl = FD->getTemplateInstantiationPattern()) - if (SpecDecl->hasBody(SpecDecl)) - Loc = SpecDecl->getLocation(); - } unsigned Flags = 0; llvm::DIFile Unit = getOrCreateFile(Loc); @@ -2591,9 +2577,14 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, if (!Name.empty() && Name[0] == '\01') Name = Name.substr(1); - unsigned LineNo = getLineNumber(Loc); - if (!HasDecl || D->isImplicit()) + if (!HasDecl || D->isImplicit()) { Flags |= llvm::DIDescriptor::FlagArtificial; + // Artificial functions without a location should not silently reuse CurLoc. + if (Loc.isInvalid()) + CurLoc = SourceLocation(); + } + unsigned LineNo = getLineNumber(Loc); + unsigned ScopeLine = getLineNumber(ScopeLoc); // FIXME: The function declaration we're constructing here is mostly reusing // declarations from CXXMethodDecl and not constructing new ones for arbitrary @@ -2604,7 +2595,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, DBuilder.createFunction(FDContext, Name, LinkageName, Unit, LineNo, getOrCreateFunctionType(D, FnType, Unit), Fn->hasInternalLinkage(), true /*definition*/, - getLineNumber(CurLoc), Flags, + ScopeLine, Flags, CGM.getLangOpts().Optimize, Fn, TParamsArray, getFunctionDeclaration(D)); if (HasDecl) diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 7f2ddd0636..2fc35d5b87 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -220,8 +220,12 @@ public: /// EmitFunctionStart - Emit a call to llvm.dbg.function.start to indicate /// start of a new function. - void EmitFunctionStart(GlobalDecl GD, QualType FnType, - llvm::Function *Fn, CGBuilderTy &Builder); + /// \param Loc The location of the function header. + /// \param ScopeLoc The location of the function body. + void EmitFunctionStart(GlobalDecl GD, + SourceLocation Loc, SourceLocation ScopeLoc, + QualType FnType, llvm::Function *Fn, + CGBuilderTy &Builder); /// EmitFunctionEnd - Constructs the debug code for exiting a function. void EmitFunctionEnd(CGBuilderTy &Builder); diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index bc8620d442..558c91be95 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -179,7 +179,7 @@ static llvm::Constant *createAtExitStub(CodeGenModule &CGM, const VarDecl &VD, CGF.StartFunction(&VD, CGM.getContext().VoidTy, fn, CGM.getTypes().arrangeNullaryFunction(), FunctionArgList(), - SourceLocation()); + SourceLocation(), SourceLocation()); llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr); @@ -412,7 +412,8 @@ void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, StartFunction(GlobalDecl(D), getContext().VoidTy, Fn, getTypes().arrangeNullaryFunction(), - FunctionArgList(), D->getInit()->getExprLoc()); + FunctionArgList(), D->getLocation(), + D->getInit()->getExprLoc()); // Use guarded initialization if the global variable is weak. This // occurs for, e.g., instantiated static data members and @@ -433,7 +434,7 @@ CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, llvm::GlobalVariable *Guard) { StartFunction(GlobalDecl(), getContext().VoidTy, Fn, getTypes().arrangeNullaryFunction(), - FunctionArgList(), SourceLocation()); + FunctionArgList(), SourceLocation(), SourceLocation()); llvm::BasicBlock *ExitBlock = 0; if (Guard) { @@ -479,7 +480,7 @@ void CodeGenFunction::GenerateCXXGlobalDtorsFunc(llvm::Function *Fn, &DtorsAndObjects) { StartFunction(GlobalDecl(), getContext().VoidTy, Fn, getTypes().arrangeNullaryFunction(), - FunctionArgList(), SourceLocation()); + FunctionArgList(), SourceLocation(), SourceLocation()); // Emit the dtors, in reverse order from construction. for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) { @@ -509,7 +510,8 @@ llvm::Function *CodeGenFunction::generateDestroyHelper( llvm::Function *fn = CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor"); - StartFunction(VD, getContext().VoidTy, fn, FI, args, SourceLocation()); + StartFunction(VD, getContext().VoidTy, fn, FI, args, + SourceLocation(), SourceLocation()); emitDestroy(addr, type, destroyer, useEHCleanupForArray); diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index f78bb0b310..b34c19cb94 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -481,7 +481,8 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, CurGD = OMD; - StartFunction(OMD, OMD->getReturnType(), Fn, FI, args, StartLoc); + StartFunction(OMD, OMD->getReturnType(), Fn, FI, args, + OMD->getLocation(), StartLoc); // In ARC, certain methods get an extra cleanup. if (CGM.getLangOpts().ObjCAutoRefCount && @@ -2915,7 +2916,7 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction( "__assign_helper_atomic_property_", &CGM.getModule()); - StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); + StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation(), SourceLocation()); DeclRefExpr DstExpr(&dstDecl, false, DestTy, VK_RValue, SourceLocation()); @@ -2993,7 +2994,7 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, "__copy_helper_atomic_property_", &CGM.getModule()); - StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); + StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation(), SourceLocation()); DeclRefExpr SrcExpr(&srcDecl, false, SrcTy, VK_RValue, SourceLocation()); diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index cba9e6cd4d..d50d8b959a 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -1944,7 +1944,9 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedDecl *CD, CGM.SetInternalFunctionAttributes(CD, F, FuncInfo); // Generate the function. - StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args, CD->getBody()->getLocStart()); + StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args, + CD->getLocation(), + CD->getBody()->getLocStart()); // Set the context parameter in CapturedStmtInfo. llvm::Value *DeclPtr = LocalDeclMap[CD->getContextParam()]; diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index 0ad765ce22..08537d5f25 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -217,7 +217,7 @@ void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD, // Start defining the function. StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs, - SourceLocation()); + MD->getLocation(), SourceLocation()); // Since we didn't pass a GlobalDecl to StartFunction, do this ourselves. CGM.getCXXABI().EmitInstanceFunctionProlog(*this); diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index ffaba958fb..95e4ee498d 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -503,6 +503,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, + SourceLocation Loc, SourceLocation StartLoc) { const Decl *D = GD.getDecl(); @@ -580,9 +581,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType FnType = getContext().getFunctionType(RetTy, ArgTypes, FunctionProtoType::ExtProtoInfo()); - - DI->setLocation(StartLoc); - DI->EmitFunctionStart(GD, FnType, CurFn, Builder); + DI->EmitFunctionStart(GD, Loc, StartLoc, FnType, CurFn, Builder); } if (ShouldInstrumentFunction()) @@ -759,8 +758,24 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange(); CurEHLocation = BodyRange.getEnd(); + // Use the location of the start of the function to determine where + // the function definition is located. By default use the location + // of the declaration as the location for the subprogram. A function + // may lack a declaration in the source code if it is created by code + // gen. (examples: _GLOBAL__I_a, __cxx_global_array_dtor, thunk). + SourceLocation Loc; + if (FD) { + Loc = FD->getLocation(); + + // If this is a function specialization then use the pattern body + // as the location for the function. + if (const FunctionDecl *SpecDecl = FD->getTemplateInstantiationPattern()) + if (SpecDecl->hasBody(SpecDecl)) + Loc = SpecDecl->getLocation(); + } + // Emit the standard function prologue. - StartFunction(GD, ResTy, Fn, FnInfo, Args, BodyRange.getBegin()); + StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin()); // Generate the body of the function. PGO.assignRegionCounters(GD.getDecl(), CurFn); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 5b0653adc6..56ad76ae92 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1140,11 +1140,15 @@ public: void GenerateCode(GlobalDecl GD, llvm::Function *Fn, const CGFunctionInfo &FnInfo); + /// \brief Emit code for the start of a function. + /// \param Loc The location to be associated with the function. + /// \param StartLoc The location of the function body. void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, + SourceLocation Loc, SourceLocation StartLoc); void EmitConstructorBody(FunctionArgList &Args); diff --git a/test/CodeGenCXX/globalinit-loc.cpp b/test/CodeGenCXX/globalinit-loc.cpp new file mode 100644 index 0000000000..bf3340c157 --- /dev/null +++ b/test/CodeGenCXX/globalinit-loc.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s +// rdar://problem/14985269. +// +// Verify that the global init helper function does not get associated +// with any source location. +// +// CHECK: define internal void @_GLOBAL__I_a +// CHECK-NOT: !dbg +// CHECK: "_GLOBAL__I_a", i32 0, {{.*}}, i32 0} ; [ DW_TAG_subprogram ] [line 0] [local] [def] +# 99 "someheader.h" +class A { +public: + A(); + int foo() { return 0; } +}; +# 5 "main.cpp" +A a; + +int f() { + return a.foo(); +} +