summaryrefslogtreecommitdiff
path: root/include/clang/Basic
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2017-04-18 09:41:47 +0000
committerAlex Lorenz <arphaman@gmail.com>2017-04-18 09:41:47 +0000
commitc79938aacab81240ec20977d1dcb5a934408aa16 (patch)
tree300480232c6c0b916eb0806587ddd6fb5a17a5f8 /include/clang/Basic
parenta3307a12a12cf6e61c16b7d3076e6cf7953bd84f (diff)
downloadclang-c79938aacab81240ec20977d1dcb5a934408aa16.tar.gz
Add #pragma clang attribute
The new '#pragma clang attribute' directive can be used to apply attributes to multiple declarations. An attribute must satisfy the following conditions to be supported by the pragma: - It must have a subject list that's defined in the TableGen file. - It must be documented. - It must not be late parsed. - It must have a GNU/C++11 spelling. Differential Revision: https://reviews.llvm.org/D30009 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@300539 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang/Basic')
-rw-r--r--include/clang/Basic/Attr.td109
-rw-r--r--include/clang/Basic/AttrSubjectMatchRules.h46
-rw-r--r--include/clang/Basic/CMakeLists.txt5
-rw-r--r--include/clang/Basic/DiagnosticGroups.td4
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td37
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td19
-rw-r--r--include/clang/Basic/TokenKinds.def3
7 files changed, 222 insertions, 1 deletions
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index c5d2c7fc61..bf62408db2 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -248,6 +248,8 @@ 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
@@ -270,6 +272,102 @@ 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<string name, list<AttrSubject> subjects,
+ bit negated = 0> {
+ string Name = name;
+ list<AttrSubject> 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<LangOpt> LangOpts = [];
+}
+class AttrSubjectMatcherRule<string name, list<AttrSubject> subjects,
+ list<AttrSubjectMatcherSubRule> subrules = []> {
+ string Name = name;
+ list<AttrSubject> Subjects = subjects;
+ list<AttrSubjectMatcherSubRule> 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<LangOpt> 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<Spelling> Spellings;
@@ -305,6 +403,14 @@ 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<LangOpt> LangOpts = [];
@@ -478,6 +584,9 @@ 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
new file mode 100644
index 0000000000..955f495ad6
--- /dev/null
+++ b/include/clang/Basic/AttrSubjectMatchRules.h
@@ -0,0 +1,46 @@
+//===-- 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<SubjectMatchRule, SourceRange>;
+
+} // end namespace attr
+} // end namespace clang
+
+namespace llvm {
+
+template <>
+struct DenseMapInfo<clang::attr::SubjectMatchRule> : DenseMapInfo<int> {
+ static inline clang::attr::SubjectMatchRule getEmptyKey() {
+ return (clang::attr::SubjectMatchRule)DenseMapInfo<int>::getEmptyKey();
+ }
+ static inline clang::attr::SubjectMatchRule getTombstoneKey() {
+ return (clang::attr::SubjectMatchRule)DenseMapInfo<int>::getTombstoneKey();
+ }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt
index e4929b5b52..3e0fb8728c 100644
--- a/include/clang/Basic/CMakeLists.txt
+++ b/include/clang/Basic/CMakeLists.txt
@@ -28,6 +28,11 @@ 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 4bcf3be0a8..4cde1c81fd 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -461,7 +461,9 @@ def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes,
def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">;
def UnknownPragmas : DiagGroup<"unknown-pragmas">;
def IgnoredPragmas : DiagGroup<"ignored-pragmas", [IgnoredPragmaIntrinsic]>;
-def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas]>;
+def PragmaClangAttribute : DiagGroup<"pragma-clang-attribute">;
+def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas,
+ PragmaClangAttribute]>;
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 aebf8a9f35..d95e43c10c 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -979,6 +979,43 @@ 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 8afe61645a..3912a85491 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -750,6 +750,25 @@ 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<PragmaClangAttribute>;
+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 48e0c33f0e..968b203a38 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -790,6 +790,9 @@ 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)