21 #include "llvm/ADT/StringExtras.h"
23 using namespace clang;
30 if (!isa<NullStmt>(St)) {
33 if (isa<SwitchCase>(St)) {
35 S.
Diag(L, diag::note_fallthrough_insert_semi_fixit)
41 if (FnScope->SwitchStack.empty()) {
52 FnScope->setHasFallthroughStmt();
63 bool PragmaUnroll = PragmaNameLoc->
Ident->
getName() ==
"unroll";
64 bool PragmaNoUnroll = PragmaNameLoc->
Ident->
getName() ==
"nounroll";
65 if (St->getStmtClass() != Stmt::DoStmtClass &&
66 St->getStmtClass() != Stmt::ForStmtClass &&
67 St->getStmtClass() != Stmt::CXXForRangeStmtClass &&
68 St->getStmtClass() != Stmt::WhileStmtClass) {
70 llvm::StringSwitch<const char *>(PragmaNameLoc->
Ident->
getName())
71 .Case(
"unroll",
"#pragma unroll")
72 .Case(
"nounroll",
"#pragma nounroll")
73 .Default(
"#pragma clang loop");
74 S.
Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop) << Pragma;
78 LoopHintAttr::Spelling Spelling;
79 LoopHintAttr::OptionType Option;
80 LoopHintAttr::LoopHintState
State;
83 Spelling = LoopHintAttr::Pragma_nounroll;
84 Option = LoopHintAttr::Unroll;
85 State = LoopHintAttr::Disable;
86 }
else if (PragmaUnroll) {
87 Spelling = LoopHintAttr::Pragma_unroll;
90 Option = LoopHintAttr::UnrollCount;
91 State = LoopHintAttr::Numeric;
94 Option = LoopHintAttr::Unroll;
95 State = LoopHintAttr::Enable;
99 Spelling = LoopHintAttr::Pragma_clang_loop;
100 assert(OptionLoc && OptionLoc->
Ident &&
101 "Attribute must have valid option info.");
102 Option = llvm::StringSwitch<LoopHintAttr::OptionType>(
104 .Case(
"vectorize", LoopHintAttr::Vectorize)
105 .Case(
"vectorize_width", LoopHintAttr::VectorizeWidth)
106 .Case(
"interleave", LoopHintAttr::Interleave)
107 .Case(
"interleave_count", LoopHintAttr::InterleaveCount)
108 .Case(
"unroll", LoopHintAttr::Unroll)
109 .Case(
"unroll_count", LoopHintAttr::UnrollCount)
110 .Case(
"distribute", LoopHintAttr::Distribute)
111 .Default(LoopHintAttr::Vectorize);
112 if (Option == LoopHintAttr::VectorizeWidth ||
113 Option == LoopHintAttr::InterleaveCount ||
114 Option == LoopHintAttr::UnrollCount) {
115 assert(ValueExpr &&
"Attribute must have a valid value expression.");
118 State = LoopHintAttr::Numeric;
119 }
else if (Option == LoopHintAttr::Vectorize ||
120 Option == LoopHintAttr::Interleave ||
121 Option == LoopHintAttr::Unroll ||
122 Option == LoopHintAttr::Distribute) {
123 assert(StateLoc && StateLoc->
Ident &&
"Loop hint must have an argument");
125 State = LoopHintAttr::Disable;
126 else if (StateLoc->
Ident->
isStr(
"assume_safety"))
127 State = LoopHintAttr::AssumeSafety;
129 State = LoopHintAttr::Full;
131 State = LoopHintAttr::Enable;
133 llvm_unreachable(
"bad loop hint argument");
135 llvm_unreachable(
"bad loop hint");
138 return LoopHintAttr::CreateImplicit(S.
Context, Spelling, Option, State,
154 const LoopHintAttr *StateAttr;
155 const LoopHintAttr *NumericAttr;
156 } HintAttrs[] = {{
nullptr,
nullptr},
161 for (
const auto *
I : Attrs) {
162 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(
I);
168 LoopHintAttr::OptionType Option = LH->getOption();
169 enum { Vectorize, Interleave, Unroll, Distribute }
Category;
171 case LoopHintAttr::Vectorize:
172 case LoopHintAttr::VectorizeWidth:
175 case LoopHintAttr::Interleave:
176 case LoopHintAttr::InterleaveCount:
179 case LoopHintAttr::Unroll:
180 case LoopHintAttr::UnrollCount:
183 case LoopHintAttr::Distribute:
189 auto &CategoryState = HintAttrs[
Category];
190 const LoopHintAttr *PrevAttr;
191 if (Option == LoopHintAttr::Vectorize ||
192 Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll ||
193 Option == LoopHintAttr::Distribute) {
195 PrevAttr = CategoryState.StateAttr;
196 CategoryState.StateAttr = LH;
199 PrevAttr = CategoryState.NumericAttr;
200 CategoryState.NumericAttr = LH;
207 S.
Diag(OptionLoc, diag::err_pragma_loop_compatibility)
208 <<
true << PrevAttr->getDiagnosticName(Policy)
209 << LH->getDiagnosticName(Policy);
211 if (CategoryState.StateAttr && CategoryState.NumericAttr &&
213 CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) {
218 S.
Diag(OptionLoc, diag::err_pragma_loop_compatibility)
220 << CategoryState.StateAttr->getDiagnosticName(Policy)
221 << CategoryState.NumericAttr->getDiagnosticName(Policy);
233 S.
Diag(A.
getLoc(), diag::err_attribute_requires_opencl_version)
246 unsigned UnrollFactor = 0;
250 llvm::APSInt ArgVal(32);
253 S.
Diag(A.
getLoc(), diag::err_attribute_argument_type)
258 int Val = ArgVal.getSExtValue();
262 diag::err_attribute_requires_positive_integer)
269 return OpenCLUnrollHintAttr::CreateImplicit(S.
Context, UnrollFactor);
277 diag::warn_unhandled_ms_attribute_ignored :
278 diag::warn_unknown_attribute_ignored) << A.
getName();
280 case AttributeList::AT_FallThrough:
282 case AttributeList::AT_LoopHint:
284 case AttributeList::AT_OpenCLUnrollHint:
290 << A.
getName() << St->getLocStart();
308 return ActOnAttributedStmt(Range.
getBegin(), Attrs,
S);
Defines the clang::ASTContext interface.
SourceLocation getEnd() const
bool CheckLoopHintExpr(Expr *E, SourceLocation Loc)
const LangOptions & getLangOpts() const
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()
Describes how types, statements, expressions, and declarations should be printed. ...
const LangOptions & getLangOpts() const
detail::InMemoryDirectory::const_iterator I
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Sema - This implements semantic analysis and AST building for C.
Expr - This represents one expression.
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.
class LLVM_ALIGNAS(8) TemplateSpecializationType unsigned NumArgs
Represents a type template specialization; the template must be a class template, a type alias templa...
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.
const char * getSpelling() const
ActionResult - This structure is used while parsing/acting on expressions, stmts, etc...
Encodes a location in the source.
static Attr * handleOpenCLUnrollHint(Sema &S, Stmt *St, const AttributeList &A, SourceRange Range)
static void CheckForIncompatibleAttributes(Sema &S, const SmallVectorImpl< const Attr * > &Attrs)
bool isIntegerConstantExpr(llvm::APSInt &Result, const ASTContext &Ctx, SourceLocation *Loc=nullptr, bool isEvaluated=true) const
isIntegerConstantExpr - Return true if this expression is a valid integer constant expression...
static Attr * ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A, SourceRange Range)
SourceLocation getBegin() const
IdentifierInfo * getScopeName() 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
detail::InMemoryDirectory::const_iterator E
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 isCXX11Attribute() const
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.
AttributeList - Represents a syntactic attribute.