<commit_before>//===- IndexBody.cpp - Indexing statements --------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "IndexingContext.h"
#include "clang/AST/RecursiveASTVisitor.h"

using namespace clang;
using namespace clang::index;

namespace {

class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
  IndexingContext &IndexCtx;
  const NamedDecl *Parent;
  const DeclContext *ParentDC;
  SmallVector<Stmt*, 16> StmtStack;

  typedef RecursiveASTVisitor<BodyIndexer> base;
public:
  BodyIndexer(IndexingContext &indexCtx,
              const NamedDecl *Parent, const DeclContext *DC)
    : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }

  bool shouldWalkTypesOfTypeLocs() const { return false; }

  bool dataTraverseStmtPre(Stmt *S) {
    StmtStack.push_back(S);
    return true;
  }

  bool dataTraverseStmtPost(Stmt *S) {
    assert(StmtStack.back() == S);
    StmtStack.pop_back();
    return true;
  }

  bool TraverseTypeLoc(TypeLoc TL) {
    IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
    return true;
  }

  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
    IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
    return true;
  }

  SymbolRoleSet getRolesForRef(const Expr *E,
                               SmallVectorImpl<SymbolRelation> &Relations) {
    SymbolRoleSet Roles{};
    assert(!StmtStack.empty() && E == StmtStack.back());
    if (StmtStack.size() == 1)
      return Roles;
    auto It = StmtStack.end()-2;
    while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) {
      if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) {
        if (ICE->getCastKind() == CK_LValueToRValue)
          Roles |= (unsigned)(unsigned)SymbolRole::Read;
      }
      if (It == StmtStack.begin())
        break;
      --It;
    }
    const Stmt *Parent = *It;

    if (auto BO = dyn_cast<BinaryOperator>(Parent)) {
      if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E)
        Roles |= (unsigned)SymbolRole::Write;

    } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) {
      if (UO->isIncrementDecrementOp()) {
        Roles |= (unsigned)SymbolRole::Read;
        Roles |= (unsigned)SymbolRole::Write;
      } else if (UO->getOpcode() == UO_AddrOf) {
        Roles |= (unsigned)SymbolRole::AddressOf;
      }

    } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
      if (CA->getLHS()->IgnoreParenCasts() == E) {
        Roles |= (unsigned)SymbolRole::Read;
        Roles |= (unsigned)SymbolRole::Write;
      }

    } else if (auto CE = dyn_cast<CallExpr>(Parent)) {
      if (CE->getCallee()->IgnoreParenCasts() == E) {
        addCallRole(Roles, Relations);
        if (auto *ME = dyn_cast<MemberExpr>(E)) {
          if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
            if (CXXMD->isVirtual() && !ME->hasQualifier()) {
              Roles |= (unsigned)SymbolRole::Dynamic;
              auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType();
              if (!BaseTy.isNull())
                if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl())
                  Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
                                         CXXRD);
            }
        }
      } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
        if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) {
          OverloadedOperatorKind Op = CXXOp->getOperator();
          if (Op == OO_Equal) {
            Roles |= (unsigned)SymbolRole::Write;
          } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) ||
                     Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual ||
                     Op == OO_PlusPlus || Op == OO_MinusMinus) {
            Roles |= (unsigned)SymbolRole::Read;
            Roles |= (unsigned)SymbolRole::Write;
          } else if (Op == OO_Amp) {
            Roles |= (unsigned)SymbolRole::AddressOf;
          }
        }
      }
    }

    return Roles;
  }

  void addCallRole(SymbolRoleSet &Roles,
                   SmallVectorImpl<SymbolRelation> &Relations) {
    Roles |= (unsigned)SymbolRole::Call;
    if (auto *FD = dyn_cast<FunctionDecl>(ParentDC))
      Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD);
    else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC))
      Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD);
  }

  bool VisitDeclRefExpr(DeclRefExpr *E) {
    SmallVector<SymbolRelation, 4> Relations;
    SymbolRoleSet Roles = getRolesForRef(E, Relations);
    return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
                                    Parent, ParentDC, Roles, Relations, E);
  }

  bool VisitMemberExpr(MemberExpr *E) {
    SourceLocation Loc = E->getMemberLoc();
    if (Loc.isInvalid())
      Loc = E->getLocStart();
    SmallVector<SymbolRelation, 4> Relations;
    SymbolRoleSet Roles = getRolesForRef(E, Relations);
    return IndexCtx.handleReference(E->getMemberDecl(), Loc,
                                    Parent, ParentDC, Roles, Relations, E);
  }

  bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
    for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
      if (D.isFieldDesignator() && D.getField())
        return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent,
                                        ParentDC, SymbolRoleSet(), {}, E);
    }
    return true;
  }

  bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
    SmallVector<SymbolRelation, 4> Relations;
    SymbolRoleSet Roles = getRolesForRef(E, Relations);
    return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
                                    Parent, ParentDC, Roles, Relations, E);
  }

  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
    auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
      if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
        return false;
      if (auto *RecE = dyn_cast<ObjCMessageExpr>(
              MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
        if (RecE->getMethodFamily() == OMF_alloc)
          return false;
      }
      return true;
    };

    if (ObjCMethodDecl *MD = E->getMethodDecl()) {
      SymbolRoleSet Roles{};
      SmallVector<SymbolRelation, 2> Relations;
      addCallRole(Roles, Relations);
      if (E->isImplicit())
        Roles |= (unsigned)SymbolRole::Implicit;

      if (isDynamic(E)) {
        Roles |= (unsigned)SymbolRole::Dynamic;
        if (auto *RecD = E->getReceiverInterface())
          Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD);
      }

      return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
                                      Parent, ParentDC, Roles, Relations, E);
    }
    return true;
  }

  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
    if (E->isExplicitProperty())
      return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
                                      Parent, ParentDC, SymbolRoleSet(), {}, E);

    // No need to do a handleReference for the objc method, because there will
    // be a message expr as part of PseudoObjectExpr.
    return true;
  }

  bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
    return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
                                    Parent, ParentDC, SymbolRoleSet(), {}, E);
  }

  bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
    return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
                                    Parent, ParentDC, SymbolRoleSet(), {}, E);
  }

  bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) {
    SymbolRoleSet Roles{};
    SmallVector<SymbolRelation, 2> Relations;
    addCallRole(Roles, Relations);
    Roles |= (unsigned)SymbolRole::Implicit;
    return IndexCtx.handleReference(MD, E->getLocStart(),
                                    Parent, ParentDC, Roles, Relations, E);
  }

  bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
    if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
      return passObjCLiteralMethodCall(MD, E);
    }
    return true;
  }

  bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
    if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
      return passObjCLiteralMethodCall(MD, E);
    }
    return true;
  }

  bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
    if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
      return passObjCLiteralMethodCall(MD, E);
    }
    return true;
  }

  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
    SymbolRoleSet Roles{};
    SmallVector<SymbolRelation, 2> Relations;
    addCallRole(Roles, Relations);
    return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
                                    Parent, ParentDC, Roles, Relations, E);
  }

  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
                                   DataRecursionQueue *Q = nullptr) {
    if (E->getOperatorLoc().isInvalid())
      return true; // implicit.
    return base::TraverseCXXOperatorCallExpr(E, Q);
  }

  bool VisitDeclStmt(DeclStmt *S) {
    if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
      IndexCtx.indexDeclGroupRef(S->getDeclGroup());
      return true;
    }

    DeclGroupRef DG = S->getDeclGroup();
    for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
      const Decl *D = *I;
      if (!D)
        continue;
      if (!IndexCtx.isFunctionLocalDecl(D))
        IndexCtx.indexTopLevelDecl(D);
    }

    return true;
  }

  bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
                             Expr *Init) {
    if (C->capturesThis() || C->capturesVLAType())
      return true;

    if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
      return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
                                      Parent, ParentDC, SymbolRoleSet());

    // FIXME: Lambda init-captures.
    return true;
  }

  // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
  // the things that we visit. Make sure to only visit the semantic form.
  // Also visit things that are in the syntactic form but not the semantic one,
  // for example the indices in DesignatedInitExprs.
  bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {

    class SyntacticFormIndexer :
              public RecursiveASTVisitor<SyntacticFormIndexer> {
      IndexingContext &IndexCtx;
      const NamedDecl *Parent;
      const DeclContext *ParentDC;
      bool Visited = false;

    public:
      SyntacticFormIndexer(IndexingContext &indexCtx,
                            const NamedDecl *Parent, const DeclContext *DC)
        : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }

      bool shouldWalkTypesOfTypeLocs() const { return false; }

      bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
        // Don't visit nested InitListExprs, this visitor will be called again
        // later on for the nested ones.
        if (Visited)
          return true;
        Visited = true;
        InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
        if (SyntaxForm) {
          for (Stmt *SubStmt : SyntaxForm->children()) {
            if (!TraverseStmt(SubStmt, Q))
              return false;
          }
        }
        return true;
      }

      bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
        for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
          if (D.isFieldDesignator())
            return IndexCtx.handleReference(D.getField(), D.getFieldLoc(),
                                            Parent, ParentDC, SymbolRoleSet(),
                                            {}, E);
        }
        return true;
      }
    };

    auto visitForm = [&](InitListExpr *Form) {
      for (Stmt *SubStmt : Form->children()) {
        if (!TraverseStmt(SubStmt, Q))
          return false;
      }
      return true;
    };

    InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
    InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;

    if (SemaForm) {
      // Visit things present in syntactic form but not the semantic form.
      if (SyntaxForm) {
        SyntacticFormIndexer(IndexCtx, Parent, ParentDC).TraverseStmt(SyntaxForm);
      }
      return visitForm(SemaForm);
    }

    // No semantic, try the syntactic.
    if (SyntaxForm) {
      return visitForm(SyntaxForm);
    }

    return true;
  }
};

} // anonymous namespace

void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
                                const DeclContext *DC) {
  if (!S)
    return;

  if (!DC)
    DC = Parent->getLexicalDeclContext();
  BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
}
<commit_msg>[index] Avoid using a RecursiveASTVisitor for SyntacticFormIndexer and iterate the DesignatedInitExprs of the InitListExpr directly.<commit_after>//===- IndexBody.cpp - Indexing statements --------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "IndexingContext.h"
#include "clang/AST/RecursiveASTVisitor.h"

using namespace clang;
using namespace clang::index;

namespace {

class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
  IndexingContext &IndexCtx;
  const NamedDecl *Parent;
  const DeclContext *ParentDC;
  SmallVector<Stmt*, 16> StmtStack;

  typedef RecursiveASTVisitor<BodyIndexer> base;
public:
  BodyIndexer(IndexingContext &indexCtx,
              const NamedDecl *Parent, const DeclContext *DC)
    : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }

  bool shouldWalkTypesOfTypeLocs() const { return false; }

  bool dataTraverseStmtPre(Stmt *S) {
    StmtStack.push_back(S);
    return true;
  }

  bool dataTraverseStmtPost(Stmt *S) {
    assert(StmtStack.back() == S);
    StmtStack.pop_back();
    return true;
  }

  bool TraverseTypeLoc(TypeLoc TL) {
    IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
    return true;
  }

  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
    IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
    return true;
  }

  SymbolRoleSet getRolesForRef(const Expr *E,
                               SmallVectorImpl<SymbolRelation> &Relations) {
    SymbolRoleSet Roles{};
    assert(!StmtStack.empty() && E == StmtStack.back());
    if (StmtStack.size() == 1)
      return Roles;
    auto It = StmtStack.end()-2;
    while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) {
      if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) {
        if (ICE->getCastKind() == CK_LValueToRValue)
          Roles |= (unsigned)(unsigned)SymbolRole::Read;
      }
      if (It == StmtStack.begin())
        break;
      --It;
    }
    const Stmt *Parent = *It;

    if (auto BO = dyn_cast<BinaryOperator>(Parent)) {
      if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E)
        Roles |= (unsigned)SymbolRole::Write;

    } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) {
      if (UO->isIncrementDecrementOp()) {
        Roles |= (unsigned)SymbolRole::Read;
        Roles |= (unsigned)SymbolRole::Write;
      } else if (UO->getOpcode() == UO_AddrOf) {
        Roles |= (unsigned)SymbolRole::AddressOf;
      }

    } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
      if (CA->getLHS()->IgnoreParenCasts() == E) {
        Roles |= (unsigned)SymbolRole::Read;
        Roles |= (unsigned)SymbolRole::Write;
      }

    } else if (auto CE = dyn_cast<CallExpr>(Parent)) {
      if (CE->getCallee()->IgnoreParenCasts() == E) {
        addCallRole(Roles, Relations);
        if (auto *ME = dyn_cast<MemberExpr>(E)) {
          if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
            if (CXXMD->isVirtual() && !ME->hasQualifier()) {
              Roles |= (unsigned)SymbolRole::Dynamic;
              auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType();
              if (!BaseTy.isNull())
                if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl())
                  Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
                                         CXXRD);
            }
        }
      } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
        if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) {
          OverloadedOperatorKind Op = CXXOp->getOperator();
          if (Op == OO_Equal) {
            Roles |= (unsigned)SymbolRole::Write;
          } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) ||
                     Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual ||
                     Op == OO_PlusPlus || Op == OO_MinusMinus) {
            Roles |= (unsigned)SymbolRole::Read;
            Roles |= (unsigned)SymbolRole::Write;
          } else if (Op == OO_Amp) {
            Roles |= (unsigned)SymbolRole::AddressOf;
          }
        }
      }
    }

    return Roles;
  }

  void addCallRole(SymbolRoleSet &Roles,
                   SmallVectorImpl<SymbolRelation> &Relations) {
    Roles |= (unsigned)SymbolRole::Call;
    if (auto *FD = dyn_cast<FunctionDecl>(ParentDC))
      Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD);
    else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC))
      Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD);
  }

  bool VisitDeclRefExpr(DeclRefExpr *E) {
    SmallVector<SymbolRelation, 4> Relations;
    SymbolRoleSet Roles = getRolesForRef(E, Relations);
    return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
                                    Parent, ParentDC, Roles, Relations, E);
  }

  bool VisitMemberExpr(MemberExpr *E) {
    SourceLocation Loc = E->getMemberLoc();
    if (Loc.isInvalid())
      Loc = E->getLocStart();
    SmallVector<SymbolRelation, 4> Relations;
    SymbolRoleSet Roles = getRolesForRef(E, Relations);
    return IndexCtx.handleReference(E->getMemberDecl(), Loc,
                                    Parent, ParentDC, Roles, Relations, E);
  }

  bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
    for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
      if (D.isFieldDesignator() && D.getField())
        return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent,
                                        ParentDC, SymbolRoleSet(), {}, E);
    }
    return true;
  }

  bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
    SmallVector<SymbolRelation, 4> Relations;
    SymbolRoleSet Roles = getRolesForRef(E, Relations);
    return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
                                    Parent, ParentDC, Roles, Relations, E);
  }

  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
    auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
      if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
        return false;
      if (auto *RecE = dyn_cast<ObjCMessageExpr>(
              MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
        if (RecE->getMethodFamily() == OMF_alloc)
          return false;
      }
      return true;
    };

    if (ObjCMethodDecl *MD = E->getMethodDecl()) {
      SymbolRoleSet Roles{};
      SmallVector<SymbolRelation, 2> Relations;
      addCallRole(Roles, Relations);
      if (E->isImplicit())
        Roles |= (unsigned)SymbolRole::Implicit;

      if (isDynamic(E)) {
        Roles |= (unsigned)SymbolRole::Dynamic;
        if (auto *RecD = E->getReceiverInterface())
          Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD);
      }

      return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
                                      Parent, ParentDC, Roles, Relations, E);
    }
    return true;
  }

  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
    if (E->isExplicitProperty())
      return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
                                      Parent, ParentDC, SymbolRoleSet(), {}, E);

    // No need to do a handleReference for the objc method, because there will
    // be a message expr as part of PseudoObjectExpr.
    return true;
  }

  bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
    return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
                                    Parent, ParentDC, SymbolRoleSet(), {}, E);
  }

  bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
    return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
                                    Parent, ParentDC, SymbolRoleSet(), {}, E);
  }

  bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) {
    SymbolRoleSet Roles{};
    SmallVector<SymbolRelation, 2> Relations;
    addCallRole(Roles, Relations);
    Roles |= (unsigned)SymbolRole::Implicit;
    return IndexCtx.handleReference(MD, E->getLocStart(),
                                    Parent, ParentDC, Roles, Relations, E);
  }

  bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
    if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
      return passObjCLiteralMethodCall(MD, E);
    }
    return true;
  }

  bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
    if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
      return passObjCLiteralMethodCall(MD, E);
    }
    return true;
  }

  bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
    if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
      return passObjCLiteralMethodCall(MD, E);
    }
    return true;
  }

  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
    SymbolRoleSet Roles{};
    SmallVector<SymbolRelation, 2> Relations;
    addCallRole(Roles, Relations);
    return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
                                    Parent, ParentDC, Roles, Relations, E);
  }

  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
                                   DataRecursionQueue *Q = nullptr) {
    if (E->getOperatorLoc().isInvalid())
      return true; // implicit.
    return base::TraverseCXXOperatorCallExpr(E, Q);
  }

  bool VisitDeclStmt(DeclStmt *S) {
    if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
      IndexCtx.indexDeclGroupRef(S->getDeclGroup());
      return true;
    }

    DeclGroupRef DG = S->getDeclGroup();
    for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
      const Decl *D = *I;
      if (!D)
        continue;
      if (!IndexCtx.isFunctionLocalDecl(D))
        IndexCtx.indexTopLevelDecl(D);
    }

    return true;
  }

  bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
                             Expr *Init) {
    if (C->capturesThis() || C->capturesVLAType())
      return true;

    if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
      return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
                                      Parent, ParentDC, SymbolRoleSet());

    // FIXME: Lambda init-captures.
    return true;
  }

  // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
  // the things that we visit. Make sure to only visit the semantic form.
  // Also visit things that are in the syntactic form but not the semantic one,
  // for example the indices in DesignatedInitExprs.
  bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
    auto visitForm = [&](InitListExpr *Form) {
      for (Stmt *SubStmt : Form->children()) {
        if (!TraverseStmt(SubStmt, Q))
          return false;
      }
      return true;
    };

    auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool {
      for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
        if (D.isFieldDesignator())
          return IndexCtx.handleReference(D.getField(), D.getFieldLoc(),
                                          Parent, ParentDC, SymbolRoleSet(),
                                          {}, E);
      }
      return true;
    };

    InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
    InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;

    if (SemaForm) {
      // Visit things present in syntactic form but not the semantic form.
      if (SyntaxForm) {
        for (Expr *init : SyntaxForm->inits()) {
          if (auto *DIE = dyn_cast<DesignatedInitExpr>(init))
            visitSyntacticDesignatedInitExpr(DIE);
        }
      }
      return visitForm(SemaForm);
    }

    // No semantic, try the syntactic.
    if (SyntaxForm) {
      return visitForm(SyntaxForm);
    }

    return true;
  }
};

} // anonymous namespace

void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
                                const DeclContext *DC) {
  if (!S)
    return;

  if (!DC)
    DC = Parent->getLexicalDeclContext();
  BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
}
<|endoftext|>


<commit_before>//  Copyright 2016 Peter Georg
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

#include "sendmemorywindow.hpp"
#include "connection.hpp"

pMR::ofi::SendMemoryWindow::SendMemoryWindow(
    std::shared_ptr<Connection> const connection, void *buffer,
    std::size_t const sizeByte)
    : mConnection(connection)
    , mMemoryRegion(connection->getDomain(), buffer, {sizeByte},
#ifdef OFI_RMA
          FI_WRITE)
#else
          FI_SEND)
#endif // OFI_RMA
{
    mConnection->checkMessageSize({sizeByte});
}

void pMR::ofi::SendMemoryWindow::init()
{
}

void pMR::ofi::SendMemoryWindow::post(std::size_t const sizeByte)
{
#ifdef OFI_RMA
    mConnection->pollActiveRecv();
#else
    if(!mConnection->checkEagerSize(sizeByte))
    {
        mConnection->pollActiveRecv();
    }
#endif // OFI_RMA

#if defined OFI_RMA && !defined OFI_RMA_CONTROL
    mConnection->postRecvAddressToActive();
#elif !defined OFI_RMA || defined OFI_RMA_TARGET_RX
    mConnection->postRecvToActive();
#endif // OFI_RMA & !OFI_RMA_CONTROL // !OFI_RMA || OFI_RMA_TARGET_RX

#ifdef OFI_RMA
    mConnection->postWriteToActive(mMemoryRegion, {sizeByte});
#else
    mConnection->postSendToActive(mMemoryRegion, {sizeByte});
#endif // OFI_RMA

#ifndef OFI_RMA
    if(mConnection->checkEagerSize(sizeByte))
    {
        mConnection->pollActiveRecv();
    }
#endif // !OFI_RMA
}

void pMR::ofi::SendMemoryWindow::wait()
{
    mConnection->pollActiveSend();
}
<commit_msg>Revert "Try to improve perf for eager"<commit_after>//  Copyright 2016 Peter Georg
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

#include "sendmemorywindow.hpp"
#include "connection.hpp"

pMR::ofi::SendMemoryWindow::SendMemoryWindow(
    std::shared_ptr<Connection> const connection, void *buffer,
    std::size_t const sizeByte)
    : mConnection(connection)
    , mMemoryRegion(connection->getDomain(), buffer, {sizeByte},
#ifdef OFI_RMA
          FI_WRITE)
#else
          FI_SEND)
#endif // OFI_RMA
{
    mConnection->checkMessageSize({sizeByte});
}

void pMR::ofi::SendMemoryWindow::init()
{
}

void pMR::ofi::SendMemoryWindow::post(std::size_t const sizeByte)
{
    mConnection->pollActiveRecv();

#if defined OFI_RMA && !defined OFI_RMA_CONTROL
    mConnection->postRecvAddressToActive();
#elif !defined OFI_RMA || defined OFI_RMA_TARGET_RX
    mConnection->postRecvToActive();
#endif // OFI_RMA & !OFI_RMA_CONTROL // !OFI_RMA || OFI_RMA_TARGET_RX

#ifdef OFI_RMA
    mConnection->postWriteToActive(mMemoryRegion, {sizeByte});
#else
    mConnection->postSendToActive(mMemoryRegion, {sizeByte});
#endif // OFI_RMA
}

void pMR::ofi::SendMemoryWindow::wait()
{
    mConnection->pollActiveSend();
}
<|endoftext|>


<commit_before>#include "providers/twitch/TwitchHelpers.hpp"
#include "debug/Log.hpp"

namespace chatterino {

bool trimChannelName(const QString &channelName, QString &outChannelName)
{
    if (channelName.length() < 3) {
        log("channel name length below 3");
        return false;
    }

    outChannelName = channelName.mid(1);

    return true;
}

}  // namespace chatterino
<commit_msg>fix notices about "short channel name" channels being sent to all channels<commit_after>#include "providers/twitch/TwitchHelpers.hpp"
#include "debug/Log.hpp"

namespace chatterino {

bool trimChannelName(const QString &channelName, QString &outChannelName)
{
    if (channelName.length() < 2) {
        log("channel name length below 2");
        return false;
    }

    outChannelName = channelName.mid(1);

    return true;
}

}  // namespace chatterino
<|endoftext|>


<commit_before>#include "bitmapimage.h"

BitmapImage::BitmapImage()
{
    m_Image = NULL;
    qDebug() << "Image drawn!" << endl;
}

BitmapImage::BitmapImage(const BitmapImage &image)
{
    m_pixmap = image.m_pixmap;
    boundaries = image.boundaries;
    m_Color = image.m_Color;
}

BitmapImage::BitmapImage(Object *parent, QRect boundaries, QColor color)
{
    myParent = parent;
    this->boundaries = boundaries;
    m_Image = new QImage(boundaries.size(), QImage::Format_ARGB32_Premultiplied);
    m_Image->fill(color.rgba());
}

BitmapImage::BitmapImage(Object *parent, QRect boundaries, QImage image)
{
    myParent = parent;
    this->boundaries = boundaries;
    m_Image = new QImage(image);
    if(m_Image->width() != boundaries.width() && m_Image->height() != boundaries.height()) qDebug() << "Error 0001: Failed to load Image" << endl;
}

BitmapImage::BitmapImage(QRect boundaries, QColor color)
{
    this->boundaries = boundaries;
    QPixmap temp(boundaries.width(), boundaries.height());
    temp.fill(color);
    QPainter painter(&temp);
    if(!temp.isNull())
    {
        painter.drawPixmap(0, 0, temp);
    }
    painter.end();
    m_pixmap = temp;
}

void BitmapImage::paintImage(QPainter &painter)
{
    painter.drawPixmap(0, 0, m_pixmap);
}

void BitmapImage::paintImage(QPainter &painter, QPoint knownPoint, Brush brush, QPoint points[])
{
    painter.setBrush(brush.getBrush());
    painter.setPen(brush.getPen());
    qDebug() << "Brush"  << brush.getBrush() << endl;
    qDebug() << "Pen" << brush.getPen() << endl;
    painter.drawLine(points[1], knownPoint);
    qDebug() << "Color"  << brush.getColor() << endl;
    qDebug() << "Drawing In progress" << endl;
}

void BitmapImage::paintImage(QPainter &painter, QTabletEvent *event, Brush brush, QPoint points[])
{
    /*
    painter.setBrush(brush.getBrush());
    painter.setPen(brush.getPen());
    painter.drawLine(points[1], event->pos());
    */
    qDebug() << "Brush"  << brush.getBrush() << endl;
    qDebug() << "Pen" << brush.getPen() << endl;
    qDebug() << "Color"  << brush.getColor() << endl;

    //painter = QPainter(&m_pixmap);
    painter.setBrush(brush.getBrush());
    painter.setPen(brush.getPen());
    painter.drawLine(points[1], event->pos());
}

void BitmapImage::paintImage(QTabletEvent *event, Brush brush, QPoint points[])
{
    QPainter painter(&m_pixmap);
    painter.setBrush(brush.getBrush());
    painter.setPen(brush.getPen());
    painter.drawLine(points[1], event->pos());
}

void BitmapImage::paintImage(QMouseEvent *event, Brush brush, QPoint points[])
{
    QPainter painter(&m_pixmap);
    painter.setBrush(brush.getBrush());
    painter.setPen(brush.getPen());
    qDebug() << brush.getBrush() << endl;
    qDebug() << brush.getPen() << endl;
    qDebug() << "Brush Width: " << brush.getPen().width() << endl;

    painter.drawLine(points[1], event->pos());
}

<commit_msg>0.025c<commit_after>#include "bitmapimage.h"

BitmapImage::BitmapImage()
{
    m_Image = NULL;
    qDebug() << "Image drawn!" << endl;
}

BitmapImage::BitmapImage(const BitmapImage &image)
{
    m_pixmap = image.m_pixmap;
    boundaries = image.boundaries;
    m_Color = image.m_Color;
}

BitmapImage::BitmapImage(Object *parent, QRect boundaries, QColor color)
{
    myParent = parent;
    this->boundaries = boundaries;
    m_Image = new QImage(boundaries.size(), QImage::Format_ARGB32_Premultiplied);
    m_Image->fill(color.rgba());
}

BitmapImage::BitmapImage(Object *parent, QRect boundaries, QImage image)
{
    myParent = parent;
    this->boundaries = boundaries;
    m_Image = new QImage(image);
    if(m_Image->width() != boundaries.width() && m_Image->height() != boundaries.height()) qDebug() << "Error 0001: Failed to load Image" << endl;
}

BitmapImage::BitmapImage(QRect boundaries, QColor color)
{
    this->boundaries = boundaries;
    QPixmap temp(boundaries.width(), boundaries.height());
    temp.fill(color);
    QPainter painter(&temp);
    if(!temp.isNull())
    {
        painter.drawPixmap(0, 0, temp);
    }
    painter.end();
    m_pixmap = temp;
}

void BitmapImage::paintImage(QPainter &painter)
{
    painter.drawPixmap(0, 0, m_pixmap);
}

void BitmapImage::paintImage(QPainter &painter, QPoint knownPoint, Brush brush, QPoint points[])
{
    painter.setBrush(brush.getBrush());
    painter.setPen(brush.getPen());
    qDebug() << "Brush"  << brush.getBrush() << endl;
    qDebug() << "Pen" << brush.getPen() << endl;
    painter.drawLine(points[1], knownPoint);
    qDebug() << "Color"  << brush.getColor() << endl;
    qDebug() << "Drawing In progress" << endl;
}

void BitmapImage::paintImage(QPainter &painter, QTabletEvent *event, Brush brush, QPoint points[])
{
    /*
    painter.setBrush(brush.getBrush());
    painter.setPen(brush.getPen());
    painter.drawLine(points[1], event->pos());
    */
    qDebug() << "Brush"  << brush.getBrush() << endl;
    qDebug() << "Pen" << brush.getPen() << endl;
    qDebug() << "Color"  << brush.getColor() << endl;

    //painter = QPainter(&m_pixmap);
    painter.setBrush(brush.getBrush());
    painter.setPen(brush.getPen());
    painter.drawLine(points[1], event->pos());
}

void BitmapImage::paintImage(QTabletEvent *event, Brush brush, QPoint points[])
{
    QPainter painter(&m_pixmap);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setBrush(brush.getBrush());
    painter.setPen(brush.getPen());
    painter.drawLine(points[1], event->pos());
}

void BitmapImage::paintImage(QMouseEvent *event, Brush brush, QPoint points[])
{
    QPainter painter(&m_pixmap);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setBrush(brush.getBrush());
    painter.setPen(brush.getPen());
    qDebug() << brush.getBrush() << endl;
    qDebug() << brush.getPen() << endl;
    qDebug() << "Brush Width: " << brush.getPen().width() << endl;

    painter.drawLine(points[1], event->pos());

}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkIconGlyphFilter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkIconGlyphFilter.h"

#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkFloatArray.h"
#include "vtkIdList.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPointLocator.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"

vtkCxxRevisionMacro(vtkIconGlyphFilter, "1.3");
vtkStandardNewMacro(vtkIconGlyphFilter);

//-----------------------------------------------------------------------------
vtkIconGlyphFilter::vtkIconGlyphFilter()
{
  this->IconSize[0] = 1;
  this->IconSize[1] = 1;
  this->IconSheetSize[0] = 1;
  this->IconSheetSize[1] = 1;

  this->SetInputArrayToProcess(0, 0, 0,
    vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS);
}

//-----------------------------------------------------------------------------
vtkIconGlyphFilter::~vtkIconGlyphFilter()
{
}

//-----------------------------------------------------------------------------
void vtkIconGlyphFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "IconSize: " << IconSize[0] << " " << IconSize[1] << endl;
  os << indent << "IconSheetSize: " << IconSheetSize[0] << " " << IconSheetSize[1] << endl;
}

//-----------------------------------------------------------------------------
int vtkIconGlyphFilter::RequestData(vtkInformation *vtkNotUsed(request),
                                  vtkInformationVector **inputVector,
                                  vtkInformationVector *outputVector)
{
  // Get the information object.
  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  // Get the data objects.
  vtkPointSet *input = vtkPointSet::SafeDownCast(
                                     inInfo->Get(vtkDataObject::DATA_OBJECT()));
  vtkPolyData *output = vtkPolyData::SafeDownCast(
                                    outInfo->Get(vtkDataObject::DATA_OBJECT()));

  int numPoints = input->GetNumberOfPoints();

  if (numPoints <= 0)
    {
    // nothing to do...
    return 1;
    }

  vtkIntArray* scalars = vtkIntArray::SafeDownCast(
    this->GetInputArrayToProcess(0, inputVector));
  if (!scalars)
    {
    vtkErrorMacro("Input Scalars must be specified to index into the icon sheet.");
    return 0;
    }

  double point[3], textureCoord[2];
  double sheetXDim = this->IconSheetSize[0]/this->IconSize[0];
  double sheetYDim = this->IconSheetSize[1]/this->IconSize[1];
  int iconIndex = 0;
  int j, k;

  vtkPoints * outPoints = vtkPoints::New();
  outPoints->Allocate(4 * numPoints);

  vtkCellArray * outCells = vtkCellArray::New();
  outCells->Allocate(outCells->EstimateSize(numPoints, 4));

  vtkFloatArray *outTCoords = vtkFloatArray::New();
  outTCoords->SetNumberOfComponents(2);
  outTCoords->Allocate(8*numPoints);

  for(int i = 0; i < numPoints; i++)
    {
    iconIndex = scalars->GetValue(i);
    input->GetPoint(i, point);
    outPoints->InsertNextPoint(point[0] - 0.5, point[1] - 0.5, point[2]);

    this->IconConvertIndex(iconIndex, j, k);
    textureCoord[0] = j/sheetXDim;
    textureCoord[1] = k/sheetYDim;
    outTCoords->InsertTuple(i * 4, textureCoord);

    outPoints->InsertNextPoint(point[0] + 0.5, point[1] - 0.5, point[2]);

    this->IconConvertIndex(iconIndex, j, k);
    textureCoord[0] = (j + 1.0)/sheetXDim;
    textureCoord[1] = k/sheetYDim;
    outTCoords->InsertTuple(i * 4 + 1, textureCoord);

    outPoints->InsertNextPoint(point[0] + 0.5, point[1] + 0.5, point[2]);

    this->IconConvertIndex(iconIndex, j, k);
    textureCoord[0] = (j + 1.0)/sheetXDim;
    textureCoord[1] = (k + 1.0)/sheetYDim;
    outTCoords->InsertTuple(i * 4 + 2, textureCoord);

    outPoints->InsertNextPoint(point[0] - 0.5, point[1] + 0.5, point[2]);

    this->IconConvertIndex(iconIndex, j, k);
    textureCoord[0] = j/sheetXDim;
    textureCoord[1] = (k + 1.0)/sheetYDim;
    outTCoords->InsertTuple(i * 4 + 3, textureCoord);

    outCells->InsertNextCell(4);
    outCells->InsertCellPoint(i * 4);
    outCells->InsertCellPoint(i * 4 + 1);
    outCells->InsertCellPoint(i * 4 + 2);
    outCells->InsertCellPoint(i * 4 + 3);
    }

  output->SetPoints(outPoints);
  outPoints->Delete();

  outTCoords->SetName("TextureCoordinates");
  output->GetPointData()->SetTCoords(outTCoords);
  outTCoords->Delete();

  output->SetPolys(outCells);
  outCells->Delete();

  return 1;
}

<commit_msg>ENH: Fix PrintSelf test for vtkIconGlyphFilter.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkIconGlyphFilter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkIconGlyphFilter.h"

#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkFloatArray.h"
#include "vtkIdList.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPointLocator.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"

vtkCxxRevisionMacro(vtkIconGlyphFilter, "1.4");
vtkStandardNewMacro(vtkIconGlyphFilter);

//-----------------------------------------------------------------------------
vtkIconGlyphFilter::vtkIconGlyphFilter()
{
  this->IconSize[0] = 1;
  this->IconSize[1] = 1;
  this->IconSheetSize[0] = 1;
  this->IconSheetSize[1] = 1;

  this->SetInputArrayToProcess(0, 0, 0,
    vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS);
}

//-----------------------------------------------------------------------------
vtkIconGlyphFilter::~vtkIconGlyphFilter()
{
}

//-----------------------------------------------------------------------------
void vtkIconGlyphFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "IconSize: " << this->IconSize[0] << " " << this->IconSize[1] << endl;
  os << indent << "IconSheetSize: " << this->IconSheetSize[0] << " " << this->IconSheetSize[1] << endl;
}

//-----------------------------------------------------------------------------
int vtkIconGlyphFilter::RequestData(vtkInformation *vtkNotUsed(request),
                                  vtkInformationVector **inputVector,
                                  vtkInformationVector *outputVector)
{
  // Get the information object.
  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  // Get the data objects.
  vtkPointSet *input = vtkPointSet::SafeDownCast(
                                     inInfo->Get(vtkDataObject::DATA_OBJECT()));
  vtkPolyData *output = vtkPolyData::SafeDownCast(
                                    outInfo->Get(vtkDataObject::DATA_OBJECT()));

  int numPoints = input->GetNumberOfPoints();

  if (numPoints <= 0)
    {
    // nothing to do...
    return 1;
    }

  vtkIntArray* scalars = vtkIntArray::SafeDownCast(
    this->GetInputArrayToProcess(0, inputVector));
  if (!scalars)
    {
    vtkErrorMacro("Input Scalars must be specified to index into the icon sheet.");
    return 0;
    }

  double point[3], textureCoord[2];
  double sheetXDim = this->IconSheetSize[0]/this->IconSize[0];
  double sheetYDim = this->IconSheetSize[1]/this->IconSize[1];
  int iconIndex = 0;
  int j, k;

  vtkPoints * outPoints = vtkPoints::New();
  outPoints->Allocate(4 * numPoints);

  vtkCellArray * outCells = vtkCellArray::New();
  outCells->Allocate(outCells->EstimateSize(numPoints, 4));

  vtkFloatArray *outTCoords = vtkFloatArray::New();
  outTCoords->SetNumberOfComponents(2);
  outTCoords->Allocate(8*numPoints);

  for(int i = 0; i < numPoints; i++)
    {
    iconIndex = scalars->GetValue(i);
    input->GetPoint(i, point);
    outPoints->InsertNextPoint(point[0] - 0.5, point[1] - 0.5, point[2]);

    this->IconConvertIndex(iconIndex, j, k);
    textureCoord[0] = j/sheetXDim;
    textureCoord[1] = k/sheetYDim;
    outTCoords->InsertTuple(i * 4, textureCoord);

    outPoints->InsertNextPoint(point[0] + 0.5, point[1] - 0.5, point[2]);

    this->IconConvertIndex(iconIndex, j, k);
    textureCoord[0] = (j + 1.0)/sheetXDim;
    textureCoord[1] = k/sheetYDim;
    outTCoords->InsertTuple(i * 4 + 1, textureCoord);

    outPoints->InsertNextPoint(point[0] + 0.5, point[1] + 0.5, point[2]);

    this->IconConvertIndex(iconIndex, j, k);
    textureCoord[0] = (j + 1.0)/sheetXDim;
    textureCoord[1] = (k + 1.0)/sheetYDim;
    outTCoords->InsertTuple(i * 4 + 2, textureCoord);

    outPoints->InsertNextPoint(point[0] - 0.5, point[1] + 0.5, point[2]);

    this->IconConvertIndex(iconIndex, j, k);
    textureCoord[0] = j/sheetXDim;
    textureCoord[1] = (k + 1.0)/sheetYDim;
    outTCoords->InsertTuple(i * 4 + 3, textureCoord);

    outCells->InsertNextCell(4);
    outCells->InsertCellPoint(i * 4);
    outCells->InsertCellPoint(i * 4 + 1);
    outCells->InsertCellPoint(i * 4 + 2);
    outCells->InsertCellPoint(i * 4 + 3);
    }

  output->SetPoints(outPoints);
  outPoints->Delete();

  outTCoords->SetName("TextureCoordinates");
  output->GetPointData()->SetTCoords(outTCoords);
  outTCoords->Delete();

  output->SetPolys(outCells);
  outCells->Delete();

  return 1;
}

<|endoftext|>


<commit_before>/*
* Copyright (C) 2016 Airbus Defence and Space
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "CCPACSWingSparPosition.h"

#include "CCPACSWingCSStructure.h"
#include "CCPACSWingSegment.h"
#include "CCPACSWingComponentSegment.h"
#include "CCPACSWingSpars.h"
#include "CTiglError.h"
#include "CPACSWingRibPoint.h"
#include "CPACSEtaXsiPoint.h"
#include "CTiglUIDManager.h"

namespace tigl
{

CCPACSWingSparPosition::CCPACSWingSparPosition(CCPACSWingSparPositions* sparPositions, CTiglUIDManager* uidMgr)
: generated::CPACSSparPosition(sparPositions, uidMgr) {}

bool CCPACSWingSparPosition::isOnInnerSectionElement() const
{
    if (GetSparPositionEtaXsi_choice2()) {
        return GetEta() < 1.E-6;
    }
    else {
        return false;
    }
}

bool CCPACSWingSparPosition::isOnOuterSectionElement() const
{
    if (GetSparPositionEtaXsi_choice2()) {
        return (1 - GetEta()) < 1.E-6;
    }
    else {
        return false;
    }
}

bool CCPACSWingSparPosition::isOnSectionElement() const
{
    return isOnInnerSectionElement() || isOnOuterSectionElement();
}

bool CCPACSWingSparPosition::isOnRib() const
{
    return m_sparPositionRib_choice1 ? true : false;
}

const std::string& CCPACSWingSparPosition::GetReferenceUID() const
{
    if (m_sparPositionRib_choice1) {
        return m_sparPositionRib_choice1->GetRibDefinitionUID();
    }
    else if (m_sparPositionEtaXsi_choice2){
        return m_sparPositionEtaXsi_choice2->GetReferenceUID();
    }
    else {
        throw CTiglError("Invalid choice type");
    }
}

double CCPACSWingSparPosition::GetEta() const
{
    if (!m_sparPositionEtaXsi_choice2) {
        throw CTiglError("SparPosition is not defined via eta/xsi. Please check InputType first before calling CCPACSWingSparPosition::GetXsi()");
    }
    return m_sparPositionEtaXsi_choice2->GetEta();
}

double CCPACSWingSparPosition::GetXsi() const
{
    if (m_sparPositionRib_choice1) {
        return m_sparPositionRib_choice1->GetXsi();
    }
    else if (m_sparPositionEtaXsi_choice2) {
        return m_sparPositionEtaXsi_choice2->GetXsi();
    }
    throw CTiglError("Invalid spar position type");
}

const generated::CPACSEtaXsiPoint &CCPACSWingSparPosition::GetEtaXsiPoint() const
{
    if (!GetSparPositionEtaXsi_choice2()) {
        throw CTiglError("No EtaXsiPoint definied in SparPosition '" + GetUID() + "'");
    }

    return GetSparPositionEtaXsi_choice2().value();
}

const generated::CPACSWingRibPoint& CCPACSWingSparPosition::GetRibPoint() const
{
    if (!GetSparPositionRib_choice1()) {
        throw CTiglError("No RibPoint definied in SparPosition '" + GetUID() + "'");
    }

    return GetSparPositionRib_choice1().value();
}

int WingRibPointGetRibNumber(const generated::CPACSWingRibPoint& ribPoint)
{
    return ribPoint.GetRibNumber().value_or(1);
}

std::string WingSparPosGetElementUID(const CCPACSWingSparPosition & pos)
{
    if (!pos.isOnSectionElement()) {
        throw CTiglError("Spar Postitiong is not on section element");
    }

    const CTiglUIDManager::TypedPtr tp = pos.GetUIDManager().ResolveObject(pos.GetEtaXsiPoint().GetReferenceUID());
    if (tp.type == &typeid(CCPACSWingComponentSegment)) {
        const CCPACSWingComponentSegment& cs = *reinterpret_cast<CCPACSWingComponentSegment*>(tp.ptr);
        const SegmentList& segments = cs.GetSegmentList();
        if (pos.isOnInnerSectionElement()) {
            return segments.front()->GetInnerSectionElementUID();
        }
        else {
            return segments.back()->GetOuterSectionElementUID();
        }
    }
    else if (tp.type == &typeid(CCPACSWingSegment)) {
        const CCPACSWingSegment& segment = *reinterpret_cast<CCPACSWingSegment*>(tp.ptr);
        if (pos.isOnInnerSectionElement()) {
            return segment.GetInnerSectionElementUID();
        }
        else {
            return segment.GetOuterSectionElementUID();
        }
    }
    else {
        throw CTiglError("'" + pos.GetEtaXsiPoint().GetReferenceUID() + "' in not a wing segment or a component segment.");
    }
}

} // end namespace tigl
<commit_msg>Fixed typo<commit_after>/*
* Copyright (C) 2016 Airbus Defence and Space
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "CCPACSWingSparPosition.h"

#include "CCPACSWingCSStructure.h"
#include "CCPACSWingSegment.h"
#include "CCPACSWingComponentSegment.h"
#include "CCPACSWingSpars.h"
#include "CTiglError.h"
#include "CPACSWingRibPoint.h"
#include "CPACSEtaXsiPoint.h"
#include "CTiglUIDManager.h"

namespace tigl
{

CCPACSWingSparPosition::CCPACSWingSparPosition(CCPACSWingSparPositions* sparPositions, CTiglUIDManager* uidMgr)
: generated::CPACSSparPosition(sparPositions, uidMgr) {}

bool CCPACSWingSparPosition::isOnInnerSectionElement() const
{
    if (GetSparPositionEtaXsi_choice2()) {
        return GetEta() < 1.E-6;
    }
    else {
        return false;
    }
}

bool CCPACSWingSparPosition::isOnOuterSectionElement() const
{
    if (GetSparPositionEtaXsi_choice2()) {
        return (1 - GetEta()) < 1.E-6;
    }
    else {
        return false;
    }
}

bool CCPACSWingSparPosition::isOnSectionElement() const
{
    return isOnInnerSectionElement() || isOnOuterSectionElement();
}

bool CCPACSWingSparPosition::isOnRib() const
{
    return m_sparPositionRib_choice1 ? true : false;
}

const std::string& CCPACSWingSparPosition::GetReferenceUID() const
{
    if (m_sparPositionRib_choice1) {
        return m_sparPositionRib_choice1->GetRibDefinitionUID();
    }
    else if (m_sparPositionEtaXsi_choice2){
        return m_sparPositionEtaXsi_choice2->GetReferenceUID();
    }
    else {
        throw CTiglError("Invalid choice type");
    }
}

double CCPACSWingSparPosition::GetEta() const
{
    if (!m_sparPositionEtaXsi_choice2) {
        throw CTiglError("SparPosition is not defined via eta/xsi. Please check InputType first before calling CCPACSWingSparPosition::GetXsi()");
    }
    return m_sparPositionEtaXsi_choice2->GetEta();
}

double CCPACSWingSparPosition::GetXsi() const
{
    if (m_sparPositionRib_choice1) {
        return m_sparPositionRib_choice1->GetXsi();
    }
    else if (m_sparPositionEtaXsi_choice2) {
        return m_sparPositionEtaXsi_choice2->GetXsi();
    }
    throw CTiglError("Invalid spar position type");
}

const generated::CPACSEtaXsiPoint &CCPACSWingSparPosition::GetEtaXsiPoint() const
{
    if (!GetSparPositionEtaXsi_choice2()) {
        throw CTiglError("No EtaXsiPoint definied in SparPosition '" + GetUID() + "'");
    }

    return GetSparPositionEtaXsi_choice2().value();
}

const generated::CPACSWingRibPoint& CCPACSWingSparPosition::GetRibPoint() const
{
    if (!GetSparPositionRib_choice1()) {
        throw CTiglError("No RibPoint definied in SparPosition '" + GetUID() + "'");
    }

    return GetSparPositionRib_choice1().value();
}

int WingRibPointGetRibNumber(const generated::CPACSWingRibPoint& ribPoint)
{
    return ribPoint.GetRibNumber().value_or(1);
}

std::string WingSparPosGetElementUID(const CCPACSWingSparPosition & pos)
{
    if (!pos.isOnSectionElement()) {
        throw CTiglError("Spar positioning is not on section element");
    }

    const CTiglUIDManager::TypedPtr tp = pos.GetUIDManager().ResolveObject(pos.GetEtaXsiPoint().GetReferenceUID());
    if (tp.type == &typeid(CCPACSWingComponentSegment)) {
        const CCPACSWingComponentSegment& cs = *reinterpret_cast<CCPACSWingComponentSegment*>(tp.ptr);
        const SegmentList& segments = cs.GetSegmentList();
        if (pos.isOnInnerSectionElement()) {
            return segments.front()->GetInnerSectionElementUID();
        }
        else {
            return segments.back()->GetOuterSectionElementUID();
        }
    }
    else if (tp.type == &typeid(CCPACSWingSegment)) {
        const CCPACSWingSegment& segment = *reinterpret_cast<CCPACSWingSegment*>(tp.ptr);
        if (pos.isOnInnerSectionElement()) {
            return segment.GetInnerSectionElementUID();
        }
        else {
            return segment.GetOuterSectionElementUID();
        }
    }
    else {
        throw CTiglError("'" + pos.GetEtaXsiPoint().GetReferenceUID() + "' in not a wing segment or a component segment.");
    }
}

} // end namespace tigl
<|endoftext|>


<commit_before>//===--- ParseType.cpp - Swift Language Parser for Types ------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Type Parsing and AST Building
//
//===----------------------------------------------------------------------===//

#include "Parser.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Twine.h"
using namespace swift;

bool Parser::parseType(Type &Result) {
  return parseType(Result, "expected type");
}

/// parseType
///   type:
///     type-simple
///     type-function
///     type-array
///
///   type-function:
///     type-simple '->' type
///
///   type-simple:
///     '__builtin_int32_type'
///     identifier
///     type-tuple
///     type-oneof
///     type-protocol
///
bool Parser::parseType(Type &Result, const Twine &Message) {
  // Parse type-simple first.
  switch (Tok.getKind()) {
  case tok::identifier: {
    Identifier Name = Context.getIdentifier(Tok.getText());
    Result = ScopeInfo.lookupOrInsertTypeName(Name, Tok.getLoc());
    consumeToken(tok::identifier);
    break;
  }
  case tok::kw___builtin_float32_type:
    Result = Context.TheFloat32Type;
    consumeToken(tok::kw___builtin_float32_type);
    break;
  case tok::kw___builtin_float64_type:
    Result = Context.TheFloat64Type;
    consumeToken(tok::kw___builtin_float64_type);
    break;
  case tok::kw___builtin_int1_type:
    Result = Context.TheInt1Type;
    consumeToken(tok::kw___builtin_int1_type);
    break;
  case tok::kw___builtin_int8_type:
    Result = Context.TheInt8Type;
    consumeToken(tok::kw___builtin_int8_type);
    break;
  case tok::kw___builtin_int16_type:
    Result = Context.TheInt16Type;
    consumeToken(tok::kw___builtin_int16_type);
    break;
  case tok::kw___builtin_int32_type:
    Result = Context.TheInt32Type;
    consumeToken(tok::kw___builtin_int32_type);
    break;
  case tok::kw___builtin_int64_type:
    Result = Context.TheInt64Type;
    consumeToken(tok::kw___builtin_int64_type);
    break;
  case tok::l_paren:
  case tok::l_paren_space: {
    SMLoc LPLoc = consumeToken();
    if (parseTypeTupleBody(LPLoc, Result))
      return true;

    if (parseToken(tok::r_paren, "expected ')' at end of tuple list",
                   tok::r_paren)) {
      note(LPLoc, "to match this opening '('");
      return true;
    }
    break;
  }
  case tok::kw_oneof:
    if (parseTypeOneOf(Result)) return true;
    break;
  case tok::kw_protocol:
    if (parseTypeProtocol(Result))
      return true;
    break;
  default:
    error(Tok.getLoc(), Message);
    return true;
  }

  while (1) {
    // If there is an arrow, parse the rest of the type.
    SMLoc TokLoc = Tok.getLoc();
    if (consumeIf(tok::arrow)) {
      Type SecondHalf;
      if (parseType(SecondHalf, "expected type in result of function type"))
        return true;
      Result = FunctionType::get(Result, SecondHalf, Context);
      continue;
    }

    // If there is a square bracket, we have an array.
    if (consumeIf(tok::l_square)) {
      if (parseTypeArray(TokLoc, Result)) return true;
      continue;
    }

    break;
  }

  return false;
}

/// parseTypeTupleBody
///   type-tuple:
///     '(' type-tuple-body? ')'
///   type-tuple-body:
///     type-tuple-element (',' type-tuple-element)*
///   type-tuple-element:
///     identifier value-specifier
///     type ('=' expr)?
bool Parser::parseTypeTupleBody(SMLoc LPLoc, Type &Result) {
  SmallVector<TupleTypeElt, 8> Elements;

  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::r_brace)) {
    bool HadError = false;
    do {
      Elements.push_back(TupleTypeElt());
      TupleTypeElt &Result = Elements.back();

      // If the tuple element starts with "ident :" or "ident =", then
      // the identifier is an element tag, and it is followed by a
      // value-specifier.
      if (Tok.is(tok::identifier) &&
          (peekToken().is(tok::colon) || peekToken().is(tok::equal))) {
        parseIdentifier(Result.Name, "");

        NullablePtr<Expr> Init;
        if ((HadError = parseValueSpecifier(Result.Ty, Init, /*single*/ true)))
          break;
        Result.Init = Init.getPtrOrNull();
        continue;
      }

      // Otherwise, this has to be a type.
      if ((HadError = parseType(Result.Ty)))
        break;

      // Parse the optional default value expression.
      if (Tok.is(tok::colon)) {
        ParseResult<Expr> Init =
          parseSingleExpr("expected initializer expression after '='");

        // Die if there was a parse error.
        if (Init) {
          HadError = true;
          break;
        }

        if (!Init.isSemaError()) {
          Result.Init = Init.get();
        }
      }
    } while (consumeIf(tok::comma));

    if (HadError) {
      skipUntil(tok::r_paren);
      if (Tok.is(tok::r_paren))
        consumeToken(tok::r_paren);
      return true;
    }
  }

  Result = TupleType::get(Elements, Context);
  return false;
}

///   type-oneof:
///     'oneof' attribute-list oneof-body
///
bool Parser::parseTypeOneOf(Type &Result) {
  SMLoc OneOfLoc = consumeToken(tok::kw_oneof);

  DeclAttributes Attributes;
  parseAttributeList(Attributes);

  return parseTypeOneOfBody(OneOfLoc, Attributes, Result);
}

///   oneof-body:
///      '{' oneof-element (',' oneof-element)* '}'
///   oneof-element:
///      identifier
///      identifier ':' type
///
/// If TypeName is specified, it is the type that the constructors should be
/// built with, so that they preserve the name of the oneof decl that contains
/// this.
bool Parser::parseTypeOneOfBody(SMLoc OneOfLoc, const DeclAttributes &Attrs,
                                Type &Result, TypeAliasDecl *TypeName) {
  if (parseToken(tok::l_brace, "expected '{' in oneof"))
    return true;

  SmallVector<OneOfElementInfo, 8> ElementInfos;

  // Parse the comma separated list of oneof elements.
  while (Tok.is(tok::identifier)) {
    OneOfElementInfo ElementInfo;
    ElementInfo.Name = Tok.getText();
    ElementInfo.NameLoc = Tok.getLoc();
    ElementInfo.EltType = 0;

    consumeToken(tok::identifier);

    // See if we have a type specifier for this oneof element.  If so, parse it.
    if (consumeIf(tok::colon) &&
        parseType(ElementInfo.EltType,
                  "expected type while parsing oneof element '" +
                  ElementInfo.Name + "'")) {
      skipUntil(tok::r_brace);
      return true;
    }

    ElementInfos.push_back(ElementInfo);

    // Require comma separation.
    if (!consumeIf(tok::comma))
      break;
  }

  parseToken(tok::r_brace, "expected '}' at end of oneof");

  Result = actOnOneOfType(OneOfLoc, Attrs, ElementInfos, TypeName);
  return false;
}

OneOfType *Parser::actOnOneOfType(SMLoc OneOfLoc, const DeclAttributes &Attrs,
                                  ArrayRef<OneOfElementInfo> Elts,
                                  TypeAliasDecl *PrettyTypeName) {
  // No attributes are valid on oneof types at this time.
  if (!Attrs.empty())
    error(Attrs.LSquareLoc, "oneof types are not allowed to have attributes");

  llvm::SmallPtrSet<const char *, 16> SeenSoFar;
  SmallVector<OneOfElementDecl *, 16> EltDecls;

  // If we have a PrettyTypeName to use, use it.  Otherwise, just assign the
  // constructors a temporary dummy type.
  Type TmpTy = TupleType::getEmpty(Context);
  if (PrettyTypeName)
    TmpTy = PrettyTypeName->getAliasType(Context);

  for (const OneOfElementInfo &Elt : Elts) {
    Identifier NameI = Context.getIdentifier(Elt.Name);

    // If this was multiply defined, reject it.
    if (!SeenSoFar.insert(NameI.get())) {
      error(Elt.NameLoc, "element named '" + Elt.Name +
            "' defined multiple times");
      // Don't copy this element into NewElements.
      // TODO: QoI: add note for previous definition.
      continue;
    }

    Type EltTy = TmpTy;
    if (Type ArgTy = Elt.EltType)
      if (PrettyTypeName)
        EltTy = FunctionType::get(ArgTy, EltTy, Context);

    // Create a decl for each element, giving each a temporary type.
    EltDecls.push_back(new (Context) OneOfElementDecl(Elt.NameLoc, NameI,
                                                      EltTy, Elt.EltType,
                                                      CurDeclContext));
  }

  OneOfType *Result = OneOfType::getNew(OneOfLoc, EltDecls, CurDeclContext);
  for (OneOfElementDecl *D : EltDecls)
    D->Context = Result;

  if (PrettyTypeName) {
    // If we have a pretty name for this, complete it to its actual type.
    assert(PrettyTypeName->UnderlyingTy.isNull() &&
           "Not an incomplete decl to complete!");
    PrettyTypeName->UnderlyingTy = Result;
  } else {
    // Now that the oneof type is created, we can go back and give proper types
    // to each element decl.
    for (OneOfElementDecl *Elt : EltDecls) {
      Type EltTy = Result;
      // If the OneOf Element takes a type argument, then it is actually a
      // function that takes the type argument and returns the OneOfType.
      if (Type ArgTy = Elt->ArgumentType)
        EltTy = FunctionType::get(ArgTy, EltTy, Context);
      Elt->Ty = EltTy;
    }
  }

  return Result;
}

/// parseTypeArray - The l_square has already been consumed.
///   type-array:
///     type '[' ']'
///     type '[' expr ']'
///
bool Parser::parseTypeArray(SMLoc LSquareLoc, Type &Result) {
  // Handle the [] production, and unsized array.
  if (consumeIf(tok::r_square)) {
    if (isa<ErrorType>(Result.getPointer()))
      return Result;
    return ArrayType::get(Result, 0, Context);
  }

  ParseResult<Expr> SizeEx;
  if ((SizeEx = parseSingleExpr("expected expression for array type size")))
    return true;

  SMLoc RArrayTok = Tok.getLoc();
  if (parseToken(tok::r_square, "expected ']' in array type")) {
    note(LSquareLoc, "to match this '['");
    return true;
  }

  // If we had a semantic error on the size or if the base type is invalid,
  // propagate up an error type.
  if (SizeEx.isSemaError() || isa<ErrorType>(Result.getPointer())) {
    Result = ErrorType::get(Context);
    return false;
  }

  // Semantic analysis.

  Expr *Size = SizeEx.get();

  // FIXME: Add real support for evaluating constant expressions for array
  // sizes.
  uint64_t SizeVal;
  if (IntegerLiteralExpr *IL = dyn_cast<IntegerLiteralExpr>(Size)) {
    SizeVal = IL->getValue();
  } else {
    error(Size->getLocStart(), "invalid type size, not a constant");
    return ErrorType::get(Context);
  }

  if (SizeVal == 0) {
    error(Size->getLocStart(), "array types must be larger than zero elements");
    return ErrorType::get(Context);
  }

  Result = ArrayType::get(Result, SizeVal, Context);
  return false;
}

///   type-protocol:
///      'protocol' attribute-list protocol-body
///
bool Parser::parseTypeProtocol(Type &Result) {
  SMLoc ProtocolLoc = consumeToken(tok::kw_protocol);

  DeclAttributes Attributes;
  parseAttributeList(Attributes);

  return parseTypeProtocolBody(ProtocolLoc, Attributes, Result);
}

///   protocol-body:
///      '{' protocol-element* '}'
///   protocol-element:
///      decl-func
///      decl-var-simple
///      // 'typealias' identifier
///
bool Parser::parseTypeProtocolBody(SMLoc ProtocolLoc,
                                   const DeclAttributes &Attributes,
                                   Type &Result, TypeAliasDecl *TypeName) {
  // Parse the body.
  if (parseToken(tok::l_brace, "expected '{' in protocol"))
    return true;

  SmallVector<Decl*, 8> Elements;

  // Parse the list of protocol elements.
  do {
    switch (Tok.getKind()) {
    default:
      error(Tok.getLoc(), "unexpected token in protocol body");
      return true;
    case tok::r_brace:  // End of protocol body.
      break;

    case tok::kw_func:
      Elements.push_back(parseDeclFunc(false));
      if (Elements.back() == 0) return true;
      break;
    case tok::kw_var:
      Elements.push_back(parseDeclVarSimple());
      if (Elements.back() == 0) return true;
      break;
    }
  } while (Tok.isNot(tok::r_brace));

  consumeToken(tok::r_brace);

  // Act on what we've parsed.
  if (!Attributes.empty())
    error(Attributes.LSquareLoc,
          "protocol types are not allowed to have attributes yet");

  Result = ProtocolType::getNew(ProtocolLoc, Elements, CurDeclContext);

  if (TypeName) {
    // If we have a pretty name for this, complete it to its actual type.
    assert(TypeName->UnderlyingTy.isNull() &&
           "Not an incomplete decl to complete!");
    TypeName->UnderlyingTy = Result;
  }

  return false;
}
<commit_msg>protocol members shalt get the right declcontext and type.<commit_after>//===--- ParseType.cpp - Swift Language Parser for Types ------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Type Parsing and AST Building
//
//===----------------------------------------------------------------------===//

#include "Parser.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Twine.h"
using namespace swift;

bool Parser::parseType(Type &Result) {
  return parseType(Result, "expected type");
}

/// parseType
///   type:
///     type-simple
///     type-function
///     type-array
///
///   type-function:
///     type-simple '->' type
///
///   type-simple:
///     '__builtin_int32_type'
///     identifier
///     type-tuple
///     type-oneof
///     type-protocol
///
bool Parser::parseType(Type &Result, const Twine &Message) {
  // Parse type-simple first.
  switch (Tok.getKind()) {
  case tok::identifier: {
    Identifier Name = Context.getIdentifier(Tok.getText());
    Result = ScopeInfo.lookupOrInsertTypeName(Name, Tok.getLoc());
    consumeToken(tok::identifier);
    break;
  }
  case tok::kw___builtin_float32_type:
    Result = Context.TheFloat32Type;
    consumeToken(tok::kw___builtin_float32_type);
    break;
  case tok::kw___builtin_float64_type:
    Result = Context.TheFloat64Type;
    consumeToken(tok::kw___builtin_float64_type);
    break;
  case tok::kw___builtin_int1_type:
    Result = Context.TheInt1Type;
    consumeToken(tok::kw___builtin_int1_type);
    break;
  case tok::kw___builtin_int8_type:
    Result = Context.TheInt8Type;
    consumeToken(tok::kw___builtin_int8_type);
    break;
  case tok::kw___builtin_int16_type:
    Result = Context.TheInt16Type;
    consumeToken(tok::kw___builtin_int16_type);
    break;
  case tok::kw___builtin_int32_type:
    Result = Context.TheInt32Type;
    consumeToken(tok::kw___builtin_int32_type);
    break;
  case tok::kw___builtin_int64_type:
    Result = Context.TheInt64Type;
    consumeToken(tok::kw___builtin_int64_type);
    break;
  case tok::l_paren:
  case tok::l_paren_space: {
    SMLoc LPLoc = consumeToken();
    if (parseTypeTupleBody(LPLoc, Result))
      return true;

    if (parseToken(tok::r_paren, "expected ')' at end of tuple list",
                   tok::r_paren)) {
      note(LPLoc, "to match this opening '('");
      return true;
    }
    break;
  }
  case tok::kw_oneof:
    if (parseTypeOneOf(Result)) return true;
    break;
  case tok::kw_protocol:
    if (parseTypeProtocol(Result))
      return true;
    break;
  default:
    error(Tok.getLoc(), Message);
    return true;
  }

  while (1) {
    // If there is an arrow, parse the rest of the type.
    SMLoc TokLoc = Tok.getLoc();
    if (consumeIf(tok::arrow)) {
      Type SecondHalf;
      if (parseType(SecondHalf, "expected type in result of function type"))
        return true;
      Result = FunctionType::get(Result, SecondHalf, Context);
      continue;
    }

    // If there is a square bracket, we have an array.
    if (consumeIf(tok::l_square)) {
      if (parseTypeArray(TokLoc, Result)) return true;
      continue;
    }

    break;
  }

  return false;
}

/// parseTypeTupleBody
///   type-tuple:
///     '(' type-tuple-body? ')'
///   type-tuple-body:
///     type-tuple-element (',' type-tuple-element)*
///   type-tuple-element:
///     identifier value-specifier
///     type ('=' expr)?
bool Parser::parseTypeTupleBody(SMLoc LPLoc, Type &Result) {
  SmallVector<TupleTypeElt, 8> Elements;

  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::r_brace)) {
    bool HadError = false;
    do {
      Elements.push_back(TupleTypeElt());
      TupleTypeElt &Result = Elements.back();

      // If the tuple element starts with "ident :" or "ident =", then
      // the identifier is an element tag, and it is followed by a
      // value-specifier.
      if (Tok.is(tok::identifier) &&
          (peekToken().is(tok::colon) || peekToken().is(tok::equal))) {
        parseIdentifier(Result.Name, "");

        NullablePtr<Expr> Init;
        if ((HadError = parseValueSpecifier(Result.Ty, Init, /*single*/ true)))
          break;
        Result.Init = Init.getPtrOrNull();
        continue;
      }

      // Otherwise, this has to be a type.
      if ((HadError = parseType(Result.Ty)))
        break;

      // Parse the optional default value expression.
      if (Tok.is(tok::colon)) {
        ParseResult<Expr> Init =
          parseSingleExpr("expected initializer expression after '='");

        // Die if there was a parse error.
        if (Init) {
          HadError = true;
          break;
        }

        if (!Init.isSemaError()) {
          Result.Init = Init.get();
        }
      }
    } while (consumeIf(tok::comma));

    if (HadError) {
      skipUntil(tok::r_paren);
      if (Tok.is(tok::r_paren))
        consumeToken(tok::r_paren);
      return true;
    }
  }

  Result = TupleType::get(Elements, Context);
  return false;
}

///   type-oneof:
///     'oneof' attribute-list oneof-body
///
bool Parser::parseTypeOneOf(Type &Result) {
  SMLoc OneOfLoc = consumeToken(tok::kw_oneof);

  DeclAttributes Attributes;
  parseAttributeList(Attributes);

  return parseTypeOneOfBody(OneOfLoc, Attributes, Result);
}

///   oneof-body:
///      '{' oneof-element (',' oneof-element)* '}'
///   oneof-element:
///      identifier
///      identifier ':' type
///
/// If TypeName is specified, it is the type that the constructors should be
/// built with, so that they preserve the name of the oneof decl that contains
/// this.
bool Parser::parseTypeOneOfBody(SMLoc OneOfLoc, const DeclAttributes &Attrs,
                                Type &Result, TypeAliasDecl *TypeName) {
  if (parseToken(tok::l_brace, "expected '{' in oneof"))
    return true;

  SmallVector<OneOfElementInfo, 8> ElementInfos;

  // Parse the comma separated list of oneof elements.
  while (Tok.is(tok::identifier)) {
    OneOfElementInfo ElementInfo;
    ElementInfo.Name = Tok.getText();
    ElementInfo.NameLoc = Tok.getLoc();
    ElementInfo.EltType = 0;

    consumeToken(tok::identifier);

    // See if we have a type specifier for this oneof element.  If so, parse it.
    if (consumeIf(tok::colon) &&
        parseType(ElementInfo.EltType,
                  "expected type while parsing oneof element '" +
                  ElementInfo.Name + "'")) {
      skipUntil(tok::r_brace);
      return true;
    }

    ElementInfos.push_back(ElementInfo);

    // Require comma separation.
    if (!consumeIf(tok::comma))
      break;
  }

  parseToken(tok::r_brace, "expected '}' at end of oneof");

  Result = actOnOneOfType(OneOfLoc, Attrs, ElementInfos, TypeName);
  return false;
}

OneOfType *Parser::actOnOneOfType(SMLoc OneOfLoc, const DeclAttributes &Attrs,
                                  ArrayRef<OneOfElementInfo> Elts,
                                  TypeAliasDecl *PrettyTypeName) {
  // No attributes are valid on oneof types at this time.
  if (!Attrs.empty())
    error(Attrs.LSquareLoc, "oneof types are not allowed to have attributes");

  llvm::SmallPtrSet<const char *, 16> SeenSoFar;
  SmallVector<OneOfElementDecl *, 16> EltDecls;

  // If we have a PrettyTypeName to use, use it.  Otherwise, just assign the
  // constructors a temporary dummy type.
  Type TmpTy = TupleType::getEmpty(Context);
  if (PrettyTypeName)
    TmpTy = PrettyTypeName->getAliasType(Context);

  for (const OneOfElementInfo &Elt : Elts) {
    Identifier NameI = Context.getIdentifier(Elt.Name);

    // If this was multiply defined, reject it.
    if (!SeenSoFar.insert(NameI.get())) {
      error(Elt.NameLoc, "element named '" + Elt.Name +
            "' defined multiple times");
      // Don't copy this element into NewElements.
      // TODO: QoI: add note for previous definition.
      continue;
    }

    Type EltTy = TmpTy;
    if (Type ArgTy = Elt.EltType)
      if (PrettyTypeName)
        EltTy = FunctionType::get(ArgTy, EltTy, Context);

    // Create a decl for each element, giving each a temporary type.
    EltDecls.push_back(new (Context) OneOfElementDecl(Elt.NameLoc, NameI,
                                                      EltTy, Elt.EltType,
                                                      CurDeclContext));
  }

  OneOfType *Result = OneOfType::getNew(OneOfLoc, EltDecls, CurDeclContext);
  for (OneOfElementDecl *D : EltDecls)
    D->Context = Result;

  if (PrettyTypeName) {
    // If we have a pretty name for this, complete it to its actual type.
    assert(PrettyTypeName->UnderlyingTy.isNull() &&
           "Not an incomplete decl to complete!");
    PrettyTypeName->UnderlyingTy = Result;
  } else {
    // Now that the oneof type is created, we can go back and give proper types
    // to each element decl.
    for (OneOfElementDecl *Elt : EltDecls) {
      Type EltTy = Result;
      // If the OneOf Element takes a type argument, then it is actually a
      // function that takes the type argument and returns the OneOfType.
      if (Type ArgTy = Elt->ArgumentType)
        EltTy = FunctionType::get(ArgTy, EltTy, Context);
      Elt->Ty = EltTy;
    }
  }

  return Result;
}

/// parseTypeArray - The l_square has already been consumed.
///   type-array:
///     type '[' ']'
///     type '[' expr ']'
///
bool Parser::parseTypeArray(SMLoc LSquareLoc, Type &Result) {
  // Handle the [] production, and unsized array.
  if (consumeIf(tok::r_square)) {
    if (isa<ErrorType>(Result.getPointer()))
      return Result;
    return ArrayType::get(Result, 0, Context);
  }

  ParseResult<Expr> SizeEx;
  if ((SizeEx = parseSingleExpr("expected expression for array type size")))
    return true;

  SMLoc RArrayTok = Tok.getLoc();
  if (parseToken(tok::r_square, "expected ']' in array type")) {
    note(LSquareLoc, "to match this '['");
    return true;
  }

  // If we had a semantic error on the size or if the base type is invalid,
  // propagate up an error type.
  if (SizeEx.isSemaError() || isa<ErrorType>(Result.getPointer())) {
    Result = ErrorType::get(Context);
    return false;
  }

  // Semantic analysis.

  Expr *Size = SizeEx.get();

  // FIXME: Add real support for evaluating constant expressions for array
  // sizes.
  uint64_t SizeVal;
  if (IntegerLiteralExpr *IL = dyn_cast<IntegerLiteralExpr>(Size)) {
    SizeVal = IL->getValue();
  } else {
    error(Size->getLocStart(), "invalid type size, not a constant");
    return ErrorType::get(Context);
  }

  if (SizeVal == 0) {
    error(Size->getLocStart(), "array types must be larger than zero elements");
    return ErrorType::get(Context);
  }

  Result = ArrayType::get(Result, SizeVal, Context);
  return false;
}

///   type-protocol:
///      'protocol' attribute-list protocol-body
///
bool Parser::parseTypeProtocol(Type &Result) {
  SMLoc ProtocolLoc = consumeToken(tok::kw_protocol);

  DeclAttributes Attributes;
  parseAttributeList(Attributes);

  return parseTypeProtocolBody(ProtocolLoc, Attributes, Result);
}

///   protocol-body:
///      '{' protocol-element* '}'
///   protocol-element:
///      decl-func
///      decl-var-simple
///      // 'typealias' identifier
///
bool Parser::parseTypeProtocolBody(SMLoc ProtocolLoc,
                                   const DeclAttributes &Attributes,
                                   Type &Result, TypeAliasDecl *TypeName) {
  // Parse the body.
  if (parseToken(tok::l_brace, "expected '{' in protocol"))
    return true;

  SmallVector<Decl*, 8> Elements;

  // Parse the list of protocol elements.
  do {
    switch (Tok.getKind()) {
    default:
      error(Tok.getLoc(), "unexpected token in protocol body");
      return true;
    case tok::r_brace:  // End of protocol body.
      break;

    case tok::kw_func:
      Elements.push_back(parseDeclFunc(false));
      if (Elements.back() == 0) return true;
      break;
    case tok::kw_var:
      Elements.push_back(parseDeclVarSimple());
      if (Elements.back() == 0) return true;
      break;
    }
  } while (Tok.isNot(tok::r_brace));

  consumeToken(tok::r_brace);

  // Act on what we've parsed.
  if (!Attributes.empty())
    error(Attributes.LSquareLoc,
          "protocol types are not allowed to have attributes yet");

  ProtocolType *NewProto = ProtocolType::getNew(ProtocolLoc, Elements,
                                                CurDeclContext);

  TupleTypeElt ThisElt(NewProto, Context.getIdentifier("this"));
  TupleType *ThisTy = TupleType::get(ThisElt, Context);

  // Install all of the members of protocol into the protocol's DeclContext, and
  // give each ValueDecl member an implicit "this" argument.
  // FIXME: This isn't quite right, 'this' should be found by name lookup when
  // parsing the body of each of these.
  for (Decl *D : Elements) {
    // Install the right DeclContext.
    D->Context = NewProto;

    // Change the type of the value decls to be functions that return whatever
    // they were declared as.
    if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
      VD->Ty = FunctionType::get(ThisTy, VD->Ty, Context);
  }

  if (TypeName) {
    // If we have a pretty name for this, complete it to its actual type.
    assert(TypeName->UnderlyingTy.isNull() &&
           "Not an incomplete decl to complete!");
    TypeName->UnderlyingTy = NewProto;
  }

  Result = NewProto;
  return false;
}
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_FUNCTOR_FOR_EACH_HPP
#define STAN_MATH_PRIM_FUNCTOR_FOR_EACH_HPP

#include <stan/math/prim/meta.hpp>
#include <functional>
#include <tuple>
#include <utility>

namespace stan {
namespace math {
namespace internal {

/**
 * Implementation of for_each.
 * @note The static cast to void is used in boost::hana's for_each impl
 *  and is used to suppress unused value warnings from the compiler.
 */
template <typename F, typename T, size_t... Is>
constexpr inline auto for_each(F&& f, T&& t, std::index_sequence<Is...>) {
  using Swallow = int[];
  static_cast<void>(Swallow{
      (static_cast<void>(std::forward<F>(f)(std::get<Is>(std::forward<T>(t)))),
       0)...});
}

/**
 * Implementation of Binary for_each.
 * @note The static cast to void is used in boost::hana's for_each impl
 *  and is used to suppress unused value warnings from the compiler.
 */
template <typename F, typename T1, typename T2, size_t... Is>
constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2,
                               std::index_sequence<Is...>) {
  using Swallow = int[];
  static_cast<void>(Swallow{(
      static_cast<void>(std::forward<F>(f)(std::get<Is>(std::forward<T1>(t1)),
                                           std::get<Is>(std::forward<T2>(t2)))),
      0)...});
}

/**
 * Implementation of Trinary for_each.
 * @note The static cast to void is used in boost::hana's for_each impl
 *  and is used to suppress unused value warnings from the compiler.
 */
template <typename F, typename T1, typename T2, typename T3, size_t... Is>
constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2, T3&& t3,
                               std::index_sequence<Is...>) {
  using Swallow = int[];
  static_cast<void>(Swallow{(
      static_cast<void>(std::forward<F>(f)(std::get<Is>(std::forward<T1>(t1)),
                                           std::get<Is>(std::forward<T2>(t2)),
                                           std::get<Is>(std::forward<T3>(t3)))),
      0)...});
}
}  // namespace internal

/**
 * Apply a function to each element of a tuple
 * @tparam F type with a valid `operator()`
 * @tparam T Tuple
 * @param f A functor to apply over each element of the tuple.
 * @param t A tuple
 */
template <typename F, typename T>
constexpr inline auto for_each(F&& f, T&& t) {
  return internal::for_each(
      std::forward<F>(f), std::forward<T>(t),
      std::make_index_sequence<std::tuple_size<std::decay_t<T>>::value>());
}

/**
 * Apply a function to each element of two tuples
 * @tparam F type with a valid `operator()`
 * @tparam T1 Tuple
 * @tparam T2 Another tuple
 * @param f A functor to apply over each element of the tuple.
 * @param t1 A tuple
 * @param t2 Another tuple
 */
template <typename F, typename T1, typename T2>
constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2) {
  constexpr auto t1_size = std::tuple_size<std::decay_t<T1>>::value;
  constexpr auto t2_size = std::tuple_size<std::decay_t<T2>>::value;
  static_assert(t1_size == t2_size, "Size Mismatch between t1 and t2 in for_each");
  return internal::for_each(
      std::forward<F>(f), std::forward<T1>(t1), std::forward<T2>(t2),
      std::make_index_sequence<std::tuple_size<std::decay_t<T1>>::value>());
}

/**
 * Apply a function to each element of three tuples
 * @tparam F type with a valid `operator()`
 * @tparam T1 Tuple
 * @tparam T2 Another tuple
 * @tparam T3 Another tuple
 * @param f A functor to apply over each element of the tuple.
 * @param t1 A tuple
 * @param t2 Another tuple
 * @param t3 Another tuple
 */
template <typename F, typename T1, typename T2, typename T3>
constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2, T3&& t3) {
  constexpr auto t1_size = std::tuple_size<std::decay_t<T1>>::value;
  constexpr auto t2_size = std::tuple_size<std::decay_t<T2>>::value;
  constexpr auto t3_size = std::tuple_size<std::decay_t<T3>>::value;
  static_assert(t1_size == t2_size, "Size Mismatch between t1 and t2 in for_each");
  static_assert(t1_size == t3_size, "Size Mismatch between t1 and t3 in for_each");
  return internal::for_each(
      std::forward<F>(f), std::forward<T1>(t1), std::forward<T2>(t2),
      std::forward<T3>(t3),
      std::make_index_sequence<std::tuple_size<std::decay_t<T1>>::value>());
}

}  // namespace math
}  // namespace stan

#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final)<commit_after>#ifndef STAN_MATH_PRIM_FUNCTOR_FOR_EACH_HPP
#define STAN_MATH_PRIM_FUNCTOR_FOR_EACH_HPP

#include <stan/math/prim/meta.hpp>
#include <functional>
#include <tuple>
#include <utility>

namespace stan {
namespace math {
namespace internal {

/**
 * Implementation of for_each.
 * @note The static cast to void is used in boost::hana's for_each impl
 *  and is used to suppress unused value warnings from the compiler.
 */
template <typename F, typename T, size_t... Is>
constexpr inline auto for_each(F&& f, T&& t, std::index_sequence<Is...>) {
  using Swallow = int[];
  static_cast<void>(Swallow{
      (static_cast<void>(std::forward<F>(f)(std::get<Is>(std::forward<T>(t)))),
       0)...});
}

/**
 * Implementation of Binary for_each.
 * @note The static cast to void is used in boost::hana's for_each impl
 *  and is used to suppress unused value warnings from the compiler.
 */
template <typename F, typename T1, typename T2, size_t... Is>
constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2,
                               std::index_sequence<Is...>) {
  using Swallow = int[];
  static_cast<void>(Swallow{(
      static_cast<void>(std::forward<F>(f)(std::get<Is>(std::forward<T1>(t1)),
                                           std::get<Is>(std::forward<T2>(t2)))),
      0)...});
}

/**
 * Implementation of Trinary for_each.
 * @note The static cast to void is used in boost::hana's for_each impl
 *  and is used to suppress unused value warnings from the compiler.
 */
template <typename F, typename T1, typename T2, typename T3, size_t... Is>
constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2, T3&& t3,
                               std::index_sequence<Is...>) {
  using Swallow = int[];
  static_cast<void>(Swallow{(
      static_cast<void>(std::forward<F>(f)(std::get<Is>(std::forward<T1>(t1)),
                                           std::get<Is>(std::forward<T2>(t2)),
                                           std::get<Is>(std::forward<T3>(t3)))),
      0)...});
}
}  // namespace internal

/**
 * Apply a function to each element of a tuple
 * @tparam F type with a valid `operator()`
 * @tparam T Tuple
 * @param f A functor to apply over each element of the tuple.
 * @param t A tuple
 */
template <typename F, typename T>
constexpr inline auto for_each(F&& f, T&& t) {
  return internal::for_each(
      std::forward<F>(f), std::forward<T>(t),
      std::make_index_sequence<std::tuple_size<std::decay_t<T>>::value>());
}

/**
 * Apply a function to each element of two tuples
 * @tparam F type with a valid `operator()`
 * @tparam T1 Tuple
 * @tparam T2 Another tuple
 * @param f A functor to apply over each element of the tuple.
 * @param t1 A tuple
 * @param t2 Another tuple
 */
template <typename F, typename T1, typename T2>
constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2) {
  constexpr auto t1_size = std::tuple_size<std::decay_t<T1>>::value;
  constexpr auto t2_size = std::tuple_size<std::decay_t<T2>>::value;
  static_assert(t1_size == t2_size,
                "Size Mismatch between t1 and t2 in for_each");
  return internal::for_each(
      std::forward<F>(f), std::forward<T1>(t1), std::forward<T2>(t2),
      std::make_index_sequence<std::tuple_size<std::decay_t<T1>>::value>());
}

/**
 * Apply a function to each element of three tuples
 * @tparam F type with a valid `operator()`
 * @tparam T1 Tuple
 * @tparam T2 Another tuple
 * @tparam T3 Another tuple
 * @param f A functor to apply over each element of the tuple.
 * @param t1 A tuple
 * @param t2 Another tuple
 * @param t3 Another tuple
 */
template <typename F, typename T1, typename T2, typename T3>
constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2, T3&& t3) {
  constexpr auto t1_size = std::tuple_size<std::decay_t<T1>>::value;
  constexpr auto t2_size = std::tuple_size<std::decay_t<T2>>::value;
  constexpr auto t3_size = std::tuple_size<std::decay_t<T3>>::value;
  static_assert(t1_size == t2_size,
                "Size Mismatch between t1 and t2 in for_each");
  static_assert(t1_size == t3_size,
                "Size Mismatch between t1 and t3 in for_each");
  return internal::for_each(
      std::forward<F>(f), std::forward<T1>(t1), std::forward<T2>(t2),
      std::forward<T3>(t3),
      std::make_index_sequence<std::tuple_size<std::decay_t<T1>>::value>());
}

}  // namespace math
}  // namespace stan

#endif
<|endoftext|>