<commit_before>//===--- ParseCXXInlineMethods.cpp - C++ class inline methods parsing------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements parsing for C++ class inline methods.
//
//===----------------------------------------------------------------------===//

#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
using namespace clang;

/// ParseCXXInlineMethodDef - We parsed and verified that the specified
/// Declarator is a well formed C++ inline method definition. Now lex its body
/// and store its tokens for parsing after the C++ class is complete.
Parser::DeclPtrTy
Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
                                const ParsedTemplateInfo &TemplateInfo) {
  assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
         "This isn't a function declarator!");
  assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) &&
         "Current token not a '{', ':' or 'try'!");

  Action::MultiTemplateParamsArg TemplateParams(Actions,
                                                TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
                                                TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
  DeclPtrTy FnD;
  if (D.getDeclSpec().isFriendSpecified())
    // FIXME: Friend templates
    FnD = Actions.ActOnFriendFunctionDecl(CurScope, D, true, move(TemplateParams));
  else // FIXME: pass template information through
    FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D,
                                           move(TemplateParams), 0, 0,
                                           /*IsDefinition*/true);

  HandleMemberFunctionDefaultArgs(D, FnD);

  // Consume the tokens and store them for later parsing.

  getCurrentClass().MethodDefs.push_back(LexedMethod(FnD));
  getCurrentClass().MethodDefs.back().TemplateScope
    = CurScope->isTemplateParamScope();
  CachedTokens &Toks = getCurrentClass().MethodDefs.back().Toks;

  tok::TokenKind kind = Tok.getKind();
  // We may have a constructor initializer or function-try-block here.
  if (kind == tok::colon || kind == tok::kw_try) {
    // Consume everything up to (and including) the left brace.
    if (!ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks, tok::semi)) {
      // We didn't find the left-brace we expected after the
      // constructor initializer.
      if (Tok.is(tok::semi)) {
        // We found a semicolon; complain, consume the semicolon, and
        // don't try to parse this method later.
        Diag(Tok.getLocation(), diag::err_expected_lbrace);
        ConsumeAnyToken();
        getCurrentClass().MethodDefs.pop_back();
        return FnD;
      }
    }

  } else {
    // Begin by storing the '{' token.
    Toks.push_back(Tok);
    ConsumeBrace();
  }
  // Consume everything up to (and including) the matching right brace.
  ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);

  // If we're in a function-try-block, we need to store all the catch blocks.
  if (kind == tok::kw_try) {
    while (Tok.is(tok::kw_catch)) {
      ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks);
      ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
    }
  }

  return FnD;
}

/// ParseLexedMethodDeclarations - We finished parsing the member
/// specification of a top (non-nested) C++ class. Now go over the
/// stack of method declarations with some parts for which parsing was
/// delayed (such as default arguments) and parse them.
void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
  bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
  ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
  if (HasTemplateScope)
    Actions.ActOnReenterTemplateScope(CurScope, Class.TagOrTemplate);

  // The current scope is still active if we're the top-level class.
  // Otherwise we'll need to push and enter a new scope.
  bool HasClassScope = !Class.TopLevelClass;
  ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, HasClassScope);
  if (HasClassScope)
    Actions.ActOnStartDelayedMemberDeclarations(CurScope, Class.TagOrTemplate);

  for (; !Class.MethodDecls.empty(); Class.MethodDecls.pop_front()) {
    LateParsedMethodDeclaration &LM = Class.MethodDecls.front();

    // If this is a member template, introduce the template parameter scope.
    ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
    if (LM.TemplateScope)
      Actions.ActOnReenterTemplateScope(CurScope, LM.Method);

    // Start the delayed C++ method declaration
    Actions.ActOnStartDelayedCXXMethodDeclaration(CurScope, LM.Method);

    // Introduce the parameters into scope and parse their default
    // arguments.
    ParseScope PrototypeScope(this,
                              Scope::FunctionPrototypeScope|Scope::DeclScope);
    for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
      // Introduce the parameter into scope.
      Actions.ActOnDelayedCXXMethodParameter(CurScope, LM.DefaultArgs[I].Param);

      if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
        // Save the current token position.
        SourceLocation origLoc = Tok.getLocation();

        // Parse the default argument from its saved token stream.
        Toks->push_back(Tok); // So that the current token doesn't get lost
        PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false);

        // Consume the previously-pushed token.
        ConsumeAnyToken();

        // Consume the '='.
        assert(Tok.is(tok::equal) && "Default argument not starting with '='");
        SourceLocation EqualLoc = ConsumeToken();

        OwningExprResult DefArgResult(ParseAssignmentExpression());
        if (DefArgResult.isInvalid())
          Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param);
        else
          Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc,
                                            move(DefArgResult));

        assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
                                                           Tok.getLocation()) &&
               "ParseAssignmentExpression went over the default arg tokens!");
        // There could be leftover tokens (e.g. because of an error).
        // Skip through until we reach the original token position.
        while (Tok.getLocation() != origLoc)
          ConsumeAnyToken();

        delete Toks;
        LM.DefaultArgs[I].Toks = 0;
      }
    }
    PrototypeScope.Exit();

    // Finish the delayed C++ method declaration.
    Actions.ActOnFinishDelayedCXXMethodDeclaration(CurScope, LM.Method);
  }

  for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I)
    ParseLexedMethodDeclarations(*Class.NestedClasses[I]);

  if (HasClassScope)
    Actions.ActOnFinishDelayedMemberDeclarations(CurScope, Class.TagOrTemplate);
}

/// ParseLexedMethodDefs - We finished parsing the member specification of a top
/// (non-nested) C++ class. Now go over the stack of lexed methods that were
/// collected during its parsing and parse them all.
void Parser::ParseLexedMethodDefs(ParsingClass &Class) {
  bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
  ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
  if (HasTemplateScope)
    Actions.ActOnReenterTemplateScope(CurScope, Class.TagOrTemplate);

  bool HasClassScope = !Class.TopLevelClass;
  ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
                        HasClassScope);

  for (; !Class.MethodDefs.empty(); Class.MethodDefs.pop_front()) {
    LexedMethod &LM = Class.MethodDefs.front();

    // If this is a member template, introduce the template parameter scope.
    ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
    if (LM.TemplateScope)
      Actions.ActOnReenterTemplateScope(CurScope, LM.D);

    // Save the current token position.
    SourceLocation origLoc = Tok.getLocation();

    assert(!LM.Toks.empty() && "Empty body!");
    // Append the current token at the end of the new token stream so that it
    // doesn't get lost.
    LM.Toks.push_back(Tok);
    PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);

    // Consume the previously pushed token.
    ConsumeAnyToken();
    assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
           && "Inline method not starting with '{', ':' or 'try'");

    // Parse the method body. Function body parsing code is similar enough
    // to be re-used for method bodies as well.
    ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
    Actions.ActOnStartOfFunctionDef(CurScope, LM.D);

    if (Tok.is(tok::kw_try)) {
      ParseFunctionTryBlock(LM.D);
      assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
                                                           Tok.getLocation()) &&
             "ParseFunctionTryBlock went over the cached tokens!");
      assert(Tok.getLocation() == origLoc &&
             "ParseFunctionTryBlock left tokens in the token stream!");
      continue;
    }
    if (Tok.is(tok::colon)) {
      ParseConstructorInitializer(LM.D);

      // Error recovery.
      if (!Tok.is(tok::l_brace)) {
        Actions.ActOnFinishFunctionBody(LM.D, Action::StmtArg(Actions));
        continue;
      }
    } else
      Actions.ActOnDefaultCtorInitializers(LM.D);

    ParseFunctionStatementBody(LM.D);
    assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
                                                           Tok.getLocation()) &&
           "We consumed more than the cached tokens!");
    assert(Tok.getLocation() == origLoc &&
           "Tokens were left in the token stream!");
  }

  for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I)
    ParseLexedMethodDefs(*Class.NestedClasses[I]);
}

/// ConsumeAndStoreUntil - Consume and store the token at the passed token
/// container until the token 'T' is reached (which gets
/// consumed/stored too, if ConsumeFinalToken).
/// If EarlyAbortIf is specified, then we will stop early if we find that
/// token at the top level.
/// Returns true if token 'T1' or 'T2' was found.
/// NOTE: This is a specialized version of Parser::SkipUntil.
bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
                                  CachedTokens &Toks,
                                  tok::TokenKind EarlyAbortIf,
                                  bool ConsumeFinalToken) {
  // We always want this function to consume at least one token if the first
  // token isn't T and if not at EOF.
  bool isFirstTokenConsumed = true;
  while (1) {
    // If we found one of the tokens, stop and return true.
    if (Tok.is(T1) || Tok.is(T2)) {
      if (ConsumeFinalToken) {
        Toks.push_back(Tok);
        ConsumeAnyToken();
      }
      return true;
    }

    // If we found the early-abort token, return.
    if (Tok.is(EarlyAbortIf))
      return false;

    switch (Tok.getKind()) {
    case tok::eof:
      // Ran out of tokens.
      return false;

    case tok::l_paren:
      // Recursively consume properly-nested parens.
      Toks.push_back(Tok);
      ConsumeParen();
      ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks);
      break;
    case tok::l_square:
      // Recursively consume properly-nested square brackets.
      Toks.push_back(Tok);
      ConsumeBracket();
      ConsumeAndStoreUntil(tok::r_square, tok::unknown, Toks);
      break;
    case tok::l_brace:
      // Recursively consume properly-nested braces.
      Toks.push_back(Tok);
      ConsumeBrace();
      ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
      break;

    // Okay, we found a ']' or '}' or ')', which we think should be balanced.
    // Since the user wasn't looking for this token (if they were, it would
    // already be handled), this isn't balanced.  If there is a LHS token at a
    // higher level, we will assume that this matches the unbalanced token
    // and return it.  Otherwise, this is a spurious RHS token, which we skip.
    case tok::r_paren:
      if (ParenCount && !isFirstTokenConsumed)
        return false;  // Matches something.
      Toks.push_back(Tok);
      ConsumeParen();
      break;
    case tok::r_square:
      if (BracketCount && !isFirstTokenConsumed)
        return false;  // Matches something.
      Toks.push_back(Tok);
      ConsumeBracket();
      break;
    case tok::r_brace:
      if (BraceCount && !isFirstTokenConsumed)
        return false;  // Matches something.
      Toks.push_back(Tok);
      ConsumeBrace();
      break;

    case tok::string_literal:
    case tok::wide_string_literal:
      Toks.push_back(Tok);
      ConsumeStringToken();
      break;
    default:
      // consume this token.
      Toks.push_back(Tok);
      ConsumeToken();
      break;
    }
    isFirstTokenConsumed = false;
  }
}
<commit_msg>Fix 80-cols violtaions<commit_after>//===--- ParseCXXInlineMethods.cpp - C++ class inline methods parsing------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements parsing for C++ class inline methods.
//
//===----------------------------------------------------------------------===//

#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
using namespace clang;

/// ParseCXXInlineMethodDef - We parsed and verified that the specified
/// Declarator is a well formed C++ inline method definition. Now lex its body
/// and store its tokens for parsing after the C++ class is complete.
Parser::DeclPtrTy
Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
                                const ParsedTemplateInfo &TemplateInfo) {
  assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
         "This isn't a function declarator!");
  assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) &&
         "Current token not a '{', ':' or 'try'!");

  Action::MultiTemplateParamsArg TemplateParams(Actions,
          TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0,
          TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);

  DeclPtrTy FnD;
  if (D.getDeclSpec().isFriendSpecified())
    // FIXME: Friend templates
    FnD = Actions.ActOnFriendFunctionDecl(CurScope, D, true,
                                          move(TemplateParams));
  else // FIXME: pass template information through
    FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D,
                                           move(TemplateParams), 0, 0,
                                           /*IsDefinition*/true);

  HandleMemberFunctionDefaultArgs(D, FnD);

  // Consume the tokens and store them for later parsing.

  getCurrentClass().MethodDefs.push_back(LexedMethod(FnD));
  getCurrentClass().MethodDefs.back().TemplateScope
    = CurScope->isTemplateParamScope();
  CachedTokens &Toks = getCurrentClass().MethodDefs.back().Toks;

  tok::TokenKind kind = Tok.getKind();
  // We may have a constructor initializer or function-try-block here.
  if (kind == tok::colon || kind == tok::kw_try) {
    // Consume everything up to (and including) the left brace.
    if (!ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks, tok::semi)) {
      // We didn't find the left-brace we expected after the
      // constructor initializer.
      if (Tok.is(tok::semi)) {
        // We found a semicolon; complain, consume the semicolon, and
        // don't try to parse this method later.
        Diag(Tok.getLocation(), diag::err_expected_lbrace);
        ConsumeAnyToken();
        getCurrentClass().MethodDefs.pop_back();
        return FnD;
      }
    }

  } else {
    // Begin by storing the '{' token.
    Toks.push_back(Tok);
    ConsumeBrace();
  }
  // Consume everything up to (and including) the matching right brace.
  ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);

  // If we're in a function-try-block, we need to store all the catch blocks.
  if (kind == tok::kw_try) {
    while (Tok.is(tok::kw_catch)) {
      ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks);
      ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
    }
  }

  return FnD;
}

/// ParseLexedMethodDeclarations - We finished parsing the member
/// specification of a top (non-nested) C++ class. Now go over the
/// stack of method declarations with some parts for which parsing was
/// delayed (such as default arguments) and parse them.
void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
  bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
  ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
  if (HasTemplateScope)
    Actions.ActOnReenterTemplateScope(CurScope, Class.TagOrTemplate);

  // The current scope is still active if we're the top-level class.
  // Otherwise we'll need to push and enter a new scope.
  bool HasClassScope = !Class.TopLevelClass;
  ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
                        HasClassScope);
  if (HasClassScope)
    Actions.ActOnStartDelayedMemberDeclarations(CurScope, Class.TagOrTemplate);

  for (; !Class.MethodDecls.empty(); Class.MethodDecls.pop_front()) {
    LateParsedMethodDeclaration &LM = Class.MethodDecls.front();

    // If this is a member template, introduce the template parameter scope.
    ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
    if (LM.TemplateScope)
      Actions.ActOnReenterTemplateScope(CurScope, LM.Method);

    // Start the delayed C++ method declaration
    Actions.ActOnStartDelayedCXXMethodDeclaration(CurScope, LM.Method);

    // Introduce the parameters into scope and parse their default
    // arguments.
    ParseScope PrototypeScope(this,
                              Scope::FunctionPrototypeScope|Scope::DeclScope);
    for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
      // Introduce the parameter into scope.
      Actions.ActOnDelayedCXXMethodParameter(CurScope, LM.DefaultArgs[I].Param);

      if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
        // Save the current token position.
        SourceLocation origLoc = Tok.getLocation();

        // Parse the default argument from its saved token stream.
        Toks->push_back(Tok); // So that the current token doesn't get lost
        PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false);

        // Consume the previously-pushed token.
        ConsumeAnyToken();

        // Consume the '='.
        assert(Tok.is(tok::equal) && "Default argument not starting with '='");
        SourceLocation EqualLoc = ConsumeToken();

        OwningExprResult DefArgResult(ParseAssignmentExpression());
        if (DefArgResult.isInvalid())
          Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param);
        else
          Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc,
                                            move(DefArgResult));

        assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
                                                           Tok.getLocation()) &&
               "ParseAssignmentExpression went over the default arg tokens!");
        // There could be leftover tokens (e.g. because of an error).
        // Skip through until we reach the original token position.
        while (Tok.getLocation() != origLoc)
          ConsumeAnyToken();

        delete Toks;
        LM.DefaultArgs[I].Toks = 0;
      }
    }
    PrototypeScope.Exit();

    // Finish the delayed C++ method declaration.
    Actions.ActOnFinishDelayedCXXMethodDeclaration(CurScope, LM.Method);
  }

  for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I)
    ParseLexedMethodDeclarations(*Class.NestedClasses[I]);

  if (HasClassScope)
    Actions.ActOnFinishDelayedMemberDeclarations(CurScope, Class.TagOrTemplate);
}

/// ParseLexedMethodDefs - We finished parsing the member specification of a top
/// (non-nested) C++ class. Now go over the stack of lexed methods that were
/// collected during its parsing and parse them all.
void Parser::ParseLexedMethodDefs(ParsingClass &Class) {
  bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
  ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
  if (HasTemplateScope)
    Actions.ActOnReenterTemplateScope(CurScope, Class.TagOrTemplate);

  bool HasClassScope = !Class.TopLevelClass;
  ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
                        HasClassScope);

  for (; !Class.MethodDefs.empty(); Class.MethodDefs.pop_front()) {
    LexedMethod &LM = Class.MethodDefs.front();

    // If this is a member template, introduce the template parameter scope.
    ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
    if (LM.TemplateScope)
      Actions.ActOnReenterTemplateScope(CurScope, LM.D);

    // Save the current token position.
    SourceLocation origLoc = Tok.getLocation();

    assert(!LM.Toks.empty() && "Empty body!");
    // Append the current token at the end of the new token stream so that it
    // doesn't get lost.
    LM.Toks.push_back(Tok);
    PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);

    // Consume the previously pushed token.
    ConsumeAnyToken();
    assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
           && "Inline method not starting with '{', ':' or 'try'");

    // Parse the method body. Function body parsing code is similar enough
    // to be re-used for method bodies as well.
    ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
    Actions.ActOnStartOfFunctionDef(CurScope, LM.D);

    if (Tok.is(tok::kw_try)) {
      ParseFunctionTryBlock(LM.D);
      assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
                                                           Tok.getLocation()) &&
             "ParseFunctionTryBlock went over the cached tokens!");
      assert(Tok.getLocation() == origLoc &&
             "ParseFunctionTryBlock left tokens in the token stream!");
      continue;
    }
    if (Tok.is(tok::colon)) {
      ParseConstructorInitializer(LM.D);

      // Error recovery.
      if (!Tok.is(tok::l_brace)) {
        Actions.ActOnFinishFunctionBody(LM.D, Action::StmtArg(Actions));
        continue;
      }
    } else
      Actions.ActOnDefaultCtorInitializers(LM.D);

    ParseFunctionStatementBody(LM.D);
    assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
                                                           Tok.getLocation()) &&
           "We consumed more than the cached tokens!");
    assert(Tok.getLocation() == origLoc &&
           "Tokens were left in the token stream!");
  }

  for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I)
    ParseLexedMethodDefs(*Class.NestedClasses[I]);
}

/// ConsumeAndStoreUntil - Consume and store the token at the passed token
/// container until the token 'T' is reached (which gets
/// consumed/stored too, if ConsumeFinalToken).
/// If EarlyAbortIf is specified, then we will stop early if we find that
/// token at the top level.
/// Returns true if token 'T1' or 'T2' was found.
/// NOTE: This is a specialized version of Parser::SkipUntil.
bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
                                  CachedTokens &Toks,
                                  tok::TokenKind EarlyAbortIf,
                                  bool ConsumeFinalToken) {
  // We always want this function to consume at least one token if the first
  // token isn't T and if not at EOF.
  bool isFirstTokenConsumed = true;
  while (1) {
    // If we found one of the tokens, stop and return true.
    if (Tok.is(T1) || Tok.is(T2)) {
      if (ConsumeFinalToken) {
        Toks.push_back(Tok);
        ConsumeAnyToken();
      }
      return true;
    }

    // If we found the early-abort token, return.
    if (Tok.is(EarlyAbortIf))
      return false;

    switch (Tok.getKind()) {
    case tok::eof:
      // Ran out of tokens.
      return false;

    case tok::l_paren:
      // Recursively consume properly-nested parens.
      Toks.push_back(Tok);
      ConsumeParen();
      ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks);
      break;
    case tok::l_square:
      // Recursively consume properly-nested square brackets.
      Toks.push_back(Tok);
      ConsumeBracket();
      ConsumeAndStoreUntil(tok::r_square, tok::unknown, Toks);
      break;
    case tok::l_brace:
      // Recursively consume properly-nested braces.
      Toks.push_back(Tok);
      ConsumeBrace();
      ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
      break;

    // Okay, we found a ']' or '}' or ')', which we think should be balanced.
    // Since the user wasn't looking for this token (if they were, it would
    // already be handled), this isn't balanced.  If there is a LHS token at a
    // higher level, we will assume that this matches the unbalanced token
    // and return it.  Otherwise, this is a spurious RHS token, which we skip.
    case tok::r_paren:
      if (ParenCount && !isFirstTokenConsumed)
        return false;  // Matches something.
      Toks.push_back(Tok);
      ConsumeParen();
      break;
    case tok::r_square:
      if (BracketCount && !isFirstTokenConsumed)
        return false;  // Matches something.
      Toks.push_back(Tok);
      ConsumeBracket();
      break;
    case tok::r_brace:
      if (BraceCount && !isFirstTokenConsumed)
        return false;  // Matches something.
      Toks.push_back(Tok);
      ConsumeBrace();
      break;

    case tok::string_literal:
    case tok::wide_string_literal:
      Toks.push_back(Tok);
      ConsumeStringToken();
      break;
    default:
      // consume this token.
      Toks.push_back(Tok);
      ConsumeToken();
      break;
    }
    isFirstTokenConsumed = false;
  }
}
<|endoftext|>


<commit_before>/**
 * \file TypeTraits.cpp
 */

#include <ATK/Core/TypeTraits.h>

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_CASE( TypeTraits_test_to_double_int16_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int16_t>::to_double(std::numeric_limits<std::int16_t>::min()), -1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_to_double_int32_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int32_t>::to_double(std::numeric_limits<std::int32_t>::min()), -1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_to_double_int64_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<int64_t>::to_double(std::numeric_limits<int64_t>::min()), -1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_from_double_int16_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int16_t>::from_double(-1), std::numeric_limits<std::int16_t>::min());
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_from_double_int32_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int32_t>::from_double(-1), std::numeric_limits<std::int32_t>::min());
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_from_double_int64_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<int64_t>::from_double(-1), std::numeric_limits<int64_t>::min());
}
<commit_msg>More typetraits tests<commit_after>/**
 * \file TypeTraits.cpp
 */

#include <ATK/Core/TypeTraits.h>

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_CASE( TypeTraits_test_to_double_int16_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int16_t>::to_double(std::numeric_limits<std::int16_t>::min()), -1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_to_double_int32_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int32_t>::to_double(std::numeric_limits<std::int32_t>::min()), -1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_to_double_int64_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<int64_t>::to_double(std::numeric_limits<int64_t>::min()), -1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_from_double_int16_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int16_t>::from_double(-1), std::numeric_limits<std::int16_t>::min());
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_from_double_int32_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int32_t>::from_double(-1), std::numeric_limits<std::int32_t>::min());
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_from_double_int64_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<int64_t>::from_double(-1), std::numeric_limits<int64_t>::min());
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_conj_int16_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int16_t>::conj(-1), -1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_conj_int32_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int32_t>::conj(-1), -1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_conj_int64_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<int64_t>::conj(-1), -1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_conj_float )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<float>::conj(-1), -1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_conj_double )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<double>::conj(-1), -1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_zero_int16_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int16_t>::Zero(), 0);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_zero_int32_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int32_t>::Zero(), 0);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_zero_int64_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<int64_t>::Zero(), 0);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_zero_float )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<float>::Zero(), 0);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_zero_double )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<double>::Zero(), 0);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_one_int16_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int16_t>::One(), 1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_one_int32_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int32_t>::One(), 1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_one_int64_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<int64_t>::One(), 1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_one_float )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<float>::One(), 1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_one_double )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<double>::One(), 1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_max_int16_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int16_t>::max(0, 1), 1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_max_int32_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<std::int32_t>::max(0, 1), 1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_max_int64_t )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<int64_t>::max(0, 1), 1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_max_float )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<float>::max(0, 1), 1);
}

BOOST_AUTO_TEST_CASE( TypeTraits_test_max_double )
{
  BOOST_CHECK_EQUAL(ATK::TypeTraits<double>::max(0, 1), 1);
}
<|endoftext|>


<commit_before>//===- StripSymbols.cpp - Strip symbols and debug info from a module ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// The StripSymbols transformation implements code stripping. Specifically, it
// can delete:
//
//   * names for virtual registers
//   * symbols for internal globals and functions
//   * debug information
//
// Note that this transformation makes code much less readable, so it should
// only be used in situations where the 'strip' utility would be used, such as
// reducing code size or making it harder to reverse engineer code.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;

namespace {
  class StripSymbols : public ModulePass {
    bool OnlyDebugInfo;
  public:
    static char ID; // Pass identification, replacement for typeid
    explicit StripSymbols(bool ODI = false)
      : ModulePass(&ID), OnlyDebugInfo(ODI) {}

    virtual bool runOnModule(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };

  class StripNonDebugSymbols : public ModulePass {
  public:
    static char ID; // Pass identification, replacement for typeid
    explicit StripNonDebugSymbols()
      : ModulePass(&ID) {}

    virtual bool runOnModule(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };

  class StripDebugDeclare : public ModulePass {
  public:
    static char ID; // Pass identification, replacement for typeid
    explicit StripDebugDeclare()
      : ModulePass(&ID) {}

    virtual bool runOnModule(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };
}

char StripSymbols::ID = 0;
static RegisterPass<StripSymbols>
X("strip", "Strip all symbols from a module");

ModulePass *llvm::createStripSymbolsPass(bool OnlyDebugInfo) {
  return new StripSymbols(OnlyDebugInfo);
}

char StripNonDebugSymbols::ID = 0;
static RegisterPass<StripNonDebugSymbols>
Y("strip-nondebug", "Strip all symbols, except dbg symbols, from a module");

ModulePass *llvm::createStripNonDebugSymbolsPass() {
  return new StripNonDebugSymbols();
}

char StripDebugDeclare::ID = 0;
static RegisterPass<StripDebugDeclare>
Z("strip-debug-declare", "Strip all llvm.dbg.declare intrinsics");

ModulePass *llvm::createStripDebugDeclarePass() {
  return new StripDebugDeclare();
}

/// OnlyUsedBy - Return true if V is only used by Usr.
static bool OnlyUsedBy(Value *V, Value *Usr) {
  for(Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) {
    User *U = *I;
    if (U != Usr)
      return false;
  }
  return true;
}

static void RemoveDeadConstant(Constant *C) {
  assert(C->use_empty() && "Constant is not dead!");
  SmallPtrSet<Constant*, 4> Operands;
  for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i)
    if (isa<DerivedType>(C->getOperand(i)->getType()) &&
        OnlyUsedBy(C->getOperand(i), C))
      Operands.insert(cast<Constant>(C->getOperand(i)));
  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
    if (!GV->hasLocalLinkage()) return;   // Don't delete non static globals.
    GV->eraseFromParent();
  }
  else if (!isa<Function>(C))
    if (isa<CompositeType>(C->getType()))
      C->destroyConstant();

  // If the constant referenced anything, see if we can delete it as well.
  for (SmallPtrSet<Constant*, 4>::iterator OI = Operands.begin(),
         OE = Operands.end(); OI != OE; ++OI)
    RemoveDeadConstant(*OI);
}

// Strip the symbol table of its names.
//
static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) {
  for (ValueSymbolTable::iterator VI = ST.begin(), VE = ST.end(); VI != VE; ) {
    Value *V = VI->getValue();
    ++VI;
    if (!isa<GlobalValue>(V) || cast<GlobalValue>(V)->hasLocalLinkage()) {
      if (!PreserveDbgInfo || !V->getName().startswith("llvm.dbg"))
        // Set name to "", removing from symbol table!
        V->setName("");
    }
  }
}

// Strip the symbol table of its names.
static void StripTypeSymtab(TypeSymbolTable &ST, bool PreserveDbgInfo) {
  for (TypeSymbolTable::iterator TI = ST.begin(), E = ST.end(); TI != E; ) {
    if (PreserveDbgInfo && StringRef(TI->first).startswith("llvm.dbg"))
      ++TI;
    else
      ST.remove(TI++);
  }
}

/// Find values that are marked as llvm.used.
static void findUsedValues(GlobalVariable *LLVMUsed,
                           SmallPtrSet<const GlobalValue*, 8> &UsedValues) {
  if (LLVMUsed == 0) return;
  UsedValues.insert(LLVMUsed);

  ConstantArray *Inits = dyn_cast<ConstantArray>(LLVMUsed->getInitializer());
  if (Inits == 0) return;

  for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
    if (GlobalValue *GV =
          dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
      UsedValues.insert(GV);
}

/// StripSymbolNames - Strip symbol names.
static bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {

  SmallPtrSet<const GlobalValue*, 8> llvmUsedValues;
  findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues);
  findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues);

  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I) {
    if (I->hasLocalLinkage() && llvmUsedValues.count(I) == 0)
      if (!PreserveDbgInfo || !I->getName().startswith("llvm.dbg"))
        I->setName("");     // Internal symbols can't participate in linkage
  }

  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
    if (I->hasLocalLinkage() && llvmUsedValues.count(I) == 0)
      if (!PreserveDbgInfo || !I->getName().startswith("llvm.dbg"))
        I->setName("");     // Internal symbols can't participate in linkage
    StripSymtab(I->getValueSymbolTable(), PreserveDbgInfo);
  }

  // Remove all names from types.
  StripTypeSymtab(M.getTypeSymbolTable(), PreserveDbgInfo);

  return true;
}

// StripDebugInfo - Strip debug info in the module if it exists.
// To do this, we remove llvm.dbg.func.start, llvm.dbg.stoppoint, and
// llvm.dbg.region.end calls, and any globals they point to if now dead.
static bool StripDebugInfo(Module &M) {

  bool Changed = false;

  // Remove all of the calls to the debugger intrinsics, and remove them from
  // the module.
  if (Function *Declare = M.getFunction("llvm.dbg.declare")) {
    while (!Declare->use_empty()) {
      CallInst *CI = cast<CallInst>(Declare->use_back());
      CI->eraseFromParent();
    }
    Declare->eraseFromParent();
    Changed = true;
  }

  if (Function *DbgVal = M.getFunction("llvm.dbg.value")) {
    while (!DbgVal->use_empty()) {
      CallInst *CI = cast<CallInst>(DbgVal->use_back());
      CI->eraseFromParent();
    }
    DbgVal->eraseFromParent();
    Changed = true;
  }

  NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.gv");
  if (NMD) {
    Changed = true;
    NMD->eraseFromParent();
  }

  NMD = M.getNamedMetadata("llvm.dbg.lv");
  if (NMD) {
    Changed = true;
    NMD->eraseFromParent();
  }

  unsigned MDDbgKind = M.getMDKindID("dbg");
  for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI)
    for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE;
         ++FI)
      for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE;
           ++BI) {
        Changed = true; // FIXME: Only set if there was debug metadata.
        BI->setMetadata(MDDbgKind, 0);
      }

  return Changed;
}

bool StripSymbols::runOnModule(Module &M) {
  bool Changed = false;
  Changed |= StripDebugInfo(M);
  if (!OnlyDebugInfo)
    Changed |= StripSymbolNames(M, false);
  return Changed;
}

bool StripNonDebugSymbols::runOnModule(Module &M) {
  return StripSymbolNames(M, true);
}

bool StripDebugDeclare::runOnModule(Module &M) {

  Function *Declare = M.getFunction("llvm.dbg.declare");
  std::vector<Constant*> DeadConstants;

  if (Declare) {
    while (!Declare->use_empty()) {
      CallInst *CI = cast<CallInst>(Declare->use_back());
      Value *Arg1 = CI->getOperand(1);
      Value *Arg2 = CI->getOperand(2);
      assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
      CI->eraseFromParent();
      if (Arg1->use_empty()) {
        if (Constant *C = dyn_cast<Constant>(Arg1))
          DeadConstants.push_back(C);
        else
          RecursivelyDeleteTriviallyDeadInstructions(Arg1);
      }
      if (Arg2->use_empty())
        if (Constant *C = dyn_cast<Constant>(Arg2))
          DeadConstants.push_back(C);
    }
    Declare->eraseFromParent();
  }

  while (!DeadConstants.empty()) {
    Constant *C = DeadConstants.back();
    DeadConstants.pop_back();
    if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
      if (GV->hasLocalLinkage())
        RemoveDeadConstant(GV);
    } else
      RemoveDeadConstant(C);
  }

  return true;
}
<commit_msg>use ArgOperand API<commit_after>//===- StripSymbols.cpp - Strip symbols and debug info from a module ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// The StripSymbols transformation implements code stripping. Specifically, it
// can delete:
//
//   * names for virtual registers
//   * symbols for internal globals and functions
//   * debug information
//
// Note that this transformation makes code much less readable, so it should
// only be used in situations where the 'strip' utility would be used, such as
// reducing code size or making it harder to reverse engineer code.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;

namespace {
  class StripSymbols : public ModulePass {
    bool OnlyDebugInfo;
  public:
    static char ID; // Pass identification, replacement for typeid
    explicit StripSymbols(bool ODI = false)
      : ModulePass(&ID), OnlyDebugInfo(ODI) {}

    virtual bool runOnModule(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };

  class StripNonDebugSymbols : public ModulePass {
  public:
    static char ID; // Pass identification, replacement for typeid
    explicit StripNonDebugSymbols()
      : ModulePass(&ID) {}

    virtual bool runOnModule(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };

  class StripDebugDeclare : public ModulePass {
  public:
    static char ID; // Pass identification, replacement for typeid
    explicit StripDebugDeclare()
      : ModulePass(&ID) {}

    virtual bool runOnModule(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };
}

char StripSymbols::ID = 0;
static RegisterPass<StripSymbols>
X("strip", "Strip all symbols from a module");

ModulePass *llvm::createStripSymbolsPass(bool OnlyDebugInfo) {
  return new StripSymbols(OnlyDebugInfo);
}

char StripNonDebugSymbols::ID = 0;
static RegisterPass<StripNonDebugSymbols>
Y("strip-nondebug", "Strip all symbols, except dbg symbols, from a module");

ModulePass *llvm::createStripNonDebugSymbolsPass() {
  return new StripNonDebugSymbols();
}

char StripDebugDeclare::ID = 0;
static RegisterPass<StripDebugDeclare>
Z("strip-debug-declare", "Strip all llvm.dbg.declare intrinsics");

ModulePass *llvm::createStripDebugDeclarePass() {
  return new StripDebugDeclare();
}

/// OnlyUsedBy - Return true if V is only used by Usr.
static bool OnlyUsedBy(Value *V, Value *Usr) {
  for(Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) {
    User *U = *I;
    if (U != Usr)
      return false;
  }
  return true;
}

static void RemoveDeadConstant(Constant *C) {
  assert(C->use_empty() && "Constant is not dead!");
  SmallPtrSet<Constant*, 4> Operands;
  for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i)
    if (isa<DerivedType>(C->getOperand(i)->getType()) &&
        OnlyUsedBy(C->getOperand(i), C))
      Operands.insert(cast<Constant>(C->getOperand(i)));
  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
    if (!GV->hasLocalLinkage()) return;   // Don't delete non static globals.
    GV->eraseFromParent();
  }
  else if (!isa<Function>(C))
    if (isa<CompositeType>(C->getType()))
      C->destroyConstant();

  // If the constant referenced anything, see if we can delete it as well.
  for (SmallPtrSet<Constant*, 4>::iterator OI = Operands.begin(),
         OE = Operands.end(); OI != OE; ++OI)
    RemoveDeadConstant(*OI);
}

// Strip the symbol table of its names.
//
static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) {
  for (ValueSymbolTable::iterator VI = ST.begin(), VE = ST.end(); VI != VE; ) {
    Value *V = VI->getValue();
    ++VI;
    if (!isa<GlobalValue>(V) || cast<GlobalValue>(V)->hasLocalLinkage()) {
      if (!PreserveDbgInfo || !V->getName().startswith("llvm.dbg"))
        // Set name to "", removing from symbol table!
        V->setName("");
    }
  }
}

// Strip the symbol table of its names.
static void StripTypeSymtab(TypeSymbolTable &ST, bool PreserveDbgInfo) {
  for (TypeSymbolTable::iterator TI = ST.begin(), E = ST.end(); TI != E; ) {
    if (PreserveDbgInfo && StringRef(TI->first).startswith("llvm.dbg"))
      ++TI;
    else
      ST.remove(TI++);
  }
}

/// Find values that are marked as llvm.used.
static void findUsedValues(GlobalVariable *LLVMUsed,
                           SmallPtrSet<const GlobalValue*, 8> &UsedValues) {
  if (LLVMUsed == 0) return;
  UsedValues.insert(LLVMUsed);

  ConstantArray *Inits = dyn_cast<ConstantArray>(LLVMUsed->getInitializer());
  if (Inits == 0) return;

  for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
    if (GlobalValue *GV =
          dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
      UsedValues.insert(GV);
}

/// StripSymbolNames - Strip symbol names.
static bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {

  SmallPtrSet<const GlobalValue*, 8> llvmUsedValues;
  findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues);
  findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues);

  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I) {
    if (I->hasLocalLinkage() && llvmUsedValues.count(I) == 0)
      if (!PreserveDbgInfo || !I->getName().startswith("llvm.dbg"))
        I->setName("");     // Internal symbols can't participate in linkage
  }

  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
    if (I->hasLocalLinkage() && llvmUsedValues.count(I) == 0)
      if (!PreserveDbgInfo || !I->getName().startswith("llvm.dbg"))
        I->setName("");     // Internal symbols can't participate in linkage
    StripSymtab(I->getValueSymbolTable(), PreserveDbgInfo);
  }

  // Remove all names from types.
  StripTypeSymtab(M.getTypeSymbolTable(), PreserveDbgInfo);

  return true;
}

// StripDebugInfo - Strip debug info in the module if it exists.
// To do this, we remove llvm.dbg.func.start, llvm.dbg.stoppoint, and
// llvm.dbg.region.end calls, and any globals they point to if now dead.
static bool StripDebugInfo(Module &M) {

  bool Changed = false;

  // Remove all of the calls to the debugger intrinsics, and remove them from
  // the module.
  if (Function *Declare = M.getFunction("llvm.dbg.declare")) {
    while (!Declare->use_empty()) {
      CallInst *CI = cast<CallInst>(Declare->use_back());
      CI->eraseFromParent();
    }
    Declare->eraseFromParent();
    Changed = true;
  }

  if (Function *DbgVal = M.getFunction("llvm.dbg.value")) {
    while (!DbgVal->use_empty()) {
      CallInst *CI = cast<CallInst>(DbgVal->use_back());
      CI->eraseFromParent();
    }
    DbgVal->eraseFromParent();
    Changed = true;
  }

  NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.gv");
  if (NMD) {
    Changed = true;
    NMD->eraseFromParent();
  }

  NMD = M.getNamedMetadata("llvm.dbg.lv");
  if (NMD) {
    Changed = true;
    NMD->eraseFromParent();
  }

  unsigned MDDbgKind = M.getMDKindID("dbg");
  for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI)
    for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE;
         ++FI)
      for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE;
           ++BI) {
        Changed = true; // FIXME: Only set if there was debug metadata.
        BI->setMetadata(MDDbgKind, 0);
      }

  return Changed;
}

bool StripSymbols::runOnModule(Module &M) {
  bool Changed = false;
  Changed |= StripDebugInfo(M);
  if (!OnlyDebugInfo)
    Changed |= StripSymbolNames(M, false);
  return Changed;
}

bool StripNonDebugSymbols::runOnModule(Module &M) {
  return StripSymbolNames(M, true);
}

bool StripDebugDeclare::runOnModule(Module &M) {

  Function *Declare = M.getFunction("llvm.dbg.declare");
  std::vector<Constant*> DeadConstants;

  if (Declare) {
    while (!Declare->use_empty()) {
      CallInst *CI = cast<CallInst>(Declare->use_back());
      Value *Arg1 = CI->getArgOperand(0);
      Value *Arg2 = CI->getArgOperand(1);
      assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
      CI->eraseFromParent();
      if (Arg1->use_empty()) {
        if (Constant *C = dyn_cast<Constant>(Arg1))
          DeadConstants.push_back(C);
        else
          RecursivelyDeleteTriviallyDeadInstructions(Arg1);
      }
      if (Arg2->use_empty())
        if (Constant *C = dyn_cast<Constant>(Arg2))
          DeadConstants.push_back(C);
    }
    Declare->eraseFromParent();
  }

  while (!DeadConstants.empty()) {
    Constant *C = DeadConstants.back();
    DeadConstants.pop_back();
    if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
      if (GV->hasLocalLinkage())
        RemoveDeadConstant(GV);
    } else
      RemoveDeadConstant(C);
  }

  return true;
}
<|endoftext|>


<commit_before>#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <stdlib.h>
#include <QtGlobal>
#include <QtWidgets>
#ifndef Q_OS_DARWIN
#include <QtSingleApplication>
#endif

int main(int argc, char *argv[])
{
    // Global menubar is broken for qt5 apps in Ubuntu Unity, see:
    // https://bugs.launchpad.net/ubuntu/+source/appmenu-qt5/+bug/1323853
    // This workaround enables a local menubar.
    qputenv("UBUNTU_MENUPROXY","0");

    #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    #endif

    // Non Darwin platforms uses QSingleApplication to ensure only one running instance.
    #ifndef Q_OS_DARWIN
    QtSingleApplication app(argc, argv);
    if (app.sendMessage("")) {
        return 0;
    }
    #else
    QApplication app(argc, argv);
    #endif

    QString app_dir = app.applicationDirPath();
    QString main_qml = "/qml/Main.qml";
    QString path_prefix;
    QString url_prefix;

    if (QFileInfo::exists(":" + main_qml)) {
        // Embedded resources
        path_prefix = ":";
        url_prefix = "qrc://";
    } else if (QFileInfo::exists(app_dir + main_qml)) {
        // Try relative to executable
        path_prefix = app_dir;
        url_prefix = app_dir;
    } else {  //Assume qml/main.qml in cwd.
        app_dir = ".";
        path_prefix = ".";
        url_prefix = ".";
    }

    app.setWindowIcon(QIcon(path_prefix + "/images/windowicon.png"));

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("appDir", app_dir);
    engine.rootContext()->setContextProperty("urlPrefix", url_prefix);
    engine.rootContext()->setContextProperty("appVersion", APP_VERSION);

    qputenv("PYTHONDONTWRITEBYTECODE", "1");

    engine.load(QUrl(url_prefix + main_qml));

    #ifndef Q_OS_DARWIN
    // Wake up the root window on a message from new instance.
    for (auto object : engine.rootObjects()) {
        if (QWindow *window = qobject_cast<QWindow*>(object)) {
            QObject::connect(&app, &QtSingleApplication::messageReceived, [window]() {
                window->show();
                window->raise();
                window->requestActivate();
            });
        }
    }
    #endif

    return app.exec();
}
<commit_msg>force ANGLE on windows<commit_after>#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <stdlib.h>
#include <QtGlobal>
#include <QtWidgets>
#ifndef Q_OS_DARWIN
#include <QtSingleApplication>
#endif

int main(int argc, char *argv[])
{
    // Global menubar is broken for qt5 apps in Ubuntu Unity, see:
    // https://bugs.launchpad.net/ubuntu/+source/appmenu-qt5/+bug/1323853
    // This workaround enables a local menubar.
    qputenv("UBUNTU_MENUPROXY","0");

    // Don't write .pyc files.
    qputenv("PYTHONDONTWRITEBYTECODE", "1");

    #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    #endif

    // Non Darwin platforms uses QSingleApplication to ensure only one running instance.
    #ifndef Q_OS_DARWIN
    QtSingleApplication app(argc, argv);
    if (app.sendMessage("")) {
        return 0;
    }
    #else
    QApplication app(argc, argv);
    #endif

    QString app_dir = app.applicationDirPath();
    QString main_qml = "/qml/Main.qml";
    QString path_prefix;
    QString url_prefix;

    app.setApplicationName("YubiKey Manager");
    app.setOrganizationName("Yubico");
    app.setOrganizationDomain("com.yubico");

    // Use ANGLE on Windows
    app.setAttribute(Qt::AA_UseOpenGLES);

    if (QFileInfo::exists(":" + main_qml)) {
        // Embedded resources
        path_prefix = ":";
        url_prefix = "qrc://";
    } else if (QFileInfo::exists(app_dir + main_qml)) {
        // Try relative to executable
        path_prefix = app_dir;
        url_prefix = app_dir;
    } else {  //Assume qml/main.qml in cwd.
        app_dir = ".";
        path_prefix = ".";
        url_prefix = ".";
    }

    app.setWindowIcon(QIcon(path_prefix + "/images/windowicon.png"));

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("appDir", app_dir);
    engine.rootContext()->setContextProperty("urlPrefix", url_prefix);
    engine.rootContext()->setContextProperty("appVersion", APP_VERSION);

    engine.load(QUrl(url_prefix + main_qml));

    #ifndef Q_OS_DARWIN
    // Wake up the root window on a message from new instance.
    for (auto object : engine.rootObjects()) {
        if (QWindow *window = qobject_cast<QWindow*>(object)) {
            QObject::connect(&app, &QtSingleApplication::messageReceived, [window]() {
                window->show();
                window->raise();
                window->requestActivate();
            });
        }
    }
    #endif

    return app.exec();
}
<|endoftext|>


<commit_before><commit_msg>proper case for member functions<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2015 Facebook, Inc.
 *
 * 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 <thrift/lib/cpp/EventHandlerBase.h>

#include <gtest/gtest.h>

using namespace std;
using namespace folly;
using namespace apache::thrift;

class lulz : public exception {
 public:
  explicit lulz(string message) noexcept : message_(move(message)) {}
  const char* what() const noexcept override { return message_.c_str(); }
 private:
  string message_;
};

namespace {

class EventHandler : public TProcessorEventHandler {
 public:
  string ex_type;
  string ex_what;
  void userException(void*,
                     const char*,
                     const std::string& ex_type,
                     const std::string& ex_what) override {
    this->ex_type = ex_type;
    this->ex_what = ex_what;
  }
};

template <class E> exception_ptr to_eptr(const E& e) {
  try { throw e; }
  catch (E&) { return current_exception(); }
}

class TProcessorEventHandlerTest : public testing::Test {};

}

TEST_F(TProcessorEventHandlerTest, with_full_wrapped_eptr) {
  auto e = lulz("hello");
  auto wrap = exception_wrapper(to_eptr(e), e);
  EXPECT_EQ("lulz", wrap.class_name().toStdString());
  EXPECT_EQ("lulz: hello", wrap.what().toStdString());

  EventHandler eh;
  eh.userExceptionWrapped(nullptr, nullptr, false, wrap);
  EXPECT_EQ("lulz", eh.ex_type);
  EXPECT_EQ("hello", eh.ex_what);
}

TEST_F(TProcessorEventHandlerTest, with_half_wrapped_eptr) {
  auto e = lulz("hello");
  auto wrap = exception_wrapper(to_eptr(e));
  EXPECT_EQ("", wrap.class_name().toStdString());
  EXPECT_EQ("", wrap.what().toStdString());

  EventHandler eh;
  eh.userExceptionWrapped(nullptr, nullptr, false, wrap);
  EXPECT_EQ("lulz", eh.ex_type);
  EXPECT_EQ("hello", eh.ex_what);
}

TEST_F(TProcessorEventHandlerTest, with_wrap_surprise) {
  auto e = lulz("hello");
  auto wrap = exception_wrapper(e);
  EXPECT_EQ("lulz", wrap.class_name().toStdString());
  EXPECT_EQ("lulz: hello", wrap.what().toStdString());

  EventHandler eh;
  eh.userExceptionWrapped(nullptr, nullptr, false, wrap);
  EXPECT_EQ("lulz", eh.ex_type);
  EXPECT_EQ("lulz: hello", eh.ex_what);
}

TEST_F(TProcessorEventHandlerTest, with_wrap_declared) {
  auto e = lulz("hello");
  auto wrap = exception_wrapper(e);
  EXPECT_EQ("lulz", wrap.class_name().toStdString());
  EXPECT_EQ("lulz: hello", wrap.what().toStdString());

  EventHandler eh;
  eh.userExceptionWrapped(nullptr, nullptr, true, wrap);
  EXPECT_EQ("lulz", eh.ex_type);
  EXPECT_EQ("hello", eh.ex_what);
}
<commit_msg>Refactor some EventHandlerBaseTest setup code<commit_after>/*
 * Copyright 2015 Facebook, Inc.
 *
 * 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 <thrift/lib/cpp/EventHandlerBase.h>

#include <gtest/gtest.h>

using namespace std;
using namespace folly;
using namespace apache::thrift;

class lulz : public exception {
 public:
  explicit lulz(string message) noexcept : message_(move(message)) {}
  const char* what() const noexcept override { return message_.c_str(); }
 private:
  string message_;
};

namespace {

class EventHandler : public TProcessorEventHandler {
 public:
  string ex_type;
  string ex_what;
  void userException(void*,
                     const char*,
                     const std::string& ex_type,
                     const std::string& ex_what) override {
    this->ex_type = ex_type;
    this->ex_what = ex_what;
  }
};

template <class E> exception_ptr to_eptr(const E& e) {
  try { throw e; }
  catch (E&) { return current_exception(); }
}

exception& from_eptr(exception_ptr& eptr) {
  try {
    rethrow_exception(eptr);
  } catch (exception& e) {
    return e;
  } catch (...) {
    throw std::logic_error("impossible");
  }
}

class TProcessorEventHandlerTest : public testing::Test {};

}

TEST_F(TProcessorEventHandlerTest, with_full_wrapped_eptr) {
  auto eptr = make_exception_ptr(lulz("hello"));
  auto wrap = exception_wrapper(eptr, from_eptr(eptr));
  EXPECT_EQ("lulz", wrap.class_name().toStdString());
  EXPECT_EQ("lulz: hello", wrap.what().toStdString());

  EventHandler eh;
  eh.userExceptionWrapped(nullptr, nullptr, false, wrap);
  EXPECT_EQ("lulz", eh.ex_type);
  EXPECT_EQ("hello", eh.ex_what);
}

TEST_F(TProcessorEventHandlerTest, with_half_wrapped_eptr) {
  auto eptr = make_exception_ptr(lulz("hello"));
  auto wrap = exception_wrapper(eptr);
  EXPECT_EQ("", wrap.class_name().toStdString());
  EXPECT_EQ("", wrap.what().toStdString());

  EventHandler eh;
  eh.userExceptionWrapped(nullptr, nullptr, false, wrap);
  EXPECT_EQ("lulz", eh.ex_type);
  EXPECT_EQ("hello", eh.ex_what);
}

TEST_F(TProcessorEventHandlerTest, with_wrap_surprise) {
  auto wrap = exception_wrapper(lulz("hello"));
  EXPECT_EQ("lulz", wrap.class_name().toStdString());
  EXPECT_EQ("lulz: hello", wrap.what().toStdString());

  EventHandler eh;
  eh.userExceptionWrapped(nullptr, nullptr, false, wrap);
  EXPECT_EQ("lulz", eh.ex_type);
  EXPECT_EQ("lulz: hello", eh.ex_what);
}

TEST_F(TProcessorEventHandlerTest, with_wrap_declared) {
  auto wrap = exception_wrapper(lulz("hello"));
  EXPECT_EQ("lulz", wrap.class_name().toStdString());
  EXPECT_EQ("lulz: hello", wrap.what().toStdString());

  EventHandler eh;
  eh.userExceptionWrapped(nullptr, nullptr, true, wrap);
  EXPECT_EQ("lulz", eh.ex_type);
  EXPECT_EQ("hello", eh.ex_what);
}
<|endoftext|>


<commit_before><commit_msg>Bugfix: added missing `#include` line.<commit_after><|endoftext|>


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

#include <array>
#include <string>

#include "Assembler.h"
#include "MCInstrDescView.h"
#include "SnippetGenerator.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Program.h"

namespace exegesis {

std::vector<CodeTemplate> getSingleton(CodeTemplate &CT) {
  std::vector<CodeTemplate> Result;
  Result.push_back(std::move(CT));
  return Result;
}

SnippetGeneratorFailure::SnippetGeneratorFailure(const llvm::Twine &S)
    : llvm::StringError(S, llvm::inconvertibleErrorCode()) {}

SnippetGenerator::SnippetGenerator(const LLVMState &State) : State(State) {}

SnippetGenerator::~SnippetGenerator() = default;

llvm::Expected<std::vector<BenchmarkCode>>
SnippetGenerator::generateConfigurations(const Instruction &Instr) const {
  if (auto E = generateCodeTemplates(Instr)) {
    const auto &RATC = State.getRATC();
    std::vector<BenchmarkCode> Output;
    for (CodeTemplate &CT : E.get()) {
      const llvm::BitVector &ForbiddenRegs =
          CT.ScratchSpacePointerInReg
              ? RATC.getRegister(CT.ScratchSpacePointerInReg).aliasedBits()
              : RATC.emptyRegisters();
      // TODO: Generate as many BenchmarkCode as needed.
      {
        BenchmarkCode BC;
        BC.Info = CT.Info;
        for (InstructionTemplate &IT : CT.Instructions) {
          randomizeUnsetVariables(ForbiddenRegs, IT);
          BC.Instructions.push_back(IT.build());
        }
        if (CT.ScratchSpacePointerInReg)
          BC.LiveIns.push_back(CT.ScratchSpacePointerInReg);
        BC.RegisterInitialValues =
            computeRegisterInitialValues(CT.Instructions);
        Output.push_back(std::move(BC));
      }
    }
    return Output;
  } else
    return E.takeError();
}

std::vector<RegisterValue> SnippetGenerator::computeRegisterInitialValues(
    const std::vector<InstructionTemplate> &Instructions) const {
  // Collect all register uses and create an assignment for each of them.
  // Ignore memory operands which are handled separately.
  // Loop invariant: DefinedRegs[i] is true iif it has been set at least once
  // before the current instruction.
  llvm::BitVector DefinedRegs = State.getRATC().emptyRegisters();
  std::vector<RegisterValue> RIV;
  for (const InstructionTemplate &IT : Instructions) {
    // Returns the register that this Operand sets or uses, or 0 if this is not
    // a register.
    const auto GetOpReg = [&IT](const Operand &Op) -> unsigned {
      if (Op.isMemory())
        return 0;
      if (Op.isImplicitReg())
        return Op.getImplicitReg();
      if (Op.isExplicit() && IT.getValueFor(Op).isReg())
        return IT.getValueFor(Op).getReg();
      return 0;
    };
    // Collect used registers that have never been def'ed.
    for (const Operand &Op : IT.Instr.Operands) {
      if (Op.isUse()) {
        const unsigned Reg = GetOpReg(Op);
        if (Reg > 0 && !DefinedRegs.test(Reg)) {
          RIV.push_back(RegisterValue{Reg, llvm::APInt()});
          DefinedRegs.set(Reg);
        }
      }
    }
    // Mark defs as having been def'ed.
    for (const Operand &Op : IT.Instr.Operands) {
      if (Op.isDef()) {
        const unsigned Reg = GetOpReg(Op);
        if (Reg > 0)
          DefinedRegs.set(Reg);
      }
    }
  }
  return RIV;
}

llvm::Expected<std::vector<CodeTemplate>>
generateSelfAliasingCodeTemplates(const Instruction &Instr) {
  const AliasingConfigurations SelfAliasing(Instr, Instr);
  if (SelfAliasing.empty())
    return llvm::make_error<SnippetGeneratorFailure>("empty self aliasing");
  std::vector<CodeTemplate> Result;
  Result.emplace_back();
  CodeTemplate &CT = Result.back();
  InstructionTemplate IT(Instr);
  if (SelfAliasing.hasImplicitAliasing()) {
    CT.Info = "implicit Self cycles, picking random values.";
  } else {
    CT.Info = "explicit self cycles, selecting one aliasing Conf.";
    // This is a self aliasing instruction so defs and uses are from the same
    // instance, hence twice IT in the following call.
    setRandomAliasing(SelfAliasing, IT, IT);
  }
  CT.Instructions.push_back(std::move(IT));
  return Result;
}

llvm::Expected<std::vector<CodeTemplate>>
generateUnconstrainedCodeTemplates(const Instruction &Instr,
                                   llvm::StringRef Msg) {
  std::vector<CodeTemplate> Result;
  Result.emplace_back();
  CodeTemplate &CT = Result.back();
  CT.Info = llvm::formatv("{0}, repeating an unconstrained assignment", Msg);
  CT.Instructions.emplace_back(Instr);
  return Result;
}

std::mt19937 &randomGenerator() {
  static std::random_device RandomDevice;
  static std::mt19937 RandomGenerator(RandomDevice());
  return RandomGenerator;
}

static size_t randomIndex(size_t Size) {
  assert(Size > 0);
  std::uniform_int_distribution<> Distribution(0, Size - 1);
  return Distribution(randomGenerator());
}

template <typename C>
static auto randomElement(const C &Container) -> decltype(Container[0]) {
  return Container[randomIndex(Container.size())];
}

static void randomize(const Instruction &Instr, const Variable &Var,
                      llvm::MCOperand &AssignedValue,
                      const llvm::BitVector &ForbiddenRegs) {
  const Operand &Op = Instr.getPrimaryOperand(Var);
  switch (Op.getExplicitOperandInfo().OperandType) {
  case llvm::MCOI::OperandType::OPERAND_IMMEDIATE:
    // FIXME: explore immediate values too.
    AssignedValue = llvm::MCOperand::createImm(1);
    break;
  case llvm::MCOI::OperandType::OPERAND_REGISTER: {
    assert(Op.isReg());
    auto AllowedRegs = Op.getRegisterAliasing().sourceBits();
    assert(AllowedRegs.size() == ForbiddenRegs.size());
    for (auto I : ForbiddenRegs.set_bits())
      AllowedRegs.reset(I);
    AssignedValue = llvm::MCOperand::createReg(randomBit(AllowedRegs));
    break;
  }
  default:
    break;
  }
}

static void setRegisterOperandValue(const RegisterOperandAssignment &ROV,
                                    InstructionTemplate &IB) {
  assert(ROV.Op);
  if (ROV.Op->isExplicit()) {
    auto &AssignedValue = IB.getValueFor(*ROV.Op);
    if (AssignedValue.isValid()) {
      assert(AssignedValue.isReg() && AssignedValue.getReg() == ROV.Reg);
      return;
    }
    AssignedValue = llvm::MCOperand::createReg(ROV.Reg);
  } else {
    assert(ROV.Op->isImplicitReg());
    assert(ROV.Reg == ROV.Op->getImplicitReg());
  }
}

size_t randomBit(const llvm::BitVector &Vector) {
  assert(Vector.any());
  auto Itr = Vector.set_bits_begin();
  for (size_t I = randomIndex(Vector.count()); I != 0; --I)
    ++Itr;
  return *Itr;
}

void setRandomAliasing(const AliasingConfigurations &AliasingConfigurations,
                       InstructionTemplate &DefIB, InstructionTemplate &UseIB) {
  assert(!AliasingConfigurations.empty());
  assert(!AliasingConfigurations.hasImplicitAliasing());
  const auto &RandomConf = randomElement(AliasingConfigurations.Configurations);
  setRegisterOperandValue(randomElement(RandomConf.Defs), DefIB);
  setRegisterOperandValue(randomElement(RandomConf.Uses), UseIB);
}

void randomizeUnsetVariables(const llvm::BitVector &ForbiddenRegs,
                             InstructionTemplate &IT) {
  for (const Variable &Var : IT.Instr.Variables) {
    llvm::MCOperand &AssignedValue = IT.getValueFor(Var);
    if (!AssignedValue.isValid())
      randomize(IT.Instr, Var, AssignedValue, ForbiddenRegs);
  }
}

} // namespace exegesis
<commit_msg>[llvm-exegesis] Fix missing std::move.<commit_after>//===-- SnippetGenerator.cpp ------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include <array>
#include <string>

#include "Assembler.h"
#include "MCInstrDescView.h"
#include "SnippetGenerator.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Program.h"

namespace exegesis {

std::vector<CodeTemplate> getSingleton(CodeTemplate &CT) {
  std::vector<CodeTemplate> Result;
  Result.push_back(std::move(CT));
  return Result;
}

SnippetGeneratorFailure::SnippetGeneratorFailure(const llvm::Twine &S)
    : llvm::StringError(S, llvm::inconvertibleErrorCode()) {}

SnippetGenerator::SnippetGenerator(const LLVMState &State) : State(State) {}

SnippetGenerator::~SnippetGenerator() = default;

llvm::Expected<std::vector<BenchmarkCode>>
SnippetGenerator::generateConfigurations(const Instruction &Instr) const {
  if (auto E = generateCodeTemplates(Instr)) {
    const auto &RATC = State.getRATC();
    std::vector<BenchmarkCode> Output;
    for (CodeTemplate &CT : E.get()) {
      const llvm::BitVector &ForbiddenRegs =
          CT.ScratchSpacePointerInReg
              ? RATC.getRegister(CT.ScratchSpacePointerInReg).aliasedBits()
              : RATC.emptyRegisters();
      // TODO: Generate as many BenchmarkCode as needed.
      {
        BenchmarkCode BC;
        BC.Info = CT.Info;
        for (InstructionTemplate &IT : CT.Instructions) {
          randomizeUnsetVariables(ForbiddenRegs, IT);
          BC.Instructions.push_back(IT.build());
        }
        if (CT.ScratchSpacePointerInReg)
          BC.LiveIns.push_back(CT.ScratchSpacePointerInReg);
        BC.RegisterInitialValues =
            computeRegisterInitialValues(CT.Instructions);
        Output.push_back(std::move(BC));
      }
    }
    return Output;
  } else
    return E.takeError();
}

std::vector<RegisterValue> SnippetGenerator::computeRegisterInitialValues(
    const std::vector<InstructionTemplate> &Instructions) const {
  // Collect all register uses and create an assignment for each of them.
  // Ignore memory operands which are handled separately.
  // Loop invariant: DefinedRegs[i] is true iif it has been set at least once
  // before the current instruction.
  llvm::BitVector DefinedRegs = State.getRATC().emptyRegisters();
  std::vector<RegisterValue> RIV;
  for (const InstructionTemplate &IT : Instructions) {
    // Returns the register that this Operand sets or uses, or 0 if this is not
    // a register.
    const auto GetOpReg = [&IT](const Operand &Op) -> unsigned {
      if (Op.isMemory())
        return 0;
      if (Op.isImplicitReg())
        return Op.getImplicitReg();
      if (Op.isExplicit() && IT.getValueFor(Op).isReg())
        return IT.getValueFor(Op).getReg();
      return 0;
    };
    // Collect used registers that have never been def'ed.
    for (const Operand &Op : IT.Instr.Operands) {
      if (Op.isUse()) {
        const unsigned Reg = GetOpReg(Op);
        if (Reg > 0 && !DefinedRegs.test(Reg)) {
          RIV.push_back(RegisterValue{Reg, llvm::APInt()});
          DefinedRegs.set(Reg);
        }
      }
    }
    // Mark defs as having been def'ed.
    for (const Operand &Op : IT.Instr.Operands) {
      if (Op.isDef()) {
        const unsigned Reg = GetOpReg(Op);
        if (Reg > 0)
          DefinedRegs.set(Reg);
      }
    }
  }
  return RIV;
}

llvm::Expected<std::vector<CodeTemplate>>
generateSelfAliasingCodeTemplates(const Instruction &Instr) {
  const AliasingConfigurations SelfAliasing(Instr, Instr);
  if (SelfAliasing.empty())
    return llvm::make_error<SnippetGeneratorFailure>("empty self aliasing");
  std::vector<CodeTemplate> Result;
  Result.emplace_back();
  CodeTemplate &CT = Result.back();
  InstructionTemplate IT(Instr);
  if (SelfAliasing.hasImplicitAliasing()) {
    CT.Info = "implicit Self cycles, picking random values.";
  } else {
    CT.Info = "explicit self cycles, selecting one aliasing Conf.";
    // This is a self aliasing instruction so defs and uses are from the same
    // instance, hence twice IT in the following call.
    setRandomAliasing(SelfAliasing, IT, IT);
  }
  CT.Instructions.push_back(std::move(IT));
  return std::move(Result);
}

llvm::Expected<std::vector<CodeTemplate>>
generateUnconstrainedCodeTemplates(const Instruction &Instr,
                                   llvm::StringRef Msg) {
  std::vector<CodeTemplate> Result;
  Result.emplace_back();
  CodeTemplate &CT = Result.back();
  CT.Info = llvm::formatv("{0}, repeating an unconstrained assignment", Msg);
  CT.Instructions.emplace_back(Instr);
  return std::move(Result);
}

std::mt19937 &randomGenerator() {
  static std::random_device RandomDevice;
  static std::mt19937 RandomGenerator(RandomDevice());
  return RandomGenerator;
}

static size_t randomIndex(size_t Size) {
  assert(Size > 0);
  std::uniform_int_distribution<> Distribution(0, Size - 1);
  return Distribution(randomGenerator());
}

template <typename C>
static auto randomElement(const C &Container) -> decltype(Container[0]) {
  return Container[randomIndex(Container.size())];
}

static void randomize(const Instruction &Instr, const Variable &Var,
                      llvm::MCOperand &AssignedValue,
                      const llvm::BitVector &ForbiddenRegs) {
  const Operand &Op = Instr.getPrimaryOperand(Var);
  switch (Op.getExplicitOperandInfo().OperandType) {
  case llvm::MCOI::OperandType::OPERAND_IMMEDIATE:
    // FIXME: explore immediate values too.
    AssignedValue = llvm::MCOperand::createImm(1);
    break;
  case llvm::MCOI::OperandType::OPERAND_REGISTER: {
    assert(Op.isReg());
    auto AllowedRegs = Op.getRegisterAliasing().sourceBits();
    assert(AllowedRegs.size() == ForbiddenRegs.size());
    for (auto I : ForbiddenRegs.set_bits())
      AllowedRegs.reset(I);
    AssignedValue = llvm::MCOperand::createReg(randomBit(AllowedRegs));
    break;
  }
  default:
    break;
  }
}

static void setRegisterOperandValue(const RegisterOperandAssignment &ROV,
                                    InstructionTemplate &IB) {
  assert(ROV.Op);
  if (ROV.Op->isExplicit()) {
    auto &AssignedValue = IB.getValueFor(*ROV.Op);
    if (AssignedValue.isValid()) {
      assert(AssignedValue.isReg() && AssignedValue.getReg() == ROV.Reg);
      return;
    }
    AssignedValue = llvm::MCOperand::createReg(ROV.Reg);
  } else {
    assert(ROV.Op->isImplicitReg());
    assert(ROV.Reg == ROV.Op->getImplicitReg());
  }
}

size_t randomBit(const llvm::BitVector &Vector) {
  assert(Vector.any());
  auto Itr = Vector.set_bits_begin();
  for (size_t I = randomIndex(Vector.count()); I != 0; --I)
    ++Itr;
  return *Itr;
}

void setRandomAliasing(const AliasingConfigurations &AliasingConfigurations,
                       InstructionTemplate &DefIB, InstructionTemplate &UseIB) {
  assert(!AliasingConfigurations.empty());
  assert(!AliasingConfigurations.hasImplicitAliasing());
  const auto &RandomConf = randomElement(AliasingConfigurations.Configurations);
  setRegisterOperandValue(randomElement(RandomConf.Defs), DefIB);
  setRegisterOperandValue(randomElement(RandomConf.Uses), UseIB);
}

void randomizeUnsetVariables(const llvm::BitVector &ForbiddenRegs,
                             InstructionTemplate &IT) {
  for (const Variable &Var : IT.Instr.Variables) {
    llvm::MCOperand &AssignedValue = IT.getValueFor(Var);
    if (!AssignedValue.isValid())
      randomize(IT.Instr, Var, AssignedValue, ForbiddenRegs);
  }
}

} // namespace exegesis
<|endoftext|>


<commit_before>/*
 * Copyright 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#define BOOST_TEST_DYN_LINK

#include <random>
#include <bitset>
#include <boost/test/unit_test.hpp>
#include <boost/range/irange.hpp>
#include <seastar/core/semaphore.hh>
#include <seastar/core/reactor.hh>
#include <seastar/core/thread.hh>

#include "tests/test-utils.hh"
#include "utils/flush_queue.hh"
#include "log.hh"

#include "disk-error-handler.hh"

thread_local disk_error_signal_type commit_error;
thread_local disk_error_signal_type general_disk_error;

std::random_device rd;
std::default_random_engine e1(rd());

SEASTAR_TEST_CASE(test_queue_ordering_random_ops) {
    struct env {
        env(size_t n) : promises(n) {}

        utils::flush_queue<int> queue;
        std::vector<promise<>> promises;
        std::vector<int> result;
    };

    auto r = boost::irange(0, 100);

    return do_for_each(r, [](int) {
        constexpr size_t num_ops = 1000;

        auto e = make_lw_shared<env>(num_ops);

        int i = 0;
        for (auto& p : e->promises) {
            e->queue.run_with_ordered_post_op(i, [&p, i] {
                return p.get_future().then([i] {
                    return make_ready_future<int>(i);
                });
            }, [e](int i) {
                e->result.emplace_back(i);
            });
            ++i;
        }

        auto res = e->queue.wait_for_pending();

        std::uniform_int_distribution<size_t> dist(0, num_ops - 1);
        std::bitset<num_ops> set;

        while (!set.all()) {
            size_t i = dist(e1);
            if (!set.test(i)) {
                set[i] = true;
                e->promises[i].set_value();
            }
        }

        return res.then([e] {
            BOOST_CHECK_EQUAL(e->result.size(), e->promises.size());
            BOOST_REQUIRE(std::is_sorted(e->result.begin(), e->result.end()));
        }).finally([e] {
            return e->queue.close();
        });
    });
}

SEASTAR_TEST_CASE(test_queue_ordering_multi_ops) {
    struct env {
        env() : sem(0) {}

        utils::flush_queue<int> queue;
        std::vector<int> result;
        semaphore sem;
        size_t n = 0;
    };

    auto r = boost::irange(0, 100);

    return do_for_each(r, [](int) {
        constexpr size_t num_ops = 1000;

        auto e = make_lw_shared<env>();

        std::uniform_int_distribution<size_t> dist(0, num_ops - 1);

        for (size_t k = 0; k < num_ops*10; ++k) {
            int i = dist(e1);

            if (e->queue.has_operation(i) || (!e->queue.empty() && e->queue.highest_key() < i)) {
                e->queue.run_with_ordered_post_op(i, [e, i] {
                    return e->sem.wait().then([i] {
                        return make_ready_future<int>(i);
                    });
                }, [e](int i) {
                    e->result.emplace_back(i);
                });
                ++e->n;
            }
        }

        auto res = e->queue.wait_for_pending();

        e->sem.signal(e->n);

        return res.then([e] {
            BOOST_CHECK_EQUAL(e->result.size(), e->n);
            BOOST_REQUIRE(std::is_sorted(e->result.begin(), e->result.end()));
        }).finally([e] {
            return e->queue.close();
        });
    });
}

template<typename Func, typename Post, typename Then>
static future<> test_propagation(bool propagate, Func&& func, Post&& post, Then&& thn, bool want_except_in_run, bool want_except_in_wait) {
    auto queue = ::make_shared<utils::flush_queue<int>>(propagate);
    auto sem = ::make_shared<semaphore>();
    auto xr = ::make_shared<bool>(false);
    auto xw = ::make_shared<bool>(false);

    queue->run_with_ordered_post_op(0, [sem, func = std::forward<Func>(func)]() mutable {
        return sem->wait().then(std::forward<Func>(func));
    }, std::forward<Post>(post)).handle_exception([xr](auto p) {
        *xr = true;
    }).discard_result();

    auto f = queue->wait_for_pending(0).then(std::forward<Then>(thn)).handle_exception([xw](auto p) {
        *xw = true;
    }).discard_result();

    sem->signal();

    return f.finally([sem, queue, want_except_in_run, want_except_in_wait, xr, xw] {
        BOOST_CHECK_EQUAL(want_except_in_run, *xr);
        BOOST_CHECK_EQUAL(want_except_in_wait, *xw);
    });
}

SEASTAR_TEST_CASE(test_propagate_exception_in_op) {
    return test_propagation(true, // propagate exception to waiter
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in op
                    [] { BOOST_FAIL("should not reach (1)"); }, // should not reach post
                    [] { BOOST_FAIL("should not reach (2)"); }, // should not reach waiter "then"
                    true,
                    true
                    );
}

SEASTAR_TEST_CASE(test_propagate_exception_in_post) {
    return test_propagation(true, // propagate exception to waiter
                    [] {}, // ok func
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in post
                    [] { BOOST_FAIL("should not reach"); }, // should not reach waiter "then"
                    true,
                    true
    );
}

SEASTAR_TEST_CASE(test_no_propagate_exception_in_op) {
    return test_propagation(false, // do not propagate exception to waiter
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in op
                    [] { BOOST_FAIL("should not reach"); }, // should not reach post
                    [] {}, // should reach waiter "then"
                    true,
                    false
                    );
}

SEASTAR_TEST_CASE(test_no_propagate_exception_in_post) {
    return test_propagation(false, // do not propagate exception to waiter
                    [] {}, // ok func
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in post
                    [] {}, // should reach waiter "then"
                    true,
                    false
                    );
}
<commit_msg>flush_queue_test: Start semaphore in propagation tests not initialized<commit_after>/*
 * Copyright 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#define BOOST_TEST_DYN_LINK

#include <random>
#include <bitset>
#include <boost/test/unit_test.hpp>
#include <boost/range/irange.hpp>
#include <seastar/core/semaphore.hh>
#include <seastar/core/reactor.hh>
#include <seastar/core/thread.hh>

#include "tests/test-utils.hh"
#include "utils/flush_queue.hh"
#include "log.hh"

#include "disk-error-handler.hh"

thread_local disk_error_signal_type commit_error;
thread_local disk_error_signal_type general_disk_error;

std::random_device rd;
std::default_random_engine e1(rd());

SEASTAR_TEST_CASE(test_queue_ordering_random_ops) {
    struct env {
        env(size_t n) : promises(n) {}

        utils::flush_queue<int> queue;
        std::vector<promise<>> promises;
        std::vector<int> result;
    };

    auto r = boost::irange(0, 100);

    return do_for_each(r, [](int) {
        constexpr size_t num_ops = 1000;

        auto e = make_lw_shared<env>(num_ops);

        int i = 0;
        for (auto& p : e->promises) {
            e->queue.run_with_ordered_post_op(i, [&p, i] {
                return p.get_future().then([i] {
                    return make_ready_future<int>(i);
                });
            }, [e](int i) {
                e->result.emplace_back(i);
            });
            ++i;
        }

        auto res = e->queue.wait_for_pending();

        std::uniform_int_distribution<size_t> dist(0, num_ops - 1);
        std::bitset<num_ops> set;

        while (!set.all()) {
            size_t i = dist(e1);
            if (!set.test(i)) {
                set[i] = true;
                e->promises[i].set_value();
            }
        }

        return res.then([e] {
            BOOST_CHECK_EQUAL(e->result.size(), e->promises.size());
            BOOST_REQUIRE(std::is_sorted(e->result.begin(), e->result.end()));
        }).finally([e] {
            return e->queue.close();
        });
    });
}

SEASTAR_TEST_CASE(test_queue_ordering_multi_ops) {
    struct env {
        env() : sem(0) {}

        utils::flush_queue<int> queue;
        std::vector<int> result;
        semaphore sem;
        size_t n = 0;
    };

    auto r = boost::irange(0, 100);

    return do_for_each(r, [](int) {
        constexpr size_t num_ops = 1000;

        auto e = make_lw_shared<env>();

        std::uniform_int_distribution<size_t> dist(0, num_ops - 1);

        for (size_t k = 0; k < num_ops*10; ++k) {
            int i = dist(e1);

            if (e->queue.has_operation(i) || (!e->queue.empty() && e->queue.highest_key() < i)) {
                e->queue.run_with_ordered_post_op(i, [e, i] {
                    return e->sem.wait().then([i] {
                        return make_ready_future<int>(i);
                    });
                }, [e](int i) {
                    e->result.emplace_back(i);
                });
                ++e->n;
            }
        }

        auto res = e->queue.wait_for_pending();

        e->sem.signal(e->n);

        return res.then([e] {
            BOOST_CHECK_EQUAL(e->result.size(), e->n);
            BOOST_REQUIRE(std::is_sorted(e->result.begin(), e->result.end()));
        }).finally([e] {
            return e->queue.close();
        });
    });
}

template<typename Func, typename Post, typename Then>
static future<> test_propagation(bool propagate, Func&& func, Post&& post, Then&& thn, bool want_except_in_run, bool want_except_in_wait) {
    auto queue = ::make_shared<utils::flush_queue<int>>(propagate);
    auto sem = ::make_shared<semaphore>(0);
    auto xr = ::make_shared<bool>(false);
    auto xw = ::make_shared<bool>(false);

    queue->run_with_ordered_post_op(0, [sem, func = std::forward<Func>(func)]() mutable {
        return sem->wait().then(std::forward<Func>(func));
    }, std::forward<Post>(post)).handle_exception([xr](auto p) {
        *xr = true;
    }).discard_result();

    auto f = queue->wait_for_pending(0).then(std::forward<Then>(thn)).handle_exception([xw](auto p) {
        *xw = true;
    }).discard_result();

    sem->signal();

    return f.finally([sem, queue, want_except_in_run, want_except_in_wait, xr, xw] {
        BOOST_CHECK_EQUAL(want_except_in_run, *xr);
        BOOST_CHECK_EQUAL(want_except_in_wait, *xw);
    });
}

SEASTAR_TEST_CASE(test_propagate_exception_in_op) {
    return test_propagation(true, // propagate exception to waiter
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in op
                    [] { BOOST_FAIL("should not reach (1)"); }, // should not reach post
                    [] { BOOST_FAIL("should not reach (2)"); }, // should not reach waiter "then"
                    true,
                    true
                    );
}

SEASTAR_TEST_CASE(test_propagate_exception_in_post) {
    return test_propagation(true, // propagate exception to waiter
                    [] {}, // ok func
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in post
                    [] { BOOST_FAIL("should not reach"); }, // should not reach waiter "then"
                    true,
                    true
    );
}

SEASTAR_TEST_CASE(test_no_propagate_exception_in_op) {
    return test_propagation(false, // do not propagate exception to waiter
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in op
                    [] { BOOST_FAIL("should not reach"); }, // should not reach post
                    [] {}, // should reach waiter "then"
                    true,
                    false
                    );
}

SEASTAR_TEST_CASE(test_no_propagate_exception_in_post) {
    return test_propagation(false, // do not propagate exception to waiter
                    [] {}, // ok func
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in post
                    [] {}, // should reach waiter "then"
                    true,
                    false
                    );
}
<|endoftext|>


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

  Program:   Insight Segmentation & Registration Toolkit (ITK)
  Module:    itkPixelAccessTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2000 National Library of Medicine
All rights reserved.

See COPYRIGHT.txt for copyright details.

=========================================================================*/
#include <iostream>

#include "itkImage.h"
#include "itkScalar.h"
#include "itkVector.h"

// This routine is used to make sure that we call the "const" version
// of GetPixel() (via the operator[])
template <class T, unsigned int VImageDimension>
void TestConstPixelAccess(const itk::Image<T, VImageDimension> &in,
                          itk::Image<T, VImageDimension> &out)
{
  itk::Image<T, VImageDimension>::IndexType regionStartIndex3D = {5, 10, 15};
  itk::Image<T, VImageDimension>::IndexType regionEndIndex3D = {8, 15, 17};

  T vec;
  // Requires type T to have comma-separated-list assignment support.
  vec = 5,4,3,2,1;
  out[regionStartIndex3D] = vec;
  out[regionEndIndex3D] = in[regionStartIndex3D];
}

int main()
{
  std::cout << "Creating an image" << std::endl;
  itk::Image<itk::Vector<unsigned short, 5>, 3>::Pointer
    o3 = itk::Image<itk::Vector<unsigned short, 5>, 3>::New();

  float origin3D[3] = { 5, 2.1, 8.1};
  float spacing3D[3] = { 1.5, 2.1, 1};

  itk::Image<itk::Vector<unsigned short, 5>, 3>::SizeType imageSize3D = { 20, 40, 60 };
  itk::Image<itk::Vector<unsigned short, 5>, 3>::SizeType bufferSize3D = { 8, 20, 14 };
  itk::Image<itk::Vector<unsigned short, 5>, 3>::SizeType regionSize3D = { 4,  6,  6 };

  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType startIndex3D = {-5, 4, -1};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType bufferStartIndex3D = {2, 3, 5};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType regionStartIndex3D = {5, 10, 12};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType regionEndIndex3D = {8, 15, 17};

  itk::Image<itk::Vector<unsigned short, 5>, 3>::RegionType region;
  region.SetSize(imageSize3D);
  region.SetIndex(startIndex3D);
  o3->SetLargestPossibleRegion( region );
  region.SetSize(bufferSize3D);
  region.SetIndex(bufferStartIndex3D);
  o3->SetBufferedRegion( region );

  o3->SetOrigin(origin3D);
  o3->SetSpacing(spacing3D);

  o3->Allocate();

  std::cout << "Setting/Getting a pixel" << std::endl;
  itk::Vector<unsigned short, 5> vec;
  vec = 5,4,3,2,1;

  (*o3)[regionStartIndex3D] = vec;
  (*o3)[regionEndIndex3D] = (*o3)[regionStartIndex3D];
  TestConstPixelAccess(*o3, *o3);

  return 0;
}

<commit_msg>ERR: need extract {} for initialization.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit (ITK)
  Module:    itkPixelAccessTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2000 National Library of Medicine
All rights reserved.

See COPYRIGHT.txt for copyright details.

=========================================================================*/
#include <iostream>

#include "itkImage.h"
#include "itkScalar.h"
#include "itkVector.h"

// This routine is used to make sure that we call the "const" version
// of GetPixel() (via the operator[])
template <class T, unsigned int VImageDimension>
void TestConstPixelAccess(const itk::Image<T, VImageDimension> &in,
                          itk::Image<T, VImageDimension> &out)
{
  itk::Image<T, VImageDimension>::IndexType regionStartIndex3D = {{5, 10, 15}};
  itk::Image<T, VImageDimension>::IndexType regionEndIndex3D = {{8, 15, 17}};

  T vec;
  // Requires type T to have comma-separated-list assignment support.
  vec = 5,4,3,2,1;
  out[regionStartIndex3D] = vec;
  out[regionEndIndex3D] = in[regionStartIndex3D];
}

int main()
{
  std::cout << "Creating an image" << std::endl;
  itk::Image<itk::Vector<unsigned short, 5>, 3>::Pointer
    o3 = itk::Image<itk::Vector<unsigned short, 5>, 3>::New();

  float origin3D[3] = { 5, 2.1, 8.1};
  float spacing3D[3] = { 1.5, 2.1, 1};

  itk::Image<itk::Vector<unsigned short, 5>, 3>::SizeType imageSize3D = {{ 20, 40, 60 }};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::SizeType bufferSize3D = {{ 8, 20, 14 }};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::SizeType regionSize3D = {{ 4,  6,  6 }};

  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType startIndex3D = {{-5, 4, -1}};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType bufferStartIndex3D = {{2, 3, 5}};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType regionStartIndex3D = {{5, 10, 12}};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType regionEndIndex3D = {{8, 15, 17}};

  itk::Image<itk::Vector<unsigned short, 5>, 3>::RegionType region;
  region.SetSize(imageSize3D);
  region.SetIndex(startIndex3D);
  o3->SetLargestPossibleRegion( region );
  region.SetSize(bufferSize3D);
  region.SetIndex(bufferStartIndex3D);
  o3->SetBufferedRegion( region );

  o3->SetOrigin(origin3D);
  o3->SetSpacing(spacing3D);

  o3->Allocate();

  std::cout << "Setting/Getting a pixel" << std::endl;
  itk::Vector<unsigned short, 5> vec;
  vec = 5,4,3,2,1;

  (*o3)[regionStartIndex3D] = vec;
  (*o3)[regionEndIndex3D] = (*o3)[regionStartIndex3D];
  TestConstPixelAccess(*o3, *o3);

  return 0;
}

<|endoftext|>