From: Anders Carlsson Date: Tue, 2 Feb 2010 03:37:46 +0000 (+0000) Subject: Move pointer to data member emission to CodeGenModule and use it in CGExprConstant... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=45147d0098a34c3705f74ca121b27d7736ac113a;p=clang Move pointer to data member emission to CodeGenModule and use it in CGExprConstant. Fixes PR5674. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95063 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index c0dd68bc70..ab4f8f1935 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1093,9 +1093,12 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { if (const FunctionDecl *FD = dyn_cast(ND)) return EmitFunctionDeclLValue(*this, E, FD); + // FIXME: the qualifier check does not seem sufficient here if (E->getQualifier()) { - // FIXME: the qualifier check does not seem sufficient here - return EmitPointerToDataMemberLValue(cast(ND)); + const FieldDecl *FD = cast(ND); + llvm::Value *V = CGM.EmitPointerToDataMember(FD); + + return LValue::MakeAddr(V, MakeQualifiers(FD->getType())); } assert(false && "Unhandled DeclRefExpr"); @@ -1873,20 +1876,6 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) { return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType())); } - -LValue CodeGenFunction::EmitPointerToDataMemberLValue(const FieldDecl *Field) { - const CXXRecordDecl *ClassDecl = cast(Field->getDeclContext()); - QualType NNSpecTy = - getContext().getCanonicalType( - getContext().getTypeDeclType(const_cast(ClassDecl))); - NNSpecTy = getContext().getPointerType(NNSpecTy); - llvm::Value *V = llvm::Constant::getNullValue(ConvertType(NNSpecTy)); - LValue MemExpLV = EmitLValueForField(V, Field, /*Qualifiers=*/0); - const llvm::Type *ResultType = ConvertType(getContext().getPointerDiffType()); - V = Builder.CreatePtrToInt(MemExpLV.getAddress(), ResultType, "datamember"); - return LValue::MakeAddr(V, MakeQualifiers(Field->getType())); -} - RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee, ReturnValueSlot ReturnValue, CallExpr::const_arg_iterator ArgBeg, diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index a9a07d5b75..fba70cb88f 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -438,16 +438,16 @@ public: if (const MemberPointerType *MPT = E->getType()->getAs()) { QualType T = MPT->getPointeeType(); - if (T->isFunctionProtoType()) { - DeclRefExpr *DRE = cast(E->getSubExpr()); - - return EmitMemberFunctionPointer(cast(DRE->getDecl())); - } + DeclRefExpr *DRE = cast(E->getSubExpr()); + + NamedDecl *ND = DRE->getDecl(); + if (T->isFunctionProtoType()) + return EmitMemberFunctionPointer(cast(ND)); - // FIXME: Should we handle other member pointer types here too, - // or should they be handled by Expr::Evaluate? + // We have a pointer to data member. + return CGM.EmitPointerToDataMember(cast(ND)); } - + return 0; } @@ -959,3 +959,27 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T)); } + +llvm::Constant * +CodeGenModule::EmitPointerToDataMember(const FieldDecl *FD) { + + // Itanium C++ ABI 2.3: + // A pointer to data member is an offset from the base address of the class + // object containing it, represented as a ptrdiff_t + + const CXXRecordDecl *ClassDecl = cast(FD->getParent()); + QualType ClassType = + getContext().getTypeDeclType(const_cast(ClassDecl)); + + const llvm::StructType *ClassLTy = + cast(getTypes().ConvertType(ClassType)); + + unsigned FieldNo = getTypes().getLLVMFieldNo(FD); + uint64_t Offset = + getTargetData().getStructLayout(ClassLTy)->getElementOffset(FieldNo); + + const llvm::Type *PtrDiffTy = + getTypes().ConvertType(getContext().getPointerDiffType()); + + return llvm::ConstantInt::get(PtrDiffTy, Offset); +} diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 3ca86b8058..09db6eb16c 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -388,8 +388,6 @@ Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) { } if (SrcType->isMemberPointerType()) { - // FIXME: This is ABI specific. - // Compare against -1. llvm::Value *NegativeOne = llvm::Constant::getAllOnesValue(Src->getType()); return Builder.CreateICmpNE(Src, NegativeOne, "tobool"); diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index b6bb385fe9..6b9e5bdd7d 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -1231,13 +1231,13 @@ void VtableBuilder::AppendMethodsToVtable() { void CGVtableInfo::ComputeMethodVtableIndices(const CXXRecordDecl *RD) { // Itanium C++ ABI 2.5.2: - // The order of the virtual function pointers in a virtual table is the - // order of declaration of the corresponding member functions in the class. + // The order of the virtual function pointers in a virtual table is the + // order of declaration of the corresponding member functions in the class. // - // There is an entry for any virtual function declared in a class, - // whether it is a new function or overrides a base class function, - // unless it overrides a function from the primary base, and conversion - // between their return types does not require an adjustment. + // There is an entry for any virtual function declared in a class, + // whether it is a new function or overrides a base class function, + // unless it overrides a function from the primary base, and conversion + // between their return types does not require an adjustment. int64_t CurrentIndex = 0; diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 69b2fa222c..5de91ee335 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1007,8 +1007,6 @@ public: LValue EmitCastLValue(const CastExpr *E); LValue EmitNullInitializationLValue(const CXXZeroInitValueExpr *E); - LValue EmitPointerToDataMemberLValue(const FieldDecl *Field); - llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar); LValue EmitLValueForField(llvm::Value* Base, const FieldDecl* Field, diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index e865c2c0b9..71ae012116 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -348,6 +348,8 @@ public: llvm::Constant *EmitAnnotateAttr(llvm::GlobalValue *GV, const AnnotateAttr *AA, unsigned LineNo); + llvm::Constant *EmitPointerToDataMember(const FieldDecl *FD); + /// ErrorUnsupported - Print out an error that codegen doesn't support the /// specified stmt yet. /// \param OmitOnError - If true, then this error should only be emitted if no diff --git a/test/CodeGenCXX/pointers-to-data-members.cpp b/test/CodeGenCXX/pointers-to-data-members.cpp index c34bd5b114..79a631c93c 100644 --- a/test/CodeGenCXX/pointers-to-data-members.cpp +++ b/test/CodeGenCXX/pointers-to-data-members.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 | FileCheck %s -struct A { int a; }; +struct A { int a; int b; }; struct B { int b; }; struct C : B, A { }; @@ -17,23 +17,12 @@ namespace ZeroInit { // CHECK: @_ZN8ZeroInit1bE = global i64 -1, int A::* b = 0; - - void f() { - // CHECK: icmp ne i64 {{.*}}, -1 - if (a) { } - - // CHECK: icmp ne i64 {{.*}}, -1 - if (a != 0) { } - - // CHECK: icmp ne i64 -1, {{.*}} - if (0 != a) { } - - // CHECK: icmp eq i64 {{.*}}, -1 - if (a == 0) { } +} - // CHECK: icmp eq i64 -1, {{.*}} - if (0 == a) { } - } +// PR5674 +namespace PR5674 { + // CHECK: @_ZN6PR56742pbE = global i64 4 + int A::*pb = &A::b; } // Casts. @@ -56,3 +45,25 @@ void f() { } } + +// Comparisons +namespace Comparisons { + void f() { + int A::*a; + + // CHECK: icmp ne i64 {{.*}}, -1 + if (a) { } + + // CHECK: icmp ne i64 {{.*}}, -1 + if (a != 0) { } + + // CHECK: icmp ne i64 -1, {{.*}} + if (0 != a) { } + + // CHECK: icmp eq i64 {{.*}}, -1 + if (a == 0) { } + + // CHECK: icmp eq i64 -1, {{.*}} + if (0 == a) { } + } +}