1 //===--- SemaStmtAttr.cpp - Statement Attribute Handling ------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements stmt-related attribute processing. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Sema/SemaInternal.h" 15 #include "clang/AST/ASTContext.h" 16 #include "clang/Basic/SourceManager.h" 17 #include "clang/Sema/DelayedDiagnostic.h" 18 #include "clang/Sema/Lookup.h" 19 #include "clang/Sema/LoopHint.h" 20 #include "clang/Sema/ScopeInfo.h" 21 #include "llvm/ADT/StringExtras.h" 22 23 using namespace clang; 24 using namespace sema; 25 26 static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A, 27 SourceRange Range) { 28 if (!isa<NullStmt>(St)) { 29 S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target) 30 << St->getLocStart(); 31 if (isa<SwitchCase>(St)) { 32 SourceLocation L = S.getLocForEndOfToken(Range.getEnd()); 33 S.Diag(L, diag::note_fallthrough_insert_semi_fixit) 34 << FixItHint::CreateInsertion(L, ";"); 35 } 36 return nullptr; 37 } 38 if (S.getCurFunction()->SwitchStack.empty()) { 39 S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_outside_switch); 40 return nullptr; 41 } 42 return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context, 43 A.getAttributeSpellingListIndex()); 44 } 45 46 static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A, 47 SourceRange) { 48 if (St->getStmtClass() != Stmt::DoStmtClass && 49 St->getStmtClass() != Stmt::ForStmtClass && 50 St->getStmtClass() != Stmt::CXXForRangeStmtClass && 51 St->getStmtClass() != Stmt::WhileStmtClass) { 52 S.Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop); 53 return nullptr; 54 } 55 56 IdentifierLoc *OptionLoc = A.getArgAsIdent(0); 57 IdentifierInfo *OptionInfo = OptionLoc->Ident; 58 IdentifierLoc *ValueLoc = A.getArgAsIdent(1); 59 IdentifierInfo *ValueInfo = ValueLoc->Ident; 60 Expr *ValueExpr = A.getArgAsExpr(2); 61 62 assert(OptionInfo && "Attribute must have valid option info."); 63 64 LoopHintAttr::OptionType Option = 65 llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getName()) 66 .Case("vectorize", LoopHintAttr::Vectorize) 67 .Case("vectorize_width", LoopHintAttr::VectorizeWidth) 68 .Case("interleave", LoopHintAttr::Interleave) 69 .Case("interleave_count", LoopHintAttr::InterleaveCount) 70 .Default(LoopHintAttr::Vectorize); 71 72 int ValueInt; 73 if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave) { 74 if (!ValueInfo) { 75 S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword) 76 << /*MissingKeyword=*/true << ""; 77 return nullptr; 78 } 79 80 if (ValueInfo->isStr("disable")) 81 ValueInt = 0; 82 else if (ValueInfo->isStr("enable")) 83 ValueInt = 1; 84 else { 85 S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword) 86 << /*MissingKeyword=*/false << ValueInfo; 87 return nullptr; 88 } 89 } else if (Option == LoopHintAttr::VectorizeWidth || 90 Option == LoopHintAttr::InterleaveCount) { 91 // FIXME: We should support template parameters for the loop hint value. 92 // See bug report #19610. 93 llvm::APSInt ValueAPS; 94 if (!ValueExpr || !ValueExpr->isIntegerConstantExpr(ValueAPS, S.Context)) { 95 S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_value) 96 << /*MissingValue=*/true << ""; 97 return nullptr; 98 } 99 100 if ((ValueInt = ValueAPS.getSExtValue()) < 1) { 101 S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_value) 102 << /*MissingValue=*/false << ValueInt; 103 return nullptr; 104 } 105 } else 106 llvm_unreachable("Unknown loop hint option"); 107 108 return LoopHintAttr::CreateImplicit(S.Context, Option, ValueInt, 109 A.getRange()); 110 } 111 112 static void 113 CheckForIncompatibleAttributes(Sema &S, SmallVectorImpl<const Attr *> &Attrs) { 114 int PrevOptionValue[4] = {-1, -1, -1, -1}; 115 int OptionId[4] = {LoopHintAttr::Vectorize, LoopHintAttr::VectorizeWidth, 116 LoopHintAttr::Interleave, LoopHintAttr::InterleaveCount}; 117 118 for (const auto *I : Attrs) { 119 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I); 120 121 // Skip non loop hint attributes 122 if (!LH) 123 continue; 124 125 int State, Value; 126 int Option = LH->getOption(); 127 int ValueInt = LH->getValue(); 128 129 switch (Option) { 130 case LoopHintAttr::Vectorize: 131 case LoopHintAttr::VectorizeWidth: 132 State = 0; 133 Value = 1; 134 break; 135 case LoopHintAttr::Interleave: 136 case LoopHintAttr::InterleaveCount: 137 State = 2; 138 Value = 3; 139 break; 140 } 141 142 SourceLocation ValueLoc = LH->getRange().getEnd(); 143 144 // Compatibility testing is split into two cases. 145 // 1. if the current loop hint sets state (enable/disable) - check against 146 // previous state and value. 147 // 2. if the current loop hint sets a value - check against previous state 148 // and value. 149 150 if (Option == State) { 151 if (PrevOptionValue[State] != -1) { 152 // Cannot specify state twice. 153 int PrevValue = PrevOptionValue[State]; 154 S.Diag(ValueLoc, diag::err_pragma_loop_compatibility) 155 << /*Duplicate=*/true << LoopHintAttr::getOptionName(Option) 156 << LoopHintAttr::getValueName(PrevValue) 157 << LoopHintAttr::getOptionName(Option) 158 << LoopHintAttr::getValueName(Value); 159 } 160 161 if (PrevOptionValue[Value] != -1) { 162 // Compare state with previous width/count. 163 int PrevOption = OptionId[Value]; 164 int PrevValueInt = PrevOptionValue[Value]; 165 if ((ValueInt == 0 && PrevValueInt > 1) || 166 (ValueInt == 1 && PrevValueInt <= 1)) 167 S.Diag(ValueLoc, diag::err_pragma_loop_compatibility) 168 << /*Duplicate=*/false << LoopHintAttr::getOptionName(PrevOption) 169 << PrevValueInt << LoopHintAttr::getOptionName(Option) 170 << LoopHintAttr::getValueName(ValueInt); 171 } 172 } else { 173 if (PrevOptionValue[State] != -1) { 174 // Compare width/count value with previous state. 175 int PrevOption = OptionId[State]; 176 int PrevValueInt = PrevOptionValue[State]; 177 if ((ValueInt > 1 && PrevValueInt == 0) || 178 (ValueInt <= 1 && PrevValueInt == 1)) 179 S.Diag(ValueLoc, diag::err_pragma_loop_compatibility) 180 << /*Duplicate=*/false << LoopHintAttr::getOptionName(PrevOption) 181 << LoopHintAttr::getValueName(PrevValueInt) 182 << LoopHintAttr::getOptionName(Option) << ValueInt; 183 } 184 185 if (PrevOptionValue[Value] != -1) { 186 // Cannot specify a width/count twice. 187 int PrevValueInt = PrevOptionValue[Value]; 188 S.Diag(ValueLoc, diag::err_pragma_loop_compatibility) 189 << /*Duplicate=*/true << LoopHintAttr::getOptionName(Option) 190 << PrevValueInt << LoopHintAttr::getOptionName(Option) << ValueInt; 191 } 192 } 193 194 PrevOptionValue[Option] = ValueInt; 195 } 196 } 197 198 static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A, 199 SourceRange Range) { 200 switch (A.getKind()) { 201 case AttributeList::UnknownAttribute: 202 S.Diag(A.getLoc(), A.isDeclspecAttribute() ? 203 diag::warn_unhandled_ms_attribute_ignored : 204 diag::warn_unknown_attribute_ignored) << A.getName(); 205 return nullptr; 206 case AttributeList::AT_FallThrough: 207 return handleFallThroughAttr(S, St, A, Range); 208 case AttributeList::AT_LoopHint: 209 return handleLoopHintAttr(S, St, A, Range); 210 default: 211 // if we're here, then we parsed a known attribute, but didn't recognize 212 // it as a statement attribute => it is declaration attribute 213 S.Diag(A.getRange().getBegin(), diag::err_attribute_invalid_on_stmt) 214 << A.getName() << St->getLocStart(); 215 return nullptr; 216 } 217 } 218 219 StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList, 220 SourceRange Range) { 221 SmallVector<const Attr*, 8> Attrs; 222 for (const AttributeList* l = AttrList; l; l = l->getNext()) { 223 if (Attr *a = ProcessStmtAttribute(*this, S, *l, Range)) 224 Attrs.push_back(a); 225 } 226 227 CheckForIncompatibleAttributes(*this, Attrs); 228 229 if (Attrs.empty()) 230 return S; 231 232 return ActOnAttributedStmt(Range.getBegin(), Attrs, S); 233 } 234