diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Basic/Attributes.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Parse/ParsePragma.cpp | 535 | ||||
-rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/AttributeList.cpp | 21 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 67 | ||||
-rw-r--r-- | clang/lib/Sema/SemaAttr.cpp | 211 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 13 |
11 files changed, 39 insertions, 834 deletions
diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp index b7570d03c85..c215366fc39 100644 --- a/clang/lib/Basic/Attributes.cpp +++ b/clang/lib/Basic/Attributes.cpp @@ -1,5 +1,4 @@ #include "clang/Basic/Attributes.h" -#include "clang/Basic/AttrSubjectMatchRules.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/StringSwitch.h" using namespace clang; @@ -16,13 +15,3 @@ int clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope, return 0; } - -const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) { - switch (Rule) { -#define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract) \ - case attr::NAME: \ - return SPELLING; -#include "clang/Basic/AttrSubMatchRulesList.inc" - } - llvm_unreachable("Invalid subject match rule"); -} diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index abddb6ba670..c8de6b35f9e 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -183,17 +183,6 @@ private: Sema &Actions; }; -/// PragmaAttributeHandler - "\#pragma clang attribute ...". -struct PragmaAttributeHandler : public PragmaHandler { - PragmaAttributeHandler(AttributeFactory &AttrFactory) - : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {} - void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken) override; - - /// A pool of attributes that were parsed in \#pragma clang attribute. - ParsedAttributes AttributesForPragmaAttribute; -}; - } // end namespace void Parser::initializePragmaHandlers() { @@ -286,9 +275,6 @@ void Parser::initializePragmaHandlers() { FPHandler.reset(new PragmaFPHandler()); PP.AddPragmaHandler("clang", FPHandler.get()); - - AttributePragmaHandler.reset(new PragmaAttributeHandler(AttrFactory)); - PP.AddPragmaHandler("clang", AttributePragmaHandler.get()); } void Parser::resetPragmaHandlers() { @@ -370,9 +356,6 @@ void Parser::resetPragmaHandlers() { PP.RemovePragmaHandler("clang", FPHandler.get()); FPHandler.reset(); - - PP.RemovePragmaHandler("clang", AttributePragmaHandler.get()); - AttributePragmaHandler.reset(); } /// \brief Handle the annotation token produced for #pragma unused(...) @@ -983,423 +966,6 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { return true; } -namespace { -struct PragmaAttributeInfo { - enum ActionType { Push, Pop }; - ParsedAttributes &Attributes; - ActionType Action; - ArrayRef<Token> Tokens; - - PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {} -}; - -#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc" - -} // end anonymous namespace - -static StringRef getIdentifier(const Token &Tok) { - if (Tok.is(tok::identifier)) - return Tok.getIdentifierInfo()->getName(); - const char *S = tok::getKeywordSpelling(Tok.getKind()); - if (!S) - return ""; - return S; -} - -static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) { - using namespace attr; - switch (Rule) { -#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \ - case Value: \ - return IsAbstract; -#include "clang/Basic/AttrSubMatchRulesList.inc" - } - llvm_unreachable("Invalid attribute subject match rule"); - return false; -} - -static void diagnoseExpectedAttributeSubjectSubRule( - Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName, - SourceLocation SubRuleLoc) { - auto Diagnostic = - PRef.Diag(SubRuleLoc, - diag::err_pragma_attribute_expected_subject_sub_identifier) - << PrimaryRuleName; - if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule)) - Diagnostic << /*SubRulesSupported=*/1 << SubRules; - else - Diagnostic << /*SubRulesSupported=*/0; -} - -static void diagnoseUnknownAttributeSubjectSubRule( - Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName, - StringRef SubRuleName, SourceLocation SubRuleLoc) { - - auto Diagnostic = - PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule) - << SubRuleName << PrimaryRuleName; - if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule)) - Diagnostic << /*SubRulesSupported=*/1 << SubRules; - else - Diagnostic << /*SubRulesSupported=*/0; -} - -bool Parser::ParsePragmaAttributeSubjectMatchRuleSet( - attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc, - SourceLocation &LastMatchRuleEndLoc) { - bool IsAny = false; - BalancedDelimiterTracker AnyParens(*this, tok::l_paren); - if (getIdentifier(Tok) == "any") { - AnyLoc = ConsumeToken(); - IsAny = true; - if (AnyParens.expectAndConsume()) - return true; - } - - do { - // Parse the subject matcher rule. - StringRef Name = getIdentifier(Tok); - if (Name.empty()) { - Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier); - return true; - } - std::pair< - Optional<attr::SubjectMatchRule>, - llvm::function_ref<Optional<attr::SubjectMatchRule>(StringRef, bool)>> - Rule = isAttributeSubjectMatchRule(Name); - if (!Rule.first) { - Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name; - return true; - } - attr::SubjectMatchRule PrimaryRule = *Rule.first; - SourceLocation RuleLoc = ConsumeToken(); - - BalancedDelimiterTracker Parens(*this, tok::l_paren); - if (isAbstractAttrMatcherRule(PrimaryRule)) { - if (Parens.expectAndConsume()) - return true; - } else if (Parens.consumeOpen()) { - if (!SubjectMatchRules - .insert( - std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc))) - .second) - Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject) - << Name - << FixItHint::CreateRemoval(SourceRange( - RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc)); - LastMatchRuleEndLoc = RuleLoc; - continue; - } - - // Parse the sub-rules. - StringRef SubRuleName = getIdentifier(Tok); - if (SubRuleName.empty()) { - diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name, - Tok.getLocation()); - return true; - } - attr::SubjectMatchRule SubRule; - if (SubRuleName == "unless") { - SourceLocation SubRuleLoc = ConsumeToken(); - BalancedDelimiterTracker Parens(*this, tok::l_paren); - if (Parens.expectAndConsume()) - return true; - SubRuleName = getIdentifier(Tok); - if (SubRuleName.empty()) { - diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name, - SubRuleLoc); - return true; - } - auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true); - if (!SubRuleOrNone) { - std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")"; - diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name, - SubRuleUnlessName, SubRuleLoc); - return true; - } - SubRule = *SubRuleOrNone; - ConsumeToken(); - if (Parens.consumeClose()) - return true; - } else { - auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false); - if (!SubRuleOrNone) { - diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name, - SubRuleName, Tok.getLocation()); - return true; - } - SubRule = *SubRuleOrNone; - ConsumeToken(); - } - SourceLocation RuleEndLoc = Tok.getLocation(); - LastMatchRuleEndLoc = RuleEndLoc; - if (Parens.consumeClose()) - return true; - if (!SubjectMatchRules - .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc))) - .second) { - Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject) - << attr::getSubjectMatchRuleSpelling(SubRule) - << FixItHint::CreateRemoval(SourceRange( - RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc)); - continue; - } - } while (IsAny && TryConsumeToken(tok::comma)); - - if (IsAny) - if (AnyParens.consumeClose()) - return true; - - return false; -} - -namespace { - -/// Describes the stage at which attribute subject rule parsing was interruped. -enum class MissingAttributeSubjectRulesRecoveryPoint { - Comma, - ApplyTo, - Equals, - Any, - None, -}; - -MissingAttributeSubjectRulesRecoveryPoint -getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) { - if (const auto *II = Tok.getIdentifierInfo()) { - if (II->isStr("apply_to")) - return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo; - if (II->isStr("any")) - return MissingAttributeSubjectRulesRecoveryPoint::Any; - } - if (Tok.is(tok::equal)) - return MissingAttributeSubjectRulesRecoveryPoint::Equals; - return MissingAttributeSubjectRulesRecoveryPoint::None; -} - -/// Creates a diagnostic for the attribute subject rule parsing diagnostic that -/// suggests the possible attribute subject rules in a fix-it together with -/// any other missing tokens. -DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic( - unsigned DiagID, AttributeList &Attribute, - MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) { - SourceLocation Loc = PRef.getEndOfPreviousToken(); - if (Loc.isInvalid()) - Loc = PRef.getCurToken().getLocation(); - auto Diagnostic = PRef.Diag(Loc, DiagID); - std::string FixIt; - MissingAttributeSubjectRulesRecoveryPoint EndPoint = - getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken()); - if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma) - FixIt = ", "; - if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo && - EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo) - FixIt += "apply_to"; - if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals && - EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals) - FixIt += " = "; - SourceRange FixItRange(Loc); - if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) { - // Gather the subject match rules that are supported by the attribute. - SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet; - Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet); - if (SubjectMatchRuleSet.empty()) { - // FIXME: We can emit a "fix-it" with a subject list placeholder when - // placeholders will be supported by the fix-its. - return Diagnostic; - } - FixIt += "any("; - bool NeedsComma = false; - for (const auto &I : SubjectMatchRuleSet) { - // Ensure that the missing rule is reported in the fix-it only when it's - // supported in the current language mode. - if (!I.second) - continue; - if (NeedsComma) - FixIt += ", "; - else - NeedsComma = true; - FixIt += attr::getSubjectMatchRuleSpelling(I.first); - } - FixIt += ")"; - // Check if we need to remove the range - PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch); - FixItRange.setEnd(PRef.getCurToken().getLocation()); - } - if (FixItRange.getBegin() == FixItRange.getEnd()) - Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt); - else - Diagnostic << FixItHint::CreateReplacement( - CharSourceRange::getCharRange(FixItRange), FixIt); - return Diagnostic; -} - -} // end anonymous namespace - -void Parser::HandlePragmaAttribute() { - assert(Tok.is(tok::annot_pragma_attribute) && - "Expected #pragma attribute annotation token"); - SourceLocation PragmaLoc = Tok.getLocation(); - auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue()); - if (Info->Action == PragmaAttributeInfo::Pop) { - ConsumeToken(); - Actions.ActOnPragmaAttributePop(PragmaLoc); - return; - } - // Parse the actual attribute with its arguments. - assert(Info->Action == PragmaAttributeInfo::Push && - "Unexpected #pragma attribute command"); - PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false); - ConsumeToken(); - - ParsedAttributes &Attrs = Info->Attributes; - Attrs.clearListOnly(); - - auto SkipToEnd = [this]() { - SkipUntil(tok::eof, StopBeforeMatch); - ConsumeToken(); - }; - - if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) { - // Parse the CXX11 style attribute. - ParseCXX11AttributeSpecifier(Attrs); - } else if (Tok.is(tok::kw___attribute)) { - ConsumeToken(); - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, - "attribute")) - return SkipToEnd(); - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) - return SkipToEnd(); - - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_pragma_attribute_expected_attribute_name); - SkipToEnd(); - return; - } - IdentifierInfo *AttrName = Tok.getIdentifierInfo(); - SourceLocation AttrNameLoc = ConsumeToken(); - - if (Tok.isNot(tok::l_paren)) - Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_GNU); - else - ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr, - /*ScopeName=*/nullptr, - /*ScopeLoc=*/SourceLocation(), - AttributeList::AS_GNU, - /*Declarator=*/nullptr); - - if (ExpectAndConsume(tok::r_paren)) - return SkipToEnd(); - if (ExpectAndConsume(tok::r_paren)) - return SkipToEnd(); - } else if (Tok.is(tok::kw___declspec)) { - ParseMicrosoftDeclSpecs(Attrs); - } else { - Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax); - if (Tok.getIdentifierInfo()) { - // If we suspect that this is an attribute suggest the use of - // '__attribute__'. - if (AttributeList::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr, - AttributeList::AS_GNU) != - AttributeList::UnknownAttribute) { - SourceLocation InsertStartLoc = Tok.getLocation(); - ConsumeToken(); - if (Tok.is(tok::l_paren)) { - ConsumeAnyToken(); - SkipUntil(tok::r_paren, StopBeforeMatch); - if (Tok.isNot(tok::r_paren)) - return SkipToEnd(); - } - Diag(Tok, diag::note_pragma_attribute_use_attribute_kw) - << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((") - << FixItHint::CreateInsertion(Tok.getEndLoc(), "))"); - } - } - SkipToEnd(); - return; - } - - if (!Attrs.getList() || Attrs.getList()->isInvalid()) { - SkipToEnd(); - return; - } - - // Ensure that we don't have more than one attribute. - if (Attrs.getList()->getNext()) { - SourceLocation Loc = Attrs.getList()->getNext()->getLoc(); - Diag(Loc, diag::err_pragma_attribute_multiple_attributes); - SkipToEnd(); - return; - } - - if (!Attrs.getList()->isSupportedByPragmaAttribute()) { - Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute) - << Attrs.getList()->getName(); - SkipToEnd(); - return; - } - AttributeList &Attribute = *Attrs.getList(); - - // Parse the subject-list. - if (!TryConsumeToken(tok::comma)) { - createExpectedAttributeSubjectRulesTokenDiagnostic( - diag::err_expected, Attribute, - MissingAttributeSubjectRulesRecoveryPoint::Comma, *this) - << tok::comma; - SkipToEnd(); - return; - } - - if (Tok.isNot(tok::identifier)) { - createExpectedAttributeSubjectRulesTokenDiagnostic( - diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute, - MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this); - SkipToEnd(); - return; - } - const IdentifierInfo *II = Tok.getIdentifierInfo(); - if (!II->isStr("apply_to")) { - createExpectedAttributeSubjectRulesTokenDiagnostic( - diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute, - MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this); - SkipToEnd(); - return; - } - ConsumeToken(); - - if (!TryConsumeToken(tok::equal)) { - createExpectedAttributeSubjectRulesTokenDiagnostic( - diag::err_expected, Attribute, - MissingAttributeSubjectRulesRecoveryPoint::Equals, *this) - << tok::equal; - SkipToEnd(); - return; - } - - attr::ParsedSubjectMatchRuleSet SubjectMatchRules; - SourceLocation AnyLoc, LastMatchRuleEndLoc; - if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc, - LastMatchRuleEndLoc)) { - SkipToEnd(); - return; - } - - // Tokens following an ill-formed attribute will remain in the token stream - // and must be removed. - if (Tok.isNot(tok::eof)) { - Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute); - SkipToEnd(); - return; - } - - // Consume the eof terminator token. - ConsumeToken(); - - Actions.ActOnPragmaAttributePush(Attribute, PragmaLoc, - std::move(SubjectMatchRules)); -} - // #pragma GCC visibility comes in two variants: // 'push' '(' [visibility] ')' // 'pop' @@ -2829,104 +2395,3 @@ void PragmaForceCUDAHostDeviceHandler::HandlePragma( PP.Diag(FirstTok.getLocation(), diag::warn_pragma_force_cuda_host_device_bad_arg); } - -/// \brief Handle the #pragma clang attribute directive. -/// -/// The syntax is: -/// \code -/// #pragma clang attribute push(attribute, subject-set) -/// #pragma clang attribute pop -/// \endcode -/// -/// The subject-set clause defines the set of declarations which receive the -/// attribute. Its exact syntax is described in the LanguageExtensions document -/// in Clang's documentation. -/// -/// This directive instructs the compiler to begin/finish applying the specified -/// attribute to the set of attribute-specific declarations in the active range -/// of the pragma. -void PragmaAttributeHandler::HandlePragma(Preprocessor &PP, - PragmaIntroducerKind Introducer, - Token &FirstToken) { - Token Tok; - PP.Lex(Tok); - auto *Info = new (PP.getPreprocessorAllocator()) - PragmaAttributeInfo(AttributesForPragmaAttribute); - - // Parse the 'push' or 'pop'. - if (Tok.isNot(tok::identifier)) { - PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_push_pop); - return; - } - const auto *II = Tok.getIdentifierInfo(); - if (II->isStr("push")) - Info->Action = PragmaAttributeInfo::Push; - else if (II->isStr("pop")) - Info->Action = PragmaAttributeInfo::Pop; - else { - PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument) - << PP.getSpelling(Tok); - return; - } - PP.Lex(Tok); - - // Parse the actual attribute. - if (Info->Action == PragmaAttributeInfo::Push) { - if (Tok.isNot(tok::l_paren)) { - PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; - return; - } - PP.Lex(Tok); - - // Lex the attribute tokens. - SmallVector<Token, 16> AttributeTokens; - int OpenParens = 1; - while (Tok.isNot(tok::eod)) { - if (Tok.is(tok::l_paren)) - OpenParens++; - else if (Tok.is(tok::r_paren)) { - OpenParens--; - if (OpenParens == 0) - break; - } - - AttributeTokens.push_back(Tok); - PP.Lex(Tok); - } - - if (AttributeTokens.empty()) { - PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute); - return; - } - if (Tok.isNot(tok::r_paren)) { - PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; - return; - } - SourceLocation EndLoc = Tok.getLocation(); - PP.Lex(Tok); - - // Terminate the attribute for parsing. - Token EOFTok; - EOFTok.startToken(); - EOFTok.setKind(tok::eof); - EOFTok.setLocation(EndLoc); - AttributeTokens.push_back(EOFTok); - - Info->Tokens = - llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator()); - } - - if (Tok.isNot(tok::eod)) - PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) - << "clang attribute"; - - // Generate the annotated pragma token. - auto TokenArray = llvm::make_unique<Token[]>(1); - TokenArray[0].startToken(); - TokenArray[0].setKind(tok::annot_pragma_attribute); - TokenArray[0].setLocation(FirstToken.getLocation()); - TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation()); - TokenArray[0].setAnnotationValue(static_cast<void *>(Info)); - PP.EnterTokenStream(std::move(TokenArray), 1, - /*DisableMacroExpansion=*/false); -} diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 7d78046d068..eaff9fe8eed 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -382,10 +382,6 @@ Retry: case tok::annot_pragma_dump: HandlePragmaDump(); return StmtEmpty(); - - case tok::annot_pragma_attribute: - HandlePragmaAttribute(); - return StmtEmpty(); } // If we reached this code, the statement must end in a semicolon. diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 265c12d7d5e..aa8ed91d382 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -602,10 +602,6 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { ConsumeToken(); return false; - case tok::annot_pragma_attribute: - HandlePragmaAttribute(); - return false; - case tok::eof: // Late template parsing can begin. if (getLangOpts().DelayedTemplateParsing) diff --git a/clang/lib/Sema/AttributeList.cpp b/clang/lib/Sema/AttributeList.cpp index 724db456785..55e9601bf5e 100644 --- a/clang/lib/Sema/AttributeList.cpp +++ b/clang/lib/Sema/AttributeList.cpp @@ -16,7 +16,6 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" -#include "clang/Basic/AttrSubjectMatchRules.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/SemaInternal.h" @@ -161,16 +160,12 @@ struct ParsedAttrInfo { unsigned IsType : 1; unsigned IsStmt : 1; unsigned IsKnownToGCC : 1; - unsigned IsSupportedByPragmaAttribute : 1; bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr, const Decl *); bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr); bool (*ExistsInTarget)(const TargetInfo &Target); unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr); - void (*GetPragmaAttributeMatchRules)( - llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules, - const LangOptions &LangOpts); }; namespace { @@ -197,18 +192,6 @@ bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const { return getInfo(*this).DiagAppertainsToDecl(S, *this, D); } -bool AttributeList::appliesToDecl(const Decl *D, - attr::SubjectMatchRule MatchRule) const { - return checkAttributeMatchRuleAppliesTo(D, MatchRule); -} - -void AttributeList::getMatchRules( - const LangOptions &LangOpts, - SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules) - const { - return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts); -} - bool AttributeList::diagnoseLangOpts(Sema &S) const { return getInfo(*this).DiagLangOpts(S, *this); } @@ -233,10 +216,6 @@ bool AttributeList::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; } -bool AttributeList::isSupportedByPragmaAttribute() const { - return getInfo(*this).IsSupportedByPragmaAttribute; -} - unsigned AttributeList::getSemanticSpelling() const { return getInfo(*this).SpellingIndexToSemanticSpelling(*this); } diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 950f0408882..294b56059b3 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -71,35 +71,42 @@ void Sema::ActOnTranslationUnitScope(Scope *S) { } Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, - TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter) - : ExternalSource(nullptr), isMultiplexExternalSource(false), - FPFeatures(pp.getLangOpts()), LangOpts(pp.getLangOpts()), PP(pp), - Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), - SourceMgr(PP.getSourceManager()), CollectStats(false), - CodeCompleter(CodeCompleter), CurContext(nullptr), - OriginalLexicalContext(nullptr), MSStructPragmaOn(false), - MSPointerToMemberRepresentationMethod( - LangOpts.getMSPointerToMemberRepresentationMethod()), - VtorDispStack(MSVtorDispAttr::Mode(LangOpts.VtorDispMode)), PackStack(0), - DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr), - CodeSegStack(nullptr), CurInitSeg(nullptr), VisContext(nullptr), - PragmaAttributeCurrentTargetDecl(nullptr), - IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr), - LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp), - StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr), - CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr), NSNumberDecl(nullptr), - NSValueDecl(nullptr), NSStringDecl(nullptr), - StringWithUTF8StringMethod(nullptr), - ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr), - ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr), - DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false), - TUKind(TUKind), NumSFINAEErrors(0), CachedFakeTopLevelModule(nullptr), - AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false), - NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1), - CurrentInstantiationScope(nullptr), DisableTypoCorrection(false), - TyposCorrected(0), AnalysisWarnings(*this), - ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr), - CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr) { + TranslationUnitKind TUKind, + CodeCompleteConsumer *CodeCompleter) + : ExternalSource(nullptr), + isMultiplexExternalSource(false), FPFeatures(pp.getLangOpts()), + LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer), + Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), + CollectStats(false), CodeCompleter(CodeCompleter), + CurContext(nullptr), OriginalLexicalContext(nullptr), + MSStructPragmaOn(false), + MSPointerToMemberRepresentationMethod( + LangOpts.getMSPointerToMemberRepresentationMethod()), + VtorDispStack(MSVtorDispAttr::Mode(LangOpts.VtorDispMode)), + PackStack(0), DataSegStack(nullptr), BSSSegStack(nullptr), + ConstSegStack(nullptr), CodeSegStack(nullptr), CurInitSeg(nullptr), + VisContext(nullptr), + IsBuildingRecoveryCallExpr(false), + Cleanup{}, LateTemplateParser(nullptr), + LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp), + StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr), + CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr), + NSNumberDecl(nullptr), NSValueDecl(nullptr), + NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr), + ValueWithBytesObjCTypeMethod(nullptr), + NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr), + NSDictionaryDecl(nullptr), DictionaryWithObjectsMethod(nullptr), + GlobalNewDeleteDeclared(false), + TUKind(TUKind), + NumSFINAEErrors(0), + CachedFakeTopLevelModule(nullptr), + AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false), + NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1), + CurrentInstantiationScope(nullptr), DisableTypoCorrection(false), + TyposCorrected(0), AnalysisWarnings(*this), ThreadSafetyDeclCache(nullptr), + VarDataSharingAttributesStack(nullptr), CurScope(nullptr), + Ident_super(nullptr), Ident___float128(nullptr) +{ TUScope = nullptr; LoadedExternalKnownNamespaces = false; @@ -724,8 +731,6 @@ void Sema::ActOnEndOfTranslationUnit() { CheckDelayedMemberExceptionSpecs(); } - DiagnoseUnterminatedPragmaAttribute(); - // All delayed member exception specs should be checked or we end up accepting // incompatible declarations. // FIXME: This is wrong for TUKind == TU_Prefix. In that case, we need to diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index dfc5d6cd015..c6e3cc88631 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -368,217 +368,6 @@ void Sema::AddCFAuditedAttribute(Decl *D) { D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc)); } -namespace { - -Optional<attr::SubjectMatchRule> -getParentAttrMatcherRule(attr::SubjectMatchRule Rule) { - using namespace attr; - switch (Rule) { - default: - return None; -#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) -#define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \ - case Value: \ - return Parent; -#include "clang/Basic/AttrSubMatchRulesList.inc" - } -} - -bool isNegatedAttrMatcherSubRule(attr::SubjectMatchRule Rule) { - using namespace attr; - switch (Rule) { - default: - return false; -#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) -#define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \ - case Value: \ - return IsNegated; -#include "clang/Basic/AttrSubMatchRulesList.inc" - } -} - -CharSourceRange replacementRangeForListElement(const Sema &S, - SourceRange Range) { - // Make sure that the ',' is removed as well. - SourceLocation AfterCommaLoc = Lexer::findLocationAfterToken( - Range.getEnd(), tok::comma, S.getSourceManager(), S.getLangOpts(), - /*SkipTrailingWhitespaceAndNewLine=*/false); - if (AfterCommaLoc.isValid()) - return CharSourceRange::getCharRange(Range.getBegin(), AfterCommaLoc); - else - return CharSourceRange::getTokenRange(Range); -} - -std::string -attrMatcherRuleListToString(ArrayRef<attr::SubjectMatchRule> Rules) { - std::string Result; - llvm::raw_string_ostream OS(Result); - for (const auto &I : llvm::enumerate(Rules)) { - if (I.index()) - OS << (I.index() == Rules.size() - 1 ? ", and " : ", "); - OS << "'" << attr::getSubjectMatchRuleSpelling(I.value()) << "'"; - } - return OS.str(); -} - -} // end anonymous namespace - -void Sema::ActOnPragmaAttributePush(AttributeList &Attribute, - SourceLocation PragmaLoc, - attr::ParsedSubjectMatchRuleSet Rules) { - SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules; - // Gather the subject match rules that are supported by the attribute. - SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> - StrictSubjectMatchRuleSet; - Attribute.getMatchRules(LangOpts, StrictSubjectMatchRuleSet); - - // Figure out which subject matching rules are valid. - if (StrictSubjectMatchRuleSet.empty()) { - // Check for contradicting match rules. Contradicting match rules are - // either: - // - a top-level rule and one of its sub-rules. E.g. variable and - // variable(is_parameter). - // - a sub-rule and a sibling that's negated. E.g. - // variable(is_thread_local) and variable(unless(is_parameter)) - llvm::SmallDenseMap<attr::SubjectMatchRule, - std::pair<attr::SubjectMatchRule, SourceRange>, 2> - RulesToFirstSpecifiedNegatedSubRule; - for (const auto &Rule : Rules) { - Optional<attr::SubjectMatchRule> ParentRule = - getParentAttrMatcherRule(Rule.first); - if (!ParentRule) - continue; - auto It = Rules.find(*ParentRule); - if (It != Rules.end()) { - // A sub-rule contradicts a parent rule. - Diag(Rule.second.getBegin(), - diag::err_pragma_attribute_matcher_subrule_contradicts_rule) - << attr::getSubjectMatchRuleSpelling(Rule.first) - << attr::getSubjectMatchRuleSpelling(*ParentRule) << It->second - << FixItHint::CreateRemoval( - replacementRangeForListElement(*this, Rule.second)); - // Keep going without removing this rule as it won't change the set of - // declarations that receive the attribute. - continue; - } - if (isNegatedAttrMatcherSubRule(Rule.first)) - RulesToFirstSpecifiedNegatedSubRule.insert( - std::make_pair(*ParentRule, Rule)); - } - bool IgnoreNegatedSubRules = false; - for (const auto &Rule : Rules) { - Optional<attr::SubjectMatchRule> ParentRule = - getParentAttrMatcherRule(Rule.first); - if (!ParentRule) - continue; - auto It = RulesToFirstSpecifiedNegatedSubRule.find(*ParentRule); - if (It != RulesToFirstSpecifiedNegatedSubRule.end() && - It->second != Rule) { - // Negated sub-rule contradicts another sub-rule. - Diag( - It->second.second.getBegin(), - diag:: - err_pragma_attribute_matcher_negated_subrule_contradicts_subrule) - << attr::getSubjectMatchRuleSpelling(It->second.first) - << attr::getSubjectMatchRuleSpelling(Rule.first) << Rule.second - << FixItHint::CreateRemoval( - replacementRangeForListElement(*this, It->second.second)); - // Keep going but ignore all of the negated sub-rules. - IgnoreNegatedSubRules = true; - RulesToFirstSpecifiedNegatedSubRule.erase(It); - } - } - - if (!IgnoreNegatedSubRules) { - for (const auto &Rule : Rules) - SubjectMatchRules.push_back(Rule.first); - } else { - for (const auto &Rule : Rules) { - if (!isNegatedAttrMatcherSubRule(Rule.first)) - SubjectMatchRules.push_back(Rule.first); - } - } - Rules.clear(); - } else { - for (const auto &Rule : StrictSubjectMatchRuleSet) { - if (Rules.erase(Rule.first)) { - // Add the rule to the set of attribute receivers only if it's supported - // in the current language mode. - if (Rule.second) - SubjectMatchRules.push_back(Rule.first); - } - } - } - - if (!Rules.empty()) { - auto Diagnostic = - Diag(PragmaLoc, diag::err_pragma_attribute_invalid_matchers) - << Attribute.getName(); - SmallVector<attr::SubjectMatchRule, 2> ExtraRules; - for (const auto &Rule : Rules) { - ExtraRules.push_back(Rule.first); - Diagnostic << FixItHint::CreateRemoval( - replacementRangeForListElement(*this, Rule.second)); - } - Diagnostic << attrMatcherRuleListToString(ExtraRules); - } - - PragmaAttributeStack.push_back( - {PragmaLoc, &Attribute, std::move(SubjectMatchRules), /*IsUsed=*/false}); -} - -void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc) { - if (PragmaAttributeStack.empty()) { - Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch); - return; - } - const PragmaAttributeEntry &Entry = PragmaAttributeStack.back(); - if (!Entry.IsUsed) { - assert(Entry.Attribute && "Expected an attribute"); - Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused) - << Entry.Attribute->getName(); - Diag(PragmaLoc, diag::note_pragma_attribute_region_ends_here); - } - PragmaAttributeStack.pop_back(); -} - -void Sema::AddPragmaAttributes(Scope *S, Decl *D) { - if (PragmaAttributeStack.empty()) - return; - for (auto &Entry : PragmaAttributeStack) { - const AttributeList *Attribute = Entry.Attribute; - assert(Attribute && "Expected an attribute"); - - // Ensure that the attribute can be applied to the given declaration. - bool Applies = false; - for (const auto &Rule : Entry.MatchRules) { - if (Attribute->appliesToDecl(D, Rule)) { - Applies = true; - break; - } - } - if (!Applies) - continue; - Entry.IsUsed = true; - assert(!Attribute->getNext() && "Expected just one attribute"); - PragmaAttributeCurrentTargetDecl = D; - ProcessDeclAttributeList(S, D, Attribute); - PragmaAttributeCurrentTargetDecl = nullptr; - } -} - -void Sema::PrintPragmaAttributeInstantiationPoint() { - assert(PragmaAttributeCurrentTargetDecl && "Expected an active declaration"); - Diags.Report(PragmaAttributeCurrentTargetDecl->getLocStart(), - diag::note_pragma_attribute_applied_decl_here); -} - -void Sema::DiagnoseUnterminatedPragmaAttribute() { - if (PragmaAttributeStack.empty()) - return; - Diag(PragmaAttributeStack.back().Loc, diag::err_pragma_attribute_no_pop_eof); -} - void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) { if(On) OptimizeOffPragmaLocation = SourceLocation(); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 075e87b75cd..c6a0b0101d3 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13674,7 +13674,6 @@ CreateNewDecl: if (Attr) ProcessDeclAttributeList(S, New, Attr); - AddPragmaAttributes(S, New); // If this has an identifier, add it to the scope stack. if (TUK == TUK_Friend) { @@ -15186,7 +15185,6 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, // Process attributes. if (Attr) ProcessDeclAttributeList(S, New, Attr); - AddPragmaAttributes(S, New); // Register this decl in the current scope stack. New->setAccess(TheEnumDecl->getAccess()); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index ae941c88ca3..a1ba9de368d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6676,9 +6676,6 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { // Finally, apply any attributes on the decl itself. if (const AttributeList *Attrs = PD.getAttributes()) ProcessDeclAttributeList(S, D, Attrs); - - // Apply additional attributes specified by '#pragma clang attribute'. - AddPragmaAttributes(S, D); } /// Is the given declaration allowed to use a forbidden type? diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index b543a731641..fd3f266c9a0 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -8445,7 +8445,6 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, Namespc->setInvalidDecl(); ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList); - AddPragmaAttributes(DeclRegionScope, Namespc); // FIXME: Should we be merging attributes? if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>()) @@ -9932,7 +9931,6 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, NewTD->setInvalidDecl(); ProcessDeclAttributeList(S, NewTD, AttrList); - AddPragmaAttributes(S, NewTD); CheckTypedefForVariablyModifiedType(S, NewTD); Invalid |= NewTD->isInvalidDecl(); diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 4f51cd399c0..e50f8b20677 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -993,7 +993,6 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc, if (AttrList) ProcessDeclAttributeList(TUScope, IDecl, AttrList); - AddPragmaAttributes(TUScope, IDecl); PushOnScopeChains(IDecl, TUScope); // Start the definition of this class. If we're in a redefinition case, there @@ -1177,8 +1176,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, if (AttrList) ProcessDeclAttributeList(TUScope, PDecl, AttrList); - AddPragmaAttributes(TUScope, PDecl); - + // Merge attributes from previous declarations. if (PrevDecl) mergeDeclAttributes(PDecl, PrevDecl); @@ -1708,8 +1706,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, if (attrList) ProcessDeclAttributeList(TUScope, PDecl, attrList); - AddPragmaAttributes(TUScope, PDecl); - + if (PrevDecl) mergeDeclAttributes(PDecl, PrevDecl); @@ -1808,7 +1805,6 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, if (AttrList) ProcessDeclAttributeList(TUScope, CDecl, AttrList); - AddPragmaAttributes(TUScope, CDecl); CheckObjCDeclScope(CDecl); return ActOnObjCContainerStartDefinition(CDecl); @@ -1958,7 +1954,6 @@ Decl *Sema::ActOnStartClassImplementation( ClassName, /*typeParamList=*/nullptr, /*PrevDecl=*/nullptr, ClassLoc, true); - AddPragmaAttributes(TUScope, IDecl); IDecl->startDefinition(); if (SDecl) { IDecl->setSuperClass(Context.getTrivialTypeSourceInfo( @@ -3048,7 +3043,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, ClassName, TypeParams, PrevIDecl, IdentLocs[i]); IDecl->setAtEndRange(IdentLocs[i]); - + PushOnScopeChains(IDecl, TUScope); CheckObjCDeclScope(IDecl); DeclsInGroup.push_back(IDecl); @@ -4404,7 +4399,6 @@ Decl *Sema::ActOnMethodDeclaration( // Apply the attributes to the parameter. ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs); - AddPragmaAttributes(TUScope, Param); if (Param->hasAttr<BlocksAttr>()) { Diag(Param->getLocation(), diag::err_block_on_nonlocal); @@ -4435,7 +4429,6 @@ Decl *Sema::ActOnMethodDeclaration( if (AttrList) ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); - AddPragmaAttributes(TUScope, ObjCMethod); // Add the method now. const ObjCMethodDecl *PrevMethod = nullptr; |