diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-10-10 18:28:20 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-10-10 18:28:20 +0000 |
commit | a6b8b2c09610b8bc4330e948ece8b940c2386406 (patch) | |
tree | f59c822c4be1f7a73f2e536222e27fe1fe35c04d /lib/Sema | |
parent | fcdd2cb2fdf35f806dd800b369fe0772a1c8c26c (diff) |
Constant expression evaluation refactoring:
- Remodel Expr::EvaluateAsInt to behave like the other EvaluateAs* functions,
and add Expr::EvaluateKnownConstInt to capture the current fold-or-assert
behaviour.
- Factor out evaluation of bitfield bit widths.
- Fix a few places which would evaluate an expression twice: once to determine
whether it is a constant expression, then again to get the value.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141561 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 19 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 10 |
7 files changed, 31 insertions, 45 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 181d40ba01..412ed0ebb5 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2897,14 +2897,9 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { IntRange::forValueOfType(C, E->getType()); } - FieldDecl *BitField = E->getBitField(); - if (BitField) { - llvm::APSInt BitWidthAP = BitField->getBitWidth()->EvaluateAsInt(C); - unsigned BitWidth = BitWidthAP.getZExtValue(); - - return IntRange(BitWidth, + if (FieldDecl *BitField = E->getBitField()) + return IntRange(BitField->getBitWidthValue(C), BitField->getType()->isUnsignedIntegerOrEnumerationType()); - } return IntRange::forValueOfType(C, E->getType()); } @@ -3106,16 +3101,14 @@ bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, Expr *OriginalInit = Init->IgnoreParenImpCasts(); - llvm::APSInt Width(32); Expr::EvalResult InitValue; - if (!Bitfield->getBitWidth()->isIntegerConstantExpr(Width, S.Context) || - !OriginalInit->Evaluate(InitValue, S.Context) || + if (!OriginalInit->Evaluate(InitValue, S.Context) || !InitValue.Val.isInt()) return false; const llvm::APSInt &Value = InitValue.Val.getInt(); unsigned OriginalWidth = Value.getBitWidth(); - unsigned FieldWidth = Width.getZExtValue(); + unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context); if (OriginalWidth <= FieldWidth) return false; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 671ba615a8..2ce8a9acae 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -8757,11 +8757,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1]; ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(ivarDecl); - if (!Ivar->isBitField()) - return; - uint64_t BitFieldSize = - Ivar->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); - if (BitFieldSize == 0) + if (!Ivar->isBitField() || Ivar->getBitWidthValue(Context) == 0) return; ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CurContext); if (!ID) { diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index ea0b06bacb..e9e9d5eb3d 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2413,9 +2413,8 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, QualType ParamType = Param->getType().getNonReferenceType(); // Suppress copying zero-width bitfields. - if (const Expr *Width = Field->getBitWidth()) - if (Width->EvaluateAsInt(SemaRef.Context) == 0) - return false; + if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0) + return false; Expr *MemberExprBase = DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param, @@ -7975,9 +7974,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, } // Suppress assigning zero-width bitfields. - if (const Expr *Width = Field->getBitWidth()) - if (Width->EvaluateAsInt(Context) == 0) - continue; + if (Field->isBitField() && Field->getBitWidthValue(Context) == 0) + continue; QualType FieldType = Field->getType().getNonReferenceType(); if (FieldType->isIncompleteArrayType()) { @@ -8396,9 +8394,8 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, } // Suppress assigning zero-width bitfields. - if (const Expr *Width = Field->getBitWidth()) - if (Width->EvaluateAsInt(Context) == 0) - continue; + if (Field->isBitField() && Field->getBitWidthValue(Context) == 0) + continue; QualType FieldType = Field->getType().getNonReferenceType(); if (FieldType->isIncompleteArrayType()) { diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 21b2622b4a..82b5b17fa4 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1008,21 +1008,18 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, assert (ClsIvar && "missing class ivar"); // First, make sure the types match. - if (Context.getCanonicalType(ImplIvar->getType()) != - Context.getCanonicalType(ClsIvar->getType())) { + if (!Context.hasSameType(ImplIvar->getType(), ClsIvar->getType())) { Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_type) << ImplIvar->getIdentifier() << ImplIvar->getType() << ClsIvar->getType(); Diag(ClsIvar->getLocation(), diag::note_previous_definition); - } else if (ImplIvar->isBitField() && ClsIvar->isBitField()) { - Expr *ImplBitWidth = ImplIvar->getBitWidth(); - Expr *ClsBitWidth = ClsIvar->getBitWidth(); - if (ImplBitWidth->EvaluateAsInt(Context).getZExtValue() != - ClsBitWidth->EvaluateAsInt(Context).getZExtValue()) { - Diag(ImplBitWidth->getLocStart(), diag::err_conflicting_ivar_bitwidth) - << ImplIvar->getIdentifier(); - Diag(ClsBitWidth->getLocStart(), diag::note_previous_definition); - } + } else if (ImplIvar->isBitField() && ClsIvar->isBitField() && + ImplIvar->getBitWidthValue(Context) != + ClsIvar->getBitWidthValue(Context)) { + Diag(ImplIvar->getBitWidth()->getLocStart(), + diag::err_conflicting_ivar_bitwidth) << ImplIvar->getIdentifier(); + Diag(ClsIvar->getBitWidth()->getLocStart(), + diag::note_previous_definition); } // Make sure the names are identical. if (ImplIvar->getIdentifier() != ClsIvar->getIdentifier()) { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index ee985f4ba7..34be5db15b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1405,7 +1405,8 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, D, NameInfo, Ty, VK); // Just in case we're building an illegal pointer-to-member. - if (isa<FieldDecl>(D) && cast<FieldDecl>(D)->getBitWidth()) + FieldDecl *FD = dyn_cast<FieldDecl>(D); + if (FD && FD->isBitField()) E->setObjectKind(OK_BitField); return Owned(E); @@ -8389,7 +8390,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, // (If the specified member is a bit-field, the behavior is undefined.) // // We diagnose this as an error. - if (MemberDecl->getBitWidth()) { + if (MemberDecl->isBitField()) { Diag(OC.LocEnd, diag::err_offsetof_bitfield) << MemberDecl->getDeclName() << SourceRange(BuiltinLoc, RParenLoc); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index e9d4b82c8c..f195d10222 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -1850,15 +1850,15 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, llvm::APSInt DesignatedStartIndex, DesignatedEndIndex; if (D->isArrayDesignator()) { IndexExpr = DIE->getArrayIndex(*D); - DesignatedStartIndex = IndexExpr->EvaluateAsInt(SemaRef.Context); + DesignatedStartIndex = IndexExpr->EvaluateKnownConstInt(SemaRef.Context); DesignatedEndIndex = DesignatedStartIndex; } else { assert(D->isArrayRangeDesignator() && "Need array-range designator"); DesignatedStartIndex = - DIE->getArrayRangeStart(*D)->EvaluateAsInt(SemaRef.Context); + DIE->getArrayRangeStart(*D)->EvaluateKnownConstInt(SemaRef.Context); DesignatedEndIndex = - DIE->getArrayRangeEnd(*D)->EvaluateAsInt(SemaRef.Context); + DIE->getArrayRangeEnd(*D)->EvaluateKnownConstInt(SemaRef.Context); IndexExpr = DIE->getArrayRangeEnd(*D); // Codegen can't handle evaluating array range designators that have side diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index b30be82cee..7abfdd09de 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -626,7 +626,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, break; } - llvm::APSInt LoVal = Lo->EvaluateAsInt(Context); + llvm::APSInt LoVal = Lo->EvaluateKnownConstInt(Context); // Convert the value to the same width/sign as the condition. ConvertIntegerToTypeWarnOnOverflow(LoVal, CondWidth, CondIsSigned, @@ -705,7 +705,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, llvm::APSInt &LoVal = CaseRanges[i].first; CaseStmt *CR = CaseRanges[i].second; Expr *Hi = CR->getRHS(); - llvm::APSInt HiVal = Hi->EvaluateAsInt(Context); + llvm::APSInt HiVal = Hi->EvaluateKnownConstInt(Context); // Convert the value to the same width/sign as the condition. ConvertIntegerToTypeWarnOnOverflow(HiVal, CondWidth, CondIsSigned, @@ -845,7 +845,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, << ED->getDeclName(); } - llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context); + llvm::APSInt Hi = + RI->second->getRHS()->EvaluateKnownConstInt(Context); AdjustAPSInt(Hi, CondWidth, CondIsSigned); while (EI != EIend && EI->first < Hi) EI++; @@ -873,7 +874,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // Drop unneeded case ranges for (; RI != CaseRanges.end(); RI++) { - llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context); + llvm::APSInt Hi = + RI->second->getRHS()->EvaluateKnownConstInt(Context); AdjustAPSInt(Hi, CondWidth, CondIsSigned); if (EI->first <= Hi) break; |