diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:52:09 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:52:09 +0000 |
commit | 519fc96c475680de2cc49e7811dbbfadb912cbcc (patch) | |
tree | 310ca684459b7e9ae13c9a3b9abf308b3a634afe /lib/AST/Expr.cpp | |
parent | 2298981669bf3bd63335a4be179bc0f96823a8f4 (diff) |
Vendor import of stripped clang trunk r375505, the last commit beforevendor/clang/clang-trunk-r375505vendor/clang
the upstream Subversion repository was made read-only, and the LLVM
project migrated to GitHub:
https://llvm.org/svn/llvm-project/cfe/trunk@375505
Notes
Notes:
svn path=/vendor/clang/dist/; revision=353942
svn path=/vendor/clang/clang-r375505/; revision=353943; tag=vendor/clang/clang-trunk-r375505
Diffstat (limited to 'lib/AST/Expr.cpp')
-rw-r--r-- | lib/AST/Expr.cpp | 140 |
1 files changed, 136 insertions, 4 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 6ef77b8aee68..3438c3aadc6b 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -85,8 +85,8 @@ const Expr *Expr::skipRValueSubobjectAdjustments( CE->getCastKind() == CK_UncheckedDerivedToBase) && E->getType()->isRecordType()) { E = CE->getSubExpr(); - CXXRecordDecl *Derived - = cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl()); + auto *Derived = + cast<CXXRecordDecl>(E->getType()->castAs<RecordType>()->getDecl()); Adjustments.push_back(SubobjectAdjustment(CE, Derived)); continue; } @@ -185,6 +185,12 @@ bool Expr::isKnownToHaveBooleanValue() const { return CO->getTrueExpr()->isKnownToHaveBooleanValue() && CO->getFalseExpr()->isKnownToHaveBooleanValue(); + if (isa<ObjCBoolLiteralExpr>(E)) + return true; + + if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E)) + return OVE->getSourceExpr()->isKnownToHaveBooleanValue(); + return false; } @@ -2563,13 +2569,31 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, case CXXTemporaryObjectExprClass: case CXXConstructExprClass: { if (const CXXRecordDecl *Type = getType()->getAsCXXRecordDecl()) { - if (Type->hasAttr<WarnUnusedAttr>()) { + const auto *WarnURAttr = Type->getAttr<WarnUnusedResultAttr>(); + if (Type->hasAttr<WarnUnusedAttr>() || + (WarnURAttr && WarnURAttr->IsCXX11NoDiscard())) { WarnE = this; Loc = getBeginLoc(); R1 = getSourceRange(); return true; } } + + const auto *CE = cast<CXXConstructExpr>(this); + if (const CXXConstructorDecl *Ctor = CE->getConstructor()) { + const auto *WarnURAttr = Ctor->getAttr<WarnUnusedResultAttr>(); + if (WarnURAttr && WarnURAttr->IsCXX11NoDiscard()) { + WarnE = this; + Loc = getBeginLoc(); + R1 = getSourceRange(); + + if (unsigned NumArgs = CE->getNumArgs()) + R2 = SourceRange(CE->getArg(0)->getBeginLoc(), + CE->getArg(NumArgs - 1)->getEndLoc()); + return true; + } + } + return false; } @@ -3181,7 +3205,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, if (ILE->getType()->isRecordType()) { unsigned ElementNo = 0; - RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl(); + RecordDecl *RD = ILE->getType()->castAs<RecordType>()->getDecl(); for (const auto *Field : RD->fields()) { // If this is a union, skip all the fields that aren't being initialized. if (RD->isUnion() && ILE->getInitializedFieldInUnion() != Field) @@ -3379,6 +3403,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case CXXUuidofExprClass: case OpaqueValueExprClass: case SourceLocExprClass: + case ConceptSpecializationExprClass: // These never have a side-effect. return false; @@ -3448,6 +3473,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case ArrayInitLoopExprClass: case ParenListExprClass: case CXXPseudoDestructorExprClass: + case CXXRewrittenBinaryOperatorClass: case CXXStdInitializerListExprClass: case SubstNonTypeTemplateParmExprClass: case MaterializeTemporaryExprClass: @@ -3897,6 +3923,112 @@ bool Expr::refersToGlobalRegisterVar() const { return false; } +bool Expr::isSameComparisonOperand(const Expr* E1, const Expr* E2) { + E1 = E1->IgnoreParens(); + E2 = E2->IgnoreParens(); + + if (E1->getStmtClass() != E2->getStmtClass()) + return false; + + switch (E1->getStmtClass()) { + default: + return false; + case CXXThisExprClass: + return true; + case DeclRefExprClass: { + // DeclRefExpr without an ImplicitCastExpr can happen for integral + // template parameters. + const auto *DRE1 = cast<DeclRefExpr>(E1); + const auto *DRE2 = cast<DeclRefExpr>(E2); + return DRE1->isRValue() && DRE2->isRValue() && + DRE1->getDecl() == DRE2->getDecl(); + } + case ImplicitCastExprClass: { + // Peel off implicit casts. + while (true) { + const auto *ICE1 = dyn_cast<ImplicitCastExpr>(E1); + const auto *ICE2 = dyn_cast<ImplicitCastExpr>(E2); + if (!ICE1 || !ICE2) + return false; + if (ICE1->getCastKind() != ICE2->getCastKind()) + return false; + E1 = ICE1->getSubExpr()->IgnoreParens(); + E2 = ICE2->getSubExpr()->IgnoreParens(); + // The final cast must be one of these types. + if (ICE1->getCastKind() == CK_LValueToRValue || + ICE1->getCastKind() == CK_ArrayToPointerDecay || + ICE1->getCastKind() == CK_FunctionToPointerDecay) { + break; + } + } + + const auto *DRE1 = dyn_cast<DeclRefExpr>(E1); + const auto *DRE2 = dyn_cast<DeclRefExpr>(E2); + if (DRE1 && DRE2) + return declaresSameEntity(DRE1->getDecl(), DRE2->getDecl()); + + const auto *Ivar1 = dyn_cast<ObjCIvarRefExpr>(E1); + const auto *Ivar2 = dyn_cast<ObjCIvarRefExpr>(E2); + if (Ivar1 && Ivar2) { + return Ivar1->isFreeIvar() && Ivar2->isFreeIvar() && + declaresSameEntity(Ivar1->getDecl(), Ivar2->getDecl()); + } + + const auto *Array1 = dyn_cast<ArraySubscriptExpr>(E1); + const auto *Array2 = dyn_cast<ArraySubscriptExpr>(E2); + if (Array1 && Array2) { + if (!isSameComparisonOperand(Array1->getBase(), Array2->getBase())) + return false; + + auto Idx1 = Array1->getIdx(); + auto Idx2 = Array2->getIdx(); + const auto Integer1 = dyn_cast<IntegerLiteral>(Idx1); + const auto Integer2 = dyn_cast<IntegerLiteral>(Idx2); + if (Integer1 && Integer2) { + if (!llvm::APInt::isSameValue(Integer1->getValue(), + Integer2->getValue())) + return false; + } else { + if (!isSameComparisonOperand(Idx1, Idx2)) + return false; + } + + return true; + } + + // Walk the MemberExpr chain. + while (isa<MemberExpr>(E1) && isa<MemberExpr>(E2)) { + const auto *ME1 = cast<MemberExpr>(E1); + const auto *ME2 = cast<MemberExpr>(E2); + if (!declaresSameEntity(ME1->getMemberDecl(), ME2->getMemberDecl())) + return false; + if (const auto *D = dyn_cast<VarDecl>(ME1->getMemberDecl())) + if (D->isStaticDataMember()) + return true; + E1 = ME1->getBase()->IgnoreParenImpCasts(); + E2 = ME2->getBase()->IgnoreParenImpCasts(); + } + + if (isa<CXXThisExpr>(E1) && isa<CXXThisExpr>(E2)) + return true; + + // A static member variable can end the MemberExpr chain with either + // a MemberExpr or a DeclRefExpr. + auto getAnyDecl = [](const Expr *E) -> const ValueDecl * { + if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) + return DRE->getDecl(); + if (const auto *ME = dyn_cast<MemberExpr>(E)) + return ME->getMemberDecl(); + return nullptr; + }; + + const ValueDecl *VD1 = getAnyDecl(E1); + const ValueDecl *VD2 = getAnyDecl(E2); + return declaresSameEntity(VD1, VD2); + } + } +} + /// isArrow - Return true if the base expression is a pointer to vector, /// return false if the base expression is a vector. bool ExtVectorElementExpr::isArrow() const { |