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