19 #include "llvm/ADT/StringExtras.h" 21 using namespace clang;
28 if (!isa<NullStmt>(St)) {
31 if (isa<SwitchCase>(St)) {
33 S.
Diag(L, diag::note_fallthrough_insert_semi_fixit)
39 if (FnScope->SwitchStack.empty()) {
50 FnScope->setHasFallthroughStmt();
57 S.
Diag(A.
getLoc(), diag::err_attribute_too_few_arguments) << A << 1;
61 std::vector<StringRef> DiagnosticIdentifiers;
62 for (
unsigned I = 0, E = A.
getNumArgs(); I != E; ++I) {
70 DiagnosticIdentifiers.push_back(RuleName);
73 return ::new (S.
Context) SuppressAttr(
85 StringRef PragmaName =
86 llvm::StringSwitch<StringRef>(PragmaNameLoc->
Ident->
getName())
87 .Cases(
"unroll",
"nounroll",
"unroll_and_jam",
"nounroll_and_jam",
95 std::string
Pragma =
"#pragma " + std::string(PragmaName);
96 S.
Diag(St->
getBeginLoc(), diag::err_pragma_loop_precedes_nonloop) << Pragma;
100 LoopHintAttr::Spelling Spelling =
102 LoopHintAttr::OptionType Option;
103 LoopHintAttr::LoopHintState
State;
105 auto SetHints = [&Option, &
State](LoopHintAttr::OptionType O,
106 LoopHintAttr::LoopHintState S) {
111 if (PragmaName ==
"nounroll") {
112 SetHints(LoopHintAttr::Unroll, LoopHintAttr::Disable);
113 }
else if (PragmaName ==
"unroll") {
116 SetHints(LoopHintAttr::UnrollCount, LoopHintAttr::Numeric);
118 SetHints(LoopHintAttr::Unroll, LoopHintAttr::Enable);
119 }
else if (PragmaName ==
"nounroll_and_jam") {
120 SetHints(LoopHintAttr::UnrollAndJam, LoopHintAttr::Disable);
121 }
else if (PragmaName ==
"unroll_and_jam") {
124 SetHints(LoopHintAttr::UnrollAndJamCount, LoopHintAttr::Numeric);
126 SetHints(LoopHintAttr::UnrollAndJam, LoopHintAttr::Enable);
129 assert(OptionLoc && OptionLoc->
Ident &&
130 "Attribute must have valid option info.");
131 Option = llvm::StringSwitch<LoopHintAttr::OptionType>(
133 .Case(
"vectorize", LoopHintAttr::Vectorize)
134 .Case(
"vectorize_width", LoopHintAttr::VectorizeWidth)
135 .Case(
"interleave", LoopHintAttr::Interleave)
136 .Case(
"interleave_count", LoopHintAttr::InterleaveCount)
137 .Case(
"unroll", LoopHintAttr::Unroll)
138 .Case(
"unroll_count", LoopHintAttr::UnrollCount)
139 .Case(
"pipeline", LoopHintAttr::PipelineDisabled)
140 .Case(
"pipeline_initiation_interval",
141 LoopHintAttr::PipelineInitiationInterval)
142 .Case(
"distribute", LoopHintAttr::Distribute)
143 .Default(LoopHintAttr::Vectorize);
144 if (Option == LoopHintAttr::VectorizeWidth ||
145 Option == LoopHintAttr::InterleaveCount ||
146 Option == LoopHintAttr::UnrollCount ||
147 Option == LoopHintAttr::PipelineInitiationInterval) {
148 assert(ValueExpr &&
"Attribute must have a valid value expression.");
151 State = LoopHintAttr::Numeric;
152 }
else if (Option == LoopHintAttr::Vectorize ||
153 Option == LoopHintAttr::Interleave ||
154 Option == LoopHintAttr::Unroll ||
155 Option == LoopHintAttr::Distribute ||
156 Option == LoopHintAttr::PipelineDisabled) {
157 assert(StateLoc && StateLoc->
Ident &&
"Loop hint must have an argument");
159 State = LoopHintAttr::Disable;
160 else if (StateLoc->
Ident->
isStr(
"assume_safety"))
161 State = LoopHintAttr::AssumeSafety;
163 State = LoopHintAttr::Full;
165 State = LoopHintAttr::Enable;
167 llvm_unreachable(
"bad loop hint argument");
169 llvm_unreachable(
"bad loop hint");
172 return LoopHintAttr::CreateImplicit(S.
Context, Spelling, Option, State,
189 const LoopHintAttr *StateAttr;
190 const LoopHintAttr *NumericAttr;
191 } HintAttrs[] = {{
nullptr,
nullptr}, {
nullptr,
nullptr}, {
nullptr,
nullptr},
192 {
nullptr,
nullptr}, {
nullptr,
nullptr}, {
nullptr,
nullptr}};
194 for (
const auto *I : Attrs) {
195 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);
201 LoopHintAttr::OptionType Option = LH->getOption();
211 case LoopHintAttr::Vectorize:
212 case LoopHintAttr::VectorizeWidth:
213 Category = Vectorize;
215 case LoopHintAttr::Interleave:
216 case LoopHintAttr::InterleaveCount:
217 Category = Interleave;
219 case LoopHintAttr::Unroll:
220 case LoopHintAttr::UnrollCount:
223 case LoopHintAttr::UnrollAndJam:
224 case LoopHintAttr::UnrollAndJamCount:
225 Category = UnrollAndJam;
227 case LoopHintAttr::Distribute:
229 Category = Distribute;
231 case LoopHintAttr::PipelineDisabled:
232 case LoopHintAttr::PipelineInitiationInterval:
237 assert(Category <
sizeof(HintAttrs) /
sizeof(HintAttrs[0]));
238 auto &CategoryState = HintAttrs[
Category];
239 const LoopHintAttr *PrevAttr;
240 if (Option == LoopHintAttr::Vectorize ||
241 Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll ||
242 Option == LoopHintAttr::UnrollAndJam ||
243 Option == LoopHintAttr::PipelineDisabled ||
244 Option == LoopHintAttr::Distribute) {
246 PrevAttr = CategoryState.StateAttr;
247 CategoryState.StateAttr = LH;
250 PrevAttr = CategoryState.NumericAttr;
251 CategoryState.NumericAttr = LH;
258 S.
Diag(OptionLoc, diag::err_pragma_loop_compatibility)
259 <<
true << PrevAttr->getDiagnosticName(Policy)
260 << LH->getDiagnosticName(Policy);
262 if (CategoryState.StateAttr && CategoryState.NumericAttr &&
263 (Category == Unroll || Category == UnrollAndJam ||
264 CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) {
269 S.
Diag(OptionLoc, diag::err_pragma_loop_compatibility)
271 << CategoryState.StateAttr->getDiagnosticName(Policy)
272 << CategoryState.NumericAttr->getDiagnosticName(Policy);
288 S.
Diag(A.
getLoc(), diag::err_attribute_too_many_arguments) << A << 1;
292 unsigned UnrollFactor = 0;
296 llvm::APSInt ArgVal(32);
299 S.
Diag(A.
getLoc(), diag::err_attribute_argument_type)
304 int Val = ArgVal.getSExtValue();
308 diag::err_attribute_requires_positive_integer)
315 return OpenCLUnrollHintAttr::CreateImplicit(S.
Context, UnrollFactor);
323 ? (unsigned)diag::warn_unhandled_ms_attribute_ignored
324 : (
unsigned)diag::warn_unknown_attribute_ignored)
327 case ParsedAttr::AT_FallThrough:
329 case ParsedAttr::AT_LoopHint:
331 case ParsedAttr::AT_OpenCLUnrollHint:
333 case ParsedAttr::AT_Suppress:
358 return ActOnAttributedStmt(Range.
getBegin(), Attrs, S);
Defines the clang::ASTContext interface.
const char * getSpelling() const
bool CheckLoopHintExpr(Expr *E, SourceLocation Loc)
bool isDeclspecAttribute() const
static void CheckForIncompatibleAttributes(Sema &S, const SmallVectorImpl< const Attr *> &Attrs)
Stmt - This represents one statement.
Defines the SourceManager interface.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Expr * getArgAsExpr(unsigned Arg) const
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Calls Lexer::getLocForEndOfToken()
static Attr * handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
bool isCXX11Attribute() const
Describes how types, statements, expressions, and declarations should be printed. ...
unsigned getAttributeSpellingListIndex() const
Get an index into the attribute spelling list defined in Attr.td.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
SourceLocation getBeginLoc() const LLVM_READONLY
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
const LangOptions & getLangOpts() const
Sema - This implements semantic analysis and AST building for C.
static Attr * handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
This represents one expression.
Defines the classes clang::DelayedDiagnostic and clang::AccessedEntity.
SourceLocation getEnd() const
Wraps an identifier and optional source location for the identifier.
static Attr * ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
ActionResult - This structure is used while parsing/acting on expressions, stmts, etc...
Encodes a location in the source.
ParsedAttr - Represents a syntactic attribute.
SourceRange getRange() const
StringRef getName() const
Return the actual identifier string.
Dataflow Directional Tag Classes.
StmtClass getStmtClass() const
SourceLocation getLoc() const
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...
IdentifierInfo * getName() 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.
StmtResult ProcessStmtAttributes(Stmt *Stmt, const ParsedAttributesView &Attrs, SourceRange Range)
Stmt attributes - this routine is the top level dispatcher.
sema::FunctionScopeInfo * getCurFunction() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
static Attr * handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
bool checkStringLiteralArgumentAttr(const ParsedAttr &Attr, unsigned ArgNum, StringRef &Str, SourceLocation *ArgLocation=nullptr)
Check if the argument ArgNum of Attr is a ASCII string literal.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
IdentifierLoc * getArgAsIdent(unsigned Arg) const
static Attr * handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange)
Attr - This represents one attribute.
IdentifierInfo * getScopeName() const