Beispiel #1
0
Parser::StmtResult Parser::ParseAssignStmt() {
  SourceLocation Loc = ConsumeToken();

  auto Value = ParseStatementLabelReference(false);
  if(Value.isInvalid()) {
    Diag.Report(getExpectedLoc(), diag::err_expected_stmt_label_after)
        << "ASSIGN";
    return StmtError();
  }
  ConsumeToken();
  if(!ExpectAndConsumeFixedFormAmbiguous(tok::kw_TO, diag::err_expected_kw, "to"))
    return StmtError();

  auto IDInfo = Tok.getIdentifierInfo();
  auto IDRange = getTokenRange();
  auto IDLoc = Tok.getLocation();
  if(!ExpectAndConsume(tok::identifier))
    return StmtError();
  auto VD = Actions.ExpectVarRefOrDeclImplicitVar(IDLoc, IDInfo);
  if(!VD)
    return StmtError();
  auto Var = VarExpr::Create(Context, IDRange, VD);

  return Actions.ActOnAssignStmt(Context, Loc, Value, Var, StmtLabel);
}
Decl *Sema::ActOnIntrinsicEntityDecl(ASTContext &C, QualType T,
                                     SourceLocation IDLoc, const IdentifierInfo *IDInfo) {
  auto FuncResult = IntrinsicFunctionMapping.Resolve(IDInfo);
  if(FuncResult.IsInvalid) {
    Diags.Report(IDLoc, diag::err_intrinsic_invalid_func)
      << IDInfo << getTokenRange(IDLoc);
    return nullptr;
  }

  QualType Type = T.isNull()? C.RealTy : T;
  if (auto Prev = LookupIdentifier(IDInfo)) {
    auto Quals = getDeclQualifiers(Prev);
    if(Quals.hasAttributeSpec(Qualifiers::AS_intrinsic)) {
      Diags.Report(IDLoc, diag::err_duplicate_attr_spec)
        << DeclSpec::getSpecifierName(Qualifiers::AS_intrinsic);
      return Prev;
    }

    auto VD = dyn_cast<VarDecl>(Prev);
    if(VD && VD->isUnusedSymbol()) {
      Type = VD->getType();
      CurContext->removeDecl(VD);
    } else {
      DiagnoseRedefinition(IDLoc, IDInfo, Prev);
      return nullptr;
    }
  }

  auto Decl = IntrinsicFunctionDecl::Create(C, CurContext, IDLoc, IDInfo,
                                            Type, FuncResult.Function);
  CurContext->addDecl(Decl);
  return Decl;
}
void Sema::ActOnENDTYPE(ASTContext &C, SourceLocation Loc,
                        SourceLocation IDLoc, const IdentifierInfo* IDInfo) {
  auto Record = dyn_cast<RecordDecl>(CurContext);
  if(IDInfo && IDInfo != Record->getIdentifier()) {
    Diags.Report(IDLoc, diag::err_expected_type_name)
      << Record->getIdentifier() << /*Kind=*/ 0
      << getTokenRange(IDLoc);
  }
}
Beispiel #4
0
Parser::StmtResult Parser::ParseDoStmt() {
  auto Loc = ConsumeToken();
  auto CurStmtLoc = LocFirstStmtToken;

  ExprResult TerminalStmt;
  VarExpr *DoVar = nullptr;
  ExprResult E1, E2, E3;
  auto EqLoc = Loc;

  if(IsPresent(tok::int_literal_constant)) {
    TerminalStmt = ParseStatementLabelReference();
    if(TerminalStmt.isInvalid()) return StmtError();
  }
  bool isDo = ConsumeIfPresent(tok::comma);
  if(isDo && IsPresent(tok::kw_WHILE))
    return ParseDoWhileStmt(isDo);

  // the do var
  auto IDInfo = Tok.getIdentifierInfo();
  auto IDRange = getTokenRange();
  auto IDLoc = Tok.getLocation();
  if(!ExpectAndConsume(tok::identifier))
    goto error;

  EqLoc = getMaxLocationOfCurrentToken();
  if(Features.FixedForm && !isDo && IsPresent(tok::l_paren))
    return ReparseAmbiguousAssignmentStatement();
  if(!ExpectAndConsume(tok::equal))
    goto error;
  E1 = ParseExpectedFollowupExpression("=");
  if(E1.isInvalid()) goto error;
  if(Features.FixedForm && !isDo && Tok.isAtStartOfStatement())
    return ReparseAmbiguousAssignmentStatement(CurStmtLoc);
  if(!ExpectAndConsume(tok::comma)) goto error;
  E2 = ParseExpectedFollowupExpression(",");
  if(E2.isInvalid()) goto error;
  if(ConsumeIfPresent(tok::comma)) {
    E3 = ParseExpectedFollowupExpression(",");
    if(E3.isInvalid()) goto error;
  }

  if(auto VD = Actions.ExpectVarRefOrDeclImplicitVar(IDLoc, IDInfo))
    DoVar = VarExpr::Create(Context, IDRange, VD);
  return Actions.ActOnDoStmt(Context, Loc, EqLoc, TerminalStmt,
                             DoVar, E1, E2, E3, StmtConstructName, StmtLabel);
error:
  if(IDInfo) {
    if(auto VD = Actions.ExpectVarRefOrDeclImplicitVar(IDLoc, IDInfo))
      DoVar = VarExpr::Create(Context, IDRange, VD);
  }
  SkipUntilNextStatement();
  return Actions.ActOnDoStmt(Context, Loc, EqLoc, TerminalStmt,
                             DoVar, E1, E2, E3, StmtConstructName, StmtLabel);
}
Beispiel #5
0
ExprResult Parser::ParseRecursiveCallExpression(SourceRange IDRange) {
  auto Func = Actions.CurrentContextAsFunction();
  auto IDLoc = IDRange.Start;
  if(Func->isSubroutine()) {
    Diag.Report(IDLoc, diag::err_invalid_subroutine_use)
     << Func->getIdentifier() << getTokenRange(IDLoc);
    return ExprError();
  }
  if(!Actions.CheckRecursiveFunction(IDLoc))
    return ExprError();

  if(!IsPresent(tok::l_paren))
    return FunctionRefExpr::Create(Context, IDRange, Func);
  return ParseCallExpression(IDLoc, Func);
}
bool Sema::CheckEquivalenceObject(SourceLocation Loc, Expr *E, VarDecl *& Object) {
  if(auto Var = dyn_cast<VarExpr>(E)) {
    auto VD = Var->getVarDecl();
    if(VD->isArgument() || VD->isParameter()) {
      Diags.Report(Loc, diag::err_spec_requires_local_var)
        << E->getSourceRange();
      Diags.Report(VD->getLocation(), diag::note_previous_definition_kind)
          << VD->getIdentifier() << (VD->isArgument()? 0 : 1)
          << getTokenRange(VD->getLocation());
      return true;
    }
    if(VD->isUnusedSymbol())
      const_cast<VarDecl*>(VD)->MarkUsedAsVariable(E->getLocation());
    Object = const_cast<VarDecl*>(VD);
  }  else {
    Diags.Report(Loc, diag::err_spec_requires_var_or_arr_el)
      << E->getSourceRange();
    return true;
  }
  return false;
}
Beispiel #7
0
/// ParseNameOrCall - Parse a name or a call expression
ExprResult Parser::ParseNameOrCall() {
  auto IDInfo = Tok.getIdentifierInfo();
  assert(IDInfo && "Token isn't an identifier");
  auto IDRange = getTokenRange();
  auto IDLoc = ConsumeToken();

  if(DontResolveIdentifiers)
    return UnresolvedIdentifierExpr::Create(Context,
                                            IDRange, IDInfo);

  // [R504]:
  //   object-name :=
  //       name
  auto Declaration = Actions.ResolveIdentifier(IDInfo);
  if(!Declaration) {
    if(IsPresent(tok::l_paren))
      Declaration = Actions.ActOnImplicitFunctionDecl(Context, IDLoc, IDInfo);
    else
      Declaration = Actions.ActOnImplicitEntityDecl(Context, IDLoc, IDInfo);
    if(!Declaration)
      return ExprError();
  } else {
    // INTEGER f
    // X = f(10) <-- implicit function declaration.
    if(IsPresent(tok::l_paren))
      Declaration = Actions.ActOnPossibleImplicitFunctionDecl(Context, IDLoc, IDInfo, Declaration);
  }

  if(VarDecl *VD = dyn_cast<VarDecl>(Declaration)) {
    // FIXME: function returing array
    if(IsPresent(tok::l_paren) &&
       VD->isFunctionResult() && isa<FunctionDecl>(Actions.CurContext)) {
      // FIXME: accessing function results from inner recursive functions
      return ParseRecursiveCallExpression(IDRange);
    }
    // the VarDecl is obtained from a NamedDecl which does not have a type
    // apply implicit typing rules in case VD does not have a type
    // FIXME: there should be a way to avoid re-applying the implicit rules
    // by returning a VarDecl instead of a NamedDecl when looking up a name in
    // the scope
    if (VD->getType().isNull()) Actions.ApplyImplicitRulesToArgument(VD,IDRange);
    return VarExpr::Create(Context, IDRange, VD);
  }
  else if(IntrinsicFunctionDecl *IFunc = dyn_cast<IntrinsicFunctionDecl>(Declaration)) {
    SmallVector<Expr*, 8> Arguments;
    SourceLocation RParenLoc = Tok.getLocation();
    auto Result = ParseFunctionCallArgumentList(Arguments, RParenLoc);
    if(Result.isInvalid())
      return ExprError();
    return Actions.ActOnIntrinsicFunctionCallExpr(Context, IDLoc, IFunc, Arguments);
  } else if(FunctionDecl *Func = dyn_cast<FunctionDecl>(Declaration)) {
    // FIXME: allow subroutines, but errors in sema
    if(!IsPresent(tok::l_paren))
      return FunctionRefExpr::Create(Context, IDRange, Func);
    if(!Func->isSubroutine()) {
      return ParseCallExpression(IDLoc, Func);
    }
  } else if(isa<SelfDecl>(Declaration) && isa<FunctionDecl>(Actions.CurContext))
    return ParseRecursiveCallExpression(IDRange);
  else if(auto Record = dyn_cast<RecordDecl>(Declaration))
    return ParseTypeConstructor(IDLoc, Record);
  Diag.Report(IDLoc, diag::err_expected_var);
  return ExprError();
}
Beispiel #8
0
// ParsePrimaryExpr - Parse a primary expression.
//
//   [R701]:
//     primary :=
//         constant
//      or designator
//      or array-constructor
//      or structure-constructor
//      or function-reference
//      or type-param-inquiry
//      or type-param-name
//      or ( expr )
Parser::ExprResult Parser::ParsePrimaryExpr(bool IsLvalue) {
  ExprResult E;
  SourceLocation Loc = Tok.getLocation();

  // FIXME: Add rest of the primary expressions.
  switch (Tok.getKind()) {
  default:
    if (isTokenIdentifier())
      goto possible_keyword_as_ident;
    Diag.Report(getExpectedLoc(), diag::err_expected_expression);
    return ExprError();
  case tok::error:
    Lex();
    return ExprError();
  case tok::l_paren: {
    ConsumeParen();

    E = ParseExpression();
    // complex constant.
    if(ConsumeIfPresent(tok::comma)) {
      if(E.isInvalid()) return E;
      auto ImPart = ParseExpectedFollowupExpression(",");
      if(ImPart.isInvalid()) return ImPart;
      E = Actions.ActOnComplexConstantExpr(Context, Loc,
                                           getMaxLocationOfCurrentToken(),
                                           E, ImPart);
    }

    ExpectAndConsume(tok::r_paren, 0, "", tok::r_paren);
    break;
  }
  case tok::l_parenslash : {
    return ParseArrayConstructor();
    break;
  }
  case tok::logical_literal_constant: {
    std::string NumStr;
    CleanLiteral(Tok, NumStr);

    StringRef Data(NumStr);
    std::pair<StringRef, StringRef> StrPair = Data.split('_');
    E = LogicalConstantExpr::Create(Context, getTokenRange(),
                                    StrPair.first, Context.LogicalTy);
    SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second);
    ConsumeToken();
    break;
  }
  case tok::binary_boz_constant:
  case tok::octal_boz_constant:
  case tok::hex_boz_constant: {
    std::string NumStr;
    CleanLiteral(Tok, NumStr);

    StringRef Data(NumStr);
    std::pair<StringRef, StringRef> StrPair = Data.split('_');
    E = BOZConstantExpr::Create(Context, Loc,
                                getMaxLocationOfCurrentToken(),
                                StrPair.first);
    SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second);
    ConsumeToken();
    break;
  }
  case tok::char_literal_constant: {
    std::string NumStr;
    CleanLiteral(Tok, NumStr);
    E = CharacterConstantExpr::Create(Context, getTokenRange(),
                                      StringRef(NumStr), Context.CharacterTy);
    ConsumeToken();
    // Possible substring
    if(IsPresent(tok::l_paren))
      return ParseSubstring(E);
    break;
  }
  case tok::int_literal_constant: {
    std::string NumStr;
    CleanLiteral(Tok, NumStr);

    StringRef Data(NumStr);
    std::pair<StringRef, StringRef> StrPair = Data.split('_');
    E = IntegerConstantExpr::Create(Context, getTokenRange(),
                                    StrPair.first);
    SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second);

    Lex();
    break;
  }
  case tok::real_literal_constant: {
    std::string NumStr;
    CleanLiteral(Tok, NumStr);

    StringRef Data(NumStr);
    std::pair<StringRef, StringRef> StrPair = Data.split('_');
    E = RealConstantExpr::Create(Context, getTokenRange(),
                                 NumStr, Context.RealTy);
    SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second);
    ConsumeToken();
    break;
  }
  case tok::double_precision_literal_constant: {
    std::string NumStr;
    CleanLiteral(Tok, NumStr);
    // Replace the d/D exponent into e exponent
    for(size_t I = 0, Len = NumStr.length(); I < Len; ++I) {
      if(NumStr[I] == 'd' || NumStr[I] == 'D') {
        NumStr[I] = 'e';
        break;
      } else if(NumStr[I] == '_') break;
    }

    StringRef Data(NumStr);
    std::pair<StringRef, StringRef> StrPair = Data.split('_');
    E = RealConstantExpr::Create(Context, getTokenRange(),
                                 NumStr, Context.DoublePrecisionTy);
    SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second);
    ConsumeToken();
    break;
  }
  case tok::identifier:
    possible_keyword_as_ident:
    E = Parser::ParseDesignator(IsLvalue);
    if (E.isInvalid()) return E;
    break;
  case tok::minus:
    Lex();
    E = Parser::ParsePrimaryExpr();
    if (E.isInvalid()) return E;
    E = Actions.ActOnUnaryExpr(Context, Loc, UnaryExpr::Minus, E);
    break;
  case tok::plus:
    Lex();
    E = Parser::ParsePrimaryExpr();
    if (E.isInvalid()) return E;
    E = Actions.ActOnUnaryExpr(Context, Loc, UnaryExpr::Plus, E);
    break;
  }

  return E;
}
void OMPPragmaHandler::HandlePragma(Preprocessor &PP,
                                    PragmaIntroducerKind Introducer,
                                    SourceRange IntroducerRange,
                                    Token &FirstTok) {


  Diags.Report(IntroducerRange.getBegin(), DiagFoundPragmaStmt);
                                    
  // TODO: Clean this up because I'm too lazy to now
  PragmaDirective * DirectivePointer = new PragmaDirective;
  PragmaDirective &Directive = *DirectivePointer;
    
  // First lex the pragma statement extracting the variable names

  SourceLocation Loc = IntroducerRange.getBegin();
  Token Tok = FirstTok;
  StringRef ident = getIdentifier(Tok);
  
  if (ident != "omp") {
    LexUntil(PP, Tok, clang::tok::eod);
    return;
  }
    
  PP.Lex(Tok);
  ident = getIdentifier(Tok);
  
  bool isParallel = false;
  bool isThreadPrivate = false;

  if (ident == "parallel") {

    PragmaConstruct C;
    C.Type = ParallelConstruct;
    C.Range = getTokenRange(Tok, PP);
    Directive.insertConstruct(C);
    isParallel = true;

  } else if (ident == "sections"
             || ident == "section"
             || ident == "task"
             || ident == "taskyield"
             || ident == "taskwait"
             || ident == "atomic"
             || ident == "ordered") {

    Diags.Report(Tok.getLocation(), DiagUnsupportedConstruct);

    LexUntil(PP, Tok, clang::tok::eod);
    return;

  } else if (ident == "for") {

    PragmaConstruct C;
    C.Type = ForConstruct;
    C.Range = getTokenRange(Tok, PP);
    Directive.insertConstruct(C);

  } else if (ident == "threadprivate") {
  
    isThreadPrivate = true;

    PragmaConstruct C;
    C.Type = ThreadprivateConstruct;
    C.Range = getTokenRange(Tok, PP);
    Directive.insertConstruct(C);
  
  } else if (ident == "single") {

    PragmaConstruct C;
    C.Type = SingleConstruct;
    C.Range = getTokenRange(Tok, PP);
    Directive.insertConstruct(C);

  } else if (ident == "master") {

    PragmaConstruct C;
    C.Type = MasterConstruct;
    C.Range = getTokenRange(Tok, PP);
    Directive.insertConstruct(C);

  } else if (ident == "critical"
             || ident == "flush") {

    // Ignored Directive
    // (Critical, Flush)
    LexUntil(PP, Tok, clang::tok::eod);
    return;
  
  } else if (ident == "barrier") {

    PragmaConstruct C;
    C.Type = BarrierConstruct;
    C.Range = getTokenRange(Tok, PP);
    Directive.insertConstruct(C);

  } else {
    
    Diags.Report(Tok.getLocation(), DiagUnknownDirective);
    return;
    
  }
  
  if (!isThreadPrivate) {
    PP.Lex(Tok);
  }

  if (isParallel) {

    ident = getIdentifier(Tok);
    
    if (ident == "sections") {

      Diags.Report(Tok.getLocation(), DiagUnsupportedConstruct);

      LexUntil(PP, Tok, clang::tok::eod);
      return;

    } else if (ident == "for") {

      PragmaConstruct C;
      C.Type = ForConstruct;
      C.Range = getTokenRange(Tok, PP);
      Directive.insertConstruct(C);
    
      PP.Lex(Tok);
      
    } else {

      // Just a standard "#pragma omp parallel" clause
      if (Tok.isNot(clang::tok::eod)
             && PragmaDirective::getClauseType(ident)
                == UnknownClause) {
       
        Diags.Report(Tok.getLocation(), DiagUnknownClause);
        return;
                
      }

    }
  
  }
  
  // If we've made it this far then we either have:
  // "#pragma omp parallel",
  // "#pragma omp parallel for",
  // "#pragma omp for",
  // "#pragma omp threadprivate
  
  // Need to read in the options, if they exists
  // Don't really care about them unless there exists a private(...) list
  // In which case, get the variables inside that list
  // But we read them all in anyway.

  // There's also threadprivate, which won't have any clauses, but will have
  // a list of private variables just after the threadprivate directive
  // Treating threadprivate as a clause and directive at the same time.
  
  while(Tok.isNot(clang::tok::eod)) {
  
    PragmaClause C;

    ident = getIdentifier(Tok);
    C.Type = PragmaDirective::getClauseType(ident);

    if (C.Type == UnknownClause) {
     
      Diags.Report(Tok.getLocation(), DiagUnknownClause);
      return;
              
    }

    SourceLocation clauseStart = Tok.getLocation();
    SourceLocation clauseEnd = PP.getLocForEndOfToken(clauseStart);

    PP.Lex(Tok);
      
    if (Tok.is(clang::tok::l_paren)) {

      if (!handleList(Tok, PP, C)) {
  
        Diags.Report(clauseStart, DiagMalformedStatement);

        LexUntil(PP, Tok, clang::tok::eod);
        return;
      }
      
      clauseEnd = PP.getLocForEndOfToken(Tok.getLocation());

      // Eat the clang::tok::r_paren
      PP.Lex(Tok);

    }
    
    C.Range = SourceRange(clauseStart, clauseEnd);
    
    Directive.insertClause(C);

  }
  
  SourceLocation EndLoc = PP.getLocForEndOfToken(Tok.getLocation());

  Directive.setRange(SourceRange(Loc, EndLoc));

  Directives.insert(std::make_pair(Loc.getRawEncoding(), DirectivePointer));

  // Then replace with parseable compound statement to catch in Sema, and 
  // references to private variables;
  // {
  //   i;
  //   j;
  //   k;
  // }
  
  // If it's a threadprivate directive, then we skip this completely
  if (isThreadPrivate) {
    return;
  }
  
  set<IdentifierInfo *> PrivateVars = Directive.getPrivateIdentifiers();

  int tokenCount = 2 + 2 * PrivateVars.size();
  int currentToken = 0;    
  
  Token * Toks = new Token[tokenCount];

  Toks[currentToken++] = createToken(Loc, clang::tok::l_brace);

  set<IdentifierInfo *>::iterator PrivIt;
  for (PrivIt = PrivateVars.begin(); PrivIt != PrivateVars.end(); PrivIt++) {
  
    Toks[currentToken++] = createToken(Loc, clang::tok::identifier, *PrivIt);
    Toks[currentToken++] = createToken(Loc, clang::tok::semi);

  }

  Toks[currentToken++] = createToken(EndLoc, clang::tok::r_brace);

  assert(currentToken == tokenCount);
  
  Diags.setDiagnosticGroupMapping("unused-value", 
                                  clang::diag::MAP_IGNORE,
                                  Loc);

  Diags.setDiagnosticGroupMapping("unused-value", 
                                  clang::diag::MAP_WARNING,
                                  EndLoc);

  PP.EnterTokenStream(Toks, tokenCount, true, true);
  
}