aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ASTContext.h3
-rw-r--r--include/clang/AST/Decl.h8
-rw-r--r--lib/AST/Decl.cpp15
-rw-r--r--lib/AST/ExprConstant.cpp13
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp22
-rw-r--r--lib/CodeGen/CGBlocks.cpp14
-rw-r--r--lib/CodeGen/CGCXXABI.cpp4
-rw-r--r--lib/CodeGen/CGCXXABI.h3
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp5
-rw-r--r--lib/CodeGen/CGDecl.cpp4
-rw-r--r--lib/CodeGen/CGExprConstant.cpp527
-rw-r--r--lib/CodeGen/CodeGenModule.cpp7
-rw-r--r--lib/CodeGen/CodeGenModule.h10
-rw-r--r--lib/CodeGen/ItaniumCXXABI.cpp49
-rw-r--r--test/CodeGen/2007-09-28-PackedUnionMember.c2
-rw-r--r--test/CodeGenCXX/blocks.cpp8
-rw-r--r--test/CodeGenCXX/const-init-cxx11.cpp188
-rw-r--r--test/CodeGenCXX/pr9965.cpp1
18 files changed, 646 insertions, 237 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index c272580650..226613641b 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -1309,6 +1309,9 @@ public:
/// of class definition.
const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD);
+ /// Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
+ uint64_t getFieldOffset(const ValueDecl *FD) const;
+
bool isNearlyEmpty(const CXXRecordDecl *RD) const;
MangleContext *createMangleContext();
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 4221239ec8..a5e5fcd39b 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -1024,9 +1024,11 @@ public:
/// \brief Attempt to evaluate the value of the initializer attached to this
/// declaration, and produce notes explaining why it cannot be evaluated or is
- /// not a constant expression. Returns true if evaluation succeeded.
- /// The value can be obtained by calling getEvaluatedValue.
- bool evaluateValue(llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const;
+ /// not a constant expression. Returns a pointer to the value if evaluation
+ /// succeeded, 0 otherwise.
+ APValue *evaluateValue() const;
+ APValue *evaluateValue(
+ llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const;
/// \brief Return the already-evaluated value of this variable's
/// initializer, or NULL if the value is not yet known. Returns pointer
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 9132b0a190..3caca9d7e6 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1379,15 +1379,20 @@ EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const {
return Eval;
}
-bool VarDecl::evaluateValue(
- llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
+APValue *VarDecl::evaluateValue() const {
+ llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+ return evaluateValue(Notes);
+}
+
+APValue *VarDecl::evaluateValue(
+ llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
EvaluatedStmt *Eval = ensureEvaluatedStmt();
// We only produce notes indicating why an initializer is non-constant the
// first time it is evaluated. FIXME: The notes won't always be emitted the
// first time we try evaluation, so might not be produced at all.
if (Eval->WasEvaluated)
- return !Eval->Evaluated.isUninit();
+ return Eval->Evaluated.isUninit() ? 0 : &Eval->Evaluated;
const Expr *Init = cast<Expr>(Eval->Value);
assert(!Init->isValueDependent());
@@ -1396,7 +1401,7 @@ bool VarDecl::evaluateValue(
// FIXME: Produce a diagnostic for self-initialization.
Eval->CheckedICE = true;
Eval->IsICE = false;
- return false;
+ return 0;
}
Eval->IsEvaluating = true;
@@ -1418,7 +1423,7 @@ bool VarDecl::evaluateValue(
Eval->IsICE = Notes.empty();
}
- return Result;
+ return Result ? &Eval->Evaluated : 0;
}
bool VarDecl::checkInitIsICE() const {
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 912b111d61..ec5111579a 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -5413,15 +5413,12 @@ bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const {
return true;
}
- // FIXME: Evaluating initializers for large arrays can cause performance
- // problems, and we don't use such values yet. Once we have a more efficient
- // array representation, this should be reinstated, and used by CodeGen.
- // The same problem affects large records.
+ // FIXME: Evaluating values of large array and record types can cause
+ // performance problems. Only do so in C++11 for now.
if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) &&
!Ctx.getLangOptions().CPlusPlus0x)
return false;
- // FIXME: If this is the initializer for an lvalue, pass that in.
EvalInfo Info(Ctx, Result);
return ::EvaluateAsRValue(Info, this, Result.Val);
}
@@ -5461,6 +5458,12 @@ bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const {
bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
const VarDecl *VD,
llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
+ // FIXME: Evaluating initializers for large array and record types can cause
+ // performance problems. Only do so in C++11 for now.
+ if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) &&
+ !Ctx.getLangOptions().CPlusPlus0x)
+ return false;
+
Expr::EvalStatus EStatus;
EStatus.Diag = &Notes;
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 5223219a30..d094461dc3 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -2153,6 +2153,28 @@ const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) {
return Entry;
}
+static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD) {
+ const ASTRecordLayout &Layout = C.getASTRecordLayout(FD->getParent());
+ return Layout.getFieldOffset(FD->getFieldIndex());
+}
+
+uint64_t ASTContext::getFieldOffset(const ValueDecl *VD) const {
+ uint64_t OffsetInBits;
+ if (const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
+ OffsetInBits = ::getFieldOffset(*this, FD);
+ } else {
+ const IndirectFieldDecl *IFD = cast<IndirectFieldDecl>(VD);
+
+ OffsetInBits = 0;
+ for (IndirectFieldDecl::chain_iterator CI = IFD->chain_begin(),
+ CE = IFD->chain_end();
+ CI != CE; ++CI)
+ OffsetInBits += ::getFieldOffset(*this, cast<FieldDecl>(*CI));
+ }
+
+ return OffsetInBits;
+}
+
/// getObjCLayout - Get or compute information about the layout of the
/// given interface.
///
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 8fc4344201..e6ecb6a88b 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -215,6 +215,7 @@ static bool isSafeForCXXConstantCapture(QualType type) {
/// acceptable because we make no promises about address stability of
/// captured variables.
static llvm::Constant *tryCaptureAsConstant(CodeGenModule &CGM,
+ CodeGenFunction *CGF,
const VarDecl *var) {
QualType type = var->getType();
@@ -235,7 +236,7 @@ static llvm::Constant *tryCaptureAsConstant(CodeGenModule &CGM,
const Expr *init = var->getInit();
if (!init) return 0;
- return CGM.EmitConstantExpr(init, var->getType());
+ return CGM.EmitConstantInit(*var, CGF);
}
/// Get the low bit of a nonzero character count. This is the
@@ -278,7 +279,8 @@ static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info,
/// Compute the layout of the given block. Attempts to lay the block
/// out with minimal space requirements.
-static void computeBlockInfo(CodeGenModule &CGM, CGBlockInfo &info) {
+static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
+ CGBlockInfo &info) {
ASTContext &C = CGM.getContext();
const BlockDecl *block = info.getBlockDecl();
@@ -342,7 +344,7 @@ static void computeBlockInfo(CodeGenModule &CGM, CGBlockInfo &info) {
// Otherwise, build a layout chunk with the size and alignment of
// the declaration.
- if (llvm::Constant *constant = tryCaptureAsConstant(CGM, variable)) {
+ if (llvm::Constant *constant = tryCaptureAsConstant(CGM, CGF, variable)) {
info.Captures[variable] = CGBlockInfo::Capture::makeConstant(constant);
continue;
}
@@ -497,7 +499,7 @@ static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) {
// Compute information about the layout, etc., of this block,
// pushing cleanups as necessary.
- computeBlockInfo(CGF.CGM, blockInfo);
+ computeBlockInfo(CGF.CGM, &CGF, blockInfo);
// Nothing else to do if it can be global.
if (blockInfo.CanBeGlobal) return;
@@ -604,7 +606,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
// layout for it.
if (!blockExpr->getBlockDecl()->hasCaptures()) {
CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName());
- computeBlockInfo(CGM, blockInfo);
+ computeBlockInfo(CGM, this, blockInfo);
blockInfo.BlockExpression = blockExpr;
return EmitBlockLiteral(blockInfo);
}
@@ -911,7 +913,7 @@ CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *blockExpr,
blockInfo.BlockExpression = blockExpr;
// Compute information about the layout, etc., of this block.
- computeBlockInfo(*this, blockInfo);
+ computeBlockInfo(*this, 0, blockInfo);
// Using that metadata, generate the actual block function.
llvm::Constant *blockFn;
diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp
index 248448ccdc..702029dd34 100644
--- a/lib/CodeGen/CGCXXABI.cpp
+++ b/lib/CodeGen/CGCXXABI.cpp
@@ -110,6 +110,10 @@ llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
return GetBogusMemberPointer(CGM, QualType(MPT, 0));
}
+llvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) {
+ return GetBogusMemberPointer(CGM, MPT);
+}
+
bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
// Fake answer.
return true;
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h
index c2abf35832..e86e639627 100644
--- a/lib/CodeGen/CGCXXABI.h
+++ b/lib/CodeGen/CGCXXABI.h
@@ -125,6 +125,9 @@ public:
virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
CharUnits offset);
+ /// Create a member pointer for the given member pointer constant.
+ virtual llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT);
+
/// Emit a comparison between two member pointers. Returns an i1.
virtual llvm::Value *
EmitMemberPointerComparison(CodeGenFunction &CGF,
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 31e4bcf5f8..ba89d3756e 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -1112,9 +1112,8 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
for (RecordDecl::decl_iterator I = RD->decls_begin(), E = RD->decls_end();
I != E; ++I)
if (const VarDecl *V = dyn_cast<VarDecl>(*I)) {
- llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
- if (V->getInit() && V->evaluateValue(Notes)) {
- APValue *Value = V->getEvaluatedValue();
+ if (V->getInit()) {
+ const APValue *Value = V->evaluateValue();
if (Value && Value->isInt()) {
llvm::ConstantInt *CI
= llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt());
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 05087f0e95..dd7cdb69a8 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -203,7 +203,7 @@ CodeGenFunction::CreateStaticVarDecl(const VarDecl &D,
llvm::GlobalVariable *
CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
llvm::GlobalVariable *GV) {
- llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), D.getType(), this);
+ llvm::Constant *Init = CGM.EmitConstantInit(D, this);
// If constant emission failed, then this should be a C++ static
// initializer.
@@ -972,7 +972,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
llvm::Constant *constant = 0;
if (emission.IsConstantAggregate) {
assert(!capturedByInit && "constant init contains a capturing block?");
- constant = CGM.EmitConstantExpr(D.getInit(), type, this);
+ constant = CGM.EmitConstantInit(D, this);
}
if (!constant) {
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index a8399d719f..f27586da04 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -44,14 +44,16 @@ class ConstStructBuilder {
public:
static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF,
InitListExpr *ILE);
-
-private:
+ static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF,
+ const APValue &Value, QualType ValTy);
+
+private:
ConstStructBuilder(CodeGenModule &CGM, CodeGenFunction *CGF)
: CGM(CGM), CGF(CGF), Packed(false),
NextFieldOffsetInChars(CharUnits::Zero()),
LLVMStructAlignment(CharUnits::One()) { }
- bool AppendField(const FieldDecl *Field, uint64_t FieldOffset,
+ void AppendField(const FieldDecl *Field, uint64_t FieldOffset,
llvm::Constant *InitExpr);
void AppendBitField(const FieldDecl *Field, uint64_t FieldOffset,
@@ -62,8 +64,10 @@ private:
void AppendTailPadding(CharUnits RecordSize);
void ConvertStructToPacked();
-
+
bool Build(InitListExpr *ILE);
+ void Build(const APValue &Val, QualType ValTy);
+ llvm::Constant *Finalize(QualType Ty);
CharUnits getAlignment(const llvm::Constant *C) const {
if (Packed) return CharUnits::One();
@@ -77,7 +81,7 @@ private:
}
};
-bool ConstStructBuilder::
+void ConstStructBuilder::
AppendField(const FieldDecl *Field, uint64_t FieldOffset,
llvm::Constant *InitCst) {
@@ -99,14 +103,13 @@ AppendField(const FieldDecl *Field, uint64_t FieldOffset,
// Convert the struct to a packed struct.
ConvertStructToPacked();
-
+
AlignedNextFieldOffsetInChars = NextFieldOffsetInChars;
}
if (AlignedNextFieldOffsetInChars < FieldOffsetInChars) {
// We need to append padding.
- AppendPadding(
- FieldOffsetInChars - NextFieldOffsetInChars);
+ AppendPadding(FieldOffsetInChars - NextFieldOffsetInChars);
assert(NextFieldOffsetInChars == FieldOffsetInChars &&
"Did not add enough padding!");
@@ -118,14 +121,12 @@ AppendField(const FieldDecl *Field, uint64_t FieldOffset,
Elements.push_back(InitCst);
NextFieldOffsetInChars = AlignedNextFieldOffsetInChars +
getSizeInChars(InitCst);
-
+
if (Packed)
- assert(LLVMStructAlignment == CharUnits::One() &&
+ assert(LLVMStructAlignment == CharUnits::One() &&
"Packed struct not byte-aligned!");
else
LLVMStructAlignment = std::max(LLVMStructAlignment, FieldAlignment);
-
- return true;
}
void ConstStructBuilder::AppendBitField(const FieldDecl *Field,
@@ -382,8 +383,7 @@ bool ConstStructBuilder::Build(InitListExpr *ILE) {
if (!Field->isBitField()) {
// Handle non-bitfield members.
- if (!AppendField(*Field, Layout.getFieldOffset(FieldNo), EltInit))
- return false;
+ AppendField(*Field, Layout.getFieldOffset(FieldNo), EltInit);
} else {
// Otherwise we have a bitfield.
AppendBitField(*Field, Layout.getFieldOffset(FieldNo),
@@ -391,6 +391,77 @@ bool ConstStructBuilder::Build(InitListExpr *ILE) {
}
}
+ return true;
+}
+
+void ConstStructBuilder::Build(const APValue &Val, QualType ValTy) {
+ RecordDecl *RD = ValTy->getAs<RecordType>()->getDecl();
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+
+ if (CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) {
+ unsigned BaseNo = 0;
+ for (CXXRecordDecl::base_class_iterator Base = CD->bases_begin(),
+ BaseEnd = CD->bases_end(); Base != BaseEnd; ++Base, ++BaseNo) {
+ // Build the base class subobject at the appropriately-offset location
+ // within this object.
+ const CXXRecordDecl *BD = Base->getType()->getAsCXXRecordDecl();
+ CharUnits BaseOffset = Layout.getBaseClassOffset(BD);
+ NextFieldOffsetInChars -= BaseOffset;
+
+ Build(Val.getStructBase(BaseNo), Base->getType());
+
+ NextFieldOffsetInChars += BaseOffset;
+ }
+ }
+
+ unsigned FieldNo = 0;
+ const FieldDecl *LastFD = 0;
+ bool IsMsStruct = RD->hasAttr<MsStructAttr>();
+
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
+ if (IsMsStruct) {
+ // Zero-length bitfields following non-bitfield members are
+ // ignored:
+ if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((*Field), LastFD)) {
+ --FieldNo;
+ continue;
+ }
+ LastFD = (*Field);
+ }
+
+ // If this is a union, skip all the fields that aren't being initialized.
+ if (RD->isUnion() && Val.getUnionField() != *Field)
+ continue;
+
+ // Don't emit anonymous bitfields, they just affect layout.
+ if (Field->isUnnamedBitfield()) {
+ LastFD = (*Field);
+ continue;
+ }
+
+ // Emit the value of the initializer.
+ const APValue &FieldValue =
+ RD->isUnion() ? Val.getUnionValue() : Val.getStructField(FieldNo);
+ llvm::Constant *EltInit =
+ CGM.EmitConstantValue(FieldValue, Field->getType(), CGF);
+ assert(EltInit && "EmitConstantValue can't fail");
+
+ if (!Field->isBitField()) {
+ // Handle non-bitfield members.
+ AppendField(*Field, Layout.getFieldOffset(FieldNo), EltInit);
+ } else {
+ // Otherwise we have a bitfield.
+ AppendBitField(*Field, Layout.getFieldOffset(FieldNo),
+ cast<llvm::ConstantInt>(EltInit));
+ }
+ }
+}
+
+llvm::Constant *ConstStructBuilder::Finalize(QualType Ty) {
+ RecordDecl *RD = Ty->getAs<RecordType>()->getDecl();
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+
CharUnits LayoutSizeInChars = Layout.getSize();
if (NextFieldOffsetInChars > LayoutSizeInChars) {
@@ -398,62 +469,69 @@ bool ConstStructBuilder::Build(InitListExpr *ILE) {
// we must have a flexible array member at the end.
assert(RD->hasFlexibleArrayMember() &&
"Must have flexible array member if struct is bigger than type!");
-
+
// No tail padding is necessary.
- return true;
- }
+ } else {
+ // Append tail padding if necessary.
+ AppendTailPadding(LayoutSizeInChars);
- CharUnits LLVMSizeInChars =
- NextFieldOffsetInChars.RoundUpToAlignment(LLVMStructAlignment);
+ CharUnits LLVMSizeInChars =
+ NextFieldOffsetInChars.RoundUpToAlignment(LLVMStructAlignment);
- // Check if we need to convert the struct to a packed struct.
- if (NextFieldOffsetInChars <= LayoutSizeInChars &&
- LLVMSizeInChars > LayoutSizeInChars) {
- assert(!Packed && "Size mismatch!");
-
- ConvertStructToPacked();
- assert(NextFieldOffsetInChars <= LayoutSizeInChars &&
- "Converting to packed did not help!");
- }
+ // Check if we need to convert the struct to a packed struct.
+ if (NextFieldOffsetInChars <= LayoutSizeInChars &&
+ LLVMSizeInChars > LayoutSizeInChars) {
+ assert(!Packed && "Size mismatch!");
- // Append tail padding if necessary.
- AppendTailPadding(LayoutSizeInChars);
+ ConvertStructToPacked();
+ assert(NextFieldOffsetInChars <= LayoutSizeInChars &&
+ "Converting to packed did not help!");
+ }
- assert(LayoutSizeInChars == NextFieldOffsetInChars &&
- "Tail padding mismatch!");
+ assert(LayoutSizeInChars == NextFieldOffsetInChars &&
+ "Tail padding mismatch!");
+ }
- return true;
-}
-
-llvm::Constant *ConstStructBuilder::
- BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF, InitListExpr *ILE) {
- ConstStructBuilder Builder(CGM, CGF);
-
- if (!Builder.Build(ILE))
- return 0;
-
// Pick the type to use. If the type is layout identical to the ConvertType
// type then use it, otherwise use whatever the builder produced for us.
llvm::StructType *STy =
llvm::ConstantStruct::getTypeForElements(CGM.getLLVMContext(),
- Builder.Elements,Builder.Packed);
- llvm::Type *ILETy = CGM.getTypes().ConvertType(ILE->getType());
- if (llvm::StructType *ILESTy = dyn_cast<llvm::StructType>(ILETy)) {
- if (ILESTy->isLayoutIdentical(STy))
- STy = ILESTy;
+ Elements, Packed);
+ llvm::Type *ValTy = CGM.getTypes().ConvertType(Ty);
+ if (llvm::StructType *ValSTy = dyn_cast<llvm::StructType>(ValTy)) {
+ if (ValSTy->isLayoutIdentical(STy))
+ STy = ValSTy;
}
-
- llvm::Constant *Result =
- llvm::ConstantStruct::get(STy, Builder.Elements);
-
- assert(Builder.NextFieldOffsetInChars.RoundUpToAlignment(
- Builder.getAlignment(Result)) ==
- Builder.getSizeInChars(Result) && "Size mismatch!");
-
+
+ llvm::Constant *Result = llvm::ConstantStruct::get(STy, Elements);
+
+ assert(NextFieldOffsetInChars.RoundUpToAlignment(getAlignment(Result)) ==
+ getSizeInChars(Result) && "Size mismatch!");
+
return Result;
}
-
+llvm::Constant *ConstStructBuilder::BuildStruct(CodeGenModule &CGM,
+ CodeGenFunction *CGF,
+ InitListExpr *ILE) {
+ ConstStructBuilder Builder(CGM, CGF);
+
+ if (!Builder.Build(ILE))
+ return 0;
+
+ return Builder.Finalize(ILE->getType());
+}
+
+llvm::Constant *ConstStructBuilder::BuildStruct(CodeGenModule &CGM,
+ CodeGenFunction *CGF,
+ const APValue &Val,
+ QualType ValTy) {
+ ConstStructBuilder Builder(CGM, CGF);
+ Builder.Build(Val, ValTy);
+ return Builder.Finalize(ValTy);
+}
+
+
//===----------------------------------------------------------------------===//
// ConstExprEmitter
//===----------------------------------------------------------------------===//
@@ -863,6 +941,22 @@ public:
} // end anonymous namespace.
+llvm::Constant *CodeGenModule::EmitConstantInit(const VarDecl &D,
+ CodeGenFunction *CGF) {
+ if (const APValue *Value = D.evaluateValue())
+ return EmitConstantValue(*Value, D.getType(), CGF);
+
+ const Expr *E = D.getInit();
+ assert(E && "No initializer to emit");
+
+ llvm::Constant* C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E));
+ if (C && C->getType()->isIntegerTy(1)) {
+ llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
+ C = llvm::ConstantExpr::getZExt(C, BoolTy);
+ }
+ return C;
+}
+
llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
QualType DestType,
CodeGenFunction *CGF) {
@@ -875,155 +969,192 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
else
Success = E->EvaluateAsRValue(Result, Context);
- if (Success && !Result.HasSideEffects) {
- switch (Result.Val.getKind()) {
- case APValue::Uninitialized:
- llvm_unreachable("Constant expressions should be initialized.");
- case APValue::LValue: {
- llvm::Type *DestTy = getTypes().ConvertTypeForMem(DestType);
- llvm::Constant *Offset =
- llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
- Result.Val.getLValueOffset().getQuantity());
-
- llvm::Constant *C;
- if (APValue::LValueBase LVBase = Result.Val.getLValueBase()) {
- C = ConstExprEmitter(*this, CGF).EmitLValue(LVBase);
-
- // Apply offset if necessary.
- if (!Offset->isNullValue()) {
- llvm::Type *Type = llvm::Type::getInt8PtrTy(VMContext);
- llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(C, Type);
- Casted = llvm::ConstantExpr::getGetElementPtr(Casted, Offset);
- C = llvm::ConstantExpr::getBitCast(Casted, C->getType());
- }
-
- // Convert to the appropriate type; this could be an lvalue for
- // an integer.
- if (isa<llvm::PointerType>(DestTy))
- return llvm::ConstantExpr::getBitCast(C, DestTy);
+ if (Success && !Result.HasSideEffects)
+ return EmitConstantValue(Result.Val, DestType, CGF);
- return llvm::ConstantExpr::getPtrToInt(C, DestTy);
- } else {
- C = Offset;
+ llvm::Constant* C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E));
+ if (C && C->getType()->isIntegerTy(1)) {
+ llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
+ C = llvm::ConstantExpr::getZExt(C, BoolTy);
+ }
+ return C;
+}
- // Convert to the appropriate type; this could be an lvalue for
- // an integer.
- if (isa<llvm::PointerType>(DestTy))
- return llvm::ConstantExpr::getIntToPtr(C, DestTy);
+llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
+ QualType DestType,
+ CodeGenFunction *CGF) {
+ switch (Value.getKind()) {
+ case APValue::Uninitialized:
+ llvm_unreachable("Constant expressions should be initialized.");
+ case APValue::LValue: {
+ llvm::Type *DestTy = getTypes().ConvertTypeForMem(DestType);
+ llvm::Constant *Offset =
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ Value.getLValueOffset().getQuantity());
+
+ llvm::Constant *C;
+ if (APValue::LValueBase LVBase = Value.getLValueBase()) {
+ // An array can be represented as an lvalue referring to the base.
+ if (isa<llvm::ArrayType>(DestTy)) {
+ assert(Offset->isNullValue() && "offset on array initializer");
+ return ConstExprEmitter(*this, CGF).Visit(
+ const_cast<Expr*>(LVBase.get<const Expr*>()));
+ }
- // If the types don't match this should only be a truncate.
- if (C->getType() != DestTy)
- return llvm::ConstantExpr::getTrunc(C, DestTy);
+ C = ConstExprEmitter(*this, CGF).EmitLValue(LVBase);
- return C;
+ // Apply offset if necessary.
+ if (!Offset->isNullValue()) {
+ llvm::Type *Type = llvm::Type::getInt8PtrTy(VMContext);
+ llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(C, Type);
+ Casted = llvm::ConstantExpr::getGetElementPtr(Casted, Offset);
+ C = llvm::ConstantExpr::getBitCast(Casted, C->getType());
}
- }
- case APValue::Int: {
- llvm::Constant *C = llvm::ConstantInt::get(VMContext,
- Result.Val.getInt());
- if (C->getType()->isIntegerTy(1)) {
- llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
- C = llvm::ConstantExpr::getZExt(C, BoolTy);
- }
- return C;
- }
- case APValue::ComplexInt: {
- llvm::Constant *Complex[2];
-
- Complex[0] = llvm::ConstantInt::get(VMContext,
- Result.Val.getComplexIntReal());
- Complex[1] = llvm::ConstantInt::get(VMContext,
- Result.Val.getComplexIntImag());
-
- // FIXME: the target may want to specify that this is packed.
- llvm::StructType *STy = llvm::StructType::get(Complex[0]->getType(),
- Complex[1]->getType(),
- NULL);
- return llvm::ConstantStruct::get(STy, Complex);
- }
- case APValue::Float: {
- const llvm::APFloat &Init = Result.Val.getFloat();
- if (&Init.getSemantics() == &llvm::APFloat::IEEEhalf)
- return llvm::ConstantInt::get(VMContext, Init.bitcastToAPInt());
- else
- return llvm::ConstantFP::get(VMContext, Init);
- }
- case APValue::ComplexFloat: {
- llvm::Constant *Complex[2];
-
- Complex[0] = llvm::ConstantFP::get(VMContext,
- Result.Val.getComplexFloatReal());
- Complex[1] = llvm::ConstantFP::get(VMContext,
- Result.Val.getComplexFloatImag());
-
- // FIXME: the target may want to specify that this is packed.
- llvm::StructType *STy = llvm::StructType::get(Complex[0]->getType(),
- Complex[1]->getType(),
- NULL);
- return llvm::ConstantStruct::get(STy, Complex);
- }
- case APValue::Vector: {
- SmallVector<llvm::Constant *, 4> Inits;
- unsigned NumElts = Result.Val.getVectorLength();
+ // Convert to the appropriate type; this could be an lvalue for
+ // an integer.
+ if (isa<llvm::PointerType>(DestTy))
+ return llvm::ConstantExpr::getBitCast(C, DestTy);
- if (Context.getLangOptions().AltiVec &&
- isa<CastExpr>(E) &&
- cast<CastExpr>(E)->getCastKind() == CK_VectorSplat) {
- // AltiVec vector initialization with a single literal
- APValue &Elt = Result.Val.getVectorElt(0);
+ return llvm::ConstantExpr::getPtrToInt(C, DestTy);
+ } else {
+ C = Offset;
- llvm::Constant* InitValue = Elt.isInt()
- ? cast<llvm::Constant>
- (llvm::ConstantInt::get(VMContext, Elt.getInt()))
- : cast<llvm::Constant>
- (llvm::ConstantFP::get(VMContext, Elt.getFloat()));
+ // Convert to the appropriate type; this could be an lvalue for
+ // an integer.
+ if (isa<llvm::PointerType>(DestTy))
+ return llvm::ConstantExpr::getIntToPtr(C, DestTy);
- for (unsigned i = 0; i != NumElts; ++i)
- Inits.push_back(InitValue);
+ // If the types don't match this should only be a truncate.
+ if (C->getType() != DestTy)
+ return llvm::ConstantExpr::getTrunc(C, DestTy);
- } else {
- for (unsigned i = 0; i != NumElts; ++i) {
- APValue &Elt = Result.Val.getVectorElt(i);
- if (Elt.isInt())
- Inits.push_back(llvm::ConstantInt::get(VMContext, Elt.getInt()));
- else
- Inits.push_back(llvm::ConstantFP::get(VMContext, Elt.getFloat()));
- }
- }
- return llvm::ConstantVector::get(Inits);
+ return C;
}
- case APValue::AddrLabelDiff: {
- const AddrLabelExpr *LHSExpr = Result.Val.getAddrLabelDiffLHS();
- const AddrLabelExpr *RHSExpr = Result.Val.getAddrLabelDiffRHS();
- llvm::Constant *LHS = EmitConstantExpr(LHSExpr, LHSExpr->getType(), CGF);
- llvm::Constant *RHS = EmitConstantExpr(RHSExpr, RHSExpr->getType(), CGF);
-
- // Compute difference
- llvm::Type *ResultType = getTypes().ConvertType(E->getType());
- LHS = llvm::ConstantExpr::getPtrToInt(LHS, IntPtrTy);
- RHS = llvm::ConstantExpr::getPtrToInt(RHS, IntPtrTy);
- llvm::Constant *AddrLabelDiff = llvm::ConstantExpr::getSub(LHS, RHS);
-
- // LLVM is a bit sensitive about the exact format of the
- // address-of-label difference; make sure to truncate after
- // the subtraction.
- return llvm::ConstantExpr::getTruncOrBitCast(AddrLabelDiff, ResultType);
+ }
+ case APValue::Int: {
+ llvm::Constant *C = llvm::ConstantInt::get(VMContext,
+ Value.getInt());
+
+ if (C->getType()->isIntegerTy(1)) {
+ llvm::Type *BoolTy = getTypes().ConvertTypeForMem(DestType);
+ C = llvm::ConstantExpr::getZExt(C, BoolTy);
}
- case APValue::Array:
- case APValue::Struct:
- case APValue::Union:
- case APValue::MemberPointer:
- break;
+ return C;
+ }
+ case APValue::ComplexInt: {
+ llvm::Constant *Complex[2];
+
+ Complex[0] = llvm::ConstantInt::get(VMContext,
+ Value.getComplexIntReal());
+ Complex[1] = llvm::ConstantInt::get(VMContext,
+ Value.getComplexIntImag());
+
+ // FIXME: the target may want to specify that this is packed.
+ llvm::StructType *STy = llvm::StructType::get(Complex[0]->getType(),
+ Complex[1]->getType(),
+ NULL);
+ return llvm::ConstantStruct::get(STy, Complex);
+ }
+ case APValue::Float: {
+ const llvm::APFloat &Init = Value.getFloat();
+ if (&Init.getSemantics() == &llvm::APFloat::IEEEhalf)
+ return llvm::ConstantInt::get(VMContext, Init.bitcastToAPInt());
+ else
+ return llvm::ConstantFP::get(VMContext, Init);
+ }
+ case APValue::ComplexFloat: {
+ llvm::Constant *Complex[2];
+
+ Complex[0] = llvm::ConstantFP::get(VMContext,
+ Value.getComplexFloatReal());
+ Complex[1] = llvm::ConstantFP::get(VMContext,
+ Value.getComplexFloatImag());
+
+ // FIXME: the target may want to specify that this is packed.
+ llvm::StructType *STy = llvm::StructType::get(Complex[0]->getType(),
+ Complex[1]->getType(),
+ NULL);
+ return llvm::ConstantStruct::get(STy, Complex);
+ }
+ case APValue::Vector: {
+ SmallVector<llvm::Constant *, 4> Inits;
+ unsigned NumElts = Value.getVectorLength();
+
+ for (unsigned i = 0; i != NumElts; ++i) {
+ const APValue &Elt = Value.getVectorElt(i);
+ if (Elt.isInt())
+ Inits.push_back(llvm::ConstantInt::get(VMContext, Elt.getInt()));
+ else
+ Inits.push_back(llvm::ConstantFP::get(VMContext, Elt.getFloat()));
}
+ return llvm::ConstantVector::get(Inits);
+ }
+ case APValue::AddrLabelDiff: {
+ const AddrLabelExpr *LHSExpr = Value.getAddrLabelDiffLHS();
+ const AddrLabelExpr *RHSExpr = Value.getAddrLabelDiffRHS();
+ llvm::Constant *LHS = EmitConstantExpr(LHSExpr, LHSExpr->getType(), CGF);
+ llvm::Constant *RHS = EmitConstantExpr(RHSExpr, RHSExpr->getType(), CGF);
+
+ // Compute difference
+ llvm::Type *ResultType = getTypes().ConvertType(DestType);
+ LHS = llvm::ConstantExpr::getPtrToInt(LHS, IntPtrTy);
+ RHS = llvm::ConstantExpr::getPtrToInt(RHS, IntPtrTy);
+ llvm::Constant *AddrLabelDiff = llvm::ConstantExpr::getSub(LHS, RHS);
+
+ // LLVM is a bit sensitive about the exact format of the
+ // address-of-label difference; make sure to truncate after
+ // the subtraction.
+ return llvm::ConstantExpr::getTruncOrBitCast(AddrLabelDiff, ResultType);
}
+ case APValue::Struct:
+ case APValue::Union:
+ return ConstStructBuilder::BuildStruct(*this, CGF, Value, DestType);
+ case APValue::Array: {
+ const ArrayType *CAT = Context.getAsArrayType(DestType);
+ unsigned NumElements = Value.getArraySize();
+ unsigned NumInitElts = Value.getArrayInitializedElts();
- llvm::Constant* C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E));
- if (C && C->getType()->isIntegerTy(1)) {
- llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
- C = llvm::ConstantExpr::getZExt(C, BoolTy);
+ std::vector<llvm::Constant*> Elts;
+ Elts.reserve(NumElements);
+
+ // Emit array filler, if there is one.
+ llvm::Constant *Filler = 0;
+ if (Value.hasArrayFiller())
+ Filler = EmitConstantValue(Value.getArrayFiller(),
+ CAT->getElementType(), CGF);
+
+ // Emit initializer elements.
+ llvm::Type *CommonElementType = 0;
+ for (unsigned I = 0; I < NumElements; ++I) {
+ llvm::Constant *C = Filler;
+ if (I < NumInitElts)
+ C = EmitConstantValue(Value.getArrayInitializedElt(I),
+ CAT->getElementType(), CGF);
+ if (I == 0)
+ CommonElementType = C->getType();
+ else if (C->getType() != CommonElementType)
+ CommonElementType = 0;
+ Elts.push_back(C);
+ }
+
+ if (!CommonElementType) {
+ // FIXME: Try to avoid packing the array
+ std::vector<llvm::Type*> Types;
+ for (unsigned i = 0; i < Elts.size(); ++i)
+ Types.push_back(Elts[i]->getType());
+ llvm::StructType *SType = llvm::StructType::get(VMContext, Types, true);
+ return llvm::ConstantStruct::get(SType, Elts);
+ }
+
+ llvm::ArrayType *AType =
+ llvm::ArrayType::get(CommonElementType, NumElements);
+ return llvm::ConstantArray::get(AType, Elts);
}
- return C;
+ case APValue::MemberPointer:
+ return getCXXABI().EmitMemberPointer(Value, DestType);
+ }
+ llvm_unreachable("Unknown APValue kind");
}
llvm::Constant *
@@ -1032,11 +1163,6 @@ CodeGenModule::GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E) {
return ConstExprEmitter(*this, 0).EmitLValue(E);
}
-static uint64_t getFieldOffset(ASTContext &C, const FieldDecl *field) {
- const ASTRecordLayout &layout = C.getASTRecordLayout(field->getParent());
- return layout.getFieldOffset(field->getFieldIndex());
-}
-
llvm::Constant *
CodeGenModule::getMemberPointerConstant(const UnaryOperator *uo) {
// Member pointer constants always have a very particular form.
@@ -1048,18 +1174,7 @@ CodeGenModule::getMemberPointerConstant(const UnaryOperator *uo) {
return getCXXABI().EmitMemberPointer(method);
// Otherwise, a member data pointer.
- uint64_t fieldOffset;
- if (const FieldDecl *field = dyn_cast<FieldDecl>(decl))
- fieldOffset = getFieldOffset(getContext(), field);
- else {
- const IndirectFieldDecl *ifield = cast<IndirectFieldDecl>(decl);
-
- fieldOffset = 0;
- for (IndirectFieldDecl::chain_iterator ci = ifield->chain_begin(),
- ce = ifield->chain_end(); ci != ce; ++ci)
- fieldOffset += getFieldOffset(getContext(), cast<FieldDecl>(*ci));
- }
-
+ uint64_t fieldOffset = getContext().getFieldOffset(decl);
CharUnits chars = getContext().toCharUnitsFromBits((int64_t) fieldOffset);
return getCXXABI().EmitMemberDataPointer(type, chars);
}
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 76918dd448..c993abc2ac 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1354,7 +1354,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
QualType ASTTy = D->getType();
bool NonConstInit = false;
- const Expr *InitExpr = D->getAnyInitializer();
+ const VarDecl *InitDecl;
+ const Expr *InitExpr = D->getAnyInitializer(InitDecl);
if (!InitExpr) {
// This is a tentative definition; tentative definitions are
@@ -1369,12 +1370,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
assert(!ASTTy->isIncompleteType() && "Unexpected incomplete type");
Init = EmitNullConstant(D->getType());
} else {
- Init = EmitConstantExpr(InitExpr, D->getType());
+ Init = EmitConstantInit(*InitDecl);
if (!Init) {
QualType T = InitExpr->getType();
if (D->getType()->isReferenceType())
T = D->getType();
-
+
if (getLangOptions().CPlusPlus) {
Init = EmitNullConstant(T);
NonConstInit = true;
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 4c839d1353..d94d10afc1 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -687,12 +687,22 @@ public:
llvm::Constant *getMemberPointerConstant(const UnaryOperator *e);
+ /// EmitConstantInit - Try to emit the initializer for the given declaration
+ /// as a constant; returns 0 if the expression cannot be emitted as a
+ /// constant.
+ llvm::Constant *EmitConstantInit(const VarDecl &D, CodeGenFunction *CGF = 0);
+
/// EmitConstantExpr - Try to emit the given expression as a
/// constant; returns 0 if the expression cannot be emitted as a
/// constant.
llvm::Constant *EmitConstantExpr(const Expr *E, QualType DestType,
CodeGenFunction *CGF = 0);
+ /// EmitConstantValue - Try to emit the given constant value as a
+ /// constant; returns 0 if the value cannot be emitted as a constant.
+ llvm::Constant *EmitConstantValue(const APValue &Value, QualType DestType,
+ CodeGenFunction *CGF = 0);
+
/// EmitNullConstant - Return the result of value-initializing the given
/// type, i.e. a null expression of the given type. This is usually,
/// but not always, an LLVM null constant.
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index c3f635aed6..969f03a8b0 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -82,6 +82,9 @@ public:
llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
CharUnits offset);
+ llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT);
+ llvm::Constant *BuildMemberPointer(const CXXMethodDecl *MD,
+ CharUnits ThisAdjustment);
llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
llvm::Value *L,
@@ -500,6 +503,11 @@ ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
}
llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+ return BuildMemberPointer(MD, CharUnits::Zero());
+}
+
+llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
+ CharUnits ThisAdjustment) {
assert(MD->isInstance() && "Member function must not be static!");
MD = MD->getCanonicalDecl();
@@ -524,14 +532,16 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
// discrimination as the least significant bit of ptr does for
// Itanium.
MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset);
- MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 1);
+ MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t,
+ 2 * ThisAdjustment.getQuantity() + 1);
} else {
// Itanium C++ ABI 2.3:
// For a virtual function, [the pointer field] is 1 plus the
// virtual table offset (in bytes) of the function,
// represented as a ptrdiff_t.
MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset + 1);
- MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
+ MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t,
+ ThisAdjustment.getQuantity());
}
} else {
const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
@@ -549,12 +559,45 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty);
MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, ptrdiff_t);
- MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
+ MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, (IsARM ? 2 : 1) *
+ ThisAdjustment.getQuantity());
}
return llvm::ConstantStruct::getAnon(MemPtr);
}
+llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP,
+ QualType MPType) {
+ const MemberPointerType *MPT = MPType->castAs<MemberPointerType>();
+ const ValueDecl *MPD = MP.getMemberPointerDecl();
+ if (!MPD)
+ return EmitNullMemberPointer(MPT);
+
+ // Compute the this-adjustment.
+ CharUnits ThisAdjustment = CharUnits::Zero();
+ ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath();
+ bool DerivedMember = MP.isMemberPointerToDerivedMember();
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext());
+ for (unsigned I = 0, N = Path.size(); I != N; ++I) {
+ const CXXRecordDecl *Base = RD;
+ const CXXRecordDecl *Derived = Path[I];
+ if (DerivedMember)
+ std::swap(Base, Derived);
+ ThisAdjustment +=
+ getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base);
+ RD = Path[I];
+ }
+ if (DerivedMember)
+ ThisAdjustment = -ThisAdjustment;
+
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD))
+ return BuildMemberPointer(MD, ThisAdjustment);
+
+ CharUnits FieldOffset =
+ getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
+ return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset);
+}
+
/// The comparison algorithm is pretty easy: the member pointers are
/// the same if they're either bitwise identical *or* both null.
///
diff --git a/test/CodeGen/2007-09-28-PackedUnionMember.c b/test/CodeGen/2007-09-28-PackedUnionMember.c
index 943480e4d8..f0183063dd 100644
--- a/test/CodeGen/2007-09-28-PackedUnionMember.c
+++ b/test/CodeGen/2007-09-28-PackedUnionMember.c
@@ -27,6 +27,7 @@ extern long bork(FuncPtr handler, const struct E *list);
static long hndlr()
{
struct H cmd = { 4, 412 };
+ struct H cmd2 = { 4, 412, 0 };
return 0;
}
void foo(void *inWindow) {
@@ -35,4 +36,3 @@ void foo(void *inWindow) {
};
bork(hndlr, events);
}
-
diff --git a/test/CodeGenCXX/blocks.cpp b/test/CodeGenCXX/blocks.cpp
index 921d94a138..3d7fcfddbe 100644
--- a/test/CodeGenCXX/blocks.cpp
+++ b/test/CodeGenCXX/blocks.cpp
@@ -203,3 +203,11 @@ namespace test6 {
// CHECK-NEXT: call void @_ZN5test63barEv()
// CHECK-NEXT: ret void
}
+
+namespace test7 {
+ int f() {
+ static int n;
+ int *const p = &n;
+ return ^{ return *p; }();
+ }
+}
diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp
index 5ec9a690f9..fb5d2cce00 100644
--- a/test/CodeGenCXX/const-init-cxx11.cpp
+++ b/test/CodeGenCXX/const-init-cxx11.cpp
@@ -1,5 +1,193 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin -emit-llvm -o - %s -std=c++11 | FileCheck %s
+// FIXME: The padding in all these objects should be zero-initialized.
+namespace StructUnion {
+ struct A {
+ int n;
+ double d;
+ union U {
+ constexpr U(int x) : x(x) {}
+ constexpr U(const char *y) : y(y) {}
+ int x;
+ const char *y;
+ } u;
+
+ constexpr A(int n, double d, int x) : n(n), d(d), u(x) {}
+ constexpr A(int n, double d, const char *y) : n(n), d(d), u(y) {}
+ };
+
+ // CHECK: @_ZN11StructUnion1aE = global {{.*}} { i32 1, double 2.000000e+00, {{.*}} { i32 3, [4 x i8] undef } }
+ extern constexpr A a(1, 2.0, 3);
+
+ // CHECK: @_ZN11StructUnion1bE = global {{.*}} { i32 4, double 5.000000e+00, {{.*}} { i8* getelementptr inbounds ([6 x i8]* @{{.*}}, i32 0, i32 0) } }
+ extern constexpr A b(4, 5, "hello");
+
+ struct B {
+ int n;
+ };
+
+ // CHECK: @_ZN11StructUnion1cE = global {{.*}} zeroinitializer
+ // CHECK: @_ZN11StructUnion2c2E = global {{.*}} zeroinitializer
+ B c;
+ B c2 = B();
+
+ // CHECK: @_ZN11StructUnion1dE = global {{.*}} zeroinitializer
+ B d[10];
+
+ struct C {
+ constexpr C() : c(0) {}
+ int c;
+ };
+
+ // CHECK: @_ZN11StructUnion1eE = global {{.*}} zeroinitializer
+ C e[10];
+
+ struct D {
+ constexpr D() : d(5) {}
+ int d;
+ };
+
+ // CHECK: @_ZN11StructUnion1fE = global {{.*}} { i32 5 }
+ D f;
+}
+
+namespace BaseClass {
+ template<typename T, unsigned> struct X : T {};
+ struct C { char c = 1; };
+ template<unsigned... Ns> struct Cs : X<C,Ns>... {};
+ struct N { int n = 3; };
+ struct D { double d = 4.0; };
+
+ template<typename ...Ts>
+ struct Test : Ts... { constexpr Test() : Ts()..., n(5) {} int n; };
+
+ using Test1 = Test<N, C, Cs<1,2>, D, X<C,1>>;
+ // CHECK: @_ZN9BaseClass2t1E = global {{.*}} { i32 3, i8 1, i8 1, i8 1, double 4.000000e+00, i8 1, i32 5 }, align 8
+ extern constexpr Test1 t1 = Test1();
+
+ struct DN : D, N {};
+ struct DND : DN, X<D,0> {};
+ struct DNN : DN, X<N,0> {};
+ // CHECK: @_ZN9BaseClass3dndE = global {{.*}} { double 4.000000e+00, i32 3, double 4.000000e+00 }
+ extern constexpr DND dnd = DND();
+ // Note, N subobject is laid out in DN subobject's tail padding.
+ // CHECK: @_ZN9BaseClass3dnnE = global {{.*}} { double 4.000000e+00, i32 3, i32 3 }
+ extern constexpr DNN dnn = DNN();
+
+ struct E {};
+ struct Test2 : X<E,0>, X<E,1>, X<E,2>, X<E,3> {};
+ // CHECK: @_ZN9BaseClass2t2E = global {{.*}} { [4 x i8] undef }
+ extern constexpr Test2 t2 = Test2();
+}
+
+namespace Array {
+ // CHECK: @_ZN5Array3arrE = constant [2 x i32] [i32 4, i32 0]
+ extern constexpr int arr[2] = { 4 };
+
+ // CHECK: @_ZN5Array1cE = constant [6 x [4 x i8]] [{{.*}} c"foo\00", [4 x i8] c"a\00\00\00", [4 x i8] c"bar\00", [4 x i8] c"xyz\00", [4 x i8] c"b\00\00\00", [4 x i8] c"123\00"]
+ extern constexpr char c[6][4] = { "foo", "a", { "bar" }, { 'x', 'y', 'z' }, { "b" }, '1', '2', '3' };
+
+ struct C { constexpr C() : n(5) {} int n, m = 3 * n + 1; };
+ // CHECK: @_ZN5Array5ctorsE = global [3 x {{.*}}] [{{.*}} { i32 5, i32 16 }, {{.*}} { i32 5, i32 16 }, {{.*}} { i32 5, i32 16 }]
+ extern const C ctors[3];
+ constexpr C ctors[3];
+
+ // CHECK: @_ZN5Array1dE = constant {{.*}} { [2 x i32] [i32 1, i32 2], [3 x i32] [i32 3, i32 4, i32 5] }
+ struct D { int n[2]; int m[3]; } extern constexpr d = { 1, 2, 3, 4, 5 };
+}
+
+namespace MemberPtr {
+ struct B1 {
+ int a, b;
+ virtual void f();
+ void g();
+ };
+ struct B2 {
+ int c, d;
+ virtual void h();
+ void i();
+ };
+ struct C : B1 {
+ int e;
+ virtual void j();
+ void k();
+ };
+ struct D : C, B2 {
+ int z;
+ virtual void l();
+ void m();
+ };
+
+ // CHECK: @_ZN9MemberPtr2daE = constant i64 8
+ // CHECK: @_ZN9MemberPtr2dbE = constant i64 12
+ // CHECK: @_ZN9MemberPtr2dcE = constant i64 32
+ // CHECK: @_ZN9MemberPtr2ddE = constant i64 36
+ // CHECK: @_ZN9MemberPtr2deE = constant i64 16
+ // CHECK: @_ZN9MemberPtr2dzE = constant i64 40
+ extern constexpr int (D::*da) = &B1::a;
+ extern constexpr int (D::*db) = &C::b;
+ extern constexpr int (D::*dc) = &B2::c;
+ extern constexpr int (D::*dd) = &D::d;
+ extern constexpr int (D::*de) = &C::e;
+ extern constexpr int (D::*dz) = &D::z;
+
+ // CHECK: @_ZN9MemberPtr2baE = constant i64 8
+ // CHECK: @_ZN9MemberPtr2bbE = constant i64 12
+ // CHECK: @_ZN9MemberPtr2bcE = constant i64 8
+ // CHECK: @_ZN9MemberPtr2bdE = constant i64 12
+ // CHECK: @_ZN9MemberPtr2beE = constant i64 16
+ // CHECK: @_ZN9MemberPtr3b1zE = constant i64 40
+ // CHECK: @_ZN9MemberPtr3b2zE = constant i64 16
+ extern constexpr int (B1::*ba) = (int(B1::*))&B1::a;
+ extern constexpr int (B1::*bb) = (int(B1::*))&C::b;
+ extern constexpr int (B2::*bc) = (int(B2::*))&B2::c;
+ extern constexpr int (B2::*bd) = (int(B2::*))&D::d;
+ extern constexpr int (B1::*be) = (int(B1::*))&C::e;
+ extern constexpr int (B1::*b1z) = (int(B1::*))&D::z;
+ extern constexpr int (B2::*b2z) = (int(B2::*))&D::z;
+
+ // CHECK: @_ZN9MemberPtr2dfE = constant {{.*}} { i64 1, i64 0 }
+ // CHECK: @_ZN9MemberPtr2dgE = constant {{.*}} { i64 {{.*}}2B11gEv{{.*}}, i64 0 }
+ // CHECK: @_ZN9MemberPtr2dhE = constant {{.*}} { i64 1, i64 24 }
+ // CHECK: @_ZN9MemberPtr2diE = constant {{.*}} { i64 {{.*}}2B21iEv{{.*}}, i64 24 }
+ // CHECK: @_ZN9MemberPtr2djE = constant {{.*}} { i64 9, i64 0 }
+ // CHECK: @_ZN9MemberPtr2dkE = constant {{.*}} { i64 {{.*}}1C1kEv{{.*}}, i64 0 }
+ // CHECK: @_ZN9MemberPtr2dlE = constant {{.*}} { i64 17, i64 0 }
+ // CHECK: @_ZN9MemberPtr2dmE = constant {{.*}} { i64 {{.*}}1D1mEv{{.*}}, i64 0 }
+ extern constexpr void (D::*df)() = &C::f;
+ extern constexpr void (D::*dg)() = &B1::g;
+ extern constexpr void (D::*dh)() = &B2::h;
+ extern constexpr void (D::*di)() = &D::i;
+ extern constexpr void (D::*dj)() = &C::j;
+ extern constexpr void (D::*dk)() = &C::k;
+ extern constexpr void (D::*dl)() = &D::l;
+ extern constexpr void (D::*dm)() = &D::m;
+
+ // CHECK: @_ZN9MemberPtr2bfE = constant {{.*}} { i64 1, i64 0 }
+ // CHECK: @_ZN9MemberPtr2bgE = constant {{.*}} { i64 {{.*}}2B11gEv{{.*}}, i64 0 }
+ // CHECK: @_ZN9MemberPtr2bhE = constant {{.*}} { i64 1, i64 0 }
+ // CHECK: @_ZN9MemberPtr2biE = constant {{.*}} { i64 {{.*}}2B21iEv{{.*}}, i64 0 }
+ // CHECK: @_ZN9MemberPtr2bjE = constant {{.*}} { i64 9, i64 0 }
+ // CHECK: @_ZN9MemberPtr2bkE = constant {{.*}} { i64 {{.*}}1C1kEv{{.*}}, i64 0 }
+ // CHECK: @_ZN9MemberPtr3b1lE = constant {{.*}} { i64 17, i64 0 }
+ // CHECK: @_ZN9MemberPtr3b1mE = constant {{.*}} { i64 {{.*}}1D1mEv{{.*}}, i64 0 }
+ // CHECK: @_ZN9MemberPtr3b2lE = constant {{.*}} { i64 17, i64 -24 }
+ // CHECK: @_ZN9MemberPtr3b2mE = constant {{.*}} { i64 {{.*}}1D1mEv{{.*}}, i64 -24 }
+ extern constexpr void (B1::*bf)() = (void(B1::*)())&C::f;
+ extern constexpr void (B1::*bg)() = (void(B1::*)())&B1::g;
+ extern constexpr void (B2::*bh)() = (void(B2::*)())&B2::h;
+ extern constexpr void (B2::*bi)() = (void(B2::*)())&D::i;
+ extern constexpr void (B1::*bj)() = (void(B1::*)())&C::j;
+ extern constexpr void (B1::*bk)() = (void(B1::*)())&C::k;
+ extern constexpr void (B1::*b1l)() = (void(B1::*)())&D::l;
+ extern constexpr void (B1::*b1m)() = (void(B1::*)())&D::m;
+ extern constexpr void (B2::*b2l)() = (void(B2::*)())&D::l;
+ extern constexpr void (B2::*b2m)() = (void(B2::*)())&D::m;
+}
+
+// Constant initialization tests go before this point,
+// dynamic initialization tests go after.
+
namespace CrossFuncLabelDiff {
// Make sure we refuse to constant-fold the variable b.
constexpr long a() { return (long)&&lbl + (0 && ({lbl: 0;})); }
diff --git a/test/CodeGenCXX/pr9965.cpp b/test/CodeGenCXX/pr9965.cpp
index 145fd4e424..f625f48c33 100644
--- a/test/CodeGenCXX/pr9965.cpp
+++ b/test/CodeGenCXX/pr9965.cpp
@@ -3,6 +3,7 @@ template<typename T>
struct X
{
X() = default;
+ ~X() {} // not a literal type
};
X<int> x;