1 //===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===// 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 semantic analysis for non-trivial attributes and 11 // pragmas. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "clang/AST/ASTConsumer.h" 16 #include "clang/AST/Attr.h" 17 #include "clang/AST/Expr.h" 18 #include "clang/Basic/TargetInfo.h" 19 #include "clang/Lex/Preprocessor.h" 20 #include "clang/Sema/Lookup.h" 21 #include "clang/Sema/SemaInternal.h" 22 using namespace clang; 23 24 //===----------------------------------------------------------------------===// 25 // Pragma 'pack' and 'options align' 26 //===----------------------------------------------------------------------===// 27 28 Sema::PragmaStackSentinelRAII::PragmaStackSentinelRAII(Sema &S, 29 StringRef SlotLabel, 30 bool ShouldAct) 31 : S(S), SlotLabel(SlotLabel), ShouldAct(ShouldAct) { 32 if (ShouldAct) { 33 S.VtorDispStack.SentinelAction(PSK_Push, SlotLabel); 34 S.DataSegStack.SentinelAction(PSK_Push, SlotLabel); 35 S.BSSSegStack.SentinelAction(PSK_Push, SlotLabel); 36 S.ConstSegStack.SentinelAction(PSK_Push, SlotLabel); 37 S.CodeSegStack.SentinelAction(PSK_Push, SlotLabel); 38 } 39 } 40 41 Sema::PragmaStackSentinelRAII::~PragmaStackSentinelRAII() { 42 if (ShouldAct) { 43 S.VtorDispStack.SentinelAction(PSK_Pop, SlotLabel); 44 S.DataSegStack.SentinelAction(PSK_Pop, SlotLabel); 45 S.BSSSegStack.SentinelAction(PSK_Pop, SlotLabel); 46 S.ConstSegStack.SentinelAction(PSK_Pop, SlotLabel); 47 S.CodeSegStack.SentinelAction(PSK_Pop, SlotLabel); 48 } 49 } 50 51 void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) { 52 // If there is no pack value, we don't need any attributes. 53 if (!PackStack.CurrentValue) 54 return; 55 56 // Otherwise, check to see if we need a max field alignment attribute. 57 if (unsigned Alignment = PackStack.CurrentValue) { 58 if (Alignment == Sema::kMac68kAlignmentSentinel) 59 RD->addAttr(AlignMac68kAttr::CreateImplicit(Context)); 60 else 61 RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit(Context, 62 Alignment * 8)); 63 } 64 } 65 66 void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) { 67 if (MSStructPragmaOn) 68 RD->addAttr(MSStructAttr::CreateImplicit(Context)); 69 70 // FIXME: We should merge AddAlignmentAttributesForRecord with 71 // AddMsStructLayoutForRecord into AddPragmaAttributesForRecord, which takes 72 // all active pragmas and applies them as attributes to class definitions. 73 if (VtorDispStack.CurrentValue != getLangOpts().VtorDispMode) 74 RD->addAttr( 75 MSVtorDispAttr::CreateImplicit(Context, VtorDispStack.CurrentValue)); 76 } 77 78 void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, 79 SourceLocation PragmaLoc) { 80 PragmaMsStackAction Action = Sema::PSK_Reset; 81 unsigned Alignment = 0; 82 switch (Kind) { 83 // For all targets we support native and natural are the same. 84 // 85 // FIXME: This is not true on Darwin/PPC. 86 case POAK_Native: 87 case POAK_Power: 88 case POAK_Natural: 89 Action = Sema::PSK_Push_Set; 90 Alignment = 0; 91 break; 92 93 // Note that '#pragma options align=packed' is not equivalent to attribute 94 // packed, it has a different precedence relative to attribute aligned. 95 case POAK_Packed: 96 Action = Sema::PSK_Push_Set; 97 Alignment = 1; 98 break; 99 100 case POAK_Mac68k: 101 // Check if the target supports this. 102 if (!this->Context.getTargetInfo().hasAlignMac68kSupport()) { 103 Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported); 104 return; 105 } 106 Action = Sema::PSK_Push_Set; 107 Alignment = Sema::kMac68kAlignmentSentinel; 108 break; 109 110 case POAK_Reset: 111 // Reset just pops the top of the stack, or resets the current alignment to 112 // default. 113 Action = Sema::PSK_Pop; 114 if (PackStack.Stack.empty()) { 115 if (PackStack.CurrentValue) { 116 Action = Sema::PSK_Reset; 117 } else { 118 Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed) 119 << "stack empty"; 120 return; 121 } 122 } 123 break; 124 } 125 126 PackStack.Act(PragmaLoc, Action, StringRef(), Alignment); 127 } 128 129 void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action, 130 StringRef SlotLabel, Expr *alignment) { 131 Expr *Alignment = static_cast<Expr *>(alignment); 132 133 // If specified then alignment must be a "small" power of two. 134 unsigned AlignmentVal = 0; 135 if (Alignment) { 136 llvm::APSInt Val; 137 138 // pack(0) is like pack(), which just works out since that is what 139 // we use 0 for in PackAttr. 140 if (Alignment->isTypeDependent() || 141 Alignment->isValueDependent() || 142 !Alignment->isIntegerConstantExpr(Val, Context) || 143 !(Val == 0 || Val.isPowerOf2()) || 144 Val.getZExtValue() > 16) { 145 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); 146 return; // Ignore 147 } 148 149 AlignmentVal = (unsigned) Val.getZExtValue(); 150 } 151 if (Action == Sema::PSK_Show) { 152 // Show the current alignment, making sure to show the right value 153 // for the default. 154 // FIXME: This should come from the target. 155 AlignmentVal = PackStack.CurrentValue; 156 if (AlignmentVal == 0) 157 AlignmentVal = 8; 158 if (AlignmentVal == Sema::kMac68kAlignmentSentinel) 159 Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k"; 160 else 161 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; 162 } 163 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack: 164 // "#pragma pack(pop, identifier, n) is undefined" 165 if (Action & Sema::PSK_Pop) { 166 if (Alignment && !SlotLabel.empty()) 167 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment); 168 if (PackStack.Stack.empty()) 169 Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "pack" << "stack empty"; 170 } 171 172 PackStack.Act(PragmaLoc, Action, SlotLabel, AlignmentVal); 173 } 174 175 void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) { 176 MSStructPragmaOn = (Kind == PMSST_ON); 177 } 178 179 void Sema::ActOnPragmaMSComment(SourceLocation CommentLoc, 180 PragmaMSCommentKind Kind, StringRef Arg) { 181 auto *PCD = PragmaCommentDecl::Create( 182 Context, Context.getTranslationUnitDecl(), CommentLoc, Kind, Arg); 183 Context.getTranslationUnitDecl()->addDecl(PCD); 184 Consumer.HandleTopLevelDecl(DeclGroupRef(PCD)); 185 } 186 187 void Sema::ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name, 188 StringRef Value) { 189 auto *PDMD = PragmaDetectMismatchDecl::Create( 190 Context, Context.getTranslationUnitDecl(), Loc, Name, Value); 191 Context.getTranslationUnitDecl()->addDecl(PDMD); 192 Consumer.HandleTopLevelDecl(DeclGroupRef(PDMD)); 193 } 194 195 void Sema::ActOnPragmaMSPointersToMembers( 196 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod, 197 SourceLocation PragmaLoc) { 198 MSPointerToMemberRepresentationMethod = RepresentationMethod; 199 ImplicitMSInheritanceAttrLoc = PragmaLoc; 200 } 201 202 void Sema::ActOnPragmaMSVtorDisp(PragmaMsStackAction Action, 203 SourceLocation PragmaLoc, 204 MSVtorDispAttr::Mode Mode) { 205 if (Action & PSK_Pop && VtorDispStack.Stack.empty()) 206 Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "vtordisp" 207 << "stack empty"; 208 VtorDispStack.Act(PragmaLoc, Action, StringRef(), Mode); 209 } 210 211 template<typename ValueType> 212 void Sema::PragmaStack<ValueType>::Act(SourceLocation PragmaLocation, 213 PragmaMsStackAction Action, 214 llvm::StringRef StackSlotLabel, 215 ValueType Value) { 216 if (Action == PSK_Reset) { 217 CurrentValue = DefaultValue; 218 CurrentPragmaLocation = PragmaLocation; 219 return; 220 } 221 if (Action & PSK_Push) 222 Stack.push_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation)); 223 else if (Action & PSK_Pop) { 224 if (!StackSlotLabel.empty()) { 225 // If we've got a label, try to find it and jump there. 226 auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) { 227 return x.StackSlotLabel == StackSlotLabel; 228 }); 229 // If we found the label so pop from there. 230 if (I != Stack.rend()) { 231 CurrentValue = I->Value; 232 CurrentPragmaLocation = I->PragmaLocation; 233 Stack.erase(std::prev(I.base()), Stack.end()); 234 } 235 } else if (!Stack.empty()) { 236 // We don't have a label, just pop the last entry. 237 CurrentValue = Stack.back().Value; 238 CurrentPragmaLocation = Stack.back().PragmaLocation; 239 Stack.pop_back(); 240 } 241 } 242 if (Action & PSK_Set) { 243 CurrentValue = Value; 244 CurrentPragmaLocation = PragmaLocation; 245 } 246 } 247 248 bool Sema::UnifySection(StringRef SectionName, 249 int SectionFlags, 250 DeclaratorDecl *Decl) { 251 auto Section = Context.SectionInfos.find(SectionName); 252 if (Section == Context.SectionInfos.end()) { 253 Context.SectionInfos[SectionName] = 254 ASTContext::SectionInfo(Decl, SourceLocation(), SectionFlags); 255 return false; 256 } 257 // A pre-declared section takes precedence w/o diagnostic. 258 if (Section->second.SectionFlags == SectionFlags || 259 !(Section->second.SectionFlags & ASTContext::PSF_Implicit)) 260 return false; 261 auto OtherDecl = Section->second.Decl; 262 Diag(Decl->getLocation(), diag::err_section_conflict) 263 << Decl << OtherDecl; 264 Diag(OtherDecl->getLocation(), diag::note_declared_at) 265 << OtherDecl->getName(); 266 if (auto A = Decl->getAttr<SectionAttr>()) 267 if (A->isImplicit()) 268 Diag(A->getLocation(), diag::note_pragma_entered_here); 269 if (auto A = OtherDecl->getAttr<SectionAttr>()) 270 if (A->isImplicit()) 271 Diag(A->getLocation(), diag::note_pragma_entered_here); 272 return true; 273 } 274 275 bool Sema::UnifySection(StringRef SectionName, 276 int SectionFlags, 277 SourceLocation PragmaSectionLocation) { 278 auto Section = Context.SectionInfos.find(SectionName); 279 if (Section != Context.SectionInfos.end()) { 280 if (Section->second.SectionFlags == SectionFlags) 281 return false; 282 if (!(Section->second.SectionFlags & ASTContext::PSF_Implicit)) { 283 Diag(PragmaSectionLocation, diag::err_section_conflict) 284 << "this" << "a prior #pragma section"; 285 Diag(Section->second.PragmaSectionLocation, 286 diag::note_pragma_entered_here); 287 return true; 288 } 289 } 290 Context.SectionInfos[SectionName] = 291 ASTContext::SectionInfo(nullptr, PragmaSectionLocation, SectionFlags); 292 return false; 293 } 294 295 /// \brief Called on well formed \#pragma bss_seg(). 296 void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation, 297 PragmaMsStackAction Action, 298 llvm::StringRef StackSlotLabel, 299 StringLiteral *SegmentName, 300 llvm::StringRef PragmaName) { 301 PragmaStack<StringLiteral *> *Stack = 302 llvm::StringSwitch<PragmaStack<StringLiteral *> *>(PragmaName) 303 .Case("data_seg", &DataSegStack) 304 .Case("bss_seg", &BSSSegStack) 305 .Case("const_seg", &ConstSegStack) 306 .Case("code_seg", &CodeSegStack); 307 if (Action & PSK_Pop && Stack->Stack.empty()) 308 Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName 309 << "stack empty"; 310 if (SegmentName && 311 !checkSectionName(SegmentName->getLocStart(), SegmentName->getString())) 312 return; 313 Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName); 314 } 315 316 /// \brief Called on well formed \#pragma bss_seg(). 317 void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation, 318 int SectionFlags, StringLiteral *SegmentName) { 319 UnifySection(SegmentName->getString(), SectionFlags, PragmaLocation); 320 } 321 322 void Sema::ActOnPragmaMSInitSeg(SourceLocation PragmaLocation, 323 StringLiteral *SegmentName) { 324 // There's no stack to maintain, so we just have a current section. When we 325 // see the default section, reset our current section back to null so we stop 326 // tacking on unnecessary attributes. 327 CurInitSeg = SegmentName->getString() == ".CRT$XCU" ? nullptr : SegmentName; 328 CurInitSegLoc = PragmaLocation; 329 } 330 331 void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope, 332 SourceLocation PragmaLoc) { 333 334 IdentifierInfo *Name = IdTok.getIdentifierInfo(); 335 LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName); 336 LookupParsedName(Lookup, curScope, nullptr, true); 337 338 if (Lookup.empty()) { 339 Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) 340 << Name << SourceRange(IdTok.getLocation()); 341 return; 342 } 343 344 VarDecl *VD = Lookup.getAsSingle<VarDecl>(); 345 if (!VD) { 346 Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg) 347 << Name << SourceRange(IdTok.getLocation()); 348 return; 349 } 350 351 // Warn if this was used before being marked unused. 352 if (VD->isUsed()) 353 Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name; 354 355 VD->addAttr(UnusedAttr::CreateImplicit(Context, UnusedAttr::GNU_unused, 356 IdTok.getLocation())); 357 } 358 359 void Sema::AddCFAuditedAttribute(Decl *D) { 360 SourceLocation Loc = PP.getPragmaARCCFCodeAuditedLoc(); 361 if (!Loc.isValid()) return; 362 363 // Don't add a redundant or conflicting attribute. 364 if (D->hasAttr<CFAuditedTransferAttr>() || 365 D->hasAttr<CFUnknownTransferAttr>()) 366 return; 367 368 D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc)); 369 } 370 371 namespace { 372 373 Optional<attr::SubjectMatchRule> 374 getParentAttrMatcherRule(attr::SubjectMatchRule Rule) { 375 using namespace attr; 376 switch (Rule) { 377 default: 378 return None; 379 #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) 380 #define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \ 381 case Value: \ 382 return Parent; 383 #include "clang/Basic/AttrSubMatchRulesList.inc" 384 } 385 } 386 387 bool isNegatedAttrMatcherSubRule(attr::SubjectMatchRule Rule) { 388 using namespace attr; 389 switch (Rule) { 390 default: 391 return false; 392 #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) 393 #define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \ 394 case Value: \ 395 return IsNegated; 396 #include "clang/Basic/AttrSubMatchRulesList.inc" 397 } 398 } 399 400 CharSourceRange replacementRangeForListElement(const Sema &S, 401 SourceRange Range) { 402 // Make sure that the ',' is removed as well. 403 SourceLocation AfterCommaLoc = Lexer::findLocationAfterToken( 404 Range.getEnd(), tok::comma, S.getSourceManager(), S.getLangOpts(), 405 /*SkipTrailingWhitespaceAndNewLine=*/false); 406 if (AfterCommaLoc.isValid()) 407 return CharSourceRange::getCharRange(Range.getBegin(), AfterCommaLoc); 408 else 409 return CharSourceRange::getTokenRange(Range); 410 } 411 412 std::string 413 attrMatcherRuleListToString(ArrayRef<attr::SubjectMatchRule> Rules) { 414 std::string Result; 415 llvm::raw_string_ostream OS(Result); 416 for (const auto &I : llvm::enumerate(Rules)) { 417 if (I.index()) 418 OS << (I.index() == Rules.size() - 1 ? ", and " : ", "); 419 OS << "'" << attr::getSubjectMatchRuleSpelling(I.value()) << "'"; 420 } 421 return OS.str(); 422 } 423 424 } // end anonymous namespace 425 426 void Sema::ActOnPragmaAttributePush(AttributeList &Attribute, 427 SourceLocation PragmaLoc, 428 attr::ParsedSubjectMatchRuleSet Rules) { 429 SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules; 430 // Gather the subject match rules that are supported by the attribute. 431 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> 432 StrictSubjectMatchRuleSet; 433 Attribute.getMatchRules(LangOpts, StrictSubjectMatchRuleSet); 434 435 // Figure out which subject matching rules are valid. 436 if (StrictSubjectMatchRuleSet.empty()) { 437 // Check for contradicting match rules. Contradicting match rules are 438 // either: 439 // - a top-level rule and one of its sub-rules. E.g. variable and 440 // variable(is_parameter). 441 // - a sub-rule and a sibling that's negated. E.g. 442 // variable(is_thread_local) and variable(unless(is_parameter)) 443 llvm::SmallDenseMap<int, std::pair<int, SourceRange>, 2> 444 RulesToFirstSpecifiedNegatedSubRule; 445 for (const auto &Rule : Rules) { 446 attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first); 447 Optional<attr::SubjectMatchRule> ParentRule = 448 getParentAttrMatcherRule(MatchRule); 449 if (!ParentRule) 450 continue; 451 auto It = Rules.find(*ParentRule); 452 if (It != Rules.end()) { 453 // A sub-rule contradicts a parent rule. 454 Diag(Rule.second.getBegin(), 455 diag::err_pragma_attribute_matcher_subrule_contradicts_rule) 456 << attr::getSubjectMatchRuleSpelling(MatchRule) 457 << attr::getSubjectMatchRuleSpelling(*ParentRule) << It->second 458 << FixItHint::CreateRemoval( 459 replacementRangeForListElement(*this, Rule.second)); 460 // Keep going without removing this rule as it won't change the set of 461 // declarations that receive the attribute. 462 continue; 463 } 464 if (isNegatedAttrMatcherSubRule(MatchRule)) 465 RulesToFirstSpecifiedNegatedSubRule.insert( 466 std::make_pair(*ParentRule, Rule)); 467 } 468 bool IgnoreNegatedSubRules = false; 469 for (const auto &Rule : Rules) { 470 attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first); 471 Optional<attr::SubjectMatchRule> ParentRule = 472 getParentAttrMatcherRule(MatchRule); 473 if (!ParentRule) 474 continue; 475 auto It = RulesToFirstSpecifiedNegatedSubRule.find(*ParentRule); 476 if (It != RulesToFirstSpecifiedNegatedSubRule.end() && 477 It->second != Rule) { 478 // Negated sub-rule contradicts another sub-rule. 479 Diag( 480 It->second.second.getBegin(), 481 diag:: 482 err_pragma_attribute_matcher_negated_subrule_contradicts_subrule) 483 << attr::getSubjectMatchRuleSpelling( 484 attr::SubjectMatchRule(It->second.first)) 485 << attr::getSubjectMatchRuleSpelling(MatchRule) << Rule.second 486 << FixItHint::CreateRemoval( 487 replacementRangeForListElement(*this, It->second.second)); 488 // Keep going but ignore all of the negated sub-rules. 489 IgnoreNegatedSubRules = true; 490 RulesToFirstSpecifiedNegatedSubRule.erase(It); 491 } 492 } 493 494 if (!IgnoreNegatedSubRules) { 495 for (const auto &Rule : Rules) 496 SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first)); 497 } else { 498 for (const auto &Rule : Rules) { 499 if (!isNegatedAttrMatcherSubRule(attr::SubjectMatchRule(Rule.first))) 500 SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first)); 501 } 502 } 503 Rules.clear(); 504 } else { 505 for (const auto &Rule : StrictSubjectMatchRuleSet) { 506 if (Rules.erase(Rule.first)) { 507 // Add the rule to the set of attribute receivers only if it's supported 508 // in the current language mode. 509 if (Rule.second) 510 SubjectMatchRules.push_back(Rule.first); 511 } 512 } 513 } 514 515 if (!Rules.empty()) { 516 auto Diagnostic = 517 Diag(PragmaLoc, diag::err_pragma_attribute_invalid_matchers) 518 << Attribute.getName(); 519 SmallVector<attr::SubjectMatchRule, 2> ExtraRules; 520 for (const auto &Rule : Rules) { 521 ExtraRules.push_back(attr::SubjectMatchRule(Rule.first)); 522 Diagnostic << FixItHint::CreateRemoval( 523 replacementRangeForListElement(*this, Rule.second)); 524 } 525 Diagnostic << attrMatcherRuleListToString(ExtraRules); 526 } 527 528 PragmaAttributeStack.push_back( 529 {PragmaLoc, &Attribute, std::move(SubjectMatchRules), /*IsUsed=*/false}); 530 } 531 532 void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc) { 533 if (PragmaAttributeStack.empty()) { 534 Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch); 535 return; 536 } 537 const PragmaAttributeEntry &Entry = PragmaAttributeStack.back(); 538 if (!Entry.IsUsed) { 539 assert(Entry.Attribute && "Expected an attribute"); 540 Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused) 541 << Entry.Attribute->getName(); 542 Diag(PragmaLoc, diag::note_pragma_attribute_region_ends_here); 543 } 544 PragmaAttributeStack.pop_back(); 545 } 546 547 void Sema::AddPragmaAttributes(Scope *S, Decl *D) { 548 if (PragmaAttributeStack.empty()) 549 return; 550 for (auto &Entry : PragmaAttributeStack) { 551 const AttributeList *Attribute = Entry.Attribute; 552 assert(Attribute && "Expected an attribute"); 553 554 // Ensure that the attribute can be applied to the given declaration. 555 bool Applies = false; 556 for (const auto &Rule : Entry.MatchRules) { 557 if (Attribute->appliesToDecl(D, Rule)) { 558 Applies = true; 559 break; 560 } 561 } 562 if (!Applies) 563 continue; 564 Entry.IsUsed = true; 565 assert(!Attribute->getNext() && "Expected just one attribute"); 566 PragmaAttributeCurrentTargetDecl = D; 567 ProcessDeclAttributeList(S, D, Attribute); 568 PragmaAttributeCurrentTargetDecl = nullptr; 569 } 570 } 571 572 void Sema::PrintPragmaAttributeInstantiationPoint() { 573 assert(PragmaAttributeCurrentTargetDecl && "Expected an active declaration"); 574 Diags.Report(PragmaAttributeCurrentTargetDecl->getLocStart(), 575 diag::note_pragma_attribute_applied_decl_here); 576 } 577 578 void Sema::DiagnoseUnterminatedPragmaAttribute() { 579 if (PragmaAttributeStack.empty()) 580 return; 581 Diag(PragmaAttributeStack.back().Loc, diag::err_pragma_attribute_no_pop_eof); 582 } 583 584 void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) { 585 if(On) 586 OptimizeOffPragmaLocation = SourceLocation(); 587 else 588 OptimizeOffPragmaLocation = PragmaLoc; 589 } 590 591 void Sema::AddRangeBasedOptnone(FunctionDecl *FD) { 592 // In the future, check other pragmas if they're implemented (e.g. pragma 593 // optimize 0 will probably map to this functionality too). 594 if(OptimizeOffPragmaLocation.isValid()) 595 AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation); 596 } 597 598 void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, 599 SourceLocation Loc) { 600 // Don't add a conflicting attribute. No diagnostic is needed. 601 if (FD->hasAttr<MinSizeAttr>() || FD->hasAttr<AlwaysInlineAttr>()) 602 return; 603 604 // Add attributes only if required. Optnone requires noinline as well, but if 605 // either is already present then don't bother adding them. 606 if (!FD->hasAttr<OptimizeNoneAttr>()) 607 FD->addAttr(OptimizeNoneAttr::CreateImplicit(Context, Loc)); 608 if (!FD->hasAttr<NoInlineAttr>()) 609 FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc)); 610 } 611 612 typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack; 613 enum : unsigned { NoVisibility = ~0U }; 614 615 void Sema::AddPushedVisibilityAttribute(Decl *D) { 616 if (!VisContext) 617 return; 618 619 NamedDecl *ND = dyn_cast<NamedDecl>(D); 620 if (ND && ND->getExplicitVisibility(NamedDecl::VisibilityForValue)) 621 return; 622 623 VisStack *Stack = static_cast<VisStack*>(VisContext); 624 unsigned rawType = Stack->back().first; 625 if (rawType == NoVisibility) return; 626 627 VisibilityAttr::VisibilityType type 628 = (VisibilityAttr::VisibilityType) rawType; 629 SourceLocation loc = Stack->back().second; 630 631 D->addAttr(VisibilityAttr::CreateImplicit(Context, type, loc)); 632 } 633 634 /// FreeVisContext - Deallocate and null out VisContext. 635 void Sema::FreeVisContext() { 636 delete static_cast<VisStack*>(VisContext); 637 VisContext = nullptr; 638 } 639 640 static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) { 641 // Put visibility on stack. 642 if (!S.VisContext) 643 S.VisContext = new VisStack; 644 645 VisStack *Stack = static_cast<VisStack*>(S.VisContext); 646 Stack->push_back(std::make_pair(type, loc)); 647 } 648 649 void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType, 650 SourceLocation PragmaLoc) { 651 if (VisType) { 652 // Compute visibility to use. 653 VisibilityAttr::VisibilityType T; 654 if (!VisibilityAttr::ConvertStrToVisibilityType(VisType->getName(), T)) { 655 Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << VisType; 656 return; 657 } 658 PushPragmaVisibility(*this, T, PragmaLoc); 659 } else { 660 PopPragmaVisibility(false, PragmaLoc); 661 } 662 } 663 664 void Sema::ActOnPragmaFPContract(LangOptions::FPContractModeKind FPC) { 665 switch (FPC) { 666 case LangOptions::FPC_On: 667 FPFeatures.setAllowFPContractWithinStatement(); 668 break; 669 case LangOptions::FPC_Fast: 670 FPFeatures.setAllowFPContractAcrossStatement(); 671 break; 672 case LangOptions::FPC_Off: 673 FPFeatures.setDisallowFPContract(); 674 break; 675 } 676 } 677 678 void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr, 679 SourceLocation Loc) { 680 // Visibility calculations will consider the namespace's visibility. 681 // Here we just want to note that we're in a visibility context 682 // which overrides any enclosing #pragma context, but doesn't itself 683 // contribute visibility. 684 PushPragmaVisibility(*this, NoVisibility, Loc); 685 } 686 687 void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) { 688 if (!VisContext) { 689 Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch); 690 return; 691 } 692 693 // Pop visibility from stack 694 VisStack *Stack = static_cast<VisStack*>(VisContext); 695 696 const std::pair<unsigned, SourceLocation> *Back = &Stack->back(); 697 bool StartsWithPragma = Back->first != NoVisibility; 698 if (StartsWithPragma && IsNamespaceEnd) { 699 Diag(Back->second, diag::err_pragma_push_visibility_mismatch); 700 Diag(EndLoc, diag::note_surrounding_namespace_ends_here); 701 702 // For better error recovery, eat all pushes inside the namespace. 703 do { 704 Stack->pop_back(); 705 Back = &Stack->back(); 706 StartsWithPragma = Back->first != NoVisibility; 707 } while (StartsWithPragma); 708 } else if (!StartsWithPragma && !IsNamespaceEnd) { 709 Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch); 710 Diag(Back->second, diag::note_surrounding_namespace_starts_here); 711 return; 712 } 713 714 Stack->pop_back(); 715 // To simplify the implementation, never keep around an empty stack. 716 if (Stack->empty()) 717 FreeVisContext(); 718 } 719