21 #include "llvm/ADT/StringExtras.h"
23 using namespace clang;
28 if (!isa<NullStmt>(St)) {
31 if (isa<SwitchCase>(St)) {
33 S.
Diag(L, diag::note_fallthrough_insert_semi_fixit)
53 bool PragmaUnroll = PragmaNameLoc->
Ident->
getName() ==
"unroll";
54 bool PragmaNoUnroll = PragmaNameLoc->
Ident->
getName() ==
"nounroll";
55 if (St->getStmtClass() != Stmt::DoStmtClass &&
56 St->getStmtClass() != Stmt::ForStmtClass &&
57 St->getStmtClass() != Stmt::CXXForRangeStmtClass &&
58 St->getStmtClass() != Stmt::WhileStmtClass) {
60 llvm::StringSwitch<const char *>(PragmaNameLoc->
Ident->
getName())
61 .Case(
"unroll",
"#pragma unroll")
62 .Case(
"nounroll",
"#pragma nounroll")
63 .Default(
"#pragma clang loop");
64 S.
Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop) << Pragma;
68 LoopHintAttr::OptionType Option;
69 LoopHintAttr::Spelling Spelling;
71 Option = ValueExpr ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll;
72 Spelling = LoopHintAttr::Pragma_unroll;
73 }
else if (PragmaNoUnroll) {
74 Option = LoopHintAttr::Unroll;
75 Spelling = LoopHintAttr::Pragma_nounroll;
77 assert(OptionLoc && OptionLoc->
Ident &&
78 "Attribute must have valid option info.");
80 Option = llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->
getName())
81 .Case(
"vectorize", LoopHintAttr::Vectorize)
82 .Case(
"vectorize_width", LoopHintAttr::VectorizeWidth)
83 .Case(
"interleave", LoopHintAttr::Interleave)
84 .Case(
"interleave_count", LoopHintAttr::InterleaveCount)
85 .Case(
"unroll", LoopHintAttr::Unroll)
86 .Case(
"unroll_count", LoopHintAttr::UnrollCount)
87 .Default(LoopHintAttr::Vectorize);
88 Spelling = LoopHintAttr::Pragma_clang_loop;
91 LoopHintAttr::LoopHintState
State = LoopHintAttr::Default;
93 State = LoopHintAttr::Disable;
94 }
else if (Option == LoopHintAttr::VectorizeWidth ||
95 Option == LoopHintAttr::InterleaveCount ||
96 Option == LoopHintAttr::UnrollCount) {
97 assert(ValueExpr &&
"Attribute must have a valid value expression.");
100 }
else if (Option == LoopHintAttr::Vectorize ||
101 Option == LoopHintAttr::Interleave ||
102 Option == LoopHintAttr::Unroll) {
105 if (StateLoc && StateLoc->
Ident) {
107 State = LoopHintAttr::Disable;
108 else if (StateLoc->
Ident->
isStr(
"assume_safety"))
109 State = LoopHintAttr::AssumeSafety;
111 State = LoopHintAttr::Enable;
115 return LoopHintAttr::CreateImplicit(S.
Context, Spelling, Option, State,
131 const LoopHintAttr *StateAttr;
132 const LoopHintAttr *NumericAttr;
133 } HintAttrs[] = {{
nullptr,
nullptr}, {
nullptr,
nullptr}, {
nullptr,
nullptr}};
135 for (
const auto *I : Attrs) {
136 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);
142 int Option = LH->getOption();
144 enum { Vectorize, Interleave, Unroll };
146 case LoopHintAttr::Vectorize:
147 case LoopHintAttr::VectorizeWidth:
148 Category = Vectorize;
150 case LoopHintAttr::Interleave:
151 case LoopHintAttr::InterleaveCount:
152 Category = Interleave;
154 case LoopHintAttr::Unroll:
155 case LoopHintAttr::UnrollCount:
160 auto &CategoryState = HintAttrs[Category];
161 const LoopHintAttr *PrevAttr;
162 if (Option == LoopHintAttr::Vectorize ||
163 Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll) {
165 PrevAttr = CategoryState.StateAttr;
166 CategoryState.StateAttr = LH;
169 PrevAttr = CategoryState.NumericAttr;
170 CategoryState.NumericAttr = LH;
177 S.
Diag(OptionLoc, diag::err_pragma_loop_compatibility)
178 <<
true << PrevAttr->getDiagnosticName(Policy)
179 << LH->getDiagnosticName(Policy);
181 if (CategoryState.StateAttr && CategoryState.NumericAttr &&
182 (Category == Unroll ||
183 CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) {
187 S.
Diag(OptionLoc, diag::err_pragma_loop_compatibility)
189 << CategoryState.StateAttr->getDiagnosticName(Policy)
190 << CategoryState.NumericAttr->getDiagnosticName(Policy);
200 diag::warn_unhandled_ms_attribute_ignored :
201 diag::warn_unknown_attribute_ignored) << A.
getName();
203 case AttributeList::AT_FallThrough:
205 case AttributeList::AT_LoopHint:
211 << A.
getName() << St->getLocStart();
229 return ActOnAttributedStmt(Range.
getBegin(), Attrs,
S);
Defines the clang::ASTContext interface.
SourceLocation getEnd() const
bool CheckLoopHintExpr(Expr *E, SourceLocation Loc)
Defines the SourceManager interface.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
SourceRange getRange() const
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Calls Lexer::getLocForEndOfToken()
SmallVector< SwitchStmt *, 8 > SwitchStack
Describes how types, statements, expressions, and declarations should be printed. ...
const LangOptions & getLangOpts() const
Sema - This implements semantic analysis and AST building for C.
StringRef getName() const
Return the actual identifier string.
static Attr * handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A, SourceRange Range)
Defines the classes clang::DelayedDiagnostic and clang::AccessedEntity.
Wraps an identifier and optional source location for the identifier.
StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs, SourceRange Range)
Stmt attributes - this routine is the top level dispatcher.
unsigned getAttributeSpellingListIndex() const
Get an index into the attribute spelling list defined in Attr.td. This index is used by an attribute ...
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
static void CheckForIncompatibleAttributes(Sema &S, const SmallVectorImpl< const Attr * > &Attrs)
static Attr * ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A, SourceRange Range)
SourceLocation getBegin() const
IdentifierLoc * getArgAsIdent(unsigned Arg) const
sema::FunctionScopeInfo * getCurFunction() const
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
Expr * getArgAsExpr(unsigned Arg) const
IdentifierInfo * getName() const
SourceLocation getLoc() const
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
bool isDeclspecAttribute() const
static Attr * handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A, SourceRange)
AttributeList * getNext() const
A trivial tuple used to represent a source range.
Attr - This represents one attribute.