From 7844d0af188cb376ec177cb1fb4bcb24272dc32b Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Tue, 18 Apr 2017 10:46:41 +0000 Subject: [PATCH] Revert r300539 - Add #pragma clang attribute Some tests fail on the Windows buildbots. I will have to investigate more. This commit reverts r300539, r300540 and r300542. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@300543 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LanguageExtensions.rst | 175 ------ include/clang/Basic/Attr.td | 109 ---- include/clang/Basic/AttrSubjectMatchRules.h | 46 -- include/clang/Basic/CMakeLists.txt | 5 - include/clang/Basic/DiagnosticGroups.td | 4 +- include/clang/Basic/DiagnosticParseKinds.td | 37 -- include/clang/Basic/DiagnosticSemaKinds.td | 19 - include/clang/Basic/TokenKinds.def | 3 - include/clang/Parse/CMakeLists.txt | 6 - include/clang/Parse/Parser.h | 7 - include/clang/Sema/AttributeList.h | 8 - include/clang/Sema/Sema.h | 32 -- lib/Basic/Attributes.cpp | 11 - lib/Parse/ParsePragma.cpp | 535 ------------------ lib/Parse/ParseStmt.cpp | 4 - lib/Parse/Parser.cpp | 4 - lib/Sema/AttributeList.cpp | 21 - lib/Sema/Sema.cpp | 67 ++- lib/Sema/SemaAttr.cpp | 211 ------- lib/Sema/SemaDecl.cpp | 2 - lib/Sema/SemaDeclAttr.cpp | 3 - lib/Sema/SemaDeclCXX.cpp | 2 - lib/Sema/SemaDeclObjC.cpp | 13 +- test/FixIt/fixit-pragma-attribute.c | 6 - test/FixIt/fixit-pragma-attribute.cpp | 83 --- ...agma-attribute-cxx-subject-match-rules.cpp | 169 ------ test/Misc/pragma-attribute-cxx.cpp | 106 ---- ...ragma-attribute-objc-subject-match-rules.m | 113 ---- test/Misc/pragma-attribute-objc.m | 164 ------ test/Misc/pragma-attribute-strict-subjects.c | 222 -------- ...a-attribute-supported-attributes-list.test | 62 -- test/Parser/pragma-attribute-declspec.cpp | 13 - test/Parser/pragma-attribute.cpp | 181 ------ test/Sema/pragma-attribute-strict-subjects.c | 153 ----- test/Sema/pragma-attribute.c | 47 -- test/lit.cfg | 2 - test/lit.site.cfg.in | 1 - utils/TableGen/ClangAttrEmitter.cpp | 445 +-------------- utils/TableGen/TableGen.cpp | 31 +- utils/TableGen/TableGenBackends.h | 6 - 40 files changed, 52 insertions(+), 3076 deletions(-) delete mode 100644 include/clang/Basic/AttrSubjectMatchRules.h delete mode 100644 test/FixIt/fixit-pragma-attribute.c delete mode 100644 test/FixIt/fixit-pragma-attribute.cpp delete mode 100644 test/Misc/pragma-attribute-cxx-subject-match-rules.cpp delete mode 100644 test/Misc/pragma-attribute-cxx.cpp delete mode 100644 test/Misc/pragma-attribute-objc-subject-match-rules.m delete mode 100644 test/Misc/pragma-attribute-objc.m delete mode 100644 test/Misc/pragma-attribute-strict-subjects.c delete mode 100644 test/Misc/pragma-attribute-supported-attributes-list.test delete mode 100644 test/Parser/pragma-attribute-declspec.cpp delete mode 100644 test/Parser/pragma-attribute.cpp delete mode 100644 test/Sema/pragma-attribute-strict-subjects.c delete mode 100644 test/Sema/pragma-attribute.c diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst index 187dae751b..a8fb4623b6 100644 --- a/docs/LanguageExtensions.rst +++ b/docs/LanguageExtensions.rst @@ -2346,178 +2346,3 @@ statements in C) The pragma can also be used with ``off`` which turns FP contraction off for a section of the code. This can be useful when fast contraction is otherwise enabled for the translation unit with the ``-ffp-contract=fast`` flag. - -Specifying an attribute for multiple declarations (#pragma clang attribute) -=========================================================================== - -The ``#pragma clang attribute`` directive can be used to apply an attribute to -multiple declarations. The ``#pragma clang attribute push`` variation of the -directive pushes a new attribute to the attribute stack. The declarations that -follow the pragma receive the attributes that are on the attribute stack, until -the stack is cleared using a ``#pragma clang attribute pop`` directive. Multiple -push directives can be nested inside each other. - -The attributes that are used in the ``#pragma clang attribute`` directives -can be written using the GNU-style syntax: - -.. code-block:: c++ - - #pragma clang attribute push(__attribute__((annotate("custom"))), apply_to = function) - - void function(); // The function now has the annotate("custom") attribute - - #pragma clang attribute pop - -The attributes can also be written using the C++11 style syntax: - -.. code-block:: c++ - - #pragma clang attribute push([[noreturn]], apply_to = function) - - void function(); // The function now has the [[noreturn]] attribute - - #pragma clang attribute pop - -The ``__declspec`` style syntax is also supported: - -.. code-block:: c++ - - #pragma clang attribute push(__declspec(dllexport), apply_to = function) - - void function(); // The function now has the __declspec(dllexport) attribute - - #pragma clang attribute pop - -A single push directive accepts only one attribute regardless of the syntax -used. - -Subject Match Rules -------------------- - -The set of declarations that receive a single attribute from the attribute stack -depends on the subject match rules that were specified in the pragma. Subject -match rules are specified after the attribute. The compiler expects an -identifier that corresponds to the subject set specifier. The ``apply_to`` -specifier is currently the only supported subject set specifier. It allows you -to specify match rules that form a subset of the attribute's allowed subject -set, i.e. the compiler doesn't require all of the attribute's subjects. For -example, an attribute like ``[[nodiscard]]`` whose subject set includes -``enum``, ``record`` and ``hasType(functionType)``, requires the presence of at -least one of these rules after ``apply_to``: - -.. code-block:: c++ - - #pragma clang attribute push([[nodiscard]], apply_to = enum) - - enum Enum1 { A1, B1 }; // The enum will receive [[nodiscard]] - - struct Record1 { }; // The struct will *not* receive [[nodiscard]] - - #pragma clang attribute pop - - #pragma clang attribute push([[nodiscard]], apply_to = any(record, enum)) - - enum Enum2 { A2, B2 }; // The enum will receive [[nodiscard]] - - struct Record2 { }; // The struct *will* receive [[nodiscard]] - - #pragma clang attribute pop - - // This is an error, since [[nodiscard]] can't be applied to namespaces: - #pragma clang attribute push([[nodiscard]], apply_to = any(record, namespace)) - - #pragma clang attribute pop - -Multiple match rules can be specified using the ``any`` match rule, as shown -in the example above. The ``any`` rule applies attributes to all declarations -that are matched by at least one of the rules in the ``any``. It doesn't nest -and can't be used inside the other match rules. Redundant match rules or rules -that conflict with one another should not be used inside of ``any``. - -Clang supports the following match rules: - -- ``function``: Can be used to apply attributes to functions. This includes C++ - member functions, static functions, operators, and constructors/destructors. - -- ``function(is_member)``: Can be used to apply attributes to C++ member - functions. This includes members like static functions, operators, and - constructors/destructors. - -- ``hasType(functionType)``: Can be used to apply attributes to functions, C++ - member functions, and variables/fields whose type is a function pointer. It - does not apply attributes to Objective-C methods or blocks. - -- ``type_alias``: Can be used to apply attributes to ``typedef`` declarations - and C++11 type aliases. - -- ``record``: Can be used to apply attributes to ``struct``, ``class``, and - ``union`` declarations. - -- ``record(unless(is_union))``: Can be used to apply attributes only to - ``struct`` and ``class`` declarations. - -- ``enum``: Can be be used to apply attributes to enumeration declarations. - -- ``enum_constant``: Can be used to apply attributes to enumerators. - -- ``variable``: Can be used to apply attributes to variables, including - local variables, parameters, global variables, and static member variables. - It does not apply attributes to instance member variables or Objective-C - ivars. - -- ``variable(is_thread_local)``: Can be used to apply attributes to thread-local - variables only. - -- ``variable(is_global)``: Can be used to apply attributes to global variables - only. - -- ``variable(is_parameter)``: Can be used to apply attributes to parameters - only. - -- ``variable(unless(is_parameter))``: Can be used to apply attributes to all - the variables that are not parameters. - -- ``field``: Can be used to apply attributes to non-static member variables - in a record. This includes Objective-C ivars. - -- ``namespace``: Can be used to apply attributes to ``namespace`` declarations. - -- ``objc_interface``: Can be used to apply attributes to ``@interface`` - declarations. - -- ``objc_protocol``: Can be used to apply attributes to ``@protocol`` - declarations. - -- ``objc_category``: Can be used to apply attributes to category declarations, - including class extensions. - -- ``objc_method``: Can be used to apply attributes to Objective-C methods, - including instance and class methods. Implicit methods like implicit property - getters and setters do not receive the attribute. - -- ``objc_method(is_instance)``: Can be used to apply attributes to Objective-C - instance methods. - -- ``objc_property``: Can be used to apply attributes to ``@property`` - declarations. - -- ``block``: Can be used to apply attributes to block declarations. This does - not include variables/fields of block pointer type. - -The use of ``unless`` in match rules is currently restricted to a strict set of -sub-rules that are used by the supported attributes. That means that even though -``variable(unless(is_parameter))`` is a valid match rule, -``variable(unless(is_thread_local))`` is not. - -Supported Attributes --------------------- - -Not all attributes can be used with the ``#pragma clang attribute`` directive. -Notably, statement attributes like ``[[fallthrough]]`` or type attributes -like ``address_space`` aren't supported by this directive. You can determine -whether or not an attribute is supported by the pragma by referring to the -:doc:`individual documentation for that attribute `. - -The attributes are applied to all matching declarations individually, even when -the attribute is semantically incorrect. The attributes that aren't applied to -any declaration are not verified semantically. diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index bf62408db2..c5d2c7fc61 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -248,8 +248,6 @@ def COnly : LangOpt<"CPlusPlus", 1>; def CPlusPlus : LangOpt<"CPlusPlus">; def OpenCL : LangOpt<"OpenCL">; def RenderScript : LangOpt<"RenderScript">; -def ObjC : LangOpt<"ObjC1">; -def BlocksSupported : LangOpt<"Blocks">; // Defines targets for target-specific attributes. The list of strings should // specify architectures for which the target applies, based off the ArchType @@ -272,102 +270,6 @@ def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb"]> { let CXXABIs = ["Microsoft"]; } -// Attribute subject match rules that are used for #pragma clang attribute. -// -// A instance of AttrSubjectMatcherRule represents an individual match rule. -// An individual match rule can correspond to a number of different attribute -// subjects, e.g. "record" matching rule corresponds to the Record and -// CXXRecord attribute subjects. -// -// Match rules are used in the subject list of the #pragma clang attribute. -// Match rules can have sub-match rules that are instances of -// AttrSubjectMatcherSubRule. A sub-match rule can correspond to a number -// of different attribute subjects, and it can have a negated spelling as well. -// For example, "variable(unless(is_parameter))" matching rule corresponds to -// the NonParmVar attribute subject. -class AttrSubjectMatcherSubRule subjects, - bit negated = 0> { - string Name = name; - list Subjects = subjects; - bit Negated = negated; - // Lists language options, one of which is required to be true for the - // attribute to be applicable. If empty, the language options are taken - // from the parent matcher rule. - list LangOpts = []; -} -class AttrSubjectMatcherRule subjects, - list subrules = []> { - string Name = name; - list Subjects = subjects; - list Constraints = subrules; - // Lists language options, one of which is required to be true for the - // attribute to be applicable. If empty, no language options are required. - list LangOpts = []; -} - -// function(is_member) -def SubRuleForCXXMethod : AttrSubjectMatcherSubRule<"is_member", [CXXMethod]> { - let LangOpts = [CPlusPlus]; -} -def SubjectMatcherForFunction : AttrSubjectMatcherRule<"function", [Function], [ - SubRuleForCXXMethod -]>; -// hasType is abstract, it should be used with one of the sub-rules. -def SubjectMatcherForType : AttrSubjectMatcherRule<"hasType", [], [ - AttrSubjectMatcherSubRule<"functionType", [FunctionLike]> - - // FIXME: There's a matcher ambiguity with objc methods and blocks since - // functionType excludes them but functionProtoType includes them. - // AttrSubjectMatcherSubRule<"functionProtoType", [HasFunctionProto]> -]>; -def SubjectMatcherForTypedef : AttrSubjectMatcherRule<"type_alias", - [TypedefName]>; -def SubjectMatcherForRecord : AttrSubjectMatcherRule<"record", [Record, - CXXRecord], [ - // unless(is_union) - AttrSubjectMatcherSubRule<"is_union", [Struct], 1> -]>; -def SubjectMatcherForEnum : AttrSubjectMatcherRule<"enum", [Enum]>; -def SubjectMatcherForEnumConstant : AttrSubjectMatcherRule<"enum_constant", - [EnumConstant]>; -def SubjectMatcherForVar : AttrSubjectMatcherRule<"variable", [Var], [ - AttrSubjectMatcherSubRule<"is_thread_local", [TLSVar]>, - AttrSubjectMatcherSubRule<"is_global", [GlobalVar]>, - AttrSubjectMatcherSubRule<"is_parameter", [ParmVar]>, - // unless(is_parameter) - AttrSubjectMatcherSubRule<"is_parameter", [NonParmVar], 1> -]>; -def SubjectMatcherForField : AttrSubjectMatcherRule<"field", [Field]>; -def SubjectMatcherForNamespace : AttrSubjectMatcherRule<"namespace", - [Namespace]> { - let LangOpts = [CPlusPlus]; -} -def SubjectMatcherForObjCInterface : AttrSubjectMatcherRule<"objc_interface", - [ObjCInterface]> { - let LangOpts = [ObjC]; -} -def SubjectMatcherForObjCProtocol : AttrSubjectMatcherRule<"objc_protocol", - [ObjCProtocol]> { - let LangOpts = [ObjC]; -} -def SubjectMatcherForObjCCategory : AttrSubjectMatcherRule<"objc_category", - [ObjCCategory]> { - let LangOpts = [ObjC]; -} -def SubjectMatcherForObjCMethod : AttrSubjectMatcherRule<"objc_method", - [ObjCMethod], [ - AttrSubjectMatcherSubRule<"is_instance", [ObjCInstanceMethod]> -]> { - let LangOpts = [ObjC]; -} -def SubjectMatcherForObjCProperty : AttrSubjectMatcherRule<"objc_property", - [ObjCProperty]> { - let LangOpts = [ObjC]; -} -def SubjectMatcherForBlock : AttrSubjectMatcherRule<"block", [Block]> { - let LangOpts = [BlocksSupported]; -} - class Attr { // The various ways in which an attribute can be spelled in source list Spellings; @@ -403,14 +305,6 @@ class Attr { // Set to true if this attribute meaningful when applied to or inherited // in a class template definition. bit MeaningfulToClassTemplateDefinition = 0; - // Set to true if this attribute can be used with '#pragma clang attribute'. - // By default, when this value is false, an attribute is supported by the - // '#pragma clang attribute' only when: - // - It has documentation. - // - It has a subject list whose subjects can be represented using subject - // match rules. - // - It has GNU/CXX11 spelling and doesn't require delayed parsing. - bit ForcePragmaAttributeSupport = 0; // Lists language options, one of which is required to be true for the // attribute to be applicable. If empty, no language options are required. list LangOpts = []; @@ -584,9 +478,6 @@ def AnalyzerNoReturn : InheritableAttr { def Annotate : InheritableParamAttr { let Spellings = [GNU<"annotate">]; let Args = [StringArgument<"Annotation">]; - // Ensure that the annotate attribute can be used with - // '#pragma clang attribute' even though it has no subject list. - let ForcePragmaAttributeSupport = 1; let Documentation = [Undocumented]; } diff --git a/include/clang/Basic/AttrSubjectMatchRules.h b/include/clang/Basic/AttrSubjectMatchRules.h deleted file mode 100644 index 955f495ad6..0000000000 --- a/include/clang/Basic/AttrSubjectMatchRules.h +++ /dev/null @@ -1,46 +0,0 @@ -//===-- AttrSubjectMatchRules.h - Attribute subject match rules -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_BASIC_ATTR_SUBJECT_MATCH_RULES_H -#define LLVM_CLANG_BASIC_ATTR_SUBJECT_MATCH_RULES_H - -#include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/DenseMap.h" - -namespace clang { -namespace attr { - -/// \brief A list of all the recognized kinds of attributes. -enum SubjectMatchRule { -#define ATTR_MATCH_RULE(X, Spelling, IsAbstract) X, -#include "clang/Basic/AttrSubMatchRulesList.inc" -}; - -const char *getSubjectMatchRuleSpelling(SubjectMatchRule Rule); - -using ParsedSubjectMatchRuleSet = llvm::DenseMap; - -} // end namespace attr -} // end namespace clang - -namespace llvm { - -template <> -struct DenseMapInfo : DenseMapInfo { - static inline clang::attr::SubjectMatchRule getEmptyKey() { - return (clang::attr::SubjectMatchRule)DenseMapInfo::getEmptyKey(); - } - static inline clang::attr::SubjectMatchRule getTombstoneKey() { - return (clang::attr::SubjectMatchRule)DenseMapInfo::getTombstoneKey(); - } -}; - -} // end namespace llvm - -#endif diff --git a/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt index 3e0fb8728c..e4929b5b52 100644 --- a/include/clang/Basic/CMakeLists.txt +++ b/include/clang/Basic/CMakeLists.txt @@ -28,11 +28,6 @@ clang_tablegen(AttrList.inc -gen-clang-attr-list SOURCE Attr.td TARGET ClangAttrList) -clang_tablegen(AttrSubMatchRulesList.inc -gen-clang-attr-subject-match-rule-list - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ - SOURCE Attr.td - TARGET ClangAttrSubjectMatchRuleList) - clang_tablegen(AttrHasAttributeImpl.inc -gen-clang-attr-has-attribute-impl -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ SOURCE Attr.td diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 4cde1c81fd..4bcf3be0a8 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -461,9 +461,7 @@ def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes, def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">; def UnknownPragmas : DiagGroup<"unknown-pragmas">; def IgnoredPragmas : DiagGroup<"ignored-pragmas", [IgnoredPragmaIntrinsic]>; -def PragmaClangAttribute : DiagGroup<"pragma-clang-attribute">; -def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas, - PragmaClangAttribute]>; +def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas]>; def UnknownWarningOption : DiagGroup<"unknown-warning-option">; def NSobjectAttribute : DiagGroup<"NSObject-attribute">; def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index d95e43c10c..aebf8a9f35 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -979,43 +979,6 @@ def err_pragma_optimize_invalid_argument : Error< "expected 'on' or 'off'">; def err_pragma_optimize_extra_argument : Error< "unexpected extra argument '%0' to '#pragma clang optimize'">; -// - #pragma clang attribute -def err_pragma_attribute_expected_push_pop : Error< - "expected 'push' or 'pop' after '#pragma clang attribute'">; -def err_pragma_attribute_invalid_argument : Error< - "unexpected argument '%0' to '#pragma clang attribute'; " - "expected 'push' or 'pop'">; -def err_pragma_attribute_expected_attribute : Error< - "expected an attribute after '('">; -def err_pragma_attribute_expected_attribute_name : Error< - "expected identifier that represents an attribute name">; -def err_pragma_attribute_extra_tokens_after_attribute : Error< - "extra tokens after attribute in a '#pragma clang attribute push'">; -def err_pragma_attribute_unsupported_attribute : Error< - "attribute %0 is not supported by '#pragma clang attribute'">; -def err_pragma_attribute_multiple_attributes : Error< - "more than one attribute specified in '#pragma clang attribute push'">; -def err_pragma_attribute_expected_attribute_syntax : Error< - "expected an attribute that is specified using the GNU, C++11 or '__declspec'" - " syntax">; -def note_pragma_attribute_use_attribute_kw : Note<"use the GNU '__attribute__' " - "syntax">; -def err_pragma_attribute_invalid_subject_set_specifier : Error< - "expected attribute subject set specifier 'apply_to'">; -def err_pragma_attribute_expected_subject_identifier : Error< - "expected an identifier that corresponds to an attribute subject rule">; -def err_pragma_attribute_unknown_subject_rule : Error< - "unknown attribute subject rule '%0'">; -def err_pragma_attribute_expected_subject_sub_identifier : Error< - "expected an identifier that corresponds to an attribute subject matcher " - "sub-rule; '%0' matcher %select{does not support sub-rules|supports the " - "following sub-rules: %2|}1">; -def err_pragma_attribute_unknown_subject_sub_rule : Error< - "%select{invalid use of|unknown}2 attribute subject matcher sub-rule '%0'; " - "'%1' matcher %select{does not support sub-rules|supports the following " - "sub-rules: %3}2">; -def err_pragma_attribute_duplicate_subject : Error< - "duplicate attribute subject matcher '%0'">; def err_opencl_unroll_hint_on_non_loop : Error< "OpenCL only supports 'opencl_unroll_hint' attribute on for, while, and do statements">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 3912a85491..8afe61645a 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -750,25 +750,6 @@ def err_pragma_loop_compatibility : Error< def err_pragma_loop_precedes_nonloop : Error< "expected a for, while, or do-while loop to follow '%0'">; -def err_pragma_attribute_matcher_subrule_contradicts_rule : Error< - "redundant attribute subject matcher sub-rule '%0'; '%1' already matches " - "those declarations">; -def err_pragma_attribute_matcher_negated_subrule_contradicts_subrule : Error< - "negated attribute subject matcher sub-rule '%0' contradicts sub-rule '%1'">; -def err_pragma_attribute_invalid_matchers : Error< - "attribute %0 can't be applied to %1">; -def err_pragma_attribute_stack_mismatch : Error< - "'#pragma clang attribute pop' with no matching '#pragma clang attribute push'">; -def warn_pragma_attribute_unused : Warning< - "unused attribute %0 in '#pragma clang attribute push' region">, - InGroup; -def note_pragma_attribute_region_ends_here : Note< - "'#pragma clang attribute push' regions ends here">; -def err_pragma_attribute_no_pop_eof : Error<"unterminated " - "'#pragma clang attribute push' at end of file">; -def note_pragma_attribute_applied_decl_here : Note< - "when applied to this declaration">; - /// Objective-C parser diagnostics def err_duplicate_class_def : Error< "duplicate interface definition for class %0">; diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 968b203a38..48e0c33f0e 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -790,9 +790,6 @@ ANNOTATION(pragma_loop_hint) ANNOTATION(pragma_fp) -// Annotation for the attribute pragma directives - #pragma clang attribute ... -ANNOTATION(pragma_attribute) - // Annotations for module import translated from #include etc. ANNOTATION(module_include) ANNOTATION(module_begin) diff --git a/include/clang/Parse/CMakeLists.txt b/include/clang/Parse/CMakeLists.txt index 2cc7e54b3b..ec75f7b96b 100644 --- a/include/clang/Parse/CMakeLists.txt +++ b/include/clang/Parse/CMakeLists.txt @@ -2,9 +2,3 @@ clang_tablegen(AttrParserStringSwitches.inc -gen-clang-attr-parser-string-switch -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ SOURCE ../Basic/Attr.td TARGET ClangAttrParserStringSwitches) - -clang_tablegen(AttrSubMatchRulesParserStringSwitches.inc - -gen-clang-attr-subject-match-rules-parser-string-switches - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ - SOURCE ../Basic/Attr.td - TARGET ClangAttrSubMatchRulesParserStringSwitches) diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 8d0935dec1..5f4e5fb4b2 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -184,7 +184,6 @@ class Parser : public CodeCompletionHandler { std::unique_ptr UnrollHintHandler; std::unique_ptr NoUnrollHintHandler; std::unique_ptr FPHandler; - std::unique_ptr AttributePragmaHandler; std::unique_ptr CommentSemaHandler; @@ -566,12 +565,6 @@ private: /// #pragma clang loop and #pragma unroll. bool HandlePragmaLoopHint(LoopHint &Hint); - bool ParsePragmaAttributeSubjectMatchRuleSet( - attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, - SourceLocation &AnyLoc, SourceLocation &LastMatchRuleEndLoc); - - void HandlePragmaAttribute(); - /// GetLookAheadToken - This peeks ahead N tokens and returns that token /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1) /// returns the token after Tok, etc. diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index f3b042c9ce..7c1678086c 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -15,7 +15,6 @@ #ifndef LLVM_CLANG_SEMA_ATTRIBUTELIST_H #define LLVM_CLANG_SEMA_ATTRIBUTELIST_H -#include "clang/Basic/AttrSubjectMatchRules.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/VersionTuple.h" @@ -510,14 +509,9 @@ public: unsigned getMaxArgs() const; bool hasVariadicArg() const; bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const; - bool appliesToDecl(const Decl *D, attr::SubjectMatchRule MatchRule) const; - void getMatchRules(const LangOptions &LangOpts, - SmallVectorImpl> - &MatchRules) const; bool diagnoseLangOpts(class Sema &S) const; bool existsInTarget(const TargetInfo &Target) const; bool isKnownToGCC() const; - bool isSupportedByPragmaAttribute() const; /// \brief If the parsed attribute has a semantic equivalent, and it would /// have a semantic Spelling enumeration (due to having semantically-distinct @@ -780,8 +774,6 @@ public: void clear() { list = nullptr; pool.clear(); } AttributeList *getList() const { return list; } - void clearListOnly() { list = nullptr; } - /// Returns a reference to the attribute list. Try not to introduce /// dependencies on this method, it may not be long-lived. AttributeList *&getListRef() { return list; } diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index bd68842c9f..5a3cdfb77c 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -437,20 +437,6 @@ public: /// VisContext - Manages the stack for \#pragma GCC visibility. void *VisContext; // Really a "PragmaVisStack*" - /// \brief This represents the stack of attributes that were pushed by - /// \#pragma clang attribute. - struct PragmaAttributeEntry { - SourceLocation Loc; - AttributeList *Attribute; - SmallVector MatchRules; - bool IsUsed; - }; - SmallVector PragmaAttributeStack; - - /// \brief The declaration that is currently receiving an attribute from the - /// #pragma attribute stack. - const Decl *PragmaAttributeCurrentTargetDecl; - /// \brief This represents the last location of a "#pragma clang optimize off" /// directive if such a directive has not been closed by an "on" yet. If /// optimizations are currently "on", this is set to an invalid location. @@ -7220,13 +7206,9 @@ public: PrintInstantiationStack(); LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size(); } - if (PragmaAttributeCurrentTargetDecl) - PrintPragmaAttributeInstantiationPoint(); } void PrintInstantiationStack(); - void PrintPragmaAttributeInstantiationPoint(); - /// \brief Determines whether we are currently in a context where /// template argument substitution failures are not considered /// errors. @@ -8170,20 +8152,6 @@ public: /// the appropriate attribute. void AddCFAuditedAttribute(Decl *D); - /// \brief Called on well-formed '\#pragma clang attribute push'. - void ActOnPragmaAttributePush(AttributeList &Attribute, - SourceLocation PragmaLoc, - attr::ParsedSubjectMatchRuleSet Rules); - - /// \brief Called on well-formed '\#pragma clang attribute pop'. - void ActOnPragmaAttributePop(SourceLocation PragmaLoc); - - /// \brief Adds the attributes that have been specified using the - /// '\#pragma clang attribute push' directives to the given declaration. - void AddPragmaAttributes(Scope *S, Decl *D); - - void DiagnoseUnterminatedPragmaAttribute(); - /// \brief Called on well formed \#pragma clang optimize. void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc); diff --git a/lib/Basic/Attributes.cpp b/lib/Basic/Attributes.cpp index b7570d03c8..c215366fc3 100644 --- a/lib/Basic/Attributes.cpp +++ b/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/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index abddb6ba67..c8de6b35f9 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/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 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, - llvm::function_ref(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, 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(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 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(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(Info)); - PP.EnterTokenStream(std::move(TokenArray), 1, - /*DisableMacroExpansion=*/false); -} diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 7d78046d06..eaff9fe8ee 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/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/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 265c12d7d5..aa8ed91d38 100644 --- a/lib/Parse/Parser.cpp +++ b/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/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp index 724db45678..55e9601bf5 100644 --- a/lib/Sema/AttributeList.cpp +++ b/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> &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> &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/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 950f040888..294b56059b 100644 --- a/lib/Sema/Sema.cpp +++ b/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/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index dfc5d6cd01..c6e3cc8863 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -368,217 +368,6 @@ void Sema::AddCFAuditedAttribute(Decl *D) { D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc)); } -namespace { - -Optional -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 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 SubjectMatchRules; - // Gather the subject match rules that are supported by the attribute. - SmallVector, 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, 2> - RulesToFirstSpecifiedNegatedSubRule; - for (const auto &Rule : Rules) { - Optional 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 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 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/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 075e87b75c..c6a0b0101d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/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/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index ae941c88ca..a1ba9de368 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/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/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index b543a73164..fd3f266c9a 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/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()) @@ -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/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 4f51cd399c..e50f8b2067 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/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()) { 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; diff --git a/test/FixIt/fixit-pragma-attribute.c b/test/FixIt/fixit-pragma-attribute.c deleted file mode 100644 index f166eb2978..0000000000 --- a/test/FixIt/fixit-pragma-attribute.c +++ /dev/null @@ -1,6 +0,0 @@ -// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s -// Verify that the suggested attribute subject match rules don't include the -// rules that are not applicable in the current language mode. - -#pragma clang attribute push (__attribute__((abi_tag("a")))) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:60}:", apply_to = any(record(unless(is_union)), variable, function)" diff --git a/test/FixIt/fixit-pragma-attribute.cpp b/test/FixIt/fixit-pragma-attribute.cpp deleted file mode 100644 index 8e3f6d9392..0000000000 --- a/test/FixIt/fixit-pragma-attribute.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -Wno-pragma-clang-attribute %s 2>&1 | FileCheck %s - -#pragma clang attribute push (annotate) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:31-[[@LINE-1]]:31}:"__attribute__((" -// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:39-[[@LINE-2]]:39}:"))" -#pragma clang attribute push (annotate(("test"))) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:31-[[@LINE-1]]:31}:"__attribute__((" -// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:49-[[@LINE-2]]:49}:"))" - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( enum, function, function, namespace, function )) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:97-[[@LINE-1]]:107}:"" -// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:118-[[@LINE-2]]:127}:"" - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(is_global), function, variable(is_global), variable(is_global) )) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:112-[[@LINE-1]]:133}:"" -// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:133-[[@LINE-2]]:153}:"" - -#pragma clang attribute push (__attribute__((annotate("subRuleContradictions"))), apply_to = any(variable, variable(is_parameter), function(is_member), variable(is_global))) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:108-[[@LINE-1]]:132}:"" -// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:153-[[@LINE-2]]:172}:"" - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((annotate("subRuleContradictions2"))), apply_to = any(function(is_member),function)) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:99-[[@LINE-1]]:119}:"" - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((annotate("negatedSubRuleContradictions1"))), apply_to = any(variable(is_parameter), variable(unless(is_parameter)))) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:130-[[@LINE-1]]:160}:"" -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((annotate("negatedSubRuleContradictions2"))), apply_to = any(variable(unless(is_parameter)), variable(is_thread_local), function, variable(is_global))) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:106-[[@LINE-1]]:137}:"" -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(enum, variable)) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:77-[[@LINE-1]]:82}:"" -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a")))) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:60}:", apply_to = any(record(unless(is_union)), variable, function, namespace)" -#pragma clang attribute push (__attribute__((abi_tag("a"))) apply_to=function) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:60}:", " -#pragma clang attribute push (__attribute__((abi_tag("a"))) = function) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:60}:", apply_to" -#pragma clang attribute push (__attribute__((abi_tag("a"))) any(function)) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:60}:", apply_to = " - -#pragma clang attribute push (__attribute__((abi_tag("a"))) 22) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:63}:", apply_to = any(record(unless(is_union)), variable, function, namespace)" -#pragma clang attribute push (__attribute__((abi_tag("a"))) function) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:69}:", apply_to = any(record(unless(is_union)), variable, function, namespace)" -#pragma clang attribute push (__attribute__((abi_tag("a"))) (function)) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:71}:", apply_to = any(record(unless(is_union)), variable, function, namespace)" - -#pragma clang attribute push (__attribute__((abi_tag("a"))), ) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:61-[[@LINE-1]]:62}:"apply_to = any(record(unless(is_union)), variable, function, namespace)" -#pragma clang attribute push (__attribute__((abi_tag("a"))), = function) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:61-[[@LINE-1]]:61}:"apply_to" -#pragma clang attribute push (__attribute__((abi_tag("a"))), any(function)) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:61-[[@LINE-1]]:61}:"apply_to = " - -#pragma clang attribute push (__attribute__((abi_tag("a"))), 22) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:61-[[@LINE-1]]:64}:"apply_to = any(record(unless(is_union)), variable, function, namespace)" -#pragma clang attribute push (__attribute__((abi_tag("a"))), 1, 2) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:61-[[@LINE-1]]:66}:"apply_to = any(record(unless(is_union)), variable, function, namespace)" -#pragma clang attribute push (__attribute__((abi_tag("a"))), function) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:61-[[@LINE-1]]:70}:"apply_to = any(record(unless(is_union)), variable, function, namespace)" -#pragma clang attribute push (__attribute__((abi_tag("a"))), (function)) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:61-[[@LINE-1]]:72}:"apply_to = any(record(unless(is_union)), variable, function, namespace)" - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:70-[[@LINE-1]]:70}:" = any(record(unless(is_union)), variable, function, namespace)" -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to any(function)) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:70-[[@LINE-1]]:70}:" = " - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to 41 (22)) -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:70-[[@LINE-1]]:78}:" = any(record(unless(is_union)), variable, function, namespace)" - -// Don't give fix-it to attributes without a strict subject set -#pragma clang attribute push (__attribute__((annotate("a")))) -// CHECK-NO: [[@LINE-1]]:61 diff --git a/test/Misc/pragma-attribute-cxx-subject-match-rules.cpp b/test/Misc/pragma-attribute-cxx-subject-match-rules.cpp deleted file mode 100644 index b7741343ad..0000000000 --- a/test/Misc/pragma-attribute-cxx-subject-match-rules.cpp +++ /dev/null @@ -1,169 +0,0 @@ -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=namespace" %s | FileCheck --check-prefix=CHECK-NAMESPACE %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=type_alias" %s | FileCheck --check-prefix=CHECK-TYPE_ALIAS %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=enum" %s | FileCheck --check-prefix=CHECK-ENUM %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=enum_constant" %s | FileCheck --check-prefix=CHECK-ENUM_CONSTANT %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=record" %s | FileCheck --check-prefix=CHECK-RECORD %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=record(unless(is_union))" %s | FileCheck --check-prefix=CHECK-RECORD_UNLESS_IS_UNION %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=field" %s | FileCheck --check-prefix=CHECK-FIELD %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=function" %s | FileCheck --check-prefix=CHECK-FUNCTION %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=hasType(functionType)" %s | FileCheck --check-prefix=CHECK-HAS_TYPE_FUNCTION_TYPE %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=function(is_member)" %s | FileCheck --check-prefix=CHECK-FUNCTION_IS_MEMBER %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=variable" %s | FileCheck --check-prefix=CHECK-VARIABLE %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=variable(is_global)" %s | FileCheck --check-prefix=CHECK-VARIABLE_IS_GLOBAL %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=variable(is_parameter)" %s | FileCheck --check-prefix=CHECK-VARIABLE_IS_PARAMETER %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=variable(unless(is_parameter))" %s | FileCheck --check-prefix=CHECK-VARIABLE_UNLESS_IS_PARAMETER %s - -#pragma clang attribute push (__attribute__((annotate("test"))), apply_to = any(SUBJECT)) - -namespace testNamespace { -// CHECK-NAMESPACE: NamespaceDecl{{.*}} testNamespace -// CHECK-NAMESPACE-NEXT: AnnotateAttr{{.*}} "test" - -typedef int testTypedef; -// CHECK-TYPE_ALIAS: TypedefDecl{{.*}} testTypedef -// CHECK-TYPE_ALIAS-NEXT: BuiltinType -// CHECK-TYPE_ALIAS-NEXT: AnnotateAttr{{.*}} "test" - -using testTypeAlias = double; -// CHECK-TYPE_ALIAS: TypeAliasDecl{{.*}} testTypeAlias -// CHECK-TYPE_ALIAS-NEXT: BuiltinType -// CHECK-TYPE_ALIAS-NEXT: AnnotateAttr{{.*}} "test" - -enum testEnum { - testEnumCase1, - testEnumCase2 -}; -// CHECK-ENUM: EnumDecl{{.*}} testEnum -// CHECK-ENUM-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-ENUM_CONSTANT: EnumConstantDecl{{.*}} testEnumCase1 -// CHECK-ENUM_CONSTANT-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-ENUM_CONSTANT: EnumConstantDecl{{.*}} testEnumCase2 -// CHECK-ENUM_CONSTANT-NEXT: AnnotateAttr{{.*}} "test" - -struct testStructRecord { - int testStructRecordField; -}; -// CHECK-RECORD: CXXRecordDecl{{.*}} testStructRecord -// CHECK-RECORD-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-RECORD_UNLESS_IS_UNION-LABEL: CXXRecordDecl{{.*}} testStructRecord -// CHECK-RECORD_UNLESS_IS_UNION-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-FIELD: FieldDecl{{.*}} testStructRecordField -// CHECK-FIELD-NEXT: AnnotateAttr{{.*}} "test" - -class testClassRecord { - int testClassRecordField; -}; -// CHECK-RECORD: CXXRecordDecl{{.*}} testClassRecord -// CHECK-RECORD-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-RECORD_UNLESS_IS_UNION-LABEL: CXXRecordDecl{{.*}} testClassRecord -// CHECK-RECORD_UNLESS_IS_UNION-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-FIELD: FieldDecl{{.*}} testClassRecordField -// CHECK-FIELD-NEXT: AnnotateAttr{{.*}} "test" - -union testUnionRecord { - int testUnionRecordField; -}; -// CHECK-RECORD: CXXRecordDecl{{.*}} testUnionRecord -// CHECK-RECORD-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-RECORD_UNLESS_IS_UNION-LABEL: CXXRecordDecl{{.*}} testUnionRecord -// CHECK-RECORD_UNLESS_IS_UNION-NOT: AnnotateAttr{{.*}} "test" -// CHECK-FIELD: FieldDecl{{.*}} testUnionRecordField -// CHECK-FIELD-NEXT: AnnotateAttr{{.*}} "test" - -// CHECK-RECORD_UNLESS_IS_UNION-LABEL: CXXRecordDecl -void testFunctionDecl(); -// CHECK-FUNCTION: FunctionDecl{{.*}} testFunctionDecl -// CHECK-FUNCTION-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-HAS_TYPE_FUNCTION_TYPE: FunctionDecl{{.*}} testFunctionDecl -// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: AnnotateAttr{{.*}} "test" - -void testFunctionDecl() { } -// CHECK-FUNCTION: FunctionDecl{{.*}} testFunctionDecl -// CHECK-FUNCTION-NEXT: CompoundStmt -// CHECK-FUNCTION-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-HAS_TYPE_FUNCTION_TYPE: FunctionDecl{{.*}} testFunctionDecl -// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: CompoundStmt -// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: AnnotateAttr{{.*}} "test" - -void (*testFunctionVar)(); -// CHECK-HAS_TYPE_FUNCTION_TYPE: VarDecl{{.*}} testFunctionVar -// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: AnnotateAttr{{.*}} "test" -// 'function' should not apply to variables with a function type! -// CHECK-FUNCTION: VarDecl{{.*}} testFunctionVar -// CHECK-FUNCTION-NOT: AnnotateAttr{{.*}} "test" - -class testMethods { - testMethods(); - void testMethod(); -}; -void testMethods::testMethod() { } -void testFunctionNotMethod(); -// CHECK-FUNCTION-LABEL: CXXConstructorDecl{{.*}} testMethods -// CHECK-FUNCTION-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-FUNCTION_IS_MEMBER: CXXConstructorDecl{{.*}} testMethods -// CHECK-FUNCTION_IS_MEMBER-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-HAS_TYPE_FUNCTION_TYPE: CXXConstructorDecl{{.*}} testMethods -// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-FUNCTION: CXXMethodDecl{{.*}} testMethod -// CHECK-FUNCTION-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-FUNCTION_IS_MEMBER: CXXMethodDecl{{.*}} testMethod -// CHECK-FUNCTION_IS_MEMBER-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-HAS_TYPE_FUNCTION_TYPE: CXXMethodDecl{{.*}} testMethod -// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-FUNCTION: CXXMethodDecl{{.*}} testMethod -// CHECK-FUNCTION-NEXT: CompoundStmt -// CHECK-FUNCTION-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-FUNCTION_IS_MEMBER: CXXMethodDecl{{.*}} testMethod -// CHECK-FUNCTION_IS_MEMBER-NEXT: CompoundStmt -// CHECK-CXX_METHOD-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-HAS_TYPE_FUNCTION_TYPE: CXXMethodDecl{{.*}} testMethod -// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: CompoundStmt -// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-FUNCTION_IS_MEMBER: FunctionDecl{{.*}} testFunctionNotMethod -// CHECK-FUNCTION_IS_MEMBER-NOT: AnnotateAttr{{.*}} "test" - -int testVariable; -// CHECK-VARIABLE: VarDecl{{.*}} testVariable -// CHECK-VARIABLE-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-VARIABLE_IS_GLOBAL-LABEL: VarDecl{{.*}} testVariable -// CHECK-VARIABLE_IS_GLOBAL-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-VARIABLE_IS_PARAMETER-LABEL: VarDecl{{.*}} testVariable -// CHECK-VARIABLE_IS_PARAMETER-NOT: AnnotateAttr{{.*}} "test" -// CHECK-VARIABLE_UNLESS_IS_PARAMETER-LABEL: VarDecl{{.*}} testVariable -// CHECK-VARIABLE_UNLESS_IS_PARAMETER-NEXT: AnnotateAttr{{.*}} "test" -void testVarFunction(int testParam) { -// CHECK-VARIABLE: VarDecl{{.*}} testParam -// CHECK-VARIABLE-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-VARIABLE_IS_GLOBAL-LABEL: VarDecl{{.*}} testParam -// CHECK-VARIABLE_IS_GLOBAL-NOT: AnnotateAttr{{.*}} "test" -// CHECK-VARIABLE_IS_PARAMETER-LABEL: VarDecl{{.*}} testParam -// CHECK-VARIABLE_IS_PARAMETER-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-VARIABLE_UNLESS_IS_PARAMETER-LABEL: VarDecl{{.*}} testParam -// CHECK-VARIABLE_UNLESS_IS_PARAMETER-NOT: AnnotateAttr{{.*}} "test" - - int testLocalVariable; -// CHECK-VARIABLE: VarDecl{{.*}} testLocalVariable -// CHECK-VARIABLE-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-VARIABLE_IS_GLOBAL-LABEL: VarDecl{{.*}} testLocalVariable -// CHECK-VARIABLE_IS_GLOBAL-NOT: AnnotateAttr{{.*}} "test" -// CHECK-VARIABLE_IS_PARAMETER-LABEL: VarDecl{{.*}} testLocalVariable -// CHECK-VARIABLE_IS_PARAMETER-NOT: AnnotateAttr{{.*}} "test" -// CHECK-VARIABLE_UNLESS_IS_PARAMETER-LABEL: VarDecl{{.*}} testLocalVariable -// CHECK-VARIABLE_UNLESS_IS_PARAMETER-NEXT: AnnotateAttr{{.*}} "test" -} -class testVarClass { - static int testStaticVar; -}; -// CHECK-VARIABLE: VarDecl{{.*}} testStaticVar -// CHECK-VARIABLE-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-VARIABLE_IS_GLOBAL-LABEL: VarDecl{{.*}} testStaticVar -// CHECK-VARIABLE_IS_GLOBAL-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-VARIABLE_IS_PARAMETER-LABEL: VarDecl{{.*}} testStaticVar -// CHECK-VARIABLE_IS_PARAMETER-NOT: AnnotateAttr{{.*}} "test" -// CHECK-VARIABLE_UNLESS_IS_PARAMETER-LABEL: VarDecl{{.*}} testStaticVar -// CHECK-VARIABLE_UNLESS_IS_PARAMETER-NEXT: AnnotateAttr{{.*}} "test" - - -} - -#pragma clang attribute pop diff --git a/test/Misc/pragma-attribute-cxx.cpp b/test/Misc/pragma-attribute-cxx.cpp deleted file mode 100644 index c241c4e4bd..0000000000 --- a/test/Misc/pragma-attribute-cxx.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fcxx-exceptions %s -// RUN: %clang_cc1 -fsyntax-only -ast-dump -ast-dump-filter test -std=c++11 -fcxx-exceptions %s | FileCheck %s -// expected-no-diagnostics - -class testClass1 { -}; -// CHECK-LABEL: CXXRecordDecl{{.*}} testClass1 -// CHECK-NOT: AnnotateAttr - -#pragma clang attribute push (__attribute__((annotate("test"))), apply_to=any(record, field, variable, function, namespace, type_alias)) - -class testClass2 { - void testMethod1(int param); - - testClass2(); - - testClass2 *operator -> (); -}; -// CHECK-LABEL: CXXRecordDecl{{.*}} testClass2 -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK: CXXMethodDecl{{.*}} testMethod1 -// CHECK-NEXT: ParmVarDecl{{.*}} param -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NEXT: CXXConstructorDecl -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NEXT: CXXMethodDecl{{.*}} operator-> -// CHECK-NEXT: AnnotateAttr{{.*}} "test" - -#pragma clang attribute push (__attribute__((annotate("method"))), apply_to=any(record, field, variable, function, namespace, type_alias)) - -void testClass2::testMethod1(int param) { - -#pragma clang attribute pop -} -// CHECK-LABEL: CXXMethodDecl{{.*}}prev{{.*}} testMethod1 -// CHECK-NEXT: ParmVarDecl{{.*}} param -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NEXT: AnnotateAttr{{.*}} "method" -// CHECK-NEXT: CompoundStmt -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NEXT: AnnotateAttr{{.*}} "method" - -namespace testNamespace { -} -// CHECK-LABEL: NamespaceDecl{{.*}} testNamespace -// CHECK-NEXT: AnnotateAttr{{.*}} "test" - -class testClassForward; -// CHECK-LABEL: CXXRecordDecl{{.*}} testClassForward -// CHECK-NEXT: AnnotateAttr{{.*}} "test" - -namespace testNamespaceAlias = testNamespace; -// CHECK-LABEL: NamespaceAliasDecl{{.*}} testNamespaceAlias -// CHECK-NOT: AnnotateAttr - -using testTypeAlias = testClass2; -// CHECK-LABEL: TypeAliasDecl{{.*}} testTypeAlias -// CHECK: AnnotateAttr{{.*}} "test" - -void testCatchVariable() { - try { - } catch (int testCatch) { - } - testCatchVariable(); -} -// CHECK-LABEL: FunctionDecl{{.*}} testCatchVariable -// CHECK: CXXCatchStmt -// CHECK-NEXT: VarDecl{{.*}} testCatch -// CHECK-NEXT: AnnotateAttr{{.*}} "test" - -void testLambdaMethod() { - auto l = [] () { }; - testLambdaMethod(); -} -// CHECK-LABEL: FunctionDecl{{.*}} testLambdaMethod -// CHECK: LambdaExpr -// CHECK-NEXT: CXXRecordDecl -// CHECK-NEXT: CXXMethodDecl{{.*}} operator() -// CHECK-NEXT: CompoundStmt -// CHECK-NEXT: AnnotateAttr{{.*}} "test" - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((require_constant_initialization)), apply_to=variable(is_global)) - -int testCI1 = 1; -// CHECK-LABEL: VarDecl{{.*}} testCI1 -// CHECK-NEXT: IntegerLiteral -// CHECK-NEXT: RequireConstantInitAttr - -#pragma clang attribute pop - -int testNoCI = 0; -// CHECK-LABEL: VarDecl{{.*}} testNoCI -// CHECK-NEXT: IntegerLiteral -// CHECK-NOT: RequireConstantInitAttr - -// Check support for CXX11 style attributes -#pragma clang attribute push ([[noreturn]], apply_to = function) - -void testNoReturn(); -// CHECK-LABEL: FunctionDecl{{.*}} testNoReturn -// CHECK-NEXT: CXX11NoReturnAttr - -#pragma clang attribute pop diff --git a/test/Misc/pragma-attribute-objc-subject-match-rules.m b/test/Misc/pragma-attribute-objc-subject-match-rules.m deleted file mode 100644 index 09ab5e1f33..0000000000 --- a/test/Misc/pragma-attribute-objc-subject-match-rules.m +++ /dev/null @@ -1,113 +0,0 @@ -// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump "-DSUBJECT=objc_interface" %s | FileCheck --check-prefix=CHECK-OBJC_INTERFACE %s -// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=objc_protocol" %s | FileCheck --check-prefix=CHECK-OBJC_PROTOCOL %s -// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump "-DSUBJECT=objc_category" %s | FileCheck --check-prefix=CHECK-OBJC_CATEGORY %s -// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=objc_method" %s | FileCheck --check-prefix=CHECK-OBJC_METHOD %s -// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=objc_method(is_instance)" %s | FileCheck --check-prefix=CHECK-OBJC_METHOD_IS_INSTANCE %s -// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=field" %s | FileCheck --check-prefix=CHECK-FIELD %s -// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=objc_property" %s | FileCheck --check-prefix=CHECK-OBJC_PROPERTY %s -// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=block" %s | FileCheck --check-prefix=CHECK-BLOCK %s -// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=hasType(functionType)" %s | FileCheck --check-prefix=CHECK-HAS_TYPE_FUNCTION_TYPE %s - -#pragma clang attribute push (__attribute__((annotate("test"))), apply_to = any(SUBJECT)) - -@interface testInterface -@end -// CHECK-OBJC_INTERFACE: ObjCInterfaceDecl{{.*}} testInterface -// CHECK-OBJC_INTERFACE-NEXT: AnnotateAttr{{.*}} "test" - -@interface testInterface () -@end -// CHECK-OBJC_INTERFACE: ObjCCategoryDecl -// CHECK-OBJC_INTERFACE-NOT: AnnotateAttr{{.*}} "test" -// CHECK-OBJC_CATEGORY: ObjCCategoryDecl -// CHECK-OBJC_CATEGORY-NEXT: ObjCInterface -// CHECK-OBJC_CATEGORY-NEXT: AnnotateAttr{{.*}} "test" - -@interface testInterface (testCategory) -@end -// CHECK-OBJC_INTERFACE: ObjCCategoryDecl{{.*}} testCategory -// CHECK-OBJC_INTERFACE-NOT: AnnotateAttr{{.*}} "test" -// CHECK-OBJC_CATEGORY: ObjCCategoryDecl{{.*}} testCategory -// CHECK-OBJC_CATEGORY-NEXT: ObjCInterface -// CHECK-OBJC_CATEGORY-NEXT: AnnotateAttr{{.*}} "test" - -// CHECK-OBJC_INTERFACE-LABEL: ObjCProtocolDecl -@protocol testProtocol -@end -// CHECK-OBJC_PROTOCOL: ObjCProtocolDecl{{.*}} testProtocol -// CHECK-OBJC_PROTOCOL-NEXT: AnnotateAttr{{.*}} "test" - -@interface methodContainer -- (void) testInstanceMethod; -+ (void) testClassMethod; -@end -// CHECK-OBJC_METHOD: ObjCMethodDecl{{.*}} testInstanceMethod -// CHECK-OBJC_METHOD-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-OBJC_METHOD: ObjCMethodDecl{{.*}} testClassMethod -// CHECK-OBJC_METHOD-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-OBJC_METHOD_IS_INSTANCE: ObjCMethodDecl{{.*}} testInstanceMethod -// CHECK-OBJC_METHOD_IS_INSTANCE-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-OBJC_METHOD_IS_INSTANCE-LABEL: ObjCMethodDecl{{.*}} testClassMethod -// CHECK-OBJC_METHOD_IS_INSTANCE-NOT: AnnotateAttr{{.*}} "test" -// CHECK-HAS_TYPE_FUNCTION_TYPE-LABEL: ObjCMethodDecl{{.*}} testInstanceMethod -// CHECK-HAS_TYPE_FUNCTION_TYPE-NOT: AnnotateAttr{{.*}} "test" -// CHECK-HAS_TYPE_FUNCTION_TYPE-LABEL: ObjCMethodDecl{{.*}} testClassMethod -// CHECK-HAS_TYPE_FUNCTION_TYPE-NOT: AnnotateAttr{{.*}} "test" - -@implementation methodContainer -- (void) testInstanceMethod { } -+ (void) testClassMethod { } -@end -// CHECK-OBJC_METHOD: ObjCMethodDecl{{.*}} testInstanceMethod -// CHECK-OBJC_METHOD-NEXT: ImplicitParamDecl -// CHECK-OBJC_METHOD-NEXT: ImplicitParamDecl -// CHECK-OBJC_METHOD-NEXT: CompoundStmt -// CHECK-OBJC_METHOD-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-OBJC_METHOD: ObjCMethodDecl{{.*}} testClassMethod -// CHECK-OBJC_METHOD-NEXT: ImplicitParamDecl -// CHECK-OBJC_METHOD-NEXT: ImplicitParamDecl -// CHECK-OBJC_METHOD-NEXT: CompoundStmt -// CHECK-OBJC_METHOD-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-OBJC_METHOD_IS_INSTANCE-LABEL: ObjCMethodDecl{{.*}} testInstanceMethod -// CHECK-OBJC_METHOD_IS_INSTANCE-NEXT: ImplicitParamDecl -// CHECK-OBJC_METHOD_IS_INSTANCE-NEXT: ImplicitParamDecl -// CHECK-OBJC_METHOD_IS_INSTANCE-NEXT: CompoundStmt -// CHECK-OBJC_METHOD_IS_INSTANCE-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-OBJC_METHOD_IS_INSTANCE: ObjCMethodDecl{{.*}} testClassMethod -// CHECK-OBJC_METHOD_IS_INSTANCE-NOT: AnnotateAttr{{.*}} "test" - -// CHECK-HAS_TYPE_FUNCTION_TYPE-LABEL: ObjCMethodDecl{{.*}} testInstanceMethod -// CHECK-HAS_TYPE_FUNCTION_TYPE-NOT: AnnotateAttr{{.*}} "test" -// CHECK-HAS_TYPE_FUNCTION_TYPE-LABEL: ObjCMethodDecl{{.*}} testClassMethod -// CHECK-HAS_TYPE_FUNCTION_TYPE-NOT: AnnotateAttr{{.*}} "test" -@interface propertyContainer { - int testIvar; -// CHECK-FIELD: ObjCIvarDecl{{.*}} testIvar -// CHECK-FIELD-NEXT: AnnotateAttr{{.*}} "test" - -} -@property int testProperty; -// CHECK-OBJC_PROPERTY: ObjCPropertyDecl{{.*}} testProperty -// CHECK-OBJC_PROPERTY-NEXT: AnnotateAttr{{.*}} "test" - -@end - -void (^testBlockVar)(); -// CHECK-BLOCK: VarDecl{{.*}} testBlockVar -// CHECK-BLOCK-NOT: AnnotateAttr{{.*}} "test" - -void testBlock() { - (void)(^ { }); -} -// CHECK-BLOCK-LABEL: BlockDecl -// CHECK-BLOCK-NEXT: CompoundStmt -// CHECK-BLOCK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-HAS_TYPE_FUNCTION_TYPE-LABEL: FunctionDecl{{.*}} testBlock -// CHECK-HAS_TYPE_FUNCTION_TYPE: BlockDecl -// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: CompoundStmt -// The attribute applies to function, but not to block: -// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-HAS_TYPE_FUNCTION_TYPE-NOT: AnnotateAttr{{.*}} "test" - - -#pragma clang attribute pop diff --git a/test/Misc/pragma-attribute-objc.m b/test/Misc/pragma-attribute-objc.m deleted file mode 100644 index 541cfa9ad3..0000000000 --- a/test/Misc/pragma-attribute-objc.m +++ /dev/null @@ -1,164 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s -// RUN: %clang_cc1 -fsyntax-only -Wno-objc-root-class -ast-dump -ast-dump-filter test %s | FileCheck %s - -#pragma clang attribute push (__attribute__((annotate("test"))), apply_to = any(objc_interface, objc_protocol, objc_property, field, objc_method, variable)) -#pragma clang attribute push (__attribute__((objc_subclassing_restricted)), apply_to = objc_interface) - -@interface testInterface1 -// CHECK-LABEL: ObjCInterfaceDecl{{.*}}testInterface1 -// CHECK-NEXT: ObjCImplementation -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NEXT: ObjCSubclassingRestrictedAttr{{.*}} - -// CHECK-NOT: AnnotateAttr -// CHECK-NOT: ObjCSubclassingRestrictedAttr - -{ - int testIvar1; - // CHECK-LABEL: ObjCIvarDecl{{.*}} testIvar1 - // CHECK-NEXT: AnnotateAttr{{.*}} "test" - // CHECK-NOT: ObjCSubclassingRestrictedAttr -} - -@property int testProp1; -// CHECK-LABEL: ObjCPropertyDecl{{.*}} testProp1 -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NOT: ObjCSubclassingRestrictedAttr - -- (void)testIm:(int) x; -// CHECK-LABEL: ObjCMethodDecl{{.*}}testIm -// CHECK-NEXT: ParmVarDecl{{.*}} x -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NOT: ObjCSubclassingRestrictedAttr - -+ (void)testCm; -// CHECK-LABEL: ObjCMethodDecl{{.*}}testCm -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NOT: ObjCSubclassingRestrictedAttr - -// Implicit getters/setters shouldn't receive the attributes. -// CHECK-LABEL: ObjCMethodDecl{{.*}}testProp1 -// CHECK-NOT: AnnotateAttr -// CHECK-LABEL: ObjCMethodDecl{{.*}}setTestProp1 -// CHECK-NOT: AnnotateAttr - -@end - -// @implementation can't receive explicit attributes, so don't add the pragma -// attributes to them. -@implementation testInterface1 -// CHECK-LABEL: ObjCImplementationDecl{{.*}}testInterface1 -// CHECK-NOT: AnnotateAttr -// CHECK-NOT: ObjCSubclassingRestrictedAttr - -{ - int testIvar2; - // CHECK-LABEL: ObjCIvarDecl{{.*}} testIvar2 - // CHECK-NEXT: AnnotateAttr{{.*}} "test" - // CHECK-NOT: ObjCSubclassingRestrictedAttr -} - -// Don't add attributes to implicit parameters! -- (void)testIm:(int) x { -// CHECK-LABEL: ObjCMethodDecl{{.*}}testIm -// CHECK-NEXT: ImplicitParamDecl -// CHECK-NEXT: ImplicitParamDecl -// CHECK-NEXT: ParmVarDecl{{.*}} x -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NEXT: CompoundStmt -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NOT: ObjCSubclassingRestrictedAttr -} - -+ (void)testCm { -// CHECK-LABEL: ObjCMethodDecl{{.*}}testCm -// CHECK: AnnotateAttr{{.*}} "test" -// CHECK-NOT: ObjCSubclassingRestrictedAttr -// CHECK-NOT: AnnotateAttr - _Pragma("clang attribute push (__attribute__((annotate(\"applied at container start\"))), apply_to=objc_interface)"); -} - -// Implicit ivars shouldn't receive the attributes. -// CHECK-LABEL: ObjCIvarDecl{{.*}}_testProp1 -// CHECK-NOT: AnnotateAttr - -@end - -@implementation testImplWithoutInterface // expected-warning {{cannot find interface declaration for 'testImplWithoutInterface'}} -// CHECK-LABEL: ObjCInterfaceDecl{{.*}}testImplWithoutInterface -// CHECK-NEXT: ObjCImplementation -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NEXT: ObjCSubclassingRestrictedAttr -// CHECK-NEXT: AnnotateAttr{{.*}} "applied at container start" - -// CHECK-LABEL: ObjCImplementationDecl{{.*}}testImplWithoutInterface -// CHECK-NOT: AnnotateAttr -// CHECK-NOT: ObjCSubclassingRestrictedAttr - -@end - -#pragma clang attribute pop - -@protocol testProtocol -// CHECK-LABEL: ObjCProtocolDecl{{.*}}testProtocol -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NOT: ObjCSubclassingRestrictedAttr -// CHECK-NOT: AnnotateAttr - -- (void)testProtIm; -// CHECK-LABEL: ObjCMethodDecl{{.*}}testProtIm -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NOT: ObjCSubclassingRestrictedAttr - -@end - -@protocol testForwardProtocol; -// CHECK-LABEL: ObjCProtocolDecl{{.*}}testForwardProtocol -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NOT: ObjCSubclassingRestrictedAttr - - -// Categories can't receive explicit attributes, so don't add pragma attributes -// to them. -@interface testInterface1(testCat) -// CHECK-LABEL: ObjCCategoryDecl{{.*}}testCat -// CHECK-NOT: AnnotateAttr -// CHECK-NOT: ObjCSubclassingRestrictedAttr - -@end - -@implementation testInterface1(testCat) -// CHECK-LABEL: ObjCCategoryImplDecl{{.*}}testCat -// CHECK-NOT: AnnotateAttr -// CHECK-NOT: ObjCSubclassingRestrictedAttr - -@end - -// @class/@compatibility_alias declarations can't receive explicit attributes, -// so don't add pragma attributes to them. -@class testClass; -// CHECK-LABEL: ObjCInterfaceDecl{{.*}}testClass -// CHECK-NOT: AnnotateAttr -// CHECK-NOT: ObjCSubclassingRestrictedAttr - -@compatibility_alias testCompat testInterface1; -// CHECK-LABEL: ObjCCompatibleAliasDecl{{.*}}testCompat -// CHECK-NOT: AnnotateAttr -// CHECK-NOT: ObjCSubclassingRestrictedAttr - -#pragma clang attribute pop // objc_subclassing_restricted - -@interface testInterface3 -// CHECK-LABEL: ObjCInterfaceDecl{{.*}}testInterface3 -// CHECK-NEXT: AnnotateAttr{{.*}} "test" -// CHECK-NOT: ObjCSubclassingRestrictedAttr -@end - -#pragma clang attribute pop // annotate("test") - -@interface testInterface4 -// CHECK-LABEL: ObjCInterfaceDecl{{.*}}testInterface4 -// CHECK-NOT: AnnotateAttr -// CHECK-NOT: ObjCSubclassingRestrictedAttr -@end diff --git a/test/Misc/pragma-attribute-strict-subjects.c b/test/Misc/pragma-attribute-strict-subjects.c deleted file mode 100644 index ecd551bee6..0000000000 --- a/test/Misc/pragma-attribute-strict-subjects.c +++ /dev/null @@ -1,222 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -Wno-pragma-clang-attribute -verify %s -// RUN: not %clang_cc1 -fsyntax-only -ast-dump -ast-dump-filter test %s | FileCheck %s - -// Check for contradictions in rules for attribute without a strict subject set: - -#pragma clang attribute push (__attribute__((annotate("subRuleContradictions"))), apply_to = any(variable, variable(is_parameter), function(is_member), variable(is_global))) -// expected-error@-1 {{redundant attribute subject matcher sub-rule 'variable(is_parameter)'; 'variable' already matches those declarations}} -// expected-error@-2 {{redundant attribute subject matcher sub-rule 'variable(is_global)'; 'variable' already matches those declarations}} - -// Ensure that we've recovered from the error: -int testRecoverSubRuleContradiction = 0; -// CHECK-LABEL: VarDecl{{.*}} testRecoverSubRuleContradiction -// CHECK-NEXT: IntegerLiteral -// CHECK-NEXT: AnnotateAttr{{.*}} "subRuleContradictions" - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((annotate("negatedSubRuleContradictions2"))), apply_to = any(variable(unless(is_parameter)), variable(is_thread_local), function, variable(is_global))) -// expected-error@-1 {{negated attribute subject matcher sub-rule 'variable(unless(is_parameter))' contradicts sub-rule 'variable(is_global)'}} -// We have just one error, don't error on 'variable(is_global)' - -// Ensure that we've recovered from the error: -int testRecoverNegatedContradiction = 0; -// CHECK-LABEL: VarDecl{{.*}} testRecoverNegatedContradiction -// CHECK-NEXT: IntegerLiteral -// CHECK-NEXT: AnnotateAttr{{.*}} "negatedSubRuleContradictions2" - -void testRecoverNegatedContradictionFunc(void); -// CHECK-LABEL: FunctionDecl{{.*}} testRecoverNegatedContradictionFunc -// CHECK-NEXT: AnnotateAttr{{.*}} "negatedSubRuleContradictions2" - -#pragma clang attribute pop - -// Verify the strict subject set verification. - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function)) - -int testRecoverStrictnessVar = 0; -// CHECK-LABEL: VarDecl{{.*}} testRecoverStrictnessVar -// CHECK-NEXT: IntegerLiteral -// CHECK-NOT: AbiTagAttr - -void testRecoverStrictnessFunc(void); -// CHECK-LABEL: FunctionDecl{{.*}} testRecoverStrictnessFunc -// CHECK-NEXT: AbiTagAttr - -struct testRecoverStrictnessStruct { }; -// CHECK-LABEL: RecordDecl{{.*}} testRecoverStrictnessStruct -// CHECK-NOT: AbiTagAttr - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, record(unless(is_union)), variable, enum)) -// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} - -int testRecoverExtraVar = 0; -// CHECK-LABEL: VarDecl{{.*}} testRecoverExtraVar -// CHECK-NEXT: IntegerLiteral -// CHECK-NEXT: AbiTagAttr - -void testRecoverExtraFunc(void); -// CHECK-LABEL: FunctionDecl{{.*}} testRecoverExtraFunc -// CHECK-NEXT: AbiTagAttr - -struct testRecoverExtraStruct { }; -// CHECK-LABEL: RecordDecl{{.*}} testRecoverExtraStruct -// CHECK-NEXT: AbiTagAttr - -enum testNoEnumAbiTag { CaseCase }; -// CHECK-LABEL: EnumDecl{{.*}} testNoEnumAbiTag -// CHECK-NO: AbiTagAttr - -#pragma clang attribute pop - -// Verify the non-strict subject set verification. - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function)) - -int testSubset1Var; -// CHECK-LABEL: VarDecl{{.*}} testSubset1Var -// CHECK-NOT: AbiTagAttr - -void testSubset1Func(void); -// CHECK-LABEL: FunctionDecl{{.*}} testSubset1Func -// CHECK-NEXT: AbiTagAttr - -struct testSubset1Struct { }; -// CHECK-LABEL: RecordDecl{{.*}} testSubset1Struct -// CHECK-NOT: AbiTagAttr - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = variable) - -int testSubset2Var; -// CHECK-LABEL: VarDecl{{.*}} testSubset2Var -// CHECK-NEXT: AbiTagAttr - -void testSubset2Func(void); -// CHECK-LABEL: FunctionDecl{{.*}} testSubset2Func -// CHECK-NOT: AbiTagAttr - -struct testSubset2Struct { }; -// CHECK-LABEL: RecordDecl{{.*}} testSubset2Struct -// CHECK-NOT: AbiTagAttr - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)))) - -int testSubset3Var; -// CHECK-LABEL: VarDecl{{.*}} testSubset3Var -// CHECK-NOT: AbiTagAttr - -void testSubset3Func(void); -// CHECK-LABEL: FunctionDecl{{.*}} testSubset3Func -// CHECK-NOT: AbiTagAttr - -struct testSubset3Struct { }; -// CHECK-LABEL: RecordDecl{{.*}} testSubset3Struct -// CHECK-NEXT: AbiTagAttr - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, variable)) - -int testSubset4Var; -// CHECK-LABEL: VarDecl{{.*}} testSubset4Var -// CHECK-NEXT: AbiTagAttr - -void testSubset4Func(void); -// CHECK-LABEL: FunctionDecl{{.*}} testSubset4Func -// CHECK-NEXT: AbiTagAttr - -struct testSubset4Struct { }; -// CHECK-LABEL: RecordDecl{{.*}} testSubset4Struct -// CHECK-NOT: AbiTagAttr - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(variable, record(unless(is_union)))) - -int testSubset5Var; -// CHECK-LABEL: VarDecl{{.*}} testSubset5Var -// CHECK-NEXT: AbiTagAttr - -void testSubset5Func(void); -// CHECK-LABEL: FunctionDecl{{.*}} testSubset5Func -// CHECK-NOT: AbiTagAttr - -struct testSubset5Struct { }; -// CHECK-LABEL: RecordDecl{{.*}} testSubset5Struct -// CHECK-NEXT: AbiTagAttr - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function)) - -int testSubset6Var; -// CHECK-LABEL: VarDecl{{.*}} testSubset6Var -// CHECK-NOT: AbiTagAttr - -void testSubset6Func(void); -// CHECK-LABEL: FunctionDecl{{.*}} testSubset6Func -// CHECK-NEXT: AbiTagAttr - -struct testSubset6Struct { }; -// CHECK-LABEL: RecordDecl{{.*}} testSubset6Struct -// CHECK-NEXT: AbiTagAttr - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable)) - -int testSubset7Var; -// CHECK-LABEL: VarDecl{{.*}} testSubset7Var -// CHECK-NEXT: AbiTagAttr - -void testSubset7Func(void); -// CHECK-LABEL: FunctionDecl{{.*}} testSubset7Func -// CHECK-NEXT: AbiTagAttr - -struct testSubset7Struct { }; -// CHECK-LABEL: RecordDecl{{.*}} testSubset7Struct -// CHECK-NEXT: AbiTagAttr - -#pragma clang attribute pop - - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable, enum, enum_constant)) -// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum_constant', and 'enum'}} - -int testSubsetRecoverVar; -// CHECK-LABEL: VarDecl{{.*}} testSubsetRecoverVar -// CHECK-NEXT: AbiTagAttr - -void testSubsetRecoverFunc(void); -// CHECK-LABEL: FunctionDecl{{.*}} testSubsetRecoverFunc -// CHECK-NEXT: AbiTagAttr - -struct testSubsetRecoverStruct { }; -// CHECK-LABEL: RecordDecl{{.*}} testSubsetRecoverStruct -// CHECK-NEXT: AbiTagAttr - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = enum) -// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} - -int testSubsetNoVar; -// CHECK-LABEL: VarDecl{{.*}} testSubsetNoVar -// CHECK-NOT: AbiTagAttr - -void testSubsetNoFunc(void); -// CHECK-LABEL: FunctionDecl{{.*}} testSubsetNoFunc -// CHECK-NOT: AbiTagAttr - -struct testSubsetNoStruct { }; -// CHECK-LABEL: RecordDecl{{.*}} testSubsetNoStruct -// CHECK-NOT: AbiTagAttr - -#pragma clang attribute pop diff --git a/test/Misc/pragma-attribute-supported-attributes-list.test b/test/Misc/pragma-attribute-supported-attributes-list.test deleted file mode 100644 index b1f2e66ab3..0000000000 --- a/test/Misc/pragma-attribute-supported-attributes-list.test +++ /dev/null @@ -1,62 +0,0 @@ -// RUN: clang-tblgen -gen-clang-test-pragma-attribute-supported-attributes -I%src_include_dir %src_include_dir/clang/Basic/Attr.td -o - | FileCheck %s - -// The number of supported attributes should never go down! - -// CHECK: #pragma clang attribute supports 57 attributes: -// CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function) -// CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function) -// CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function) -// CHECK-NEXT: AMDGPUWavesPerEU (SubjectMatchRule_function) -// CHECK-NEXT: AVRSignal (SubjectMatchRule_function) -// CHECK-NEXT: AbiTag (SubjectMatchRule_record_not_is_union, SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_namespace) -// CHECK-NEXT: AlignValue (SubjectMatchRule_variable, SubjectMatchRule_type_alias) -// CHECK-NEXT: AllocSize (SubjectMatchRule_function) -// CHECK-NEXT: Annotate () -// CHECK-NEXT: AssumeAligned (SubjectMatchRule_objc_method, SubjectMatchRule_function) -// CHECK-NEXT: CXX11NoReturn (SubjectMatchRule_function) -// CHECK-NEXT: CallableWhen (SubjectMatchRule_function_is_member) -// CHECK-NEXT: CarriesDependency (SubjectMatchRule_variable_is_parameter, SubjectMatchRule_objc_method, SubjectMatchRule_function) -// CHECK-NEXT: Consumable (SubjectMatchRule_record) -// CHECK-NEXT: Convergent (SubjectMatchRule_function) -// CHECK-NEXT: DLLExport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface) -// CHECK-NEXT: DLLImport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface) -// CHECK-NEXT: DisableTailCalls (SubjectMatchRule_function, SubjectMatchRule_objc_method) -// CHECK-NEXT: EnableIf (SubjectMatchRule_function) -// CHECK-NEXT: EnumExtensibility (SubjectMatchRule_enum) -// CHECK-NEXT: FlagEnum (SubjectMatchRule_enum) -// CHECK-NEXT: Flatten (SubjectMatchRule_function) -// CHECK-NEXT: IFunc (SubjectMatchRule_function) -// CHECK-NEXT: InternalLinkage (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record) -// CHECK-NEXT: LTOVisibilityPublic (SubjectMatchRule_record) -// CHECK-NEXT: NoDebug (SubjectMatchRule_hasType_functionType, SubjectMatchRule_objc_method, SubjectMatchRule_variable_not_is_parameter) -// CHECK-NEXT: NoDuplicate (SubjectMatchRule_function) -// CHECK-NEXT: NoSanitize (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global) -// CHECK-NEXT: NoSanitizeSpecific (SubjectMatchRule_function, SubjectMatchRule_variable_is_global) -// CHECK-NEXT: NoSplitStack (SubjectMatchRule_function) -// CHECK-NEXT: NotTailCalled (SubjectMatchRule_function) -// CHECK-NEXT: ObjCBoxable (SubjectMatchRule_record) -// CHECK-NEXT: ObjCMethodFamily (SubjectMatchRule_objc_method) -// CHECK-NEXT: ObjCRequiresSuper (SubjectMatchRule_objc_method) -// CHECK-NEXT: ObjCRuntimeName (SubjectMatchRule_objc_interface, SubjectMatchRule_objc_protocol) -// CHECK-NEXT: ObjCRuntimeVisible (SubjectMatchRule_objc_interface) -// CHECK-NEXT: ObjCSubclassingRestricted (SubjectMatchRule_objc_interface) -// CHECK-NEXT: OpenCLNoSVM (SubjectMatchRule_variable) -// CHECK-NEXT: OptimizeNone (SubjectMatchRule_function, SubjectMatchRule_objc_method) -// CHECK-NEXT: Overloadable (SubjectMatchRule_function) -// CHECK-NEXT: ParamTypestate (SubjectMatchRule_variable_is_parameter) -// CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter) -// CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function) -// CHECK-NEXT: RequireConstantInit (SubjectMatchRule_variable_is_global) -// CHECK-NEXT: ReturnTypestate (SubjectMatchRule_function, SubjectMatchRule_variable_is_parameter) -// CHECK-NEXT: ReturnsNonNull (SubjectMatchRule_objc_method, SubjectMatchRule_function) -// CHECK-NEXT: Section (SubjectMatchRule_function, SubjectMatchRule_variable_is_global, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property) -// CHECK-NEXT: SetTypestate (SubjectMatchRule_function_is_member) -// CHECK-NEXT: SwiftContext (SubjectMatchRule_variable_is_parameter) -// CHECK-NEXT: SwiftErrorResult (SubjectMatchRule_variable_is_parameter) -// CHECK-NEXT: SwiftIndirectResult (SubjectMatchRule_variable_is_parameter) -// CHECK-NEXT: TLSModel (SubjectMatchRule_variable_is_thread_local) -// CHECK-NEXT: Target (SubjectMatchRule_function) -// CHECK-NEXT: TestTypestate (SubjectMatchRule_function_is_member) -// CHECK-NEXT: WarnUnusedResult (SubjectMatchRule_objc_method, SubjectMatchRule_enum, SubjectMatchRule_record, SubjectMatchRule_hasType_functionType) -// CHECK-NEXT: XRayInstrument (SubjectMatchRule_function_is_member, SubjectMatchRule_objc_method, SubjectMatchRule_function) -// CHECK-NEXT: XRayLogArgs (SubjectMatchRule_function_is_member, SubjectMatchRule_objc_method, SubjectMatchRule_function) diff --git a/test/Parser/pragma-attribute-declspec.cpp b/test/Parser/pragma-attribute-declspec.cpp deleted file mode 100644 index 28785ba900..0000000000 --- a/test/Parser/pragma-attribute-declspec.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// RUN: %clang_cc1 -triple i386-pc-win32 -std=c++11 -verify -Wno-pragma-clang-attribute -fms-extensions -fms-compatibility %s - -#pragma clang attribute push(__declspec(dllexport), apply_to = function) - -void function(); - -#pragma clang attribute pop - -#pragma clang attribute push(__declspec(dllexport, dllimport), apply_to = function) // expected-error {{more than one attribute specified in '#pragma clang attribute push'}} - -#pragma clang attribute push(__declspec(align), apply_to = variable) // expected-error {{attribute 'align' is not supported by '#pragma clang attribute'}} - -#pragma clang attribute push(__declspec(), apply_to = variable) // A noop diff --git a/test/Parser/pragma-attribute.cpp b/test/Parser/pragma-attribute.cpp deleted file mode 100644 index b28ec8c2c8..0000000000 --- a/test/Parser/pragma-attribute.cpp +++ /dev/null @@ -1,181 +0,0 @@ -// RUN: %clang_cc1 -Wno-pragma-clang-attribute -verify -std=c++11 %s - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = function) - -void function(); - -#pragma clang attribute pop - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(variable(is_parameter), function)) -#pragma clang attribute pop - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = variable(unless(is_parameter))) -#pragma clang attribute pop - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(variable(unless(is_parameter)))) -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a")))) // expected-error {{expected ','}} -#pragma clang attribute push (__attribute__((abi_tag("a"))) apply_to=function) // expected-error {{expected ','}} -#pragma clang attribute push (__attribute__((abi_tag("a"))) = function) // expected-error {{expected ','}} -#pragma clang attribute push (__attribute__((abi_tag("a"))) any(function)) // expected-error {{expected ','}} - -#pragma clang attribute push (__attribute__((abi_tag("a"))) 22) // expected-error {{expected ','}} -#pragma clang attribute push (__attribute__((abi_tag("a"))) function) // expected-error {{expected ','}} -#pragma clang attribute push (__attribute__((abi_tag("a"))) (function)) // expected-error {{expected ','}} - -#pragma clang attribute push(__attribute__((annotate("test"))), ) // expected-error {{expected attribute subject set specifier 'apply_to'}} -#pragma clang attribute push(__attribute__((annotate("test"))), = any(function)) // expected-error {{expected attribute subject set specifier 'apply_to'}} -#pragma clang attribute push(__attribute__((annotate("test"))), = function) // expected-error {{expected attribute subject set specifier 'apply_to'}} -#pragma clang attribute push(__attribute__((annotate("test"))), any(function)) // expected-error {{expected attribute subject set specifier 'apply_to'}} -#pragma clang attribute push(__attribute__((annotate("test"))), function) // expected-error {{expected attribute subject set specifier 'apply_to'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply = any(function )) // expected-error {{expected attribute subject set specifier 'apply_to'}} -#pragma clang attribute push(__attribute__((annotate("test"))), to = function) // expected-error {{expected attribute subject set specifier 'apply_to'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_only_to = function) // expected-error {{expected attribute subject set specifier 'apply_to'}} - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to any(function)) // expected-error {{expected '='}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to function) // expected-error {{expected '='}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to) // expected-error {{expected '='}} -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to 41 (22)) // expected-error {{expected '='}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any) // expected-error {{expected '('}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any {) // expected-error {{expected '('}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any function) // expected-error {{expected '('}} - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = { function, enum }) // expected-error {{expected an identifier that corresponds to an attribute subject rule}} - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(function ) // expected-error {{expected ')'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(function, )) // expected-error {{expected an identifier that corresponds to an attribute subject rule}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, enum ) // expected-error {{expected ')'}} - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = () ) // expected-error {{expected an identifier that corresponds to an attribute subject rule}} - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( + ) ) // expected-error {{expected an identifier that corresponds to an attribute subject rule}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any()) // expected-error {{expected an identifier that corresponds to an attribute subject rule}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, 42 )) // expected-error {{expected an identifier that corresponds to an attribute subject rule}} - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( diag )) // expected-error {{unknown attribute subject rule 'diag'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( a )) // expected-error {{unknown attribute subject rule 'a'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, for)) // expected-error {{unknown attribute subject rule 'for'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function42, for )) // expected-error {{unknown attribute subject rule 'function42'}} - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(hasType)) // expected-error {{expected '('}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = hasType) // expected-error {{expected '('}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = hasType(functionType)) // OK - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable( )) // expected-error {{expected ')'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable( ) )) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(is ) )) // expected-error {{unknown attribute subject matcher sub-rule 'is'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(is_parameter, not) )) // expected-error {{expected ')'}} expected-note {{to match this '('}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable is_parameter )) // expected-error {{expected ')'}} expected-note {{to match this '('}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable ( ) // expected-error {{expected ')'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = variable ( // expected-error {{expected ')'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, variable (is ()) )) // expected-error {{unknown attribute subject matcher sub-rule 'is'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, variable (42) )) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, namespace("test") )) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'namespace' matcher does not support sub-rules}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, variable ("test" )) // expected-error {{expected ')'}} - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = enum(is_parameter)) // expected-error {{invalid use of attribute subject matcher sub-rule 'is_parameter'; 'enum' matcher does not support sub-rules}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(enum(is_parameter))) // expected-error {{invalid use of attribute subject matcher sub-rule 'is_parameter'; 'enum' matcher does not support sub-rules}} - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any (function, variable (unless) )) // expected-error {{expected '('}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any (function, variable (unless() )) // expected-error {{expected ')'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any ( function, variable (unless(is)) )) // expected-error {{unknown attribute subject matcher sub-rule 'unless(is)'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless(is_parameter, not)) )) // expected-error {{expected ')'}} expected-note {{to match this '('}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless(is_parameter), not) ) // expected-error {{expected ')'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable unless is_parameter )) // expected-error {{expected ')'}} expected-note {{to match this '('}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless is_parameter) )) // expected-error {{expected '('}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, variable (unless(42)) )) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, enum(unless("test")) )) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'enum' matcher does not support sub-rules}} - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, variable (unless(is_global)) )) // expected-error {{unknown attribute subject matcher sub-rule 'unless(is_global)'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( enum(unless(is_parameter)) )) // expected-error {{invalid use of attribute subject matcher sub-rule 'unless(is_parameter)'; 'enum' matcher does not support sub-rules}} - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, function )) // expected-error {{duplicate attribute subject matcher 'function'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, function, function )) // expected-error 2 {{duplicate attribute subject matcher 'function'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, enum, function )) // expected-error {{duplicate attribute subject matcher 'function'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( enum, enum, function )) // expected-error {{duplicate attribute subject matcher 'enum'}} - -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(is_global), variable(is_global) )) // expected-error {{duplicate attribute subject matcher 'variable(is_global)'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(is_global), function, variable(is_global), variable(is_global) )) // expected-error 2 {{duplicate attribute subject matcher 'variable(is_global)'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless(is_parameter)), variable(unless(is_parameter)) )) // expected-error {{duplicate attribute subject matcher 'variable(unless(is_parameter))'}} -#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless(is_parameter)), variable(unless(is_parameter)), enum, variable(unless(is_parameter)) )) // expected-error 2 {{duplicate attribute subject matcher 'variable(unless(is_parameter))'}} - -#pragma clang attribute // expected-error {{expected 'push' or 'pop' after '#pragma clang attribute'}} -#pragma clang attribute 42 // expected-error {{expected 'push' or 'pop' after '#pragma clang attribute'}} -#pragma clang attribute pushpop // expected-error {{unexpected argument 'pushpop' to '#pragma clang attribute'; expected 'push' or 'pop'}} - -#pragma clang attribute push // expected-error {{expected '('}} -#pragma clang attribute push ( // expected-error {{expected an attribute after '('}} -#pragma clang attribute push (__attribute__((annotate)) // expected-error {{expected ')'}} -#pragma clang attribute push () // expected-error {{expected an attribute after '('}} - -#pragma clang attribute push (__attribute__((annotate("test"))), apply_to = function) () // expected-warning {{extra tokens at end of '#pragma clang attribute'}} -// expected-error@-1 {{expected unqualified-id}} -// expected-error@-2 {{unterminated '#pragma clang attribute push' at end of file}} - -#pragma clang attribute pop () // expected-warning {{extra tokens at end of '#pragma clang attribute'}} - -; - -#pragma clang attribute push (__attribute__((42))) // expected-error {{expected identifier that represents an attribute name}} - -#pragma clang attribute push (__attribute__((annotate)) foo) // expected-error {{expected ','}} -#pragma clang attribute push (__attribute__((annotate)), apply_to=function foo) // expected-error {{extra tokens after attribute in a '#pragma clang attribute push'}} - -#pragma clang attribute push (__attribute__((availability(macos, foo=1))), apply_to=function) // expected-error {{'foo' is not an availability stage; use 'introduced', 'deprecated', or 'obsoleted'}} -// expected-error@-1 {{attribute 'availability' is not supported by '#pragma clang attribute'}} -#pragma clang attribute push (__attribute__((availability(macos, 1))), apply_to=function) // expected-error {{expected 'introduced', 'deprecated', or 'obsoleted'}} - -#pragma clang attribute push (__attribute__((used)), apply_to=function) // expected-error {{attribute 'used' is not supported by '#pragma clang attribute'}} - -void statementPragmasAndPragmaExpression() { -#pragma clang attribute push (__attribute__((annotate("hello"))), apply_to=variable) -#pragma clang attribute pop -int x = 0; -_Pragma("clang attribute push (__attribute__((annotate(\"hi\"))), apply_to = function)"); - -_Pragma("clang attribute push (__attribute__((annotate(\"hi\"))), apply_to = any(function(is_method ))"); // expected-error {{expected ')'}} -} - -_Pragma("clang attribute pop"); - -#pragma clang attribute push (__attribute__((address_space(0))), apply_to=variable) // expected-error {{attribute 'address_space' is not supported by '#pragma clang attribute'}} - -// Check support for CXX11 style attributes -#pragma clang attribute push ([[noreturn]], apply_to = any(function)) -#pragma clang attribute pop - -#pragma clang attribute push ([[clang::disable_tail_calls]], apply_to = function) -#pragma clang attribute pop - -#pragma clang attribute push ([[gnu::abi_tag]], apply_to=any(function)) -#pragma clang attribute pop - -#pragma clang attribute push ([[clang::disable_tail_calls, noreturn]], apply_to = function) // expected-error {{more than one attribute specified in '#pragma clang attribute push'}} -#pragma clang attribute push ([[clang::disable_tail_calls, noreturn]]) // expected-error {{more than one attribute specified in '#pragma clang attribute push'}} - -#pragma clang attribute push ([[gnu::abi_tag]], apply_to=namespace) -#pragma clang attribute pop - -#pragma clang attribute push ([[fallthrough]], apply_to=function) // expected-error {{attribute 'fallthrough' is not supported by '#pragma clang attribute'}} -#pragma clang attribute push ([[clang::fallthrough]], apply_to=function) // expected-error {{attribute 'fallthrough' is not supported by '#pragma clang attribute'}} - -#pragma clang attribute push ([[]], apply_to = function) // A noop - -#pragma clang attribute push ([[noreturn ""]], apply_to=function) // expected-error {{expected ']'}} -#pragma clang attribute pop -#pragma clang attribute push ([[noreturn 42]]) // expected-error {{expected ']'}} expected-error {{expected ','}} - -#pragma clang attribute push(__attribute__, apply_to=function) // expected-error {{expected '(' after 'attribute'}} -#pragma clang attribute push(__attribute__(), apply_to=function) // expected-error {{expected '(' after '('}} -#pragma clang attribute push(__attribute__(()), apply_to=function) // expected-error {{expected identifier that represents an attribute name}} -#pragma clang attribute push(__attribute__((annotate, apply_to=function))) // expected-error {{expected ')'}} -#pragma clang attribute push(__attribute__((annotate("test"), apply_to=function))) // expected-error {{expected ')'}} -#pragma clang attribute push(__attribute__((annotate), apply_to=function)) // expected-error {{expected ')'}} - -#pragma clang attribute push (42) // expected-error {{expected an attribute that is specified using the GNU, C++11 or '__declspec' syntax}} -#pragma clang attribute push (test) // expected-error {{expected an attribute that is specified using the GNU, C++11 or '__declspec' syntax}} -#pragma clang attribute push (annotate) // expected-error {{expected an attribute that is specified using the GNU, C++11 or '__declspec' syntax}} -// expected-note@-1 {{use the GNU '__attribute__' syntax}} -#pragma clang attribute push (annotate("test")) // expected-error {{expected an attribute that is specified using the GNU, C++11 or '__declspec' syntax}} -// expected-note@-1 {{use the GNU '__attribute__' syntax}} diff --git a/test/Sema/pragma-attribute-strict-subjects.c b/test/Sema/pragma-attribute-strict-subjects.c deleted file mode 100644 index a84e2bde38..0000000000 --- a/test/Sema/pragma-attribute-strict-subjects.c +++ /dev/null @@ -1,153 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -Wno-pragmas -verify %s - -#pragma clang attribute push (__attribute__((annotate("test"))), apply_to = any(function, variable)) - -#pragma clang attribute pop - -// Check for contradictions in rules for attribute without a strict subject set: - -#pragma clang attribute push (__attribute__((annotate("subRuleContradictions"))), apply_to = any(variable, variable(is_parameter), function(is_member), variable(is_global))) -// expected-error@-1 {{redundant attribute subject matcher sub-rule 'variable(is_parameter)'; 'variable' already matches those declarations}} -// expected-error@-2 {{redundant attribute subject matcher sub-rule 'variable(is_global)'; 'variable' already matches those declarations}} - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((annotate("subRuleContradictions2"))), apply_to = any(function(is_member), function)) -// expected-error@-1 {{redundant attribute subject matcher sub-rule 'function(is_member)'; 'function' already matches those declarations}} - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((annotate("subRuleContradictions3"))), apply_to = any(variable, variable(unless(is_parameter)))) -// expected-error@-1 {{redundant attribute subject matcher sub-rule 'variable(unless(is_parameter))'; 'variable' already matches those declarations}} - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((annotate("negatedSubRuleContradictions1"))), apply_to = any(variable(is_parameter), variable(unless(is_parameter)))) -// expected-error@-1 {{negated attribute subject matcher sub-rule 'variable(unless(is_parameter))' contradicts sub-rule 'variable(is_parameter)'}} - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((annotate("negatedSubRuleContradictions2"))), apply_to = any(variable(unless(is_parameter)), variable(is_thread_local), function, variable(is_global))) -// expected-error@-1 {{negated attribute subject matcher sub-rule 'variable(unless(is_parameter))' contradicts sub-rule 'variable(is_global)'}} -// We have just one error, don't error on 'variable(is_global)' - -#pragma clang attribute pop - -// Verify the strict subject set verification. - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function)) -// No error -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable)) -// No error -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, variable, record(unless(is_union)))) -// No error -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(variable, record(unless(is_union)), function)) -// No error -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, record(unless(is_union)), variable, enum)) -// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(enum_constant, function, record(unless(is_union)), variable, variable(is_parameter))) -// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'variable(is_parameter)', and 'enum_constant'}} -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, record(unless(is_union)), enum)) -// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} -#pragma clang attribute pop - -// Verify the non-strict subject set verification. - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function)) - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = variable) - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)))) - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, variable)) - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(variable, record(unless(is_union)))) - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function)) - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable)) - -#pragma clang attribute pop - - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable, enum, enum_constant)) -// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum_constant', and 'enum'}} - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = enum) -// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} - -#pragma clang attribute pop - -// Handle attributes whose subjects are supported only in other language modes: - -#pragma clang attribute push(__attribute__((abi_tag("b"))), apply_to = any(namespace, record(unless(is_union)), variable, function)) -// 'namespace' is accepted! -#pragma clang attribute pop - -#pragma clang attribute push(__attribute__((abi_tag("b"))), apply_to = any(namespace)) -// 'namespace' is accepted! -#pragma clang attribute pop - -#pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = objc_interface) -// No error! -#pragma clang attribute pop - -#pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = objc_interface) -// No error! -#pragma clang attribute pop - -#pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = any(objc_interface, objc_protocol)) -// expected-error@-1 {{attribute 'objc_subclassing_restricted' can't be applied to 'objc_protocol'}} -#pragma clang attribute pop - -#pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = any(objc_protocol)) -// expected-error@-1 {{attribute 'objc_subclassing_restricted' can't be applied to 'objc_protocol'}} -// Don't report an error about missing 'objc_interface' as we aren't parsing -// Objective-C. -#pragma clang attribute pop - -#pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = any(objc_interface, objc_protocol)) -// expected-error@-1 {{attribute 'objc_subclassing_restricted' can't be applied to 'objc_protocol'}} -#pragma clang attribute pop - -#pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = any(objc_protocol)) -// expected-error@-1 {{attribute 'objc_subclassing_restricted' can't be applied to 'objc_protocol'}} -// Don't report an error about missing 'objc_interface' as we aren't parsing -// Objective-C. -#pragma clang attribute pop - -// Use of matchers from other language modes should not cause for attributes -// without subject list: -#pragma clang attribute push (__attribute__((annotate("test"))), apply_to = objc_method) - -#pragma clang attribute pop - -#pragma clang attribute push (__attribute__((annotate("test"))), apply_to = any(objc_interface, objc_protocol)) - -#pragma clang attribute pop diff --git a/test/Sema/pragma-attribute.c b/test/Sema/pragma-attribute.c deleted file mode 100644 index d321f2ce4b..0000000000 --- a/test/Sema/pragma-attribute.c +++ /dev/null @@ -1,47 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -#pragma clang attribute pop // expected-error {{'#pragma clang attribute pop' with no matching '#pragma clang attribute push'}} - -// Don't verify unused attributes. -#pragma clang attribute push (__attribute__((annotate)), apply_to = function) // expected-warning {{unused attribute 'annotate' in '#pragma clang attribute push' region}} -#pragma clang attribute pop // expected-note {{'#pragma clang attribute push' regions ends here}} - -// Ensure we only report any errors once. -#pragma clang attribute push (__attribute__((annotate)), apply_to = function) // expected-error 4 {{'annotate' attribute takes one argument}} - -void test5_begin(); // expected-note {{when applied to this declaration}} -void test5_1(); // expected-note {{when applied to this declaration}} - -#pragma clang attribute push (__attribute__((annotate())), apply_to = function) // expected-error 2 {{'annotate' attribute takes one argument}} - -void test5_2(); // expected-note 2 {{when applied to this declaration}} - -#pragma clang attribute push (__attribute__((annotate("hello", "world"))), apply_to = function) // expected-error {{'annotate' attribute takes one argument}} - -void test5_3(); // expected-note 3 {{when applied to this declaration}} - -#pragma clang attribute pop -#pragma clang attribute pop -#pragma clang attribute pop - -// Verify that the warnings are reported for each receiver declaration - -#pragma clang attribute push (__attribute__((optnone)), apply_to = function) // expected-note 2 {{conflicting attribute is here}} - -__attribute__((always_inline)) void optnone1() { } // expected-warning {{'always_inline' attribute ignored}} -// expected-note@-1 {{when applied to this declaration}} - -void optnone2() { } - -__attribute__((always_inline)) void optnone3() { } // expected-warning {{'always_inline' attribute ignored}} -// expected-note@-1 {{when applied to this declaration}} - -#pragma clang attribute pop - -#pragma clang attribute push ([[]], apply_to = function) // A noop - -#pragma clang attribute pop // expected-error {{'#pragma clang attribute pop' with no matching '#pragma clang attribute push'}} - -#pragma clang attribute push (__attribute__((annotate("func"))), apply_to = function) // expected-error {{unterminated '#pragma clang attribute push' at end of file}} - -void function(); diff --git a/test/lit.cfg b/test/lit.cfg index a5e8b9de99..e4a13054ba 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -284,8 +284,6 @@ if config.host_triple and config.host_triple != '@LLVM_HOST_TRIPLE@': else: config.substitutions.append( ('%target_itanium_abi_host_triple', '') ) -config.substitutions.append( ('%src_include_dir', config.clang_src_dir + '/include') ) - # FIXME: Find nicer way to prohibit this. config.substitutions.append( (' clang ', """*** Do not use 'clang' in tests, use '%clang'. ***""") ) diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index 63d7139874..8fdfbfc484 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -10,7 +10,6 @@ config.llvm_shlib_dir = "@SHLIBDIR@" config.llvm_plugin_ext = "@LLVM_PLUGIN_EXT@" config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" config.clang_obj_root = "@CLANG_BINARY_DIR@" -config.clang_src_dir = "@CLANG_SOURCE_DIR@" config.clang_tools_dir = "@CLANG_TOOLS_DIR@" config.host_triple = "@LLVM_HOST_TRIPLE@" config.target_triple = "@TARGET_TRIPLE@" diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index 65dbccde62..8aaa28beaa 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -12,15 +12,13 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" @@ -1524,334 +1522,6 @@ static void emitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n"; } -static bool hasGNUorCXX11Spelling(const Record &Attribute) { - std::vector Spellings = GetFlattenedSpellings(Attribute); - for (const auto &I : Spellings) { - if (I.variety() == "GNU" || I.variety() == "CXX11") - return true; - } - return false; -} - -namespace { - -struct AttributeSubjectMatchRule { - const Record *MetaSubject; - const Record *Constraint; - - AttributeSubjectMatchRule(const Record *MetaSubject, const Record *Constraint) - : MetaSubject(MetaSubject), Constraint(Constraint) { - assert(MetaSubject && "Missing subject"); - } - - bool isSubRule() const { return Constraint != nullptr; } - - std::vector getSubjects() const { - return (Constraint ? Constraint : MetaSubject) - ->getValueAsListOfDefs("Subjects"); - } - - std::vector getLangOpts() const { - if (Constraint) { - // Lookup the options in the sub-rule first, in case the sub-rule - // overrides the rules options. - std::vector Opts = Constraint->getValueAsListOfDefs("LangOpts"); - if (!Opts.empty()) - return Opts; - } - return MetaSubject->getValueAsListOfDefs("LangOpts"); - } - - // Abstract rules are used only for sub-rules - bool isAbstractRule() const { return getSubjects().empty(); } - - std::string getName() const { - return (Constraint ? Constraint : MetaSubject)->getValueAsString("Name"); - } - - bool isNegatedSubRule() const { - assert(isSubRule() && "Not a sub-rule"); - return Constraint->getValueAsBit("Negated"); - } - - std::string getSpelling() const { - std::string Result = MetaSubject->getValueAsString("Name"); - if (isSubRule()) { - Result += '('; - if (isNegatedSubRule()) - Result += "unless("; - Result += getName(); - if (isNegatedSubRule()) - Result += ')'; - Result += ')'; - } - return Result; - } - - std::string getEnumValueName() const { - std::string Result = - "SubjectMatchRule_" + MetaSubject->getValueAsString("Name"); - if (isSubRule()) { - Result += "_"; - if (isNegatedSubRule()) - Result += "not_"; - Result += Constraint->getValueAsString("Name"); - } - if (isAbstractRule()) - Result += "_abstract"; - return Result; - } - - std::string getEnumValue() const { return "attr::" + getEnumValueName(); } - - static const char *EnumName; -}; - -const char *AttributeSubjectMatchRule::EnumName = "attr::SubjectMatchRule"; - -struct PragmaClangAttributeSupport { - std::vector Rules; - llvm::DenseMap SubjectsToRules; - - PragmaClangAttributeSupport(RecordKeeper &Records); - - bool isAttributedSupported(const Record &Attribute); - - void emitMatchRuleList(raw_ostream &OS); - - std::string generateStrictConformsTo(const Record &Attr, raw_ostream &OS); - - void generateParsingHelpers(raw_ostream &OS); -}; - -} // end anonymous namespace - -PragmaClangAttributeSupport::PragmaClangAttributeSupport( - RecordKeeper &Records) { - std::vector MetaSubjects = - Records.getAllDerivedDefinitions("AttrSubjectMatcherRule"); - auto MapFromSubjectsToRules = [this](const Record *SubjectContainer, - const Record *MetaSubject, - const Record *Constraint = nullptr) { - Rules.emplace_back(MetaSubject, Constraint); - std::vector ApplicableSubjects = - SubjectContainer->getValueAsListOfDefs("Subjects"); - for (const auto *Subject : ApplicableSubjects) { - bool Inserted = - SubjectsToRules.try_emplace(Subject, MetaSubject, Constraint).second; - if (!Inserted) { - PrintFatalError("Attribute subject match rules should not represent" - "same attribute subjects."); - } - } - }; - for (const auto *MetaSubject : MetaSubjects) { - MapFromSubjectsToRules(MetaSubject, MetaSubject); - std::vector Constraints = - MetaSubject->getValueAsListOfDefs("Constraints"); - for (const auto *Constraint : Constraints) - MapFromSubjectsToRules(Constraint, MetaSubject, Constraint); - } -} - -static PragmaClangAttributeSupport & -getPragmaAttributeSupport(RecordKeeper &Records) { - static PragmaClangAttributeSupport Instance(Records); - return Instance; -} - -void PragmaClangAttributeSupport::emitMatchRuleList(raw_ostream &OS) { - OS << "#ifndef ATTR_MATCH_SUB_RULE\n"; - OS << "#define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, " - "IsNegated) " - << "ATTR_MATCH_RULE(Value, Spelling, IsAbstract)\n"; - OS << "#endif\n"; - for (const auto &Rule : Rules) { - OS << (Rule.isSubRule() ? "ATTR_MATCH_SUB_RULE" : "ATTR_MATCH_RULE") << '('; - OS << Rule.getEnumValueName() << ", \"" << Rule.getSpelling() << "\", " - << Rule.isAbstractRule(); - if (Rule.isSubRule()) - OS << ", " - << AttributeSubjectMatchRule(Rule.MetaSubject, nullptr).getEnumValue() - << ", " << Rule.isNegatedSubRule(); - OS << ")\n"; - } - OS << "#undef ATTR_MATCH_SUB_RULE\n"; -} - -bool PragmaClangAttributeSupport::isAttributedSupported( - const Record &Attribute) { - if (Attribute.getValueAsBit("ForcePragmaAttributeSupport")) - return true; - // Opt-out rules: - // FIXME: The documentation check should be moved before - // the ForcePragmaAttributeSupport check after annotate is documented. - // No documentation present. - if (Attribute.isValueUnset("Documentation")) - return false; - std::vector Docs = Attribute.getValueAsListOfDefs("Documentation"); - if (Docs.empty()) - return false; - if (Docs.size() == 1 && Docs[0]->getName() == "Undocumented") - return false; - // An attribute requires delayed parsing (LateParsed is on) - if (Attribute.getValueAsBit("LateParsed")) - return false; - // An attribute has no GNU/CXX11 spelling - if (!hasGNUorCXX11Spelling(Attribute)) - return false; - // An attribute subject list has a subject that isn't covered by one of the - // subject match rules or has no subjects at all. - if (Attribute.isValueUnset("Subjects")) - return false; - const Record *SubjectObj = Attribute.getValueAsDef("Subjects"); - std::vector Subjects = SubjectObj->getValueAsListOfDefs("Subjects"); - if (Subjects.empty()) - return false; - for (const auto *Subject : Subjects) { - if (SubjectsToRules.find(Subject) == SubjectsToRules.end()) - return false; - } - return true; -} - -std::string -PragmaClangAttributeSupport::generateStrictConformsTo(const Record &Attr, - raw_ostream &OS) { - if (!isAttributedSupported(Attr)) - return "nullptr"; - // Generate a function that constructs a set of matching rules that describe - // to which declarations the attribute should apply to. - std::string FnName = "matchRulesFor" + Attr.getName().str(); - std::stringstream SS; - SS << "static void " << FnName << "(llvm::SmallVectorImpl> &MatchRules, const LangOptions &LangOpts) {\n"; - if (Attr.isValueUnset("Subjects")) { - SS << "}\n\n"; - OS << SS.str(); - return FnName; - } - const Record *SubjectObj = Attr.getValueAsDef("Subjects"); - std::vector Subjects = SubjectObj->getValueAsListOfDefs("Subjects"); - for (const auto *Subject : Subjects) { - auto It = SubjectsToRules.find(Subject); - assert(It != SubjectsToRules.end() && - "This attribute is unsupported by #pragma clang attribute"); - AttributeSubjectMatchRule Rule = It->getSecond(); - // The rule might be language specific, so only subtract it from the given - // rules if the specific language options are specified. - std::vector LangOpts = Rule.getLangOpts(); - SS << " MatchRules.push_back(std::make_pair(" << Rule.getEnumValue() - << ", /*IsSupported=*/"; - if (!LangOpts.empty()) { - for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) { - std::string Part = (*I)->getValueAsString("Name"); - if ((*I)->getValueAsBit("Negated")) - SS << "!"; - SS << "LangOpts." + Part; - if (I + 1 != E) - SS << " || "; - } - } else - SS << "true"; - SS << "));\n"; - } - SS << "}\n\n"; - OS << SS.str(); - return FnName; -} - -void PragmaClangAttributeSupport::generateParsingHelpers(raw_ostream &OS) { - // Generate routines that check the names of sub-rules. - OS << "Optional " - "defaultIsAttributeSubjectMatchSubRuleFor(StringRef, bool) {\n"; - OS << " return None;\n"; - OS << "}\n\n"; - - std::map> - SubMatchRules; - for (const auto &Rule : Rules) { - if (!Rule.isSubRule()) - continue; - SubMatchRules[Rule.MetaSubject].push_back(Rule); - } - - for (const auto &SubMatchRule : SubMatchRules) { - OS << "Optional isAttributeSubjectMatchSubRuleFor_" - << SubMatchRule.first->getValueAsString("Name") - << "(StringRef Name, bool IsUnless) {\n"; - OS << " if (IsUnless)\n"; - OS << " return " - "llvm::StringSwitch>(Name).\n"; - for (const auto &Rule : SubMatchRule.second) { - if (Rule.isNegatedSubRule()) - OS << " Case(\"" << Rule.getName() << "\", " << Rule.getEnumValue() - << ").\n"; - } - OS << " Default(None);\n"; - OS << " return " - "llvm::StringSwitch>(Name).\n"; - for (const auto &Rule : SubMatchRule.second) { - if (!Rule.isNegatedSubRule()) - OS << " Case(\"" << Rule.getName() << "\", " << Rule.getEnumValue() - << ").\n"; - } - OS << " Default(None);\n"; - OS << "}\n\n"; - } - - // Generate the function that checks for the top-level rules. - OS << "std::pair, " - "llvm::function_ref (StringRef, " - "bool)>> isAttributeSubjectMatchRule(StringRef Name) {\n"; - OS << " return " - "llvm::StringSwitch, " - "llvm::function_ref (StringRef, " - "bool)>>>(Name).\n"; - for (const auto &Rule : Rules) { - if (Rule.isSubRule()) - continue; - std::string SubRuleFunction; - if (SubMatchRules.count(Rule.MetaSubject)) - SubRuleFunction = "isAttributeSubjectMatchSubRuleFor_" + Rule.getName(); - else - SubRuleFunction = "defaultIsAttributeSubjectMatchSubRuleFor"; - OS << " Case(\"" << Rule.getName() << "\", std::make_pair(" - << Rule.getEnumValue() << ", " << SubRuleFunction << ")).\n"; - } - OS << " Default(std::make_pair(None, " - "defaultIsAttributeSubjectMatchSubRuleFor));\n"; - OS << "}\n\n"; - - // Generate the function that checks for the submatch rules. - OS << "const char *validAttributeSubjectMatchSubRules(" - << AttributeSubjectMatchRule::EnumName << " Rule) {\n"; - OS << " switch (Rule) {\n"; - for (const auto &SubMatchRule : SubMatchRules) { - OS << " case " - << AttributeSubjectMatchRule(SubMatchRule.first, nullptr).getEnumValue() - << ":\n"; - OS << " return \"'"; - bool IsFirst = true; - for (const auto &Rule : SubMatchRule.second) { - if (!IsFirst) - OS << ", '"; - IsFirst = false; - if (Rule.isNegatedSubRule()) - OS << "unless("; - OS << Rule.getName(); - if (Rule.isNegatedSubRule()) - OS << ')'; - OS << "'"; - } - OS << "\";\n"; - } - OS << " default: return nullptr;\n"; - OS << " }\n"; - OS << "}\n\n"; -} - template static void forEachUniqueSpelling(const Record &Attr, Fn &&F) { std::vector Spellings = GetFlattenedSpellings(Attr); @@ -2439,17 +2109,6 @@ void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { OS << "#undef PRAGMA_SPELLING_ATTR\n"; } -// Emits the enumeration list for attributes. -void EmitClangAttrSubjectMatchRuleList(RecordKeeper &Records, raw_ostream &OS) { - emitSourceFileHeader( - "List of all attribute subject matching rules that Clang recognizes", OS); - PragmaClangAttributeSupport &PragmaAttributeSupport = - getPragmaAttributeSupport(Records); - emitDefaultDefine(OS, "ATTR_MATCH_RULE", nullptr); - PragmaAttributeSupport.emitMatchRuleList(OS); - OS << "#undef ATTR_MATCH_RULE\n"; -} - // Emits the code to read an attribute from a precompiled header. void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) { emitSourceFileHeader("Attribute deserialization code", OS); @@ -3045,13 +2704,9 @@ static std::string GetSubjectWithSuffix(const Record *R) { return B + "Decl"; } -static std::string functionNameForCustomAppertainsTo(const Record &Subject) { - return "is" + Subject.getName().str(); -} - static std::string GenerateCustomAppertainsTo(const Record &Subject, raw_ostream &OS) { - std::string FnName = functionNameForCustomAppertainsTo(Subject); + std::string FnName = "is" + Subject.getName().str(); // If this code has already been generated, simply return the previous // instance of it. @@ -3136,42 +2791,6 @@ static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) { return FnName; } -static void -emitAttributeMatchRules(PragmaClangAttributeSupport &PragmaAttributeSupport, - raw_ostream &OS) { - OS << "static bool checkAttributeMatchRuleAppliesTo(const Decl *D, " - << AttributeSubjectMatchRule::EnumName << " rule) {\n"; - OS << " switch (rule) {\n"; - for (const auto &Rule : PragmaAttributeSupport.Rules) { - if (Rule.isAbstractRule()) { - OS << " case " << Rule.getEnumValue() << ":\n"; - OS << " assert(false && \"Abstract matcher rule isn't allowed\");\n"; - OS << " return false;\n"; - continue; - } - std::vector Subjects = Rule.getSubjects(); - assert(!Subjects.empty() && "Missing subjects"); - OS << " case " << Rule.getEnumValue() << ":\n"; - OS << " return "; - for (auto I = Subjects.begin(), E = Subjects.end(); I != E; ++I) { - // If the subject has custom code associated with it, use the function - // that was generated for GenerateAppertainsTo to check if the declaration - // is valid. - if ((*I)->isSubClassOf("SubsetSubject")) - OS << functionNameForCustomAppertainsTo(**I) << "(D)"; - else - OS << "isa<" << GetSubjectWithSuffix(*I) << ">(D)"; - - if (I + 1 != E) - OS << " || "; - } - OS << ";\n"; - } - OS << " }\n"; - OS << " llvm_unreachable(\"Invalid match rule\");\nreturn false;\n"; - OS << "}\n\n"; -} - static void GenerateDefaultLangOptRequirements(raw_ostream &OS) { OS << "static bool defaultDiagnoseLangOpts(Sema &, "; OS << "const AttributeList &) {\n"; @@ -3330,9 +2949,6 @@ static bool IsKnownToGCC(const Record &Attr) { void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) { emitSourceFileHeader("Parsed attribute helpers", OS); - PragmaClangAttributeSupport &PragmaAttributeSupport = - getPragmaAttributeSupport(Records); - // Get the list of parsed attributes, and accept the optional list of // duplicates due to the ParseKind. ParsedAttrMap Dupes; @@ -3366,13 +2982,10 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) { SS << ", " << I->second->isSubClassOf("TypeAttr"); SS << ", " << I->second->isSubClassOf("StmtAttr"); SS << ", " << IsKnownToGCC(*I->second); - SS << ", " << PragmaAttributeSupport.isAttributedSupported(*I->second); SS << ", " << GenerateAppertainsTo(*I->second, OS); SS << ", " << GenerateLangOptRequirements(*I->second, OS); SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS); SS << ", " << GenerateSpellingIndexToSemanticSpelling(*I->second, OS); - SS << ", " - << PragmaAttributeSupport.generateStrictConformsTo(*I->second, OS); SS << " }"; if (I + 1 != E) @@ -3384,9 +2997,6 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) { OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n"; OS << SS.str(); OS << "};\n\n"; - - // Generate the attribute match rules. - emitAttributeMatchRules(PragmaAttributeSupport, OS); } // Emits the kind list of parsed attributes @@ -3526,11 +3136,6 @@ void EmitClangAttrParserStringSwitches(RecordKeeper &Records, emitClangAttrLateParsedList(Records, OS); } -void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper &Records, - raw_ostream &OS) { - getPragmaAttributeSupport(Records).generateParsingHelpers(OS); -} - class DocumentationData { public: const Record *Documentation; @@ -3562,8 +3167,8 @@ enum SpellingKind { Pragma = 1 << 5 }; -static void WriteDocumentation(RecordKeeper &Records, - const DocumentationData &Doc, raw_ostream &OS) { +static void WriteDocumentation(const DocumentationData &Doc, + raw_ostream &OS) { // FIXME: there is no way to have a per-spelling category for the attribute // documentation. This may not be a limiting factor since the spellings // should generally be consistently applied across the category. @@ -3645,7 +3250,7 @@ static void WriteDocumentation(RecordKeeper &Records, // List what spelling syntaxes the attribute supports. OS << ".. csv-table:: Supported Syntaxes\n"; OS << " :header: \"GNU\", \"C++11\", \"__declspec\", \"Keyword\","; - OS << " \"Pragma\", \"Pragma clang attribute\"\n\n"; + OS << " \"Pragma\"\n\n"; OS << " \""; if (SupportedSpellings & GNU) OS << "X"; OS << "\",\""; @@ -3656,9 +3261,6 @@ static void WriteDocumentation(RecordKeeper &Records, if (SupportedSpellings & Keyword) OS << "X"; OS << "\", \""; if (SupportedSpellings & Pragma) OS << "X"; - OS << "\", \""; - if (getPragmaAttributeSupport(Records).isAttributedSupported(*Doc.Attribute)) - OS << "X"; OS << "\"\n\n"; // If the attribute is deprecated, print a message about it, and possibly @@ -3725,40 +3327,7 @@ void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) { // Walk over each of the attributes in the category and write out their // documentation. for (const auto &Doc : I.second) - WriteDocumentation(Records, Doc, OS); - } -} - -void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records, - raw_ostream &OS) { - PragmaClangAttributeSupport Support = getPragmaAttributeSupport(Records); - ParsedAttrMap Attrs = getParsedAttrList(Records); - unsigned NumAttrs = 0; - for (const auto &I : Attrs) { - if (Support.isAttributedSupported(*I.second)) - ++NumAttrs; - } - OS << "#pragma clang attribute supports " << NumAttrs << " attributes:\n"; - for (const auto &I : Attrs) { - if (!Support.isAttributedSupported(*I.second)) - continue; - OS << I.first; - if (I.second->isValueUnset("Subjects")) { - OS << " ()\n"; - continue; - } - const Record *SubjectObj = I.second->getValueAsDef("Subjects"); - std::vector Subjects = - SubjectObj->getValueAsListOfDefs("Subjects"); - OS << " ("; - for (const auto &Subject : llvm::enumerate(Subjects)) { - if (Subject.index()) - OS << ", "; - OS << Support.SubjectsToRules.find(Subject.value()) - ->getSecond() - .getEnumValueName(); - } - OS << ")\n"; + WriteDocumentation(Doc, OS); } } diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index 781518ddbc..fd7999be38 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -25,10 +25,8 @@ using namespace clang; enum ActionType { GenClangAttrClasses, GenClangAttrParserStringSwitches, - GenClangAttrSubjectMatchRulesParserStringSwitches, GenClangAttrImpl, GenClangAttrList, - GenClangAttrSubjectMatchRuleList, GenClangAttrPCHRead, GenClangAttrPCHWrite, GenClangAttrHasAttributeImpl, @@ -56,8 +54,7 @@ enum ActionType { GenArmNeonTest, GenAttrDocs, GenDiagDocs, - GenOptDocs, - GenTestPragmaAttributeSupportedAttributes + GenOptDocs }; namespace { @@ -69,17 +66,10 @@ cl::opt Action( clEnumValN(GenClangAttrParserStringSwitches, "gen-clang-attr-parser-string-switches", "Generate all parser-related attribute string switches"), - clEnumValN(GenClangAttrSubjectMatchRulesParserStringSwitches, - "gen-clang-attr-subject-match-rules-parser-string-switches", - "Generate all parser-related attribute subject match rule" - "string switches"), clEnumValN(GenClangAttrImpl, "gen-clang-attr-impl", "Generate clang attribute implementations"), clEnumValN(GenClangAttrList, "gen-clang-attr-list", "Generate a clang attribute list"), - clEnumValN(GenClangAttrSubjectMatchRuleList, - "gen-clang-attr-subject-match-rule-list", - "Generate a clang attribute subject match rule list"), clEnumValN(GenClangAttrPCHRead, "gen-clang-attr-pch-read", "Generate clang PCH attribute reader"), clEnumValN(GenClangAttrPCHWrite, "gen-clang-attr-pch-write", @@ -90,7 +80,8 @@ cl::opt Action( clEnumValN(GenClangAttrSpellingListIndex, "gen-clang-attr-spelling-index", "Generate a clang attribute spelling index"), - clEnumValN(GenClangAttrASTVisitor, "gen-clang-attr-ast-visitor", + clEnumValN(GenClangAttrASTVisitor, + "gen-clang-attr-ast-visitor", "Generate a recursive AST visitor for clang attributes"), clEnumValN(GenClangAttrTemplateInstantiate, "gen-clang-attr-template-instantiate", @@ -146,11 +137,8 @@ cl::opt Action( "Generate attribute documentation"), clEnumValN(GenDiagDocs, "gen-diag-docs", "Generate diagnostic documentation"), - clEnumValN(GenOptDocs, "gen-opt-docs", "Generate option documentation"), - clEnumValN(GenTestPragmaAttributeSupportedAttributes, - "gen-clang-test-pragma-attribute-supported-attributes", - "Generate a list of attributes supported by #pragma clang " - "attribute for testing purposes"))); + clEnumValN(GenOptDocs, "gen-opt-docs", + "Generate option documentation"))); cl::opt ClangComponent("clang-component", @@ -165,18 +153,12 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) { case GenClangAttrParserStringSwitches: EmitClangAttrParserStringSwitches(Records, OS); break; - case GenClangAttrSubjectMatchRulesParserStringSwitches: - EmitClangAttrSubjectMatchRulesParserStringSwitches(Records, OS); - break; case GenClangAttrImpl: EmitClangAttrImpl(Records, OS); break; case GenClangAttrList: EmitClangAttrList(Records, OS); break; - case GenClangAttrSubjectMatchRuleList: - EmitClangAttrSubjectMatchRuleList(Records, OS); - break; case GenClangAttrPCHRead: EmitClangAttrPCHRead(Records, OS); break; @@ -262,9 +244,6 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) { case GenOptDocs: EmitClangOptDocs(Records, OS); break; - case GenTestPragmaAttributeSupportedAttributes: - EmitTestPragmaAttributeSupportedAttributes(Records, OS); - break; } return false; diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h index e1b7d0ec63..033cb78f36 100644 --- a/utils/TableGen/TableGenBackends.h +++ b/utils/TableGen/TableGenBackends.h @@ -33,12 +33,9 @@ void EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS, const std::string &N, const std::string &S); void EmitClangAttrParserStringSwitches(RecordKeeper &Records, raw_ostream &OS); -void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper &Records, - raw_ostream &OS); void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS); void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS); void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS); -void EmitClangAttrSubjectMatchRuleList(RecordKeeper &Records, raw_ostream &OS); void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS); void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS); void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS); @@ -75,9 +72,6 @@ void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS); void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS); void EmitClangOptDocs(RecordKeeper &Records, raw_ostream &OS); -void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records, - raw_ostream &OS); - } // end namespace clang #endif -- 2.40.0