19 #include "llvm/ADT/StringExtras.h" 21 using namespace clang;
27 if (!isa<NullStmt>(St)) {
30 if (isa<SwitchCase>(St)) {
32 S.
Diag(L, diag::note_fallthrough_insert_semi_fixit)
38 if (FnScope->SwitchStack.empty()) {
49 FnScope->setHasFallthroughStmt();
56 S.
Diag(A.
getLoc(), diag::err_attribute_too_few_arguments) << A << 1;
60 std::vector<StringRef> DiagnosticIdentifiers;
61 for (
unsigned I = 0, E = A.
getNumArgs(); I != E; ++I) {
69 DiagnosticIdentifiers.push_back(RuleName);
72 return ::new (S.
Context) SuppressAttr(
73 S.
Context, A, DiagnosticIdentifiers.data(), DiagnosticIdentifiers.size());
83 StringRef PragmaName =
84 llvm::StringSwitch<StringRef>(PragmaNameLoc->
Ident->
getName())
85 .Cases(
"unroll",
"nounroll",
"unroll_and_jam",
"nounroll_and_jam",
93 std::string
Pragma =
"#pragma " + std::string(PragmaName);
94 S.
Diag(St->
getBeginLoc(), diag::err_pragma_loop_precedes_nonloop) << Pragma;
98 LoopHintAttr::OptionType Option;
99 LoopHintAttr::LoopHintState
State;
101 auto SetHints = [&Option, &
State](LoopHintAttr::OptionType O,
102 LoopHintAttr::LoopHintState S) {
107 if (PragmaName ==
"nounroll") {
108 SetHints(LoopHintAttr::Unroll, LoopHintAttr::Disable);
109 }
else if (PragmaName ==
"unroll") {
112 SetHints(LoopHintAttr::UnrollCount, LoopHintAttr::Numeric);
114 SetHints(LoopHintAttr::Unroll, LoopHintAttr::Enable);
115 }
else if (PragmaName ==
"nounroll_and_jam") {
116 SetHints(LoopHintAttr::UnrollAndJam, LoopHintAttr::Disable);
117 }
else if (PragmaName ==
"unroll_and_jam") {
120 SetHints(LoopHintAttr::UnrollAndJamCount, LoopHintAttr::Numeric);
122 SetHints(LoopHintAttr::UnrollAndJam, LoopHintAttr::Enable);
125 assert(OptionLoc && OptionLoc->
Ident &&
126 "Attribute must have valid option info.");
127 Option = llvm::StringSwitch<LoopHintAttr::OptionType>(
129 .Case(
"vectorize", LoopHintAttr::Vectorize)
130 .Case(
"vectorize_width", LoopHintAttr::VectorizeWidth)
131 .Case(
"interleave", LoopHintAttr::Interleave)
132 .Case(
"vectorize_predicate", LoopHintAttr::VectorizePredicate)
133 .Case(
"interleave_count", LoopHintAttr::InterleaveCount)
134 .Case(
"unroll", LoopHintAttr::Unroll)
135 .Case(
"unroll_count", LoopHintAttr::UnrollCount)
136 .Case(
"pipeline", LoopHintAttr::PipelineDisabled)
137 .Case(
"pipeline_initiation_interval",
138 LoopHintAttr::PipelineInitiationInterval)
139 .Case(
"distribute", LoopHintAttr::Distribute)
140 .Default(LoopHintAttr::Vectorize);
141 if (Option == LoopHintAttr::VectorizeWidth ||
142 Option == LoopHintAttr::InterleaveCount ||
143 Option == LoopHintAttr::UnrollCount ||
144 Option == LoopHintAttr::PipelineInitiationInterval) {
145 assert(ValueExpr &&
"Attribute must have a valid value expression.");
148 State = LoopHintAttr::Numeric;
149 }
else if (Option == LoopHintAttr::Vectorize ||
150 Option == LoopHintAttr::Interleave ||
151 Option == LoopHintAttr::VectorizePredicate ||
152 Option == LoopHintAttr::Unroll ||
153 Option == LoopHintAttr::Distribute ||
154 Option == LoopHintAttr::PipelineDisabled) {
155 assert(StateLoc && StateLoc->
Ident &&
"Loop hint must have an argument");
157 State = LoopHintAttr::Disable;
158 else if (StateLoc->
Ident->
isStr(
"assume_safety"))
159 State = LoopHintAttr::AssumeSafety;
161 State = LoopHintAttr::Full;
163 State = LoopHintAttr::Enable;
165 llvm_unreachable(
"bad loop hint argument");
167 llvm_unreachable(
"bad loop hint");
170 return LoopHintAttr::CreateImplicit(S.
Context, Option, State, ValueExpr, A);
186 const LoopHintAttr *StateAttr;
187 const LoopHintAttr *NumericAttr;
188 } HintAttrs[] = {{
nullptr,
nullptr}, {
nullptr,
nullptr}, {
nullptr,
nullptr},
189 {
nullptr,
nullptr}, {
nullptr,
nullptr}, {
nullptr,
nullptr},
192 for (
const auto *I : Attrs) {
193 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);
199 LoopHintAttr::OptionType Option = LH->getOption();
210 case LoopHintAttr::Vectorize:
211 case LoopHintAttr::VectorizeWidth:
212 Category = Vectorize;
214 case LoopHintAttr::Interleave:
215 case LoopHintAttr::InterleaveCount:
216 Category = Interleave;
218 case LoopHintAttr::Unroll:
219 case LoopHintAttr::UnrollCount:
222 case LoopHintAttr::UnrollAndJam:
223 case LoopHintAttr::UnrollAndJamCount:
224 Category = UnrollAndJam;
226 case LoopHintAttr::Distribute:
228 Category = Distribute;
230 case LoopHintAttr::PipelineDisabled:
231 case LoopHintAttr::PipelineInitiationInterval:
234 case LoopHintAttr::VectorizePredicate:
235 Category = VectorizePredicate;
239 assert(Category <
sizeof(HintAttrs) /
sizeof(HintAttrs[0]));
240 auto &CategoryState = HintAttrs[
Category];
241 const LoopHintAttr *PrevAttr;
242 if (Option == LoopHintAttr::Vectorize ||
243 Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll ||
244 Option == LoopHintAttr::UnrollAndJam ||
245 Option == LoopHintAttr::VectorizePredicate ||
246 Option == LoopHintAttr::PipelineDisabled ||
247 Option == LoopHintAttr::Distribute) {
249 PrevAttr = CategoryState.StateAttr;
250 CategoryState.StateAttr = LH;
253 PrevAttr = CategoryState.NumericAttr;
254 CategoryState.NumericAttr = LH;
261 S.
Diag(OptionLoc, diag::err_pragma_loop_compatibility)
262 <<
true << PrevAttr->getDiagnosticName(Policy)
263 << LH->getDiagnosticName(Policy);
265 if (CategoryState.StateAttr && CategoryState.NumericAttr &&
266 (Category == Unroll || Category == UnrollAndJam ||
267 CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) {
272 S.
Diag(OptionLoc, diag::err_pragma_loop_compatibility)
274 << CategoryState.StateAttr->getDiagnosticName(Policy)
275 << CategoryState.NumericAttr->getDiagnosticName(Policy);
291 S.
Diag(A.
getLoc(), diag::err_attribute_too_many_arguments) << A << 1;
295 unsigned UnrollFactor = 0;
302 S.
Diag(A.
getLoc(), diag::err_attribute_argument_type)
307 int Val = ArgVal.getSExtValue();
311 diag::err_attribute_requires_positive_integer)
318 return OpenCLUnrollHintAttr::CreateImplicit(S.
Context, UnrollFactor);
326 ? (unsigned)diag::warn_unhandled_ms_attribute_ignored
327 : (
unsigned)diag::warn_unknown_attribute_ignored)
330 case ParsedAttr::AT_FallThrough:
332 case ParsedAttr::AT_LoopHint:
334 case ParsedAttr::AT_OpenCLUnrollHint:
336 case ParsedAttr::AT_Suppress:
361 return ActOnAttributedStmt(Range.
getBegin(), Attrs, S);
Defines the clang::ASTContext interface.
bool CheckLoopHintExpr(Expr *E, SourceLocation Loc)
SourceLocation getLoc() 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)
Describes how types, statements, expressions, and declarations should be printed. ...
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.
AttributeCommonInfo::Kind getKind() const
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.
bool isDeclspecAttribute() const
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
bool isCXX11Attribute() 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...
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...
const IdentifierInfo * getScopeName() const
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.