diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp | 128 |
1 files changed, 65 insertions, 63 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp index a32e0fb..19e2c8e 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp @@ -47,30 +47,36 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A, SourceRange) { IdentifierLoc *PragmaNameLoc = A.getArgAsIdent(0); IdentifierLoc *OptionLoc = A.getArgAsIdent(1); - IdentifierInfo *OptionInfo = OptionLoc->Ident; - IdentifierLoc *ValueLoc = A.getArgAsIdent(2); - IdentifierInfo *ValueInfo = ValueLoc ? ValueLoc->Ident : nullptr; + IdentifierLoc *StateLoc = A.getArgAsIdent(2); Expr *ValueExpr = A.getArgAsExpr(3); - assert(OptionInfo && "Attribute must have valid option info."); - + bool PragmaUnroll = PragmaNameLoc->Ident->getName() == "unroll"; + bool PragmaNoUnroll = PragmaNameLoc->Ident->getName() == "nounroll"; if (St->getStmtClass() != Stmt::DoStmtClass && St->getStmtClass() != Stmt::ForStmtClass && St->getStmtClass() != Stmt::CXXForRangeStmtClass && St->getStmtClass() != Stmt::WhileStmtClass) { - const char *Pragma = PragmaNameLoc->Ident->getName() == "unroll" - ? "#pragma unroll" - : "#pragma clang loop"; + const char *Pragma = + llvm::StringSwitch<const char *>(PragmaNameLoc->Ident->getName()) + .Case("unroll", "#pragma unroll") + .Case("nounroll", "#pragma nounroll") + .Default("#pragma clang loop"); S.Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop) << Pragma; return nullptr; } LoopHintAttr::OptionType Option; LoopHintAttr::Spelling Spelling; - if (PragmaNameLoc->Ident->getName() == "unroll") { - Option = ValueLoc ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll; + if (PragmaUnroll) { + Option = ValueExpr ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll; Spelling = LoopHintAttr::Pragma_unroll; + } else if (PragmaNoUnroll) { + Option = LoopHintAttr::Unroll; + Spelling = LoopHintAttr::Pragma_nounroll; } else { + assert(OptionLoc && OptionLoc->Ident && + "Attribute must have valid option info."); + IdentifierInfo *OptionInfo = OptionLoc->Ident; Option = llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getName()) .Case("vectorize", LoopHintAttr::Vectorize) .Case("vectorize_width", LoopHintAttr::VectorizeWidth) @@ -82,53 +88,45 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A, Spelling = LoopHintAttr::Pragma_clang_loop; } - int ValueInt; - if (Option == LoopHintAttr::Unroll && - Spelling == LoopHintAttr::Pragma_unroll) { - ValueInt = 1; - } else if (Option == LoopHintAttr::Vectorize || - Option == LoopHintAttr::Interleave || - Option == LoopHintAttr::Unroll) { - if (!ValueInfo) { - S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword); - return nullptr; - } - if (ValueInfo->isStr("disable")) - ValueInt = 0; - else if (ValueInfo->isStr("enable")) - ValueInt = 1; - else { - S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword); - return nullptr; - } + LoopHintAttr::LoopHintState State = LoopHintAttr::Default; + if (PragmaNoUnroll) { + State = LoopHintAttr::Disable; } else if (Option == LoopHintAttr::VectorizeWidth || Option == LoopHintAttr::InterleaveCount || Option == LoopHintAttr::UnrollCount) { - // FIXME: We should support template parameters for the loop hint value. - // See bug report #19610. - llvm::APSInt ValueAPS; - if (!ValueExpr || !ValueExpr->isIntegerConstantExpr(ValueAPS, S.Context) || - (ValueInt = ValueAPS.getSExtValue()) < 1) { - S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_value); + assert(ValueExpr && "Attribute must have a valid value expression."); + if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart())) return nullptr; + } else if (Option == LoopHintAttr::Vectorize || + Option == LoopHintAttr::Interleave || + Option == LoopHintAttr::Unroll) { + // Default state is assumed if StateLoc is not specified, such as with + // '#pragma unroll'. + if (StateLoc && StateLoc->Ident) { + if (StateLoc->Ident->isStr("disable")) + State = LoopHintAttr::Disable; + else + State = LoopHintAttr::Enable; } - } else - llvm_unreachable("Unknown loop hint option"); + } - return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, ValueInt, - A.getRange()); + return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, State, + ValueExpr, A.getRange()); } -static void CheckForIncompatibleAttributes( - Sema &S, const SmallVectorImpl<const Attr *> &Attrs) { - // There are 3 categories of loop hints: vectorize, interleave, and - // unroll. Each comes in two variants: an enable/disable form and a - // form which takes a numeric argument. For example: - // unroll(enable|disable) and unroll_count(N). The following array - // accumulate the hints encountered while iterating through the - // attributes to check for compatibility. +static void +CheckForIncompatibleAttributes(Sema &S, + const SmallVectorImpl<const Attr *> &Attrs) { + // There are 3 categories of loop hints attributes: vectorize, interleave, + // and unroll. Each comes in two variants: a state form and a numeric form. + // The state form selectively defaults/enables/disables the transformation + // for the loop (for unroll, default indicates full unrolling rather than + // enabling the transformation). The numeric form form provides an integer + // hint (for example, unroll count) to the transformer. The following array + // accumulates the hints encountered while iterating through the attributes + // to check for compatibility. struct { - const LoopHintAttr *EnableAttr; + const LoopHintAttr *StateAttr; const LoopHintAttr *NumericAttr; } HintAttrs[] = {{nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}}; @@ -141,49 +139,53 @@ static void CheckForIncompatibleAttributes( int Option = LH->getOption(); int Category; + enum { Vectorize, Interleave, Unroll }; switch (Option) { case LoopHintAttr::Vectorize: case LoopHintAttr::VectorizeWidth: - Category = 0; + Category = Vectorize; break; case LoopHintAttr::Interleave: case LoopHintAttr::InterleaveCount: - Category = 1; + Category = Interleave; break; case LoopHintAttr::Unroll: case LoopHintAttr::UnrollCount: - Category = 2; + Category = Unroll; break; }; auto &CategoryState = HintAttrs[Category]; - SourceLocation OptionLoc = LH->getRange().getBegin(); const LoopHintAttr *PrevAttr; if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll) { // Enable|disable hint. For example, vectorize(enable). - PrevAttr = CategoryState.EnableAttr; - CategoryState.EnableAttr = LH; + PrevAttr = CategoryState.StateAttr; + CategoryState.StateAttr = LH; } else { // Numeric hint. For example, vectorize_width(8). PrevAttr = CategoryState.NumericAttr; CategoryState.NumericAttr = LH; } + PrintingPolicy Policy(S.Context.getLangOpts()); + SourceLocation OptionLoc = LH->getRange().getBegin(); if (PrevAttr) // Cannot specify same type of attribute twice. S.Diag(OptionLoc, diag::err_pragma_loop_compatibility) - << /*Duplicate=*/true << PrevAttr->getDiagnosticName() - << LH->getDiagnosticName(); - - if (CategoryState.EnableAttr && !CategoryState.EnableAttr->getValue() && - CategoryState.NumericAttr) { - // Disable hints are not compatible with numeric hints of the - // same category. + << /*Duplicate=*/true << PrevAttr->getDiagnosticName(Policy) + << LH->getDiagnosticName(Policy); + + if (CategoryState.StateAttr && CategoryState.NumericAttr && + (Category == Unroll || + CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) { + // Disable hints are not compatible with numeric hints of the same + // category. As a special case, numeric unroll hints are also not + // compatible with "enable" form of the unroll pragma, unroll(full). S.Diag(OptionLoc, diag::err_pragma_loop_compatibility) << /*Duplicate=*/false - << CategoryState.EnableAttr->getDiagnosticName() - << CategoryState.NumericAttr->getDiagnosticName(); + << CategoryState.StateAttr->getDiagnosticName(Policy) + << CategoryState.NumericAttr->getDiagnosticName(Policy); } } } |