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); } }
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); }
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; }
/// 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(); }
// 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); }