Author: abataev Date: Tue Apr 12 00:28:34 2016 New Revision: 266041 URL: http://llvm.org/viewvc/llvm-project?rev=266041&view=rev Log: [OPENMP 4.0] Support for 'uniform' clause in 'declare simd' directive.
OpenMP 4.0 defines clause 'uniform' in 'declare simd' directive: 'uniform' '(' <argument-list> ')' The uniform clause declares one or more arguments to have an invariant value for all concurrent invocations of the function in the execution of a single SIMD loop. The special this pointer can be used as if was one of the arguments to the function in any of the linear, aligned, or uniform clauses. Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h cfe/trunk/include/clang/Basic/Attr.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Basic/OpenMPKinds.h cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/AST/OpenMPClause.cpp cfe/trunk/lib/Basic/OpenMPKinds.cpp cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp cfe/trunk/lib/Parse/ParseOpenMP.cpp cfe/trunk/lib/Sema/SemaOpenMP.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp cfe/trunk/test/OpenMP/declare_simd_ast_print.c cfe/trunk/test/OpenMP/declare_simd_ast_print.cpp cfe/trunk/test/OpenMP/declare_simd_messages.cpp Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=266041&r1=266040&r2=266041&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original) +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Apr 12 00:28:34 2016 @@ -2517,6 +2517,7 @@ bool RecursiveASTVisitor<Derived>::Trave break; #include "clang/Basic/OpenMPKinds.def" case OMPC_threadprivate: + case OMPC_uniform: case OMPC_unknown: break; } Modified: cfe/trunk/include/clang/Basic/Attr.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=266041&r1=266040&r2=266041&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Attr.td (original) +++ cfe/trunk/include/clang/Basic/Attr.td Tue Apr 12 00:28:34 2016 @@ -2276,7 +2276,7 @@ def OMPDeclareSimdDecl : Attr { EnumArgument<"BranchState", "BranchStateTy", [ "", "inbranch", "notinbranch" ], [ "BS_Undefined", "BS_Inbranch", "BS_Notinbranch" ]>, - ExprArgument<"Simdlen"> + ExprArgument<"Simdlen">, VariadicExprArgument<"Uniforms"> ]; let AdditionalMembers = [{ void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy) @@ -2288,6 +2288,16 @@ def OMPDeclareSimdDecl : Attr { E->printPretty(OS, nullptr, Policy); OS << ") "; } + if (uniforms_size() > 0) { + OS << "uniform"; + StringRef Sep = "("; + for (auto *E : uniforms()) { + OS << Sep; + E->printPretty(OS, nullptr, Policy); + Sep = ", "; + } + OS << ") "; + } } }]; } Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=266041&r1=266040&r2=266041&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Apr 12 00:28:34 2016 @@ -8179,7 +8179,9 @@ def err_omp_schedule_nonmonotonic_ordere def err_omp_ordered_simd : Error< "'ordered' clause with a parameter can not be specified in '#pragma omp %0' directive">; def err_omp_variable_in_map_and_dsa : Error< - "%0 variable cannot be in a map clause in '#pragma omp %1' directive">; + "%0 variable cannot be in a map clause in '#pragma omp %1' directive">; +def err_omp_param_or_this_in_clause : Error< + "expected reference to one of the parameters of function %0%select{| or 'this'}1">; } // end of OpenMP category let CategoryName = "Related Result Type Issue" in { Modified: cfe/trunk/include/clang/Basic/OpenMPKinds.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenMPKinds.h?rev=266041&r1=266040&r2=266041&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/OpenMPKinds.h (original) +++ cfe/trunk/include/clang/Basic/OpenMPKinds.h Tue Apr 12 00:28:34 2016 @@ -35,6 +35,7 @@ enum OpenMPClauseKind { OMPC_##Name, #include "clang/Basic/OpenMPKinds.def" OMPC_threadprivate, + OMPC_uniform, OMPC_unknown }; Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=266041&r1=266040&r2=266041&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Tue Apr 12 00:28:34 2016 @@ -2528,6 +2528,25 @@ public: /// constructs. /// \param RLoc Returned location of right paren. ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc); + + /// Data used for parsing list of variables in OpenMP clauses. + struct OpenMPVarListDataTy { + Expr *TailExpr = nullptr; + SourceLocation ColonLoc; + CXXScopeSpec ReductionIdScopeSpec; + DeclarationNameInfo ReductionId; + OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown; + OpenMPLinearClauseKind LinKind = OMPC_LINEAR_val; + OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown; + OpenMPMapClauseKind MapType = OMPC_MAP_unknown; + bool IsMapTypeImplicit = false; + SourceLocation DepLinMapLoc; + }; + + /// Parses clauses with list. + bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, + SmallVectorImpl<Expr *> &Vars, + OpenMPVarListDataTy &Data); bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=266041&r1=266040&r2=266041&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Tue Apr 12 00:28:34 2016 @@ -8110,10 +8110,9 @@ public: /// \brief Called on well-formed '\#pragma omp declare simd' after parsing of /// the associated method/function. - DeclGroupPtrTy - ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, - OMPDeclareSimdDeclAttr::BranchStateTy BS, - Expr *Simdlen, SourceRange SR); + DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective( + DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, + Expr *Simdlen, ArrayRef<Expr *> Uniforms, SourceRange SR); OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, Modified: cfe/trunk/lib/AST/OpenMPClause.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/OpenMPClause.cpp?rev=266041&r1=266040&r2=266041&view=diff ============================================================================== --- cfe/trunk/lib/AST/OpenMPClause.cpp (original) +++ cfe/trunk/lib/AST/OpenMPClause.cpp Tue Apr 12 00:28:34 2016 @@ -86,6 +86,7 @@ const OMPClauseWithPreInit *OMPClauseWit case OMPC_hint: case OMPC_defaultmap: case OMPC_unknown: + case OMPC_uniform: break; } @@ -146,6 +147,7 @@ const OMPClauseWithPostUpdate *OMPClause case OMPC_hint: case OMPC_defaultmap: case OMPC_unknown: + case OMPC_uniform: break; } Modified: cfe/trunk/lib/Basic/OpenMPKinds.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/OpenMPKinds.cpp?rev=266041&r1=266040&r2=266041&view=diff ============================================================================== --- cfe/trunk/lib/Basic/OpenMPKinds.cpp (original) +++ cfe/trunk/lib/Basic/OpenMPKinds.cpp Tue Apr 12 00:28:34 2016 @@ -55,6 +55,7 @@ OpenMPClauseKind clang::getOpenMPClauseK return llvm::StringSwitch<OpenMPClauseKind>(Str) #define OPENMP_CLAUSE(Name, Class) .Case(#Name, OMPC_##Name) #include "clang/Basic/OpenMPKinds.def" + .Case("uniform", OMPC_uniform) .Default(OMPC_unknown); } @@ -67,6 +68,8 @@ const char *clang::getOpenMPClauseName(O case OMPC_##Name: \ return #Name; #include "clang/Basic/OpenMPKinds.def" + case OMPC_uniform: + return "uniform"; case OMPC_threadprivate: return "threadprivate or thread local"; } @@ -158,6 +161,7 @@ unsigned clang::getOpenMPSimpleClauseTyp case OMPC_nogroup: case OMPC_num_tasks: case OMPC_hint: + case OMPC_uniform: break; } llvm_unreachable("Invalid OpenMP simple clause kind"); @@ -292,6 +296,7 @@ const char *clang::getOpenMPSimpleClause case OMPC_nogroup: case OMPC_num_tasks: case OMPC_hint: + case OMPC_uniform: break; } llvm_unreachable("Invalid OpenMP simple clause kind"); Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=266041&r1=266040&r2=266041&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original) +++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Tue Apr 12 00:28:34 2016 @@ -2975,6 +2975,7 @@ static void EmitOMPAtomicExpr(CodeGenFun case OMPC_hint: case OMPC_dist_schedule: case OMPC_defaultmap: + case OMPC_uniform: llvm_unreachable("Clause is not allowed in 'omp atomic'."); } } Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=266041&r1=266040&r2=266041&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original) +++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Tue Apr 12 00:28:34 2016 @@ -332,10 +332,12 @@ Parser::ParseOpenMPDeclareReductionDirec /// Parses clauses for 'declare simd' directive. /// clause: /// 'inbranch' | 'notinbranch' -/// 'simdlen' '('<expr> ')' +/// 'simdlen' '(' <expr> ')' +/// { 'uniform' '(' <argument_list> ')' } static bool parseDeclareSimdClauses(Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, - ExprResult &SimdLen) { + ExprResult &SimdLen, + SmallVectorImpl<Expr *> &Uniforms) { SourceRange BSRange; const Token &Tok = P.getCurToken(); bool IsError = false; @@ -367,6 +369,13 @@ static bool parseDeclareSimdClauses(Pars SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc); if (SimdLen.isInvalid()) IsError = true; + } else if (ClauseName.equals("uniform")) { + Parser::OpenMPVarListDataTy Data; + + P.ConsumeToken(); + if (P.ParseOpenMPVarList(OMPD_declare_simd, + getOpenMPClauseKind(ClauseName), Uniforms, Data)) + IsError = true; } else // TODO: add parsing of other clauses. break; @@ -446,7 +455,8 @@ Parser::ParseOMPDeclareSimdClauses(Parse OMPDeclareSimdDeclAttr::BranchStateTy BS = OMPDeclareSimdDeclAttr::BS_Undefined; ExprResult Simdlen; - bool IsError = parseDeclareSimdClauses(*this, BS, Simdlen); + SmallVector<Expr *, 4> Uniforms; + bool IsError = parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms); // Need to check for extra tokens. if (Tok.isNot(tok::annot_pragma_openmp_end)) { Diag(Tok, diag::warn_omp_extra_tokens_at_eol) @@ -457,8 +467,8 @@ Parser::ParseOMPDeclareSimdClauses(Parse // Skip the last annot_pragma_openmp_end. SourceLocation EndLoc = ConsumeToken(); if (!IsError) - return Actions.ActOnOpenMPDeclareSimdDirective(Ptr, BS, Simdlen.get(), - SourceRange(Loc, EndLoc)); + return Actions.ActOnOpenMPDeclareSimdDirective( + Ptr, BS, Simdlen.get(), Uniforms, SourceRange(Loc, EndLoc)); return Ptr; } @@ -526,8 +536,12 @@ Parser::DeclGroupPtrTy Parser::ParseOpen // ConsumeToken(); CachedTokens Toks; - ConsumeAndStoreUntil(tok::annot_pragma_openmp_end, Toks, - /*StopAtSemi=*/false, /*ConsumeFinalToken=*/true); + while(Tok.isNot(tok::annot_pragma_openmp_end)) { + Toks.push_back(Tok); + ConsumeAnyToken(); + } + Toks.push_back(Tok); + ConsumeAnyToken(); DeclGroupPtrTy Ptr; if (Tok.is(tok::annot_pragma_openmp)) @@ -1081,6 +1095,7 @@ OMPClause *Parser::ParseOpenMPClause(Ope SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); break; case OMPC_threadprivate: + case OMPC_uniform: Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); @@ -1402,61 +1417,20 @@ static bool ParseReductionId(Parser &P, TemplateKWLoc, ReductionId); } -/// \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 | source ')' -/// map-clause: -/// 'map' '(' [ [ always , ] -/// to | from | tofrom | alloc | release | delete ':' ] 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(OpenMPDirectiveKind DKind, - 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; +/// Parses clauses with list. +bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, + OpenMPClauseKind Kind, + SmallVectorImpl<Expr *> &Vars, + OpenMPVarListDataTy &Data) { + UnqualifiedId UnqualifiedReductionId; 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; - OpenMPMapClauseKind MapType = OMPC_MAP_unknown; - OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown; - bool MapTypeIsImplicit = false; bool MapTypeModifierSpecified = false; - SourceLocation DepLinMapLoc; // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, getOpenMPClauseName(Kind))) - return nullptr; + return true; bool NeedRParenForLinear = false; BalancedDelimiterTracker LinearT(*this, tok::l_paren, @@ -1465,47 +1439,45 @@ OMPClause *Parser::ParseOpenMPVarListCla if (Kind == OMPC_reduction) { ColonProtectionRAIIObject ColonRAII(*this); if (getLangOpts().CPlusPlus) - ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, + ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec, /*ObjectType=*/nullptr, /*EnteringContext=*/false); - InvalidReductionId = - ParseReductionId(*this, ReductionIdScopeSpec, ReductionId); + InvalidReductionId = ParseReductionId(*this, Data.ReductionIdScopeSpec, + UnqualifiedReductionId); if (InvalidReductionId) { SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } - if (Tok.is(tok::colon)) { - ColonLoc = ConsumeToken(); - } else { + if (Tok.is(tok::colon)) + Data.ColonLoc = ConsumeToken(); + else Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; - } + if (!InvalidReductionId) + Data.ReductionId = + Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId); } 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) : "")); - DepLinMapLoc = Tok.getLocation(); + Data.DepKind = + static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType( + Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); + Data.DepLinMapLoc = Tok.getLocation(); - if (DepKind == OMPC_DEPEND_unknown) { + if (Data.DepKind == OMPC_DEPEND_unknown) { SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } else { ConsumeToken(); // Special processing for depend(source) clause. - if (DKind == OMPD_ordered && DepKind == OMPC_DEPEND_source) { + if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) { // Parse ')'. T.consumeClose(); - return Actions.ActOnOpenMPVarListClause( - Kind, llvm::None, /*TailExpr=*/nullptr, Loc, LOpen, - /*ColonLoc=*/SourceLocation(), Tok.getLocation(), - ReductionIdScopeSpec, DeclarationNameInfo(), DepKind, - LinearModifier, MapTypeModifier, MapType, MapTypeIsImplicit, - DepLinMapLoc); + return false; } } - if (Tok.is(tok::colon)) { - ColonLoc = ConsumeToken(); - } else { + if (Tok.is(tok::colon)) + Data.ColonLoc = ConsumeToken(); + else { Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren : diag::warn_pragma_expected_colon) << "dependency type"; @@ -1513,9 +1485,9 @@ OMPClause *Parser::ParseOpenMPVarListCla } 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>( + Data.LinKind = static_cast<OpenMPLinearClauseKind>( getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); - DepLinMapLoc = ConsumeToken(); + Data.DepLinMapLoc = ConsumeToken(); LinearT.consumeOpen(); NeedRParenForLinear = true; } @@ -1525,79 +1497,76 @@ OMPClause *Parser::ParseOpenMPVarListCla /// The map clause modifier token can be either a identifier or the C++ /// delete keyword. - auto IsMapClauseModifierToken = [](const Token &Tok) { + auto &&IsMapClauseModifierToken = [](const Token &Tok) -> bool { return Tok.isOneOf(tok::identifier, tok::kw_delete); }; // The first identifier may be a list item, a map-type or a // map-type-modifier. The map modifier can also be delete which has the same // spelling of the C++ delete keyword. - MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( - Kind, IsMapClauseModifierToken(Tok) ? PP.getSpelling(Tok) : "")); - DepLinMapLoc = Tok.getLocation(); + Data.MapType = + IsMapClauseModifierToken(Tok) + ? static_cast<OpenMPMapClauseKind>( + getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))) + : OMPC_MAP_unknown; + Data.DepLinMapLoc = Tok.getLocation(); bool ColonExpected = false; if (IsMapClauseModifierToken(Tok)) { if (PP.LookAhead(0).is(tok::colon)) { - MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( - Kind, IsMapClauseModifierToken(Tok) ? PP.getSpelling(Tok) : "")); - if (MapType == OMPC_MAP_unknown) { + if (Data.MapType == OMPC_MAP_unknown) Diag(Tok, diag::err_omp_unknown_map_type); - } else if (MapType == OMPC_MAP_always) { + else if (Data.MapType == OMPC_MAP_always) Diag(Tok, diag::err_omp_map_type_missing); - } ConsumeToken(); } else if (PP.LookAhead(0).is(tok::comma)) { if (IsMapClauseModifierToken(PP.LookAhead(1)) && PP.LookAhead(2).is(tok::colon)) { - MapTypeModifier = - static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( - Kind, - IsMapClauseModifierToken(Tok) ? PP.getSpelling(Tok) : "")); - if (MapTypeModifier != OMPC_MAP_always) { + Data.MapTypeModifier = Data.MapType; + if (Data.MapTypeModifier != OMPC_MAP_always) { Diag(Tok, diag::err_omp_unknown_map_type_modifier); - MapTypeModifier = OMPC_MAP_unknown; - } else { + Data.MapTypeModifier = OMPC_MAP_unknown; + } else MapTypeModifierSpecified = true; - } ConsumeToken(); ConsumeToken(); - MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( - Kind, IsMapClauseModifierToken(Tok) ? PP.getSpelling(Tok) : "")); - if (MapType == OMPC_MAP_unknown || MapType == OMPC_MAP_always) { + Data.MapType = + IsMapClauseModifierToken(Tok) + ? static_cast<OpenMPMapClauseKind>( + getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))) + : OMPC_MAP_unknown; + if (Data.MapType == OMPC_MAP_unknown || + Data.MapType == OMPC_MAP_always) Diag(Tok, diag::err_omp_unknown_map_type); - } ConsumeToken(); } else { - MapType = OMPC_MAP_tofrom; - MapTypeIsImplicit = true; + Data.MapType = OMPC_MAP_tofrom; + Data.IsMapTypeImplicit = true; } } else { - MapType = OMPC_MAP_tofrom; - MapTypeIsImplicit = true; + Data.MapType = OMPC_MAP_tofrom; + Data.IsMapTypeImplicit = true; } } else { - MapType = OMPC_MAP_tofrom; - MapTypeIsImplicit = true; + Data.MapType = OMPC_MAP_tofrom; + Data.IsMapTypeImplicit = true; } - if (Tok.is(tok::colon)) { - ColonLoc = ConsumeToken(); - } else if (ColonExpected) { + if (Tok.is(tok::colon)) + Data.ColonLoc = ConsumeToken(); + else if (ColonExpected) Diag(Tok, diag::warn_pragma_expected_colon) << "map type"; - } } - SmallVector<Expr *, 5> Vars; bool IsComma = - ((Kind != OMPC_reduction) && (Kind != OMPC_depend) && - (Kind != OMPC_map)) || - ((Kind == OMPC_reduction) && !InvalidReductionId) || - ((Kind == OMPC_map) && (MapType != OMPC_MAP_unknown) && - (!MapTypeModifierSpecified || MapTypeModifier == OMPC_MAP_always)) || - ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown); + (Kind != OMPC_reduction && Kind != OMPC_depend && Kind != OMPC_map) || + (Kind == OMPC_reduction && !InvalidReductionId) || + (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown && + (!MapTypeModifierSpecified || + Data.MapTypeModifier == OMPC_MAP_always)) || + (Kind == OMPC_depend && Data.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))) { @@ -1605,9 +1574,9 @@ OMPClause *Parser::ParseOpenMPVarListCla // Parse variable ExprResult VarExpr = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); - if (VarExpr.isUsable()) { + if (VarExpr.isUsable()) Vars.push_back(VarExpr.get()); - } else { + else { SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } @@ -1629,15 +1598,14 @@ OMPClause *Parser::ParseOpenMPVarListCla LinearT.consumeClose(); // Parse ':' linear-step (or ':' alignment). - Expr *TailExpr = nullptr; const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); if (MustHaveTail) { - ColonLoc = Tok.getLocation(); + Data.ColonLoc = Tok.getLocation(); SourceLocation ELoc = ConsumeToken(); ExprResult Tail = ParseAssignmentExpression(); Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc); if (Tail.isUsable()) - TailExpr = Tail.get(); + Data.TailExpr = Tail.get(); else SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); @@ -1645,18 +1613,59 @@ OMPClause *Parser::ParseOpenMPVarListCla // Parse ')'. T.consumeClose(); - if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) || + if ((Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown && + Vars.empty()) || (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || - (MustHaveTail && !TailExpr) || InvalidReductionId) { + (MustHaveTail && !Data.TailExpr) || InvalidReductionId) + return true; + return false; +} + +/// \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 | source ')' +/// map-clause: +/// 'map' '(' [ [ always , ] +/// to | from | tofrom | alloc | release | delete ':' ] 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(OpenMPDirectiveKind DKind, + OpenMPClauseKind Kind) { + SourceLocation Loc = Tok.getLocation(); + SourceLocation LOpen = ConsumeToken(); + SmallVector<Expr *, 4> Vars; + OpenMPVarListDataTy Data; + + if (ParseOpenMPVarList(DKind, Kind, Vars, Data)) return nullptr; - } return Actions.ActOnOpenMPVarListClause( - Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(), - ReductionIdScopeSpec, - ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId) - : DeclarationNameInfo(), - DepKind, LinearModifier, MapTypeModifier, MapType, MapTypeIsImplicit, - DepLinMapLoc); + Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.getLocation(), + Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind, + Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit, + Data.DepLinMapLoc); } Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=266041&r1=266040&r2=266041&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original) +++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Tue Apr 12 00:28:34 2016 @@ -3190,10 +3190,9 @@ StmtResult Sema::ActOnOpenMPExecutableDi return Res; } -Sema::DeclGroupPtrTy -Sema::ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, - OMPDeclareSimdDeclAttr::BranchStateTy BS, - Expr *Simdlen, SourceRange SR) { +Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective( + DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, + ArrayRef<Expr *> Uniforms, SourceRange SR) { if (!DG || DG.get().isNull()) return DeclGroupPtrTy(); @@ -3205,9 +3204,9 @@ Sema::ActOnOpenMPDeclareSimdDirective(De if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl)) ADecl = FTD->getTemplatedDecl(); - if (!isa<FunctionDecl>(ADecl)) { - Diag(ADecl->getLocation(), diag::err_omp_function_expected) - << ADecl->getDeclContext()->isFileContext(); + auto *FD = dyn_cast<FunctionDecl>(ADecl); + if (!FD) { + Diag(ADecl->getLocation(), diag::err_omp_function_expected); return DeclGroupPtrTy(); } @@ -3215,13 +3214,30 @@ Sema::ActOnOpenMPDeclareSimdDirective(De // The parameter of the simdlen clause must be a constant positive integer // expression. ExprResult SL; - if (Simdlen) { + if (Simdlen) SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen); - if (SL.isInvalid()) - return DG; + // OpenMP [2.8.2, declare simd construct, Description] + // The special this pointer can be used as if was one of the arguments to the + // function in any of the linear, aligned, or uniform clauses. + // The uniform clause declares one or more arguments to have an invariant + // value for all concurrent invocations of the function in the execution of a + // single SIMD loop. + for (auto *E : Uniforms) { + E = E->IgnoreParenImpCasts(); + if (auto *DRE = dyn_cast<DeclRefExpr>(E)) + if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) + if (FD->getNumParams() > PVD->getFunctionScopeIndex() && + FD->getParamDecl(PVD->getFunctionScopeIndex()) + ->getCanonicalDecl() == PVD->getCanonicalDecl()) + continue; + if (isa<CXXThisExpr>(E)) + continue; + Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) + << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0); } - auto *NewAttr = - OMPDeclareSimdDeclAttr::CreateImplicit(Context, BS, SL.get(), SR); + auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit( + Context, BS, SL.get(), const_cast<Expr **>(Uniforms.data()), + Uniforms.size(), SR); ADecl->addAttr(NewAttr); return ConvertDeclToDeclGroup(ADecl); } @@ -6386,6 +6402,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprCl case OMPC_dist_schedule: case OMPC_defaultmap: case OMPC_unknown: + case OMPC_uniform: llvm_unreachable("Clause is not allowed."); } return Res; @@ -6671,6 +6688,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause case OMPC_dist_schedule: case OMPC_defaultmap: case OMPC_unknown: + case OMPC_uniform: llvm_unreachable("Clause is not allowed."); } return Res; @@ -6821,6 +6839,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWi case OMPC_num_tasks: case OMPC_hint: case OMPC_unknown: + case OMPC_uniform: llvm_unreachable("Clause is not allowed."); } return Res; @@ -7004,6 +7023,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenM case OMPC_dist_schedule: case OMPC_defaultmap: case OMPC_unknown: + case OMPC_uniform: llvm_unreachable("Clause is not allowed."); } return Res; @@ -7149,6 +7169,7 @@ OMPClause *Sema::ActOnOpenMPVarListClaus case OMPC_dist_schedule: case OMPC_defaultmap: case OMPC_unknown: + case OMPC_uniform: llvm_unreachable("Clause is not allowed."); } return Res; Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=266041&r1=266040&r2=266041&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Apr 12 00:28:34 2016 @@ -240,15 +240,42 @@ static void instantiateOMPDeclareSimdDec Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const OMPDeclareSimdDeclAttr &Attr, Decl *New) { ExprResult Simdlen; - if (auto *E = Attr.getSimdlen()) { + if (auto *E = Attr.getSimdlen()) Simdlen = S.SubstExpr(E, TemplateArgs); - if (Simdlen.isInvalid()) - return; + // Allow 'this' in clauses with varlists. + if (auto *FTD = dyn_cast<FunctionTemplateDecl>(New)) + New = FTD->getTemplatedDecl(); + auto *FD = cast<FunctionDecl>(New); + auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(FD->getDeclContext()); + SmallVector<Expr *, 4> Uniforms; + + auto &&Subst = [&](Expr *E) -> ExprResult { + if (auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) + if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) { + Sema::ContextRAII SavedContext(S, FD); + LocalInstantiationScope Local(S); + if (FD->getNumParams() > PVD->getFunctionScopeIndex()) + Local.InstantiatedLocal( + PVD, FD->getParamDecl(PVD->getFunctionScopeIndex())); + return S.SubstExpr(E, TemplateArgs); + } + Sema::CXXThisScopeRAII ThisScope(S, ThisContext, /*TypeQuals=*/0, + FD->isCXXInstanceMember()); + return S.SubstExpr(E, TemplateArgs); + }; + + if (Attr.uniforms_size() > 0) { + for(auto *E : Attr.uniforms()) { + ExprResult Inst = Subst(E); + if (Inst.isInvalid()) + continue; + Uniforms.push_back(Inst.get()); + } } (void)S.ActOnOpenMPDeclareSimdDirective(S.ConvertDeclToDeclGroup(New), Attr.getBranchState(), Simdlen.get(), - Attr.getRange()); + Uniforms, Attr.getRange()); } void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, Modified: cfe/trunk/test/OpenMP/declare_simd_ast_print.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_simd_ast_print.c?rev=266041&r1=266040&r2=266041&view=diff ============================================================================== --- cfe/trunk/test/OpenMP/declare_simd_ast_print.c (original) +++ cfe/trunk/test/OpenMP/declare_simd_ast_print.c Tue Apr 12 00:28:34 2016 @@ -8,12 +8,12 @@ #pragma omp declare simd #pragma omp declare simd simdlen(32) -#pragma omp declare simd inbranch -#pragma omp declare simd notinbranch simdlen(2) +#pragma omp declare simd inbranch, uniform(d) +#pragma omp declare simd notinbranch simdlen(2), uniform(s1, s2) void add_1(float *d, float *s1, float *s2) __attribute__((cold)); -// CHECK: #pragma omp declare simd notinbranch simdlen(2) -// CHECK-NEXT: #pragma omp declare simd inbranch +// CHECK: #pragma omp declare simd notinbranch simdlen(2) uniform(s1, s2) +// CHECK-NEXT: #pragma omp declare simd inbranch uniform(d) // CHECK-NEXT: #pragma omp declare simd simdlen(32) // CHECK-NEXT: #pragma omp declare simd // CHECK-NEXT: void add_1(float *d, float *s1, float *s2) __attribute__((cold)) Modified: cfe/trunk/test/OpenMP/declare_simd_ast_print.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_simd_ast_print.cpp?rev=266041&r1=266040&r2=266041&view=diff ============================================================================== --- cfe/trunk/test/OpenMP/declare_simd_ast_print.cpp (original) +++ cfe/trunk/test/OpenMP/declare_simd_ast_print.cpp Tue Apr 12 00:28:34 2016 @@ -48,11 +48,11 @@ void h(int *hp, int *hp2, int *hq, int * } class VV { - // CHECK: #pragma omp declare simd + // CHECK: #pragma omp declare simd uniform(this, a) // CHECK-NEXT: int add(int a, int b) __attribute__((cold)) { // CHECK-NEXT: return a + b; // CHECK-NEXT: } - #pragma omp declare simd + #pragma omp declare simd uniform(this, a) int add(int a, int b) __attribute__((cold)) { return a + b; } // CHECK: #pragma omp declare simd @@ -109,10 +109,10 @@ public: // CHECK-NEXT: } #pragma omp declare simd - #pragma omp declare simd + #pragma omp declare simd uniform(this, b) int tadd(int b) { return x[b] + b; } -// CHECK: #pragma omp declare simd +// CHECK: #pragma omp declare simd uniform(this, b) // CHECK-NEXT: #pragma omp declare simd // CHECK-NEXT: int tadd(int b) { // CHECK-NEXT: return this->x[b] + b; Modified: cfe/trunk/test/OpenMP/declare_simd_messages.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_simd_messages.cpp?rev=266041&r1=266040&r2=266041&view=diff ============================================================================== --- cfe/trunk/test/OpenMP/declare_simd_messages.cpp (original) +++ cfe/trunk/test/OpenMP/declare_simd_messages.cpp Tue Apr 12 00:28:34 2016 @@ -75,8 +75,10 @@ void h(int *hp, int *hp2, int *hq, int * #pragma omp declare simd simdlen() simdlen) void foo(); +// expected-error@+3 2 {{expected reference to one of the parameters of function 'foo'}} +// expected-error@+2 {{invalid use of 'this' outside of a non-static member function}} // expected-error@+1 {{argument to 'simdlen' clause must be a strictly positive integer value}} -#pragma omp declare simd simdlen(N) +#pragma omp declare simd simdlen(N) uniform(this, var) template<int N> void foo() {} @@ -85,12 +87,34 @@ void test() { foo<-3>(); } +// expected-error@+1 {{expected '(' after 'uniform'}} +#pragma omp declare simd uniform +// expected-note@+3 {{to match this '('}} +// expected-error@+2 {{expected ')'}} +// expected-error@+1 {{expected expression}} +#pragma omp declare simd uniform( +// expected-error@+1 {{expected expression}} +#pragma omp declare simd uniform() +// expected-note@+3 {{to match this '('}} +// expected-error@+2 {{expected ')'}} +// expected-error@+1 {{invalid use of 'this' outside of a non-static member function}} +#pragma omp declare simd uniform(this +// expected-note@+3 {{to match this '('}} +// expected-error@+2 {{expected ')'}} +// expected-error@+1 {{invalid use of 'this' outside of a non-static member function}} +#pragma omp declare simd uniform(this,a +// expected-error@+1 {{expected expression}} +#pragma omp declare simd uniform(,a) +void bar(int a); + template <class T> struct St { // expected-error@+2 {{function declaration is expected after 'declare simd' directive}} #pragma init_seg(compiler) #pragma omp declare simd #pragma init_seg(compiler) +// expected-error@+1 {{use of undeclared identifier 't'}} +#pragma omp declare simd uniform(this, t) void h(T *hp) { // expected-error@+1 {{unexpected OpenMP directive '#pragma omp declare simd'}} #pragma omp declare simd _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits