]> granicus.if.org Git - clang/commitdiff
Refactor Clang sema attribute handling.
authorMichael Han <Michael.Han@autodesk.com>
Wed, 7 Mar 2012 00:12:16 +0000 (00:12 +0000)
committerMichael Han <Michael.Han@autodesk.com>
Wed, 7 Mar 2012 00:12:16 +0000 (00:12 +0000)
This submission improves Clang sema handling by using Clang tablegen
to generate common boilerplate code. As a start, it implements AttributeList
enumerator generation and case statements for AttributeList::getKind.

A new field "SemaHandler" is introduced in Attr.td and by default set to 1
as most of attributes in Attr.td have semantic checking in Sema. For a small
number of attributes that don't appear in Sema, the value is set to 0.

Also there are a small number of attributes that only appear in Sema but not
in Attr.td. Currently these attributes are still hardcoded in Sema AttributeList.

Reviewed by Delesley Hutchins.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152169 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/Attr.td
include/clang/Sema/AttributeList.h
include/clang/Sema/CMakeLists.txt
include/clang/Sema/Makefile
lib/Parse/ParseDecl.cpp
lib/Sema/AttributeList.cpp
lib/Sema/CMakeLists.txt
lib/Sema/SemaDeclAttr.cpp
utils/TableGen/ClangAttrEmitter.cpp
utils/TableGen/ClangAttrEmitter.h
utils/TableGen/TableGen.cpp

index a7680bbb52fd05d777ed5751ba06441641b8c3e8..ee9f60f2527c2c7506903da9775beb8152123968 100644 (file)
@@ -95,6 +95,8 @@ class Attr {
   bit LateParsed = 0;  
   // Set to true for attributes which must be instantiated within templates
   bit TemplateDependent = 0;
+  // Set to true for attributes which have handler in Sema.
+  bit SemaHandler = 1;
   // Any additional text that should be included verbatim in the class.  
   code AdditionalMembers = [{}];
 }
@@ -124,6 +126,7 @@ def Aligned : InheritableAttr {
 
 def AlignMac68k : InheritableAttr {
   let Spellings = [];
+  let SemaHandler = 0;
 }
 
 def AlwaysInline : InheritableAttr {
@@ -142,6 +145,7 @@ def Annotate : InheritableParamAttr {
 def AsmLabel : InheritableAttr {
   let Spellings = [];
   let Args = [StringArgument<"Label">];
+  let SemaHandler = 0;
 }
 
 def Availability : InheritableAttr {
@@ -276,6 +280,7 @@ def FastCall : InheritableAttr {
 
 def Final : InheritableAttr { 
   let Spellings = [];
+  let SemaHandler = 0;
 }
 
 def MsStruct : InheritableAttr {
@@ -317,6 +322,7 @@ def Malloc : InheritableAttr {
 def MaxFieldAlignment : InheritableAttr {
   let Spellings = [];
   let Args = [UnsignedArgument<"Alignment">];
+  let SemaHandler = 0;
 }
 
 def MayAlias : InheritableAttr {
@@ -326,14 +332,17 @@ def MayAlias : InheritableAttr {
 def MSP430Interrupt : InheritableAttr {
   let Spellings = [];
   let Args = [UnsignedArgument<"Number">];
+  let SemaHandler = 0;
 }
 
 def MBlazeInterruptHandler : InheritableAttr {
   let Spellings = [];
+  let SemaHandler = 0;
 }
 
 def MBlazeSaveVolatiles : InheritableAttr {
   let Spellings = [];
+  let SemaHandler = 0;
 }
 
 def Naked : InheritableAttr {
@@ -449,6 +458,7 @@ def Overloadable : Attr {
 
 def Override : InheritableAttr { 
   let Spellings = [];
+  let SemaHandler = 0;
 }
 
 def Ownership : InheritableAttr {
index 545350f9ef90fa64c8d3c7124473a52a52ab16fc..142f1444f382745824f4723aaf78b842909d6a33 100644 (file)
@@ -159,124 +159,21 @@ private:
   friend class AttributeFactory;
 
 public:
-  enum Kind {             // Please keep this list alphabetized.
-    AT_acquired_after,
-    AT_acquired_before,
-    AT_address_space,
-    AT_alias,
-    AT_aligned,
-    AT_always_inline,
-    AT_analyzer_noreturn,
-    AT_annotate,
-    AT_arc_weakref_unavailable,
-    AT_objc_requires_property_definitions,
-    AT_availability,      // Clang-specific
-    AT_base_check,
-    AT_blocks,
-    AT_carries_dependency,
-    AT_cdecl,
-    AT_cf_audited_transfer,     // Clang-specific.
-    AT_cf_consumed,             // Clang-specific.
-    AT_cf_returns_autoreleased, // Clang-specific.
-    AT_cf_returns_not_retained, // Clang-specific.
-    AT_cf_returns_retained,     // Clang-specific.
-    AT_cf_unknown_transfer,     // Clang-specific.
-    AT_cleanup,
-    AT_common,
-    AT_const,
-    AT_constant,
-    AT_constructor,
-    AT_deprecated,
-    AT_destructor,
-    AT_device,
-    AT_dllexport,
-    AT_dllimport,
-    AT_exclusive_lock_function,
-    AT_exclusive_locks_required,
-    AT_exclusive_trylock_function,
-    AT_ext_vector_type,
-    AT_fastcall,
-    AT_format,
-    AT_format_arg,
-    AT_global,
-    AT_gnu_inline,
-    AT_guarded_by,
-    AT_guarded_var,
-    AT_host,
-    AT_IBAction,          // Clang-specific.
-    AT_IBOutlet,          // Clang-specific.
-    AT_IBOutletCollection, // Clang-specific.
-    AT_init_priority,
-    AT_launch_bounds,
-    AT_lock_returned,
-    AT_lockable,
-    AT_locks_excluded,
-    AT_malloc,
-    AT_may_alias,
-    AT_mode,
-    AT_MsStruct,
-    AT_naked,
-    AT_neon_polyvector_type,    // Clang-specific.
-    AT_neon_vector_type,        // Clang-specific.
-    AT_no_address_safety_analysis,
-    AT_no_instrument_function,
-    AT_no_thread_safety_analysis,
-    AT_nocommon,
-    AT_nodebug,
-    AT_noinline,
-    AT_nonnull,
-    AT_noreturn,
-    AT_nothrow,
-    AT_ns_bridged,              // Clang-specific.
-    AT_ns_consumed,             // Clang-specific.
-    AT_ns_consumes_self,        // Clang-specific.
-    AT_ns_returns_autoreleased, // Clang-specific.
-    AT_ns_returns_not_retained, // Clang-specific.
-    AT_ns_returns_retained,     // Clang-specific.
-    AT_nsobject,
-    AT_objc_exception,
-    AT_objc_gc,
-    AT_objc_method_family,
-    AT_objc_ownership,          // Clang-specific.
-    AT_objc_precise_lifetime,   // Clang-specific.
-    AT_objc_returns_inner_pointer, // Clang-specific.
-    AT_opencl_image_access,     // OpenCL-specific.
-    AT_opencl_kernel_function,  // OpenCL-specific.
-    AT_overloadable,       // Clang-specific.
-    AT_ownership_holds,    // Clang-specific.
-    AT_ownership_returns,  // Clang-specific.
-    AT_ownership_takes,    // Clang-specific.
-    AT_packed,
-    AT_pascal,
-    AT_pcs,  // ARM specific
-    AT_pt_guarded_by,
-    AT_pt_guarded_var,
-    AT_pure,
-    AT_regparm,
-    AT_reqd_wg_size,
-    AT_scoped_lockable,
-    AT_section,
-    AT_sentinel,
-    AT_shared,
-    AT_shared_lock_function,
-    AT_shared_locks_required,
-    AT_shared_trylock_function,
-    AT_stdcall,
-    AT_thiscall,
-    AT_transparent_union,
-    AT_unavailable,
-    AT_unlock_function,
-    AT_unused,
-    AT_used,
-    AT_uuid,
-    AT_vecreturn,     // PS3 PPU-specific.
-    AT_vector_size,
-    AT_visibility,
-    AT_warn_unused_result,
-    AT_weak,
-    AT_weak_import,
-    AT_weakref,
-    AT_returns_twice,
+  enum Kind {           
+    #define PARSED_ATTR(NAME) AT_##NAME,
+    #include "clang/Sema/AttrParsedAttrList.inc"
+    PARSED_ATTR(address_space)
+    PARSED_ATTR(base_check)
+    PARSED_ATTR(cf_returns_autoreleased)
+    PARSED_ATTR(ext_vector_type)
+    PARSED_ATTR(mode)
+    PARSED_ATTR(neon_polyvector_type)
+    PARSED_ATTR(neon_vector_type)
+    PARSED_ATTR(objc_gc)
+    PARSED_ATTR(objc_ownership)
+    PARSED_ATTR(opencl_image_access)
+    PARSED_ATTR(vector_size)
+    #undef PARSED_ATTR
     IgnoredAttribute,
     UnknownAttribute
   };
index 110c5f9a4bd187dd502fb3f033940270ff73b8c8..03f99a363035be4938d9a5b64a21ce68d9c75f73 100644 (file)
@@ -2,3 +2,13 @@ clang_tablegen(AttrTemplateInstantiate.inc -gen-clang-attr-template-instantiate
   -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
   SOURCE ../Basic/Attr.td
   TARGET ClangAttrTemplateInstantiate)
+  
+clang_tablegen(AttrParsedAttrList.inc -gen-clang-attr-parsed-attr-list
+  -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
+  SOURCE ../Basic/Attr.td
+  TARGET ClangAttrParsedAttrList)
+
+clang_tablegen(AttrParsedAttrKinds.inc -gen-clang-attr-parsed-attr-kinds
+  -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
+  SOURCE ../Basic/Attr.td
+  TARGET ClangAttrParsedAttrKinds)
\ No newline at end of file
index 3ec9c8bf8b9e1462cc1bdd6e36a46326e91a6264..f6662d6b08ebae4d884873d180f91f8bf5162824 100644 (file)
@@ -1,6 +1,6 @@
 CLANG_LEVEL := ../../..
 TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
-BUILT_SOURCES = AttrTemplateInstantiate.inc
+BUILT_SOURCES = AttrTemplateInstantiate.inc AttrParsedAttrList.inc AttrParsedAttrKinds.inc
 
 TABLEGEN_INC_FILES_COMMON = 1
 
@@ -11,4 +11,17 @@ $(ObjDir)/AttrTemplateInstantiate.inc.tmp : $(TD_SRC_DIR)/Attr.td \
        $(Echo) "Building Clang attribute template instantiate code with tablegen"
        $(Verb) $(ClangTableGen) -gen-clang-attr-template-instantiate -o \
          $(call SYSPATH, $@) -I $(PROJ_SRC_DIR)/../../ $<
+         
+$(ObjDir)/AttrParsedAttrList.inc.tmp : $(TD_SRC_DIR)/Attr.td \
+                                       $(CLANG_TBLGEN) $(ObjDir)/.dir
+       $(Echo) "Building Clang parsed attribute list with tablegen"
+       $(Verb) $(ClangTableGen) -gen-clang-attr-parsed-attr-list -o \
+         $(call SYSPATH, $@) -I $(PROJ_SRC_DIR)/../../ $<
+         
+$(ObjDir)/AttrParsedAttrKinds.inc.tmp : $(TD_SRC_DIR)/Attr.td \
+                                       $(CLANG_TBLGEN) $(ObjDir)/.dir
+       $(Echo) "Building Clang parsed attribute kinds with tablegen"
+       $(Verb) $(ClangTableGen) -gen-clang-attr-parsed-attr-kinds -o \
+         $(call SYSPATH, $@) -I $(PROJ_SRC_DIR)/../../ $<
+
 
index 094d53fe60efbf34fce4bb0b62cf4a901b0a0bad..3a261f010dc623a800666e8c695fe1058843c27c 100644 (file)
@@ -270,7 +270,7 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
     AttributeList *attr =
       Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), 0, AttrNameLoc,
                    ParmName, ParmLoc, ArgExprs.take(), ArgExprs.size());
-    if (BuiltinType && attr->getKind() == AttributeList::AT_IBOutletCollection)
+    if (BuiltinType && attr->getKind() == AttributeList::AT_iboutletcollection)
       Diag(Tok, diag::err_iboutletcollection_builtintype);
   }
 }
index 9b74fc03cefdeb99922d3ac4d112695e5c382e23..f142ab4c0a324407cc418f26e1de27e2d86dc5b7 100644 (file)
@@ -106,133 +106,21 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
     AttrName = AttrName.substr(2, AttrName.size() - 4);
 
   return llvm::StringSwitch<AttributeList::Kind>(AttrName)
-    .Case("weak", AT_weak)
-    .Case("weakref", AT_weakref)
-    .Case("objc_arc_weak_reference_unavailable", AT_arc_weakref_unavailable)
-    .Case("objc_requires_property_definitions", AT_objc_requires_property_definitions)
-    .Case("pure", AT_pure)
-    .Case("mode", AT_mode)
-    .Case("used", AT_used)
-    .Case("alias", AT_alias)
-    .Case("align", AT_aligned)
-    .Case("cdecl", AT_cdecl)
-    .Case("const", AT_const)
-    .Case("__const", AT_const) // some GCC headers do contain this spelling
-    .Case("blocks", AT_blocks)
-    .Case("format", AT_format)
-    .Case("malloc", AT_malloc)
-    .Case("packed", AT_packed)
-    .Case("unused", AT_unused)
-    .Case("aligned", AT_aligned)
-    .Case("cleanup", AT_cleanup)
-    .Case("naked", AT_naked)
-    .Case("nodebug", AT_nodebug)
-    .Case("nonnull", AT_nonnull)
-    .Case("nothrow", AT_nothrow)
-    .Case("objc_gc", AT_objc_gc)
-    .Case("regparm", AT_regparm)
-    .Case("section", AT_section)
-    .Case("stdcall", AT_stdcall)
-    .Case("annotate", AT_annotate)
-    .Case("fastcall", AT_fastcall)
-    .Case("ibaction", AT_IBAction)
-    .Case("iboutlet", AT_IBOutlet)
-    .Case("iboutletcollection", AT_IBOutletCollection)
-    .Case("noreturn", AT_noreturn)
-    .Case("noinline", AT_noinline)
-    .Case("sentinel", AT_sentinel)
-    .Case("NSObject", AT_nsobject)
-    .Case("dllimport", AT_dllimport)
-    .Case("dllexport", AT_dllexport)
-    .Case("may_alias", AT_may_alias)
-    .Case("base_check", AT_base_check)
-    .Case("deprecated", AT_deprecated)
-    .Case("availability", AT_availability)
-    .Case("visibility", AT_visibility)
-    .Case("destructor", AT_destructor)
-    .Case("format_arg", AT_format_arg)
-    .Case("gnu_inline", AT_gnu_inline)
-    .Case("weak_import", AT_weak_import)
-    .Case("vecreturn", AT_vecreturn)
-    .Case("vector_size", AT_vector_size)
-    .Case("constructor", AT_constructor)
-    .Case("unavailable", AT_unavailable)
-    .Case("overloadable", AT_overloadable)
+    #include "clang/Sema/AttrParsedAttrKinds.inc"
     .Case("address_space", AT_address_space)
-    .Case("opencl_image_access", AT_opencl_image_access)
-    .Case("always_inline", AT_always_inline)
-    .Case("returns_twice", AT_returns_twice)
+    .Case("align", AT_aligned) // FIXME - should it be "aligned"?
+    .Case("base_check", AT_base_check)
+    .Case("bounded", IgnoredAttribute)       // OpenBSD
+    .Case("__const", AT_const) // some GCC headers do contain this spelling
+    .Case("cf_returns_autoreleased", AT_cf_returns_autoreleased)
+    .Case("mode", AT_mode)
     .Case("vec_type_hint", IgnoredAttribute)
-    .Case("objc_exception", AT_objc_exception)
-    .Case("objc_method_family", AT_objc_method_family)
-    .Case("objc_returns_inner_pointer", AT_objc_returns_inner_pointer)
     .Case("ext_vector_type", AT_ext_vector_type)
     .Case("neon_vector_type", AT_neon_vector_type)
     .Case("neon_polyvector_type", AT_neon_polyvector_type)
-    .Case("transparent_union", AT_transparent_union)
-    .Case("analyzer_noreturn", AT_analyzer_noreturn)
-    .Case("warn_unused_result", AT_warn_unused_result)
-    .Case("carries_dependency", AT_carries_dependency)
-    .Case("ns_bridged", AT_ns_bridged)
-    .Case("ns_consumed", AT_ns_consumed)
-    .Case("ns_consumes_self", AT_ns_consumes_self)
-    .Case("ns_returns_autoreleased", AT_ns_returns_autoreleased)
-    .Case("ns_returns_not_retained", AT_ns_returns_not_retained)
-    .Case("ns_returns_retained", AT_ns_returns_retained)
-    .Case("cf_audited_transfer", AT_cf_audited_transfer)
-    .Case("cf_consumed", AT_cf_consumed)
-    .Case("cf_returns_not_retained", AT_cf_returns_not_retained)
-    .Case("cf_returns_retained", AT_cf_returns_retained)
-    .Case("cf_returns_autoreleased", AT_cf_returns_autoreleased)
-    .Case("cf_unknown_transfer", AT_cf_unknown_transfer)
-    .Case("ns_consumes_self", AT_ns_consumes_self)
-    .Case("ns_consumed", AT_ns_consumed)
+    .Case("opencl_image_access", AT_opencl_image_access)
+    .Case("objc_gc", AT_objc_gc)
     .Case("objc_ownership", AT_objc_ownership)
-    .Case("objc_precise_lifetime", AT_objc_precise_lifetime)
-    .Case("ownership_returns", AT_ownership_returns)
-    .Case("ownership_holds", AT_ownership_holds)
-    .Case("ownership_takes", AT_ownership_takes)
-    .Case("reqd_work_group_size", AT_reqd_wg_size)
-    .Case("init_priority", AT_init_priority)
-    .Case("no_instrument_function", AT_no_instrument_function)
-    .Case("thiscall", AT_thiscall)
-    .Case("bounded", IgnoredAttribute)       // OpenBSD
-    .Case("pascal", AT_pascal)
-    .Case("__cdecl", AT_cdecl)
-    .Case("__stdcall", AT_stdcall)
-    .Case("__fastcall", AT_fastcall)
-    .Case("__thiscall", AT_thiscall)
-    .Case("__pascal", AT_pascal)
-    .Case("constant", AT_constant)
-    .Case("device", AT_device)
-    .Case("global", AT_global)
-    .Case("host", AT_host)
-    .Case("shared", AT_shared)
-    .Case("launch_bounds", AT_launch_bounds)
-    .Case("common", AT_common)
-    .Case("nocommon", AT_nocommon)
-    .Case("opencl_kernel_function", AT_opencl_kernel_function)
-    .Case("uuid", AT_uuid)
-    .Case("pcs", AT_pcs)
-    .Case("ms_struct", AT_MsStruct)
-    .Case("guarded_var", AT_guarded_var)
-    .Case("pt_guarded_var", AT_pt_guarded_var)
-    .Case("scoped_lockable", AT_scoped_lockable)
-    .Case("lockable", AT_lockable)
-    .Case("no_address_safety_analysis", AT_no_address_safety_analysis)
-    .Case("no_thread_safety_analysis", AT_no_thread_safety_analysis)
-    .Case("guarded_by", AT_guarded_by)
-    .Case("pt_guarded_by", AT_pt_guarded_by)
-    .Case("acquired_after", AT_acquired_after)
-    .Case("acquired_before", AT_acquired_before)
-    .Case("exclusive_lock_function", AT_exclusive_lock_function)
-    .Case("exclusive_locks_required", AT_exclusive_locks_required)
-    .Case("exclusive_trylock_function", AT_exclusive_trylock_function)
-    .Case("lock_returned", AT_lock_returned)
-    .Case("locks_excluded", AT_locks_excluded)
-    .Case("shared_lock_function", AT_shared_lock_function)
-    .Case("shared_locks_required", AT_shared_locks_required)
-    .Case("shared_trylock_function", AT_shared_trylock_function)
-    .Case("unlock_function", AT_unlock_function)
+    .Case("vector_size", AT_vector_size)
     .Default(UnknownAttribute);
 }
index 80aef19ab99a0983b08b451f7be0228c46644627..5d297f9831d1d4531db60f2c6d833943133f7044 100644 (file)
@@ -51,4 +51,7 @@ add_clang_library(clangSema
 
 add_dependencies(clangSema ClangARMNeon ClangAttrClasses ClangAttrList 
                  ClangDiagnosticSema ClangDeclNodes ClangStmtNodes 
-                 ClangAttrTemplateInstantiate)
+                 ClangAttrTemplateInstantiate ClangAttrParsedAttrList 
+                                ClangAttrParsedAttrKinds)
+
+
index 37edeff0ecd0ad28e12d3b5775350899b386aa5c..23abefe6bf08e43467776c8c3fabcab76a09cfde 100644 (file)
@@ -3561,9 +3561,9 @@ static void ProcessNonInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
 static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
                                        const AttributeList &Attr) {
   switch (Attr.getKind()) {
-  case AttributeList::AT_IBAction:            handleIBAction(S, D, Attr); break;
-    case AttributeList::AT_IBOutlet:          handleIBOutlet(S, D, Attr); break;
-  case AttributeList::AT_IBOutletCollection:
+    case AttributeList::AT_ibaction:            handleIBAction(S, D, Attr); break;
+    case AttributeList::AT_iboutlet:          handleIBOutlet(S, D, Attr); break;
+    case AttributeList::AT_iboutletcollection:
       handleIBOutletCollection(S, D, Attr); break;
   case AttributeList::AT_address_space:
   case AttributeList::AT_opencl_image_access:
@@ -3648,17 +3648,17 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
   case AttributeList::AT_cf_returns_retained:
     handleNSReturnsRetainedAttr(S, D, Attr); break;
 
-  case AttributeList::AT_reqd_wg_size:
+  case AttributeList::AT_reqd_work_group_size:
     handleReqdWorkGroupSize(S, D, Attr); break;
 
   case AttributeList::AT_init_priority: 
       handleInitPriorityAttr(S, D, Attr); break;
       
   case AttributeList::AT_packed:      handlePackedAttr      (S, D, Attr); break;
-  case AttributeList::AT_MsStruct:    handleMsStructAttr    (S, D, Attr); break;
+  case AttributeList::AT_ms_struct:    handleMsStructAttr    (S, D, Attr); break;
   case AttributeList::AT_section:     handleSectionAttr     (S, D, Attr); break;
   case AttributeList::AT_unavailable: handleUnavailableAttr (S, D, Attr); break;
-  case AttributeList::AT_arc_weakref_unavailable: 
+  case AttributeList::AT_objc_arc_weak_reference_unavailable: 
     handleArcWeakrefUnavailableAttr (S, D, Attr); 
     break;
   case AttributeList::AT_objc_requires_property_definitions: 
@@ -3684,7 +3684,7 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
   case AttributeList::AT_objc_method_family:
     handleObjCMethodFamilyAttr(S, D, Attr);
     break;
-  case AttributeList::AT_nsobject:    handleObjCNSObject    (S, D, Attr); break;
+  case AttributeList::AT_NSObject:    handleObjCNSObject    (S, D, Attr); break;
   case AttributeList::AT_blocks:      handleBlocksAttr      (S, D, Attr); break;
   case AttributeList::AT_sentinel:    handleSentinelAttr    (S, D, Attr); break;
   case AttributeList::AT_const:       handleConstAttr       (S, D, Attr); break;
index 4d3daf605c31e58d96b073e939b90a64446efaed..7951fc467d2005fe6619bae50b1d510c0c00d89c 100644 (file)
@@ -16,6 +16,7 @@
 #include "llvm/TableGen/Record.h"
 #include <algorithm>
 #include <cctype>
+#include <set>
 
 using namespace llvm;
 
@@ -65,6 +66,30 @@ static std::string WritePCHRecord(StringRef type, StringRef name) {
     .Default("Record.push_back(" + std::string(name) + ");\n");
 }
 
+// Normalize attribute name by removing leading and trailing
+// underscores. For example, __foo, foo__, __foo__ would
+// become foo.
+static StringRef NormalizeAttrName(StringRef AttrName) {
+  if (AttrName.startswith("__"))
+    AttrName = AttrName.substr(2, AttrName.size());
+
+  if (AttrName.endswith("__"))
+    AttrName = AttrName.substr(0, AttrName.size() - 2);
+
+  return AttrName;
+}
+
+// Normalize attribute spelling only if the spelling has both leading
+// and trailing underscores. For example, __ms_struct__ will be 
+// normalized to "ms_struct"; __cdecl will remain intact.
+static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) {
+  if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) {
+    AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
+  }
+
+  return AttrSpelling;
+}
+
 namespace {
   class Argument {
     std::string lowerName, upperName;
@@ -999,3 +1024,69 @@ void ClangAttrTemplateInstantiateEmitter::run(raw_ostream &OS) {
      << "} // end namespace clang\n";
 }
 
+void ClangAttrParsedAttrListEmitter::run(raw_ostream &OS) {
+  OS << "// This file is generated by TableGen. Do not edit.\n\n";
+  
+  OS << "#ifndef PARSED_ATTR\n";
+  OS << "#define PARSED_ATTR(NAME) NAME\n";
+  OS << "#endif\n\n";
+  
+  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+  std::set<StringRef> ProcessedAttrs;
+
+  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
+       I != E; ++I) {
+    Record &Attr = **I;
+    
+    bool SemaHandler = Attr.getValueAsBit("SemaHandler");
+    
+    if (SemaHandler) {
+      std::vector<StringRef> Spellings =
+        getValueAsListOfStrings(Attr, "Spellings");
+      
+      for (std::vector<StringRef>::const_iterator I = Spellings.begin(),
+           E = Spellings.end(); I != E; ++I) {
+        StringRef AttrName = *I;
+
+        AttrName = NormalizeAttrName(AttrName);
+        // skip if a normalized version has been processed.
+        if (ProcessedAttrs.find(AttrName) != ProcessedAttrs.end())
+          continue;
+        else
+          ProcessedAttrs.insert(AttrName);
+
+        OS << "PARSED_ATTR(" << AttrName << ")\n";
+      }
+    }
+  }
+}
+
+void ClangAttrParsedAttrKindsEmitter::run(raw_ostream &OS) {
+  OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+
+  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
+       I != E; ++I) {
+    Record &Attr = **I;
+    
+    bool SemaHandler = Attr.getValueAsBit("SemaHandler");
+    
+    if (SemaHandler) {
+      std::vector<StringRef> Spellings =
+        getValueAsListOfStrings(Attr, "Spellings");
+
+      for (std::vector<StringRef>::const_iterator I = Spellings.begin(),
+           E = Spellings.end(); I != E; ++I) {
+       StringRef AttrName = *I, Spelling = *I;
+       
+       AttrName = NormalizeAttrName(AttrName);
+       Spelling = NormalizeAttrSpelling(Spelling);
+
+       OS << ".Case(\"" << Spelling << "\", " << "AT_" << AttrName << ")\n";
+      }
+    }
+  }
+}
+
+
index 91ec754346a1716e2eb2f9780522a68e536b237c..d119a094c177c90a18dbc97deda10a47963aefc3 100644 (file)
@@ -122,6 +122,32 @@ class ClangAttrTemplateInstantiateEmitter : public TableGenBackend {
   void run(raw_ostream &OS);
 };
 
+/// ClangAttrParsedAttrListEmitter emits the list of parsed attributes
+/// for clang.
+class ClangAttrParsedAttrListEmitter : public TableGenBackend {
+  RecordKeeper &Records;
+
+public:
+  explicit ClangAttrParsedAttrListEmitter(RecordKeeper &R)
+    : Records(R)
+    {}
+
+  void run(raw_ostream &OS);
+};
+
+/// ClangAttrParsedAttrKindsEmitter emits the kind list of parsed attributes
+/// for clang.
+class ClangAttrParsedAttrKindsEmitter : public TableGenBackend {
+  RecordKeeper &Records;
+
+public:
+  explicit ClangAttrParsedAttrKindsEmitter(RecordKeeper &R)
+    : Records(R)
+    {}
+
+  void run(raw_ostream &OS);
+};
+
 }
 
 #endif
index 6462b3bb74496ea5756d72c9f0edd528c7f5f242..5ff88db30156f2391923829545ee5736bd463946 100644 (file)
@@ -37,6 +37,8 @@ enum ActionType {
   GenClangAttrSpellingList,
   GenClangAttrLateParsedList,
   GenClangAttrTemplateInstantiate,
+  GenClangAttrParsedAttrList,
+  GenClangAttrParsedAttrKinds,
   GenClangDiagsDefs,
   GenClangDiagGroups,
   GenClangDiagsIndexName,
@@ -75,6 +77,12 @@ namespace {
                     clEnumValN(GenClangAttrTemplateInstantiate,
                                "gen-clang-attr-template-instantiate",
                                "Generate a clang template instantiate code"),
+                    clEnumValN(GenClangAttrParsedAttrList,
+                               "gen-clang-attr-parsed-attr-list",
+                               "Generate a clang parsed attribute list"),
+                    clEnumValN(GenClangAttrParsedAttrKinds,
+                               "gen-clang-attr-parsed-attr-kinds",
+                               "Generate a clang parsed attribute kinds"),
                     clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
                                "Generate Clang diagnostics definitions"),
                     clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
@@ -129,6 +137,12 @@ public:
     case GenClangAttrTemplateInstantiate:
       ClangAttrTemplateInstantiateEmitter(Records).run(OS);
       break;
+    case GenClangAttrParsedAttrList:
+      ClangAttrParsedAttrListEmitter(Records).run(OS);
+      break;
+    case GenClangAttrParsedAttrKinds:
+      ClangAttrParsedAttrKindsEmitter(Records).run(OS);
+      break;
     case GenClangDiagsDefs:
       ClangDiagsDefsEmitter(Records, ClangComponent).run(OS);
       break;