From 73ca56942dc55c29c4dfa4a7ce64e466fe43c891 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Tue, 9 Dec 2014 00:32:22 +0000 Subject: [PATCH] DebugInfo: Correctly identify the location of C++ member initializer list elements This particularly helps the fidelity of ASan reports (which can occur even in these examples - if, for example, one uses placement new over a buffer of insufficient size - now ASan will correctly identify which member's initialization went over the end of the buffer). This doesn't cover all types of members - more coming. llvm-svn: 223726 --- clang/lib/CodeGen/CGClass.cpp | 12 +++++---- clang/lib/CodeGen/CGDecl.cpp | 20 +++++++-------- clang/lib/CodeGen/CGExpr.cpp | 6 ++++- clang/lib/CodeGen/CodeGenFunction.h | 16 +++++++----- clang/test/CodeGenCXX/debug-info-line.cpp | 41 ++++++++++++++++++------------- 5 files changed, 55 insertions(+), 40 deletions(-) diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index e2af17c..dfd980f 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -597,17 +597,19 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, ArrayRef ArrayIndexes; if (MemberInit->getNumArrayIndices()) ArrayIndexes = MemberInit->getArrayIndexes(); - CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit(), ArrayIndexes); + CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit(), ArrayIndexes, + MemberInit->getMemberLocation()); } -void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, - LValue LHS, Expr *Init, - ArrayRef ArrayIndexes) { +void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS, + Expr *Init, + ArrayRef ArrayIndexes, + SourceLocation DbgLoc) { QualType FieldType = Field->getType(); switch (getEvaluationKind(FieldType)) { case TEK_Scalar: if (LHS.isSimple()) { - EmitExprAsInit(Init, Field, LHS, false); + EmitExprAsInit(Init, Field, LHS, false, DbgLoc); } else { RValue RHS = RValue::get(EmitScalarExpr(Init)); EmitStoreThroughLValue(RHS, LHS); diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 959ac9a..97da9ef 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -596,16 +596,15 @@ static void drillIntoBlockVariable(CodeGenFunction &CGF, lvalue.setAddress(CGF.BuildBlockByrefAddress(lvalue.getAddress(), var)); } -void CodeGenFunction::EmitScalarInit(const Expr *init, - const ValueDecl *D, - LValue lvalue, - bool capturedByInit) { +void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D, + LValue lvalue, bool capturedByInit, + SourceLocation DbgLoc) { Qualifiers::ObjCLifetime lifetime = lvalue.getObjCLifetime(); if (!lifetime) { llvm::Value *value = EmitScalarExpr(init); if (capturedByInit) drillIntoBlockVariable(*this, lvalue, cast(D)); - EmitStoreThroughLValue(RValue::get(value), lvalue, true); + EmitStoreThroughLValue(RValue::get(value), lvalue, true, DbgLoc); return; } @@ -1192,22 +1191,21 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { /// \param alignment the alignment of the address /// \param capturedByInit true if the variable is a __block variable /// whose address is potentially changed by the initializer -void CodeGenFunction::EmitExprAsInit(const Expr *init, - const ValueDecl *D, - LValue lvalue, - bool capturedByInit) { +void CodeGenFunction::EmitExprAsInit(const Expr *init, const ValueDecl *D, + LValue lvalue, bool capturedByInit, + SourceLocation DbgLoc) { QualType type = D->getType(); if (type->isReferenceType()) { RValue rvalue = EmitReferenceBindingToExpr(init); if (capturedByInit) drillIntoBlockVariable(*this, lvalue, cast(D)); - EmitStoreThroughLValue(rvalue, lvalue, true); + EmitStoreThroughLValue(rvalue, lvalue, true, DbgLoc); return; } switch (getEvaluationKind(type)) { case TEK_Scalar: - EmitScalarInit(init, D, lvalue, capturedByInit); + EmitScalarInit(init, D, lvalue, capturedByInit, DbgLoc); return; case TEK_Complex: { ComplexPairTy complex = EmitComplexExpr(init); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 6ced6e1..0ce09c8 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1437,7 +1437,11 @@ RValue CodeGenFunction::EmitLoadOfGlobalRegLValue(LValue LV) { /// lvalue, where both are guaranteed to the have the same type, and that type /// is 'Ty'. void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, - bool isInit) { + bool isInit, + SourceLocation DbgLoc) { + if (auto *DI = getDebugInfo()) + DI->EmitLocation(Builder, DbgLoc); + if (!Dst.isSimple()) { if (Dst.isVectorElt()) { // Read/modify/write the vector, inserting the new element. diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index dc21c6d..98527b2 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1299,7 +1299,8 @@ public: FunctionArgList &Args); void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init, - ArrayRef ArrayIndexes); + ArrayRef ArrayIndexes, + SourceLocation DbgLoc = SourceLocation()); /// InitializeVTablePointer - Initialize the vtable pointer of the given /// subobject. @@ -1543,8 +1544,9 @@ public: /// EmitExprAsInit - Emits the code necessary to initialize a /// location in memory with the given initializer. - void EmitExprAsInit(const Expr *init, const ValueDecl *D, - LValue lvalue, bool capturedByInit); + void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, + bool capturedByInit, + SourceLocation DbgLoc = SourceLocation()); /// hasVolatileMember - returns true if aggregate type has a volatile /// member. @@ -1830,8 +1832,9 @@ public: /// This function can be called with a null (unreachable) insert point. void EmitVarDecl(const VarDecl &D); - void EmitScalarInit(const Expr *init, const ValueDecl *D, - LValue lvalue, bool capturedByInit); + void EmitScalarInit(const Expr *init, const ValueDecl *D, LValue lvalue, + bool capturedByInit, + SourceLocation DbgLoc = SourceLocation()); void EmitScalarInit(llvm::Value *init, LValue lvalue); typedef void SpecialInitFn(CodeGenFunction &Init, const VarDecl &D, @@ -2150,7 +2153,8 @@ public: /// EmitStoreThroughLValue - Store the specified rvalue into the specified /// lvalue, where both are guaranteed to the have the same type, and that type /// is 'Ty'. - void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false); + void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit = false, + SourceLocation DbgLoc = SourceLocation()); void EmitStoreThroughExtVectorComponentLValue(RValue Src, LValue Dst); void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst); diff --git a/clang/test/CodeGenCXX/debug-info-line.cpp b/clang/test/CodeGenCXX/debug-info-line.cpp index 0434de5..00d6261 100644 --- a/clang/test/CodeGenCXX/debug-info-line.cpp +++ b/clang/test/CodeGenCXX/debug-info-line.cpp @@ -1,26 +1,33 @@ // RUN: %clang_cc1 -g -std=c++11 -S -emit-llvm %s -o - | FileCheck %s -int src(); int* sink(); +int &src(); int* sink(); void f1() { #line 100 * // The store for the assignment should be attributed to the start of the // assignment expression here, regardless of the location of subexpressions. - ( - sink - ( - ) - + - 3 - ) - = - src - ( - ) - + - 42 - ; - // CHECK: store {{.*}}, !dbg [[DBG1:!.*]] + sink() = src(); + // CHECK: store {{.*}}, !dbg [[DBG_F1:!.*]] } -// CHECK: [[DBG1]] = metadata !{i32 100, {{.*}} +struct foo { + int i; + int &j; + foo(); +}; + +foo::foo() + : +#line 200 + i + (src()), + j + (src()) + // CHECK: store i32 {{.*}} !dbg [[DBG_FOO_VALUE:!.*]] + // CHECK: store i32* {{.*}} !dbg [[DBG_FOO_REF:!.*]] +{ +} + +// CHECK: [[DBG_F1]] = metadata !{i32 100, +// CHECK: [[DBG_FOO_VALUE]] = metadata !{i32 200, +// CHECK: [[DBG_FOO_REF]] = metadata !{i32 202, -- 2.7.4