diff options
Diffstat (limited to 'clang/lib/AST')
-rw-r--r-- | clang/lib/AST/Decl.cpp | 15 | ||||
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 13 | ||||
-rw-r--r-- | clang/lib/AST/RecordLayoutBuilder.cpp | 22 |
3 files changed, 40 insertions, 10 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 9132b0a1903..3caca9d7e6c 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/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/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 912b111d617..ec5111579a2 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/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/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 5223219a306..d094461dc35 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/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. /// |