Example #1
0
ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
                                           SourceLocation TemplateKWLoc,
                                           UnqualifiedId &Id,
                                           llvm::InlineAsmIdentifierInfo &Info,
                                           bool IsUnevaluatedContext) {
  Info.clear();

  if (IsUnevaluatedContext)
    PushExpressionEvaluationContext(UnevaluatedAbstract,
                                    ReuseLambdaContextDecl);

  ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
                                        /*trailing lparen*/ false,
                                        /*is & operand*/ false,
                                        /*CorrectionCandidateCallback=*/nullptr,
                                        /*IsInlineAsmIdentifier=*/ true);

  if (IsUnevaluatedContext)
    PopExpressionEvaluationContext();

  if (!Result.isUsable()) return Result;

  Result = CheckPlaceholderExpr(Result.get());
  if (!Result.isUsable()) return Result;

  QualType T = Result.get()->getType();

  // For now, reject dependent types.
  if (T->isDependentType()) {
    Diag(Id.getLocStart(), diag::err_asm_incomplete_type) << T;
    return ExprError();
  }

  // Any sort of function type is fine.
  if (T->isFunctionType()) {
    return Result;
  }

  // Otherwise, it needs to be a complete type.
  if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) {
    return ExprError();
  }

  // Compute the type size (and array length if applicable?).
  Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity();
  if (T->isArrayType()) {
    const ArrayType *ATy = Context.getAsArrayType(T);
    Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
    Info.Length = Info.Size / Info.Type;
  }

  // We can work with the expression as long as it's not an r-value.
  if (!Result.get()->isRValue())
    Info.IsVarDecl = true;

  return Result;
}
Example #2
0
ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
                                           SourceLocation TemplateKWLoc,
                                           UnqualifiedId &Id,
                                           llvm::InlineAsmIdentifierInfo &Info,
                                           bool IsUnevaluatedContext) {
  Info.clear();

  if (IsUnevaluatedContext)
    PushExpressionEvaluationContext(UnevaluatedAbstract,
                                    ReuseLambdaContextDecl);

  ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
                                        /*trailing lparen*/ false,
                                        /*is & operand*/ false,
                                        /*CorrectionCandidateCallback=*/nullptr,
                                        /*IsInlineAsmIdentifier=*/ true);

  if (IsUnevaluatedContext)
    PopExpressionEvaluationContext();

  if (!Result.isUsable()) return Result;

  Result = CheckPlaceholderExpr(Result.get());
  if (!Result.isUsable()) return Result;

  // Referring to parameters is not allowed in naked functions.
  if (CheckNakedParmReference(Result.get(), *this))
    return ExprError();

  QualType T = Result.get()->getType();

  // For now, reject dependent types.
  if (T->isDependentType()) {
    Diag(Id.getLocStart(), diag::err_asm_incomplete_type) << T;
    return ExprError();
  }

  // Any sort of function type is fine.
  if (T->isFunctionType()) {
    return Result;
  }

  // Otherwise, it needs to be a complete type.
  if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) {
    return ExprError();
  }

  fillInlineAsmTypeInfo(Context, T, Info);

  // We can work with the expression as long as it's not an r-value.
  if (!Result.get()->isRValue())
    Info.IsVarDecl = true;

  return Result;
}
Example #3
0
Type *
TypeCheck::visit(PrimaryExpression *ast)
{
	FUNCLOG;
	//Type * t;
	switch (ast->op) {
	case PRIMARY_ID: {
		ScopedId *scopedId = ast->v.id;
		if (scopedId->scope) {
			//TODO:
		}
		UnqualifiedId *unqualifiedId = scopedId->id;
		String s = unqualifiedId->toSource();
		Type *t = SymbolTable.findVar(Symbol::symbol(s));
		if (!t) {
			SEMANTIC_ERROR(SE_UNDEFINED_SYMBOL);
		}
		return t;
	}
	case PRIMARY_INT: {
		IntType *itype = new IntType(32, true);
		if (ast->v.i == 0) {
			itype->setNullable(true);
		}
		return itype;
	}
	case PRIMARY_BOOL: return new IntType(8, false);
	case PRIMARY_STR: {
		PointerType *ptrType = new PointerType();
		ptrType->reference = new IntType(8, true);
		DBG("$$ %s", ptrType->toString().c_str());
		return ptrType;
	}
	case PRIMARY_EXP:  return ast->v.exp->accept(this);
	default:
		assert(0);
		break;
	}
	return NULL;
}
Example #4
0
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
                             UnqualifiedId &ReductionId) {
    SourceLocation TemplateKWLoc;
    if (ReductionIdScopeSpec.isEmpty()) {
        auto OOK = OO_None;
        switch (P.getCurToken().getKind()) {
        case tok::plus:
            OOK = OO_Plus;
            break;
        case tok::minus:
            OOK = OO_Minus;
            break;
        case tok::star:
            OOK = OO_Star;
            break;
        case tok::amp:
            OOK = OO_Amp;
            break;
        case tok::pipe:
            OOK = OO_Pipe;
            break;
        case tok::caret:
            OOK = OO_Caret;
            break;
        case tok::ampamp:
            OOK = OO_AmpAmp;
            break;
        case tok::pipepipe:
            OOK = OO_PipePipe;
            break;
        default:
            break;
        }
        if (OOK != OO_None) {
            SourceLocation OpLoc = P.ConsumeToken();
            SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
            ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
            return false;
        }
    }
    return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
                                /*AllowDestructorName*/ false,
                                /*AllowConstructorName*/ false, ParsedType(),
                                TemplateKWLoc, ReductionId);
}
Example #5
0
/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
/// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
///
///    private-clause:
///       'private' '(' list ')'
///    firstprivate-clause:
///       'firstprivate' '(' list ')'
///    lastprivate-clause:
///       'lastprivate' '(' list ')'
///    shared-clause:
///       'shared' '(' list ')'
///    linear-clause:
///       'linear' '(' list [ ':' linear-step ] ')'
///    aligned-clause:
///       'aligned' '(' list [ ':' alignment ] ')'
///    reduction-clause:
///       'reduction' '(' reduction-identifier ':' list ')'
///    copyprivate-clause:
///       'copyprivate' '(' list ')'
///    flush-clause:
///       'flush' '(' list ')'
///
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
    SourceLocation Loc = Tok.getLocation();
    SourceLocation LOpen = ConsumeToken();
    SourceLocation ColonLoc = SourceLocation();
    // Optional scope specifier and unqualified id for reduction identifier.
    CXXScopeSpec ReductionIdScopeSpec;
    UnqualifiedId ReductionId;
    bool InvalidReductionId = false;
    // Parse '('.
    BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
    if (T.expectAndConsume(diag::err_expected_lparen_after,
                           getOpenMPClauseName(Kind)))
        return nullptr;

    // Handle reduction-identifier for reduction clause.
    if (Kind == OMPC_reduction) {
        ColonProtectionRAIIObject ColonRAII(*this);
        if (getLangOpts().CPlusPlus) {
            ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
        }
        InvalidReductionId =
            ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
        if (InvalidReductionId) {
            SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                      StopBeforeMatch);
        }
        if (Tok.is(tok::colon)) {
            ColonLoc = ConsumeToken();
        } else {
            Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
        }
    }

    SmallVector<Expr *, 5> Vars;
    bool IsComma = !InvalidReductionId;
    const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
    while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
                       Tok.isNot(tok::annot_pragma_openmp_end))) {
        ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
        // Parse variable
        ExprResult VarExpr = ParseAssignmentExpression();
        if (VarExpr.isUsable()) {
            Vars.push_back(VarExpr.get());
        } else {
            SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                      StopBeforeMatch);
        }
        // Skip ',' if any
        IsComma = Tok.is(tok::comma);
        if (IsComma)
            ConsumeToken();
        else if (Tok.isNot(tok::r_paren) &&
                 Tok.isNot(tok::annot_pragma_openmp_end) &&
                 (!MayHaveTail || Tok.isNot(tok::colon)))
            Diag(Tok, diag::err_omp_expected_punc)
                    << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
                        : getOpenMPClauseName(Kind))
                    << (Kind == OMPC_flush);
    }

    // Parse ':' linear-step (or ':' alignment).
    Expr *TailExpr = nullptr;
    const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
    if (MustHaveTail) {
        ColonLoc = Tok.getLocation();
        ConsumeToken();
        ExprResult Tail = ParseAssignmentExpression();
        if (Tail.isUsable())
            TailExpr = Tail.get();
        else
            SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                      StopBeforeMatch);
    }

    // Parse ')'.
    T.consumeClose();
    if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId)
        return nullptr;

    return Actions.ActOnOpenMPVarListClause(
               Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
               ReductionIdScopeSpec,
               ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
               : DeclarationNameInfo());
}
Example #6
0
/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
/// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
///
///    private-clause:
///       'private' '(' list ')'
///    firstprivate-clause:
///       'firstprivate' '(' list ')'
///    lastprivate-clause:
///       'lastprivate' '(' list ')'
///    shared-clause:
///       'shared' '(' list ')'
///    linear-clause:
///       'linear' '(' linear-list [ ':' linear-step ] ')'
///    aligned-clause:
///       'aligned' '(' list [ ':' alignment ] ')'
///    reduction-clause:
///       'reduction' '(' reduction-identifier ':' list ')'
///    copyprivate-clause:
///       'copyprivate' '(' list ')'
///    flush-clause:
///       'flush' '(' list ')'
///    depend-clause:
///       'depend' '(' in | out | inout : list ')'
///
/// For 'linear' clause linear-list may have the following forms:
///  list
///  modifier(list)
/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
  SourceLocation Loc = Tok.getLocation();
  SourceLocation LOpen = ConsumeToken();
  SourceLocation ColonLoc = SourceLocation();
  // Optional scope specifier and unqualified id for reduction identifier.
  CXXScopeSpec ReductionIdScopeSpec;
  UnqualifiedId ReductionId;
  bool InvalidReductionId = false;
  OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
  // OpenMP 4.1 [2.15.3.7, linear Clause]
  //  If no modifier is specified it is assumed to be val.
  OpenMPLinearClauseKind LinearModifier = OMPC_LINEAR_val;
  SourceLocation DepLinLoc;

  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind)))
    return nullptr;

  bool NeedRParenForLinear = false;
  BalancedDelimiterTracker LinearT(*this, tok::l_paren,
                                  tok::annot_pragma_openmp_end);
  // Handle reduction-identifier for reduction clause.
  if (Kind == OMPC_reduction) {
    ColonProtectionRAIIObject ColonRAII(*this);
    if (getLangOpts().CPlusPlus) {
      ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
    }
    InvalidReductionId =
        ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
    if (InvalidReductionId) {
      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    }
    if (Tok.is(tok::colon)) {
      ColonLoc = ConsumeToken();
    } else {
      Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
    }
  } else if (Kind == OMPC_depend) {
  // Handle dependency type for depend clause.
    ColonProtectionRAIIObject ColonRAII(*this);
    DepKind = static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
        Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
    DepLinLoc = Tok.getLocation();

    if (DepKind == OMPC_DEPEND_unknown) {
      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    } else {
      ConsumeToken();
    }
    if (Tok.is(tok::colon)) {
      ColonLoc = ConsumeToken();
    } else {
      Diag(Tok, diag::warn_pragma_expected_colon) << "dependency type";
    }
  } else if (Kind == OMPC_linear) {
    // Try to parse modifier if any.
    if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
      LinearModifier = static_cast<OpenMPLinearClauseKind>(
          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
      DepLinLoc = ConsumeToken();
      LinearT.consumeOpen();
      NeedRParenForLinear = true;
    }
  }

  SmallVector<Expr *, 5> Vars;
  bool IsComma = ((Kind != OMPC_reduction) && (Kind != OMPC_depend)) ||
                 ((Kind == OMPC_reduction) && !InvalidReductionId) ||
                 ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown);
  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
                     Tok.isNot(tok::annot_pragma_openmp_end))) {
    ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
    // Parse variable
    ExprResult VarExpr =
        Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
    if (VarExpr.isUsable()) {
      Vars.push_back(VarExpr.get());
    } else {
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    }
    // Skip ',' if any
    IsComma = Tok.is(tok::comma);
    if (IsComma)
      ConsumeToken();
    else if (Tok.isNot(tok::r_paren) &&
             Tok.isNot(tok::annot_pragma_openmp_end) &&
             (!MayHaveTail || Tok.isNot(tok::colon)))
      Diag(Tok, diag::err_omp_expected_punc)
          << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
                                   : getOpenMPClauseName(Kind))
          << (Kind == OMPC_flush);
  }

  // Parse ')' for linear clause with modifier.
  if (NeedRParenForLinear)
    LinearT.consumeClose();

  // Parse ':' linear-step (or ':' alignment).
  Expr *TailExpr = nullptr;
  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
  if (MustHaveTail) {
    ColonLoc = Tok.getLocation();
    ConsumeToken();
    ExprResult Tail =
        Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
    if (Tail.isUsable())
      TailExpr = Tail.get();
    else
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
  }

  // Parse ')'.
  T.consumeClose();
  if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) ||
      (Kind != OMPC_depend && Vars.empty()) || (MustHaveTail && !TailExpr) ||
      InvalidReductionId)
    return nullptr;

  return Actions.ActOnOpenMPVarListClause(
      Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
      ReductionIdScopeSpec,
      ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
                            : DeclarationNameInfo(),
      DepKind, LinearModifier, DepLinLoc);
}
Example #7
0
/// \brief Parse a C++ template template argument.
ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
  if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) &&
      !Tok.is(tok::annot_cxxscope))
    return ParsedTemplateArgument();

  // C++0x [temp.arg.template]p1:
  //   A template-argument for a template template-parameter shall be the name
  //   of a class template or a template alias, expressed as id-expression.
  //   
  // We parse an id-expression that refers to a class template or template
  // alias. The grammar we parse is:
  //
  //   nested-name-specifier[opt] template[opt] identifier ...[opt]
  //
  // followed by a token that terminates a template argument, such as ',', 
  // '>', or (in some cases) '>>'.
  CXXScopeSpec SS; // nested-name-specifier, if present
  ParseOptionalCXXScopeSpecifier(SS, ParsedType(),
                                 /*EnteringContext=*/false);
  
  ParsedTemplateArgument Result;
  SourceLocation EllipsisLoc;
  if (SS.isSet() && Tok.is(tok::kw_template)) {
    // Parse the optional 'template' keyword following the 
    // nested-name-specifier.
    SourceLocation TemplateLoc = ConsumeToken();
    
    if (Tok.is(tok::identifier)) {
      // We appear to have a dependent template name.
      UnqualifiedId Name;
      Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
      ConsumeToken(); // the identifier
      
      // Parse the ellipsis.
      if (Tok.is(tok::ellipsis))
        EllipsisLoc = ConsumeToken();
      
      // If the next token signals the end of a template argument,
      // then we have a dependent template name that could be a template
      // template argument.
      TemplateTy Template;
      if (isEndOfTemplateArgument(Tok) &&
          Actions.ActOnDependentTemplateName(getCurScope(), TemplateLoc,
                                             SS, Name, 
                                             /*ObjectType=*/ ParsedType(),
                                             /*EnteringContext=*/false,
                                             Template))
        Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);
    }
  } else if (Tok.is(tok::identifier)) {
    // We may have a (non-dependent) template name.
    TemplateTy Template;
    UnqualifiedId Name;
    Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
    ConsumeToken(); // the identifier
    
    // Parse the ellipsis.
    if (Tok.is(tok::ellipsis))
      EllipsisLoc = ConsumeToken();

    if (isEndOfTemplateArgument(Tok)) {
      bool MemberOfUnknownSpecialization;
      TemplateNameKind TNK = Actions.isTemplateName(getCurScope(), SS,
                                               /*hasTemplateKeyword=*/false,
                                                    Name,
                                               /*ObjectType=*/ ParsedType(), 
                                                    /*EnteringContext=*/false, 
                                                    Template,
                                                MemberOfUnknownSpecialization);
      if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
        // We have an id-expression that refers to a class template or
        // (C++0x) template alias. 
        Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);
      }
    }
  }
  
  // If this is a pack expansion, build it as such.
  if (EllipsisLoc.isValid() && !Result.isInvalid())
    Result = Actions.ActOnPackExpansion(Result, EllipsisLoc);
  
  return Result;
}
Example #8
0
/// \brief Replace the tokens that form a simple-template-id with an
/// annotation token containing the complete template-id.
///
/// The first token in the stream must be the name of a template that
/// is followed by a '<'. This routine will parse the complete
/// simple-template-id and replace the tokens with a single annotation
/// token with one of two different kinds: if the template-id names a
/// type (and \p AllowTypeAnnotation is true), the annotation token is
/// a type annotation that includes the optional nested-name-specifier
/// (\p SS). Otherwise, the annotation token is a template-id
/// annotation that does not include the optional
/// nested-name-specifier.
///
/// \param Template  the declaration of the template named by the first
/// token (an identifier), as returned from \c Action::isTemplateName().
///
/// \param TemplateNameKind the kind of template that \p Template
/// refers to, as returned from \c Action::isTemplateName().
///
/// \param SS if non-NULL, the nested-name-specifier that precedes
/// this template name.
///
/// \param TemplateKWLoc if valid, specifies that this template-id
/// annotation was preceded by the 'template' keyword and gives the
/// location of that keyword. If invalid (the default), then this
/// template-id was not preceded by a 'template' keyword.
///
/// \param AllowTypeAnnotation if true (the default), then a
/// simple-template-id that refers to a class template, template
/// template parameter, or other template that produces a type will be
/// replaced with a type annotation token. Otherwise, the
/// simple-template-id is always replaced with a template-id
/// annotation token.
///
/// If an unrecoverable parse error occurs and no annotation token can be
/// formed, this function returns true.
///
bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
                                     CXXScopeSpec &SS,
                                     UnqualifiedId &TemplateName,
                                     SourceLocation TemplateKWLoc,
                                     bool AllowTypeAnnotation) {
  assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
  assert(Template && Tok.is(tok::less) &&
         "Parser isn't at the beginning of a template-id");

  // Consume the template-name.
  SourceLocation TemplateNameLoc = TemplateName.getSourceRange().getBegin();

  // Parse the enclosed template argument list.
  SourceLocation LAngleLoc, RAngleLoc;
  TemplateArgList TemplateArgs;
  bool Invalid = ParseTemplateIdAfterTemplateName(Template, 
                                                  TemplateNameLoc,
                                                  SS, false, LAngleLoc,
                                                  TemplateArgs,
                                                  RAngleLoc);

  if (Invalid) {
    // If we failed to parse the template ID but skipped ahead to a >, we're not
    // going to be able to form a token annotation.  Eat the '>' if present.
    if (Tok.is(tok::greater))
      ConsumeToken();
    return true;
  }

  ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
                                     TemplateArgs.size());

  // Build the annotation token.
  if (TNK == TNK_Type_template && AllowTypeAnnotation) {
    TypeResult Type
      = Actions.ActOnTemplateIdType(SS, 
                                    Template, TemplateNameLoc,
                                    LAngleLoc, TemplateArgsPtr,
                                    RAngleLoc);
    if (Type.isInvalid()) {
      // If we failed to parse the template ID but skipped ahead to a >, we're not
      // going to be able to form a token annotation.  Eat the '>' if present.
      if (Tok.is(tok::greater))
        ConsumeToken();
      return true;
    }

    Tok.setKind(tok::annot_typename);
    setTypeAnnotation(Tok, Type.get());
    if (SS.isNotEmpty())
      Tok.setLocation(SS.getBeginLoc());
    else if (TemplateKWLoc.isValid())
      Tok.setLocation(TemplateKWLoc);
    else
      Tok.setLocation(TemplateNameLoc);
  } else {
    // Build a template-id annotation token that can be processed
    // later.
    Tok.setKind(tok::annot_template_id);
    TemplateIdAnnotation *TemplateId
      = TemplateIdAnnotation::Allocate(TemplateArgs.size());
    TemplateId->TemplateNameLoc = TemplateNameLoc;
    if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) {
      TemplateId->Name = TemplateName.Identifier;
      TemplateId->Operator = OO_None;
    } else {
      TemplateId->Name = 0;
      TemplateId->Operator = TemplateName.OperatorFunctionId.Operator;
    }
    TemplateId->SS = SS;
    TemplateId->Template = Template;
    TemplateId->Kind = TNK;
    TemplateId->LAngleLoc = LAngleLoc;
    TemplateId->RAngleLoc = RAngleLoc;
    ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
    for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
      Args[Arg] = ParsedTemplateArgument(TemplateArgs[Arg]);
    Tok.setAnnotationValue(TemplateId);
    if (TemplateKWLoc.isValid())
      Tok.setLocation(TemplateKWLoc);
    else
      Tok.setLocation(TemplateNameLoc);

    TemplateArgsPtr.release();
  }

  // Common fields for the annotation token
  Tok.setAnnotationEndLoc(RAngleLoc);

  // In case the tokens were cached, have Preprocessor replace them with the
  // annotation token.
  PP.AnnotateCachedTokens(Tok);
  return false;
}
StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
                                SourceLocation LBraceLoc,
                                ArrayRef<Token> AsmToks,
                                SourceLocation EndLoc) {
  SmallVector<StringRef,4> Clobbers;
  std::set<std::string> ClobberRegs;
  SmallVector<IdentifierInfo*, 4> Inputs;
  SmallVector<IdentifierInfo*, 4> Outputs;
  SmallVector<Expr*, 4> InputExprs;
  SmallVector<Expr*, 4> OutputExprs;

  // Empty asm statements don't need to instantiate the AsmParser, etc.
  if (AsmToks.empty()) {
    StringRef AsmString;
    DEF_SIMPLE_MSASM;
    return Owned(NS);
  }

  std::vector<std::string> AsmStrings;
  std::vector<std::pair<unsigned,unsigned> > AsmTokRanges;
  std::string AsmString = buildMSAsmString(*this, AsmToks, AsmStrings,
                                           AsmTokRanges);

  std::vector<std::vector<StringRef> > Pieces(AsmStrings.size());
  buildMSAsmPieces(AsmStrings, Pieces);

  bool IsSimple = isSimpleMSAsm(Pieces, Context.getTargetInfo());

  // AsmParser doesn't fully support these asm statements.
  if (bailOnMSAsm(Pieces)) { DEF_SIMPLE_MSASM; return Owned(NS); }

  // Initialize targets and assembly printers/parsers.
  llvm::InitializeAllTargetInfos();
  llvm::InitializeAllTargetMCs();
  llvm::InitializeAllAsmParsers();

  // Get the target specific parser.
  std::string Error;
  const std::string &TT = Context.getTargetInfo().getTriple().getTriple();
  const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error));

  OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT));
  OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
  OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
  OwningPtr<llvm::MCSubtargetInfo>
    STI(TheTarget->createMCSubtargetInfo(TT, "", ""));

  for (unsigned StrIdx = 0, e = AsmStrings.size(); StrIdx != e; ++StrIdx) {
    llvm::SourceMgr SrcMgr;
    llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr);
    llvm::MemoryBuffer *Buffer =
      llvm::MemoryBuffer::getMemBuffer(AsmStrings[StrIdx], "<inline asm>");

    // Tell SrcMgr about this buffer, which is what the parser will pick up.
    SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());

    OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
    OwningPtr<llvm::MCAsmParser>
      Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
    OwningPtr<llvm::MCTargetAsmParser>
      TargetParser(TheTarget->createMCAsmParser(*STI, *Parser));
    // Change to the Intel dialect.
    Parser->setAssemblerDialect(1);
    Parser->setTargetParser(*TargetParser.get());

    // Prime the lexer.
    Parser->Lex();

    // Parse the opcode.
    StringRef IDVal;
    Parser->ParseIdentifier(IDVal);

    // Canonicalize the opcode to lower case.
    SmallString<128> Opcode;
    for (unsigned j = 0, e = IDVal.size(); j != e; ++j)
      Opcode.push_back(tolower(IDVal[j]));

    // Parse the operands.
    llvm::SMLoc IDLoc;
    SmallVector<llvm::MCParsedAsmOperand*, 8> Operands;
    bool HadError = TargetParser->ParseInstruction(Opcode.str(), IDLoc,
                                                   Operands);
    // If we had an error parsing the operands, fail gracefully.
    if (HadError) { DEF_SIMPLE_MSASM; return Owned(NS); }

    // Match the MCInstr.
    unsigned ErrorInfo;
    SmallVector<llvm::MCInst, 2> Instrs;
    HadError = TargetParser->MatchInstruction(IDLoc, Operands, Instrs,
                                              ErrorInfo,
                                              /*matchingInlineAsm*/ true);
    // If we had an error parsing the operands, fail gracefully.
    if (HadError) { DEF_SIMPLE_MSASM; return Owned(NS); }

    // Get the instruction descriptor.
    llvm::MCInst Inst = Instrs[0];
    const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
    const llvm::MCInstrDesc &Desc = MII->get(Inst.getOpcode());
    llvm::MCInstPrinter *IP =
      TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI);

    // Build the list of clobbers, outputs and inputs.
    unsigned NumDefs = Desc.getNumDefs();
    for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) {
      const llvm::MCOperand &Op = Inst.getOperand(i);

      // Immediate.
      if (Op.isImm() || Op.isFPImm())
        continue;

      bool isDef = NumDefs && (i < NumDefs);

      // Register/Clobber.
      if (Op.isReg() && isDef) {
        std::string Reg;
        llvm::raw_string_ostream OS(Reg);
        IP->printRegName(OS, Op.getReg());

        StringRef Clobber(OS.str());
        if (!Context.getTargetInfo().isValidClobber(Clobber))
          return StmtError(Diag(AsmLoc, diag::err_asm_unknown_register_name) <<
                           Clobber);
        ClobberRegs.insert(Reg);
        continue;
      }
      // Expr/Input or Output.
      if (Op.isExpr()) {
        const llvm::MCExpr *Expr = Op.getExpr();
        const llvm::MCSymbolRefExpr *SymRef;
        if ((SymRef = dyn_cast<llvm::MCSymbolRefExpr>(Expr))) {
          StringRef Name = SymRef->getSymbol().getName();
          IdentifierInfo *II = getIdentifierInfo(Name, AsmToks,
                                                 AsmTokRanges[StrIdx].first,
                                                 AsmTokRanges[StrIdx].second);
          if (II) {
            CXXScopeSpec SS;
            UnqualifiedId Id;
            SourceLocation Loc;
            Id.setIdentifier(II, AsmLoc);
            ExprResult Result = ActOnIdExpression(getCurScope(), SS, Loc, Id,
                                                  false, false);
            if (!Result.isInvalid()) {
              if (isDef) {
                Outputs.push_back(II);
                OutputExprs.push_back(Result.take());
              } else {
                Inputs.push_back(II);
                InputExprs.push_back(Result.take());
              }
            }
          }
        }
      }
    }
  }
  for (std::set<std::string>::iterator I = ClobberRegs.begin(),
         E = ClobberRegs.end(); I != E; ++I)
    Clobbers.push_back(*I);

  MSAsmStmt *NS =
    new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
                            /*IsVolatile*/ true, AsmToks, Inputs, Outputs,
                            InputExprs, OutputExprs, AsmString, Clobbers,
                            EndLoc);
  return Owned(NS);
}