diff options
Diffstat (limited to 'clang/lib/AST/Expr.cpp')
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 117 | 
1 files changed, 87 insertions, 30 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 3438c3aadc6b..73ddbc62482d 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -49,7 +49,7 @@ const Expr *Expr::getBestDynamicClassTypeExpr() const {      // Step into initializer for materialized temporaries.      if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) { -      E = MTE->GetTemporaryExpr(); +      E = MTE->getSubExpr();        continue;      } @@ -127,11 +127,7 @@ const Expr *Expr::skipRValueSubobjectAdjustments(    return E;  } -/// isKnownToHaveBooleanValue - Return true if this is an integer expression -/// that is known to return 0 or 1.  This happens for _Bool/bool expressions -/// but also int expressions which are produced by things like comparisons in -/// C. -bool Expr::isKnownToHaveBooleanValue() const { +bool Expr::isKnownToHaveBooleanValue(bool Semantic) const {    const Expr *E = IgnoreParens();    // If this value has _Bool type, it is obvious 0/1. @@ -142,7 +138,7 @@ bool Expr::isKnownToHaveBooleanValue() const {    if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {      switch (UO->getOpcode()) {      case UO_Plus: -      return UO->getSubExpr()->isKnownToHaveBooleanValue(); +      return UO->getSubExpr()->isKnownToHaveBooleanValue(Semantic);      case UO_LNot:        return true;      default: @@ -152,8 +148,9 @@ bool Expr::isKnownToHaveBooleanValue() const {    // Only look through implicit casts.  If the user writes    // '(int) (a && b)' treat it as an arbitrary int. +  // FIXME: Should we look through any cast expression in !Semantic mode?    if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) -    return CE->getSubExpr()->isKnownToHaveBooleanValue(); +    return CE->getSubExpr()->isKnownToHaveBooleanValue(Semantic);    if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {      switch (BO->getOpcode()) { @@ -172,24 +169,30 @@ bool Expr::isKnownToHaveBooleanValue() const {      case BO_Xor:  // Bitwise XOR operator.      case BO_Or:   // Bitwise OR operator.        // Handle things like (x==2)|(y==12). -      return BO->getLHS()->isKnownToHaveBooleanValue() && -             BO->getRHS()->isKnownToHaveBooleanValue(); +      return BO->getLHS()->isKnownToHaveBooleanValue(Semantic) && +             BO->getRHS()->isKnownToHaveBooleanValue(Semantic);      case BO_Comma:      case BO_Assign: -      return BO->getRHS()->isKnownToHaveBooleanValue(); +      return BO->getRHS()->isKnownToHaveBooleanValue(Semantic);      }    }    if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) -    return CO->getTrueExpr()->isKnownToHaveBooleanValue() && -           CO->getFalseExpr()->isKnownToHaveBooleanValue(); +    return CO->getTrueExpr()->isKnownToHaveBooleanValue(Semantic) && +           CO->getFalseExpr()->isKnownToHaveBooleanValue(Semantic);    if (isa<ObjCBoolLiteralExpr>(E))      return true;    if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E)) -    return OVE->getSourceExpr()->isKnownToHaveBooleanValue(); +    return OVE->getSourceExpr()->isKnownToHaveBooleanValue(Semantic); + +  if (const FieldDecl *FD = E->getSourceBitField()) +    if (!Semantic && FD->getType()->isUnsignedIntegerType() && +        !FD->getBitWidth()->isValueDependent() && +        FD->getBitWidthValue(FD->getASTContext()) == 1) +      return true;    return false;  } @@ -1675,6 +1678,15 @@ MemberExpr *MemberExpr::Create(    MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl,                                         NameInfo, T, VK, OK, NOUR); +  if (isa<FieldDecl>(MemberDecl)) { +    DeclContext *DC = MemberDecl->getDeclContext(); +    // dyn_cast_or_null is used to handle objC variables which do not +    // have a declaration context. +    CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(DC); +    if (RD && RD->isDependentContext() && RD->isCurrentInstantiation(DC)) +      E->setTypeDependent(T->isDependentType()); +  } +    if (HasQualOrFound) {      // FIXME: Wrong. We should be looking at the member declaration we found.      if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent()) { @@ -1811,7 +1823,7 @@ bool CastExpr::CastConsistency() const {      auto Ty = getType();      auto SETy = getSubExpr()->getType();      assert(getValueKindForType(Ty) == Expr::getValueKindForType(SETy)); -    if (/*isRValue()*/ !Ty->getPointeeType().isNull()) { +    if (isRValue()) {        Ty = Ty->getPointeeType();        SETy = SETy->getPointeeType();      } @@ -1891,7 +1903,7 @@ namespace {    const Expr *skipImplicitTemporary(const Expr *E) {      // Skip through reference binding to temporary.      if (auto *Materialize = dyn_cast<MaterializeTemporaryExpr>(E)) -      E = Materialize->GetTemporaryExpr(); +      E = Materialize->getSubExpr();      // Skip any temporary bindings; they're implicit.      if (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E)) @@ -2721,8 +2733,9 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,    case CXXDeleteExprClass:      return false;    case MaterializeTemporaryExprClass: -    return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr() -               ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); +    return cast<MaterializeTemporaryExpr>(this) +        ->getSubExpr() +        ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);    case CXXBindTemporaryExprClass:      return cast<CXXBindTemporaryExpr>(this)->getSubExpr()                 ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); @@ -2746,8 +2759,8 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {    case ImplicitCastExprClass:      return cast<ImplicitCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);    case MaterializeTemporaryExprClass: -    return cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr() -                                                      ->isOBJCGCCandidate(Ctx); +    return cast<MaterializeTemporaryExpr>(E)->getSubExpr()->isOBJCGCCandidate( +        Ctx);    case CStyleCastExprClass:      return cast<CStyleCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);    case DeclRefExprClass: { @@ -2822,7 +2835,7 @@ static Expr *IgnoreImpCastsExtraSingleStep(Expr *E) {      return SubE;    if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) -    return MTE->GetTemporaryExpr(); +    return MTE->getSubExpr();    if (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E))      return NTTP->getReplacement(); @@ -2838,7 +2851,7 @@ static Expr *IgnoreCastsSingleStep(Expr *E) {      return FE->getSubExpr();    if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) -    return MTE->GetTemporaryExpr(); +    return MTE->getSubExpr();    if (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E))      return NTTP->getReplacement(); @@ -2872,7 +2885,7 @@ static Expr *IgnoreImplicitSingleStep(Expr *E) {      return SubE;    if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) -    return MTE->GetTemporaryExpr(); +    return MTE->getSubExpr();    if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))      return BTE->getSubExpr(); @@ -2880,6 +2893,13 @@ static Expr *IgnoreImplicitSingleStep(Expr *E) {    return E;  } +static Expr *IgnoreImplicitAsWrittenSingleStep(Expr *E) { +  if (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) +    return ICE->getSubExprAsWritten(); + +  return IgnoreImplicitSingleStep(E); +} +  static Expr *IgnoreParensSingleStep(Expr *E) {    if (auto *PE = dyn_cast<ParenExpr>(E))      return PE->getSubExpr(); @@ -2959,6 +2979,10 @@ Expr *Expr::IgnoreImplicit() {    return IgnoreExprNodes(this, IgnoreImplicitSingleStep);  } +Expr *Expr::IgnoreImplicitAsWritten() { +  return IgnoreExprNodes(this, IgnoreImplicitAsWrittenSingleStep); +} +  Expr *Expr::IgnoreParens() {    return IgnoreExprNodes(this, IgnoreParensSingleStep);  } @@ -2996,10 +3020,38 @@ Expr *Expr::IgnoreParenNoopCasts(const ASTContext &Ctx) {    });  } +Expr *Expr::IgnoreUnlessSpelledInSource() { +  Expr *E = this; + +  Expr *LastE = nullptr; +  while (E != LastE) { +    LastE = E; +    E = E->IgnoreParenImpCasts(); + +    auto SR = E->getSourceRange(); + +    if (auto *C = dyn_cast<CXXConstructExpr>(E)) { +      if (C->getNumArgs() == 1) { +        Expr *A = C->getArg(0); +        if (A->getSourceRange() == SR || !isa<CXXTemporaryObjectExpr>(C)) +          E = A; +      } +    } + +    if (auto *C = dyn_cast<CXXMemberCallExpr>(E)) { +      Expr *ExprNode = C->getImplicitObjectArgument()->IgnoreParenImpCasts(); +      if (ExprNode->getSourceRange() == SR) +        E = ExprNode; +    } +  } + +  return E; +} +  bool Expr::isDefaultArgument() const {    const Expr *E = this;    if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E)) -    E = M->GetTemporaryExpr(); +    E = M->getSubExpr();    while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))      E = ICE->getSubExprAsWritten(); @@ -3011,7 +3063,7 @@ bool Expr::isDefaultArgument() const {  /// expressions.  static const Expr *skipTemporaryBindingsNoOpCastsAndParens(const Expr *E) {    if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E)) -    E = M->GetTemporaryExpr(); +    E = M->getSubExpr();    while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {      if (ICE->getCastKind() == CK_NoOp) @@ -3106,7 +3158,7 @@ bool Expr::isImplicitCXXThis() const {      if (const MaterializeTemporaryExpr *M                                        = dyn_cast<MaterializeTemporaryExpr>(E)) { -      E = M->GetTemporaryExpr(); +      E = M->getSubExpr();        continue;      } @@ -3283,8 +3335,9 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,      break;    }    case MaterializeTemporaryExprClass: -    return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr() -      ->isConstantInitializer(Ctx, false, Culprit); +    return cast<MaterializeTemporaryExpr>(this) +        ->getSubExpr() +        ->isConstantInitializer(Ctx, false, Culprit);    case SubstNonTypeTemplateParmExprClass:      return cast<SubstNonTypeTemplateParmExpr>(this)->getReplacement() @@ -3751,7 +3804,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx,      return NPCK_GNUNull;    } else if (const MaterializeTemporaryExpr *M                                     = dyn_cast<MaterializeTemporaryExpr>(this)) { -    return M->GetTemporaryExpr()->isNullPointerConstant(Ctx, NPC); +    return M->getSubExpr()->isNullPointerConstant(Ctx, NPC);    } else if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(this)) {      if (const Expr *Source = OVE->getSourceExpr())        return Source->isNullPointerConstant(Ctx, NPC); @@ -4460,7 +4513,7 @@ const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) {    if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e))      e = ewc->getSubExpr();    if (const MaterializeTemporaryExpr *m = dyn_cast<MaterializeTemporaryExpr>(e)) -    e = m->GetTemporaryExpr(); +    e = m->getSubExpr();    e = cast<CXXConstructExpr>(e)->getArg(0);    while (const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))      e = ice->getSubExpr(); @@ -4598,6 +4651,8 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {    case AO__c11_atomic_fetch_and:    case AO__c11_atomic_fetch_or:    case AO__c11_atomic_fetch_xor: +  case AO__c11_atomic_fetch_max: +  case AO__c11_atomic_fetch_min:    case AO__atomic_fetch_add:    case AO__atomic_fetch_sub:    case AO__atomic_fetch_and: @@ -4610,6 +4665,8 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {    case AO__atomic_or_fetch:    case AO__atomic_xor_fetch:    case AO__atomic_nand_fetch: +  case AO__atomic_min_fetch: +  case AO__atomic_max_fetch:    case AO__atomic_fetch_min:    case AO__atomic_fetch_max:      return 3;  | 
