summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaStmtAttr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaStmtAttr.cpp')
-rw-r--r--lib/Sema/SemaStmtAttr.cpp126
1 files changed, 60 insertions, 66 deletions
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index 44169c2fdc..a32e0fbcb6 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -45,35 +45,50 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A,
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;
+ Expr *ValueExpr = A.getArgAsExpr(3);
+
+ assert(OptionInfo && "Attribute must have valid option info.");
+
if (St->getStmtClass() != Stmt::DoStmtClass &&
St->getStmtClass() != Stmt::ForStmtClass &&
St->getStmtClass() != Stmt::CXXForRangeStmtClass &&
St->getStmtClass() != Stmt::WhileStmtClass) {
- S.Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop);
+ const char *Pragma = PragmaNameLoc->Ident->getName() == "unroll"
+ ? "#pragma unroll"
+ : "#pragma clang loop";
+ S.Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop) << Pragma;
return nullptr;
}
- IdentifierLoc *OptionLoc = A.getArgAsIdent(0);
- IdentifierInfo *OptionInfo = OptionLoc->Ident;
- IdentifierLoc *ValueLoc = A.getArgAsIdent(1);
- IdentifierInfo *ValueInfo = ValueLoc->Ident;
- Expr *ValueExpr = A.getArgAsExpr(2);
-
- assert(OptionInfo && "Attribute must have valid option info.");
-
- LoopHintAttr::OptionType Option =
- llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getName())
- .Case("vectorize", LoopHintAttr::Vectorize)
- .Case("vectorize_width", LoopHintAttr::VectorizeWidth)
- .Case("interleave", LoopHintAttr::Interleave)
- .Case("interleave_count", LoopHintAttr::InterleaveCount)
- .Case("unroll", LoopHintAttr::Unroll)
- .Case("unroll_count", LoopHintAttr::UnrollCount)
- .Default(LoopHintAttr::Vectorize);
+ LoopHintAttr::OptionType Option;
+ LoopHintAttr::Spelling Spelling;
+ if (PragmaNameLoc->Ident->getName() == "unroll") {
+ Option = ValueLoc ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll;
+ Spelling = LoopHintAttr::Pragma_unroll;
+ } else {
+ Option = llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getName())
+ .Case("vectorize", LoopHintAttr::Vectorize)
+ .Case("vectorize_width", LoopHintAttr::VectorizeWidth)
+ .Case("interleave", LoopHintAttr::Interleave)
+ .Case("interleave_count", LoopHintAttr::InterleaveCount)
+ .Case("unroll", LoopHintAttr::Unroll)
+ .Case("unroll_count", LoopHintAttr::UnrollCount)
+ .Default(LoopHintAttr::Vectorize);
+ Spelling = LoopHintAttr::Pragma_clang_loop;
+ }
int ValueInt;
- if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave ||
- Option == LoopHintAttr::Unroll) {
+ 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;
@@ -100,12 +115,12 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
} else
llvm_unreachable("Unknown loop hint option");
- return LoopHintAttr::CreateImplicit(S.Context, Option, ValueInt,
+ return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, ValueInt,
A.getRange());
}
-static void
-CheckForIncompatibleAttributes(Sema &S, SmallVectorImpl<const Attr *> &Attrs) {
+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:
@@ -113,18 +128,9 @@ CheckForIncompatibleAttributes(Sema &S, SmallVectorImpl<const Attr *> &Attrs) {
// accumulate the hints encountered while iterating through the
// attributes to check for compatibility.
struct {
- int EnableOptionId;
- int NumericOptionId;
- bool EnabledIsSet;
- bool ValueIsSet;
- bool Enabled;
- int Value;
- } Options[] = {{LoopHintAttr::Vectorize, LoopHintAttr::VectorizeWidth, false,
- false, false, 0},
- {LoopHintAttr::Interleave, LoopHintAttr::InterleaveCount,
- false, false, false, 0},
- {LoopHintAttr::Unroll, LoopHintAttr::UnrollCount, false, false,
- false, 0}};
+ const LoopHintAttr *EnableAttr;
+ const LoopHintAttr *NumericAttr;
+ } HintAttrs[] = {{nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}};
for (const auto *I : Attrs) {
const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);
@@ -134,8 +140,6 @@ CheckForIncompatibleAttributes(Sema &S, SmallVectorImpl<const Attr *> &Attrs) {
continue;
int Option = LH->getOption();
- int ValueInt = LH->getValue();
-
int Category;
switch (Option) {
case LoopHintAttr::Vectorize:
@@ -152,44 +156,34 @@ CheckForIncompatibleAttributes(Sema &S, SmallVectorImpl<const Attr *> &Attrs) {
break;
};
- auto &CategoryState = Options[Category];
- SourceLocation ValueLoc = LH->getRange().getEnd();
+ 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).
- if (CategoryState.EnabledIsSet) {
- // Cannot specify enable/disable state twice.
- S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
- << /*Duplicate=*/true << LoopHintAttr::getOptionName(Option)
- << LoopHintAttr::getValueName(CategoryState.Enabled)
- << LoopHintAttr::getOptionName(Option)
- << LoopHintAttr::getValueName(ValueInt);
- }
- CategoryState.EnabledIsSet = true;
- CategoryState.Enabled = ValueInt;
+ PrevAttr = CategoryState.EnableAttr;
+ CategoryState.EnableAttr = LH;
} else {
- // Numeric hint. For example, unroll_count(8).
- if (CategoryState.ValueIsSet) {
- // Cannot specify numeric hint twice.
- S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
- << /*Duplicate=*/true << LoopHintAttr::getOptionName(Option)
- << CategoryState.Value << LoopHintAttr::getOptionName(Option)
- << ValueInt;
- }
- CategoryState.ValueIsSet = true;
- CategoryState.Value = ValueInt;
+ // Numeric hint. For example, vectorize_width(8).
+ PrevAttr = CategoryState.NumericAttr;
+ CategoryState.NumericAttr = LH;
}
- if (CategoryState.EnabledIsSet && !CategoryState.Enabled &&
- CategoryState.ValueIsSet) {
+ 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.
- S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
+ S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
<< /*Duplicate=*/false
- << LoopHintAttr::getOptionName(CategoryState.EnableOptionId)
- << LoopHintAttr::getValueName(CategoryState.Enabled)
- << LoopHintAttr::getOptionName(CategoryState.NumericOptionId)
- << CategoryState.Value;
+ << CategoryState.EnableAttr->getDiagnosticName()
+ << CategoryState.NumericAttr->getDiagnosticName();
}
}
}