diff options
-rw-r--r-- | include/clang/Basic/Attr.td | 21 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 38 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 4 | ||||
-rw-r--r-- | test/Sema/attr-print.c | 7 | ||||
-rw-r--r-- | test/SemaCXX/attr-print.cpp | 6 | ||||
-rw-r--r-- | test/SemaCXX/cxx11-attr-print.cpp | 13 | ||||
-rw-r--r-- | utils/TableGen/ClangAttrEmitter.cpp | 47 |
8 files changed, 96 insertions, 44 deletions
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 52ebbb41db..6d70756286 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -93,6 +93,11 @@ class CXX11<string namespace, string name> : Spelling<name, "CXX11"> { } class Keyword<string name> : Spelling<name, "Keyword">; +class Accessor<string name, list<Spelling> spellings> { + string Name = name; + list<Spelling> Spellings = spellings; +} + class Attr { // The various ways in which an attribute can be spelled in source list<Spelling> Spellings; @@ -100,8 +105,10 @@ class Attr { list<AttrSubject> Subjects; // The arguments allowed on an attribute list<Argument> Args = []; - // Set to true for attributes with arguments which require delayed parsing. - bit LateParsed = 0; + // Accessors which should be generated for the attribute. + list<Accessor> Accessors = []; + // Set to true for attributes with arguments which require delayed parsing. + bit LateParsed = 0; // Set to false to prevent an attribute from being propagated from a template // to the instantiation. bit Clone = 1; @@ -115,7 +122,7 @@ class Attr { bit Ignored = 0; // Set to true if each of the spellings is a distinct attribute. bit DistinctSpellings = 0; - // Any additional text that should be included verbatim in the class. + // Any additional text that should be included verbatim in the class. code AdditionalMembers = [{}]; } @@ -140,7 +147,7 @@ class IgnoredAttr : Attr { def AddressSpace : Attr { let Spellings = [GNU<"address_space">]; let Args = [IntArgument<"AddressSpace">]; - let ASTNode = 0; + let ASTNode = 0; } def Alias : InheritableAttr { @@ -152,7 +159,11 @@ def Aligned : InheritableAttr { let Spellings = [GNU<"aligned">, Declspec<"align">, CXX11<"gnu", "aligned">, Keyword<"alignas">, Keyword<"_Alignas">]; let Subjects = [NonBitField, NormalVar, Tag]; - let Args = [AlignedArgument<"Alignment">, BoolArgument<"IsMSDeclSpec">]; + let Args = [AlignedArgument<"Alignment">]; + let Accessors = [Accessor<"isGNU", [GNU<"aligned">, CXX11<"gnu","aligned">]>, + Accessor<"isAlignas", + [Keyword<"alignas">, Keyword<"_Alignas">]>, + Accessor<"isDeclspec",[Declspec<"align">]>]; } def AlignMac68k : InheritableAttr { diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 47b2de8bd1..4a27792092 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -6531,9 +6531,9 @@ public: /// AddAlignedAttr - Adds an aligned attribute to a particular declaration. void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, - bool isDeclSpec, unsigned SpellingListIndex); + unsigned SpellingListIndex); void AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *T, - bool isDeclSpec, unsigned SpellingListIndex); + unsigned SpellingListIndex); /// \brief The kind of conversion being performed. enum CheckedConversionKind { diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index cb6e898020..8500bff6bc 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -3315,30 +3315,28 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { // ignored. if (Attr.getNumArgs() == 0) { - D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context, - true, 0, Attr.isDeclspecAttribute(), - Attr.getAttributeSpellingListIndex())); + D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context, + true, 0, Attr.getAttributeSpellingListIndex())); return; } - S.AddAlignedAttr(Attr.getRange(), D, Attr.getArg(0), - Attr.isDeclspecAttribute(), + S.AddAlignedAttr(Attr.getRange(), D, Attr.getArg(0), Attr.getAttributeSpellingListIndex()); } -void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, - bool isDeclSpec, unsigned SpellingListIndex) { +void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, + unsigned SpellingListIndex) { // FIXME: Handle pack-expansions here. if (DiagnoseUnexpandedParameterPack(E)) return; if (E->isTypeDependent() || E->isValueDependent()) { // Save dependent expressions in the AST to be instantiated. - D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, E, - isDeclSpec, SpellingListIndex)); + D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, E, + SpellingListIndex)); return; } - + SourceLocation AttrLoc = AttrRange.getBegin(); // FIXME: Cache the number on the Attr object? llvm::APSInt Alignment(32); @@ -3353,26 +3351,30 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, << E->getSourceRange(); return; } - if (isDeclSpec) { + + AlignedAttr *Attr = ::new (Context) AlignedAttr(AttrRange, Context, true, + ICE.take(), + SpellingListIndex); + + if (Attr->isDeclspec()) { // We've already verified it's a power of 2, now let's make sure it's // 8192 or less. if (Alignment.getZExtValue() > 8192) { - Diag(AttrLoc, diag::err_attribute_aligned_greater_than_8192) + Diag(AttrLoc, diag::err_attribute_aligned_greater_than_8192) << E->getSourceRange(); return; } } - D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, ICE.take(), - isDeclSpec, SpellingListIndex)); + D->addAttr(Attr); } -void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS, - bool isDeclSpec, unsigned SpellingListIndex) { +void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS, + unsigned SpellingListIndex) { // FIXME: Cache the number on the Attr object if non-dependent? // FIXME: Perform checking of type validity - D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, false, TS, - isDeclSpec, SpellingListIndex)); + D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, false, TS, + SpellingListIndex)); return; } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index f5405ff383..c146e9dd44 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -79,8 +79,7 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, ExprResult Result = SubstExpr(Aligned->getAlignmentExpr(), TemplateArgs); if (!Result.isInvalid()) - AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>(), - Aligned->getIsMSDeclSpec(), + AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>(), Aligned->getSpellingListIndex()); } else { TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(), @@ -89,7 +88,6 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, DeclarationName()); if (Result) AddAlignedAttr(Aligned->getLocation(), New, Result, - Aligned->getIsMSDeclSpec(), Aligned->getSpellingListIndex()); } continue; diff --git a/test/Sema/attr-print.c b/test/Sema/attr-print.c index b523c18cab..2659508e56 100644 --- a/test/Sema/attr-print.c +++ b/test/Sema/attr-print.c @@ -1,13 +1,10 @@ // RUN: %clang_cc1 %s -ast-print -fms-extensions | FileCheck %s -// FIXME: we need to fix the "BoolArgument<"IsMSDeclSpec">" -// hack in Attr.td for attribute "Aligned". - -// CHECK: int x __attribute__((aligned(4, 0))); +// CHECK: int x __attribute__((aligned(4))); int x __attribute__((aligned(4))); // FIXME: Print this at a valid location for a __declspec attr. -// CHECK: int y __declspec(align(4, 1)); +// CHECK: int y __declspec(align(4)); __declspec(align(4)) int y; // CHECK: void foo() __attribute__((const)); diff --git a/test/SemaCXX/attr-print.cpp b/test/SemaCXX/attr-print.cpp index c7335c5e3b..2e7478904f 100644 --- a/test/SemaCXX/attr-print.cpp +++ b/test/SemaCXX/attr-print.cpp @@ -1,12 +1,10 @@ // RUN: %clang_cc1 %s -ast-print -fms-extensions | FileCheck %s -// FIXME: align attribute print - -// CHECK: int x __attribute__((aligned(4, 0))); +// CHECK: int x __attribute__((aligned(4))); int x __attribute__((aligned(4))); // FIXME: Print this at a valid location for a __declspec attr. -// CHECK: int y __declspec(align(4, 1)); +// CHECK: int y __declspec(align(4)); __declspec(align(4)) int y; // CHECK: void foo() __attribute__((const)); diff --git a/test/SemaCXX/cxx11-attr-print.cpp b/test/SemaCXX/cxx11-attr-print.cpp index b4f5859409..336e7b3f76 100644 --- a/test/SemaCXX/cxx11-attr-print.cpp +++ b/test/SemaCXX/cxx11-attr-print.cpp @@ -1,14 +1,13 @@ // RUN: %clang_cc1 -std=c++11 -ast-print -fms-extensions %s | FileCheck %s -// FIXME: align attribute print - -// CHECK: int x __attribute__((aligned(4, 0))); +// +// CHECK: int x __attribute__((aligned(4))); int x __attribute__((aligned(4))); // FIXME: Print this at a valid location for a __declspec attr. -// CHECK: int y __declspec(align(4, 1)); +// CHECK: int y __declspec(align(4)); __declspec(align(4)) int y; -// CHECK: gnu::aligned(4, 0)]]; +// CHECK: gnu::aligned(4)]]; int z [[gnu::aligned(4)]]; // CHECK: __attribute__((deprecated("warning"))); @@ -17,10 +16,10 @@ int a __attribute__((deprecated("warning"))); // CHECK: gnu::deprecated("warning")]]; int b [[gnu::deprecated("warning")]]; -// CHECK: int cxx11_alignas alignas(4, 0); +// CHECK: int cxx11_alignas alignas(4); alignas(4) int cxx11_alignas; -// CHECK: int c11_alignas _Alignas(alignof(int), 0); +// CHECK: int c11_alignas _Alignas(alignof(int)); _Alignas(int) int c11_alignas; // CHECK: void foo() __attribute__((const)); diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index 65a009c214..544ec29fab 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -829,6 +829,51 @@ static void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args, OS << "}\n\n"; } +/// \brief Return the index of a spelling in a spelling list. +static unsigned getSpellingListIndex(const std::vector<Record*> &SpellingList, + const Record &Spelling) { + assert(SpellingList.size() && "Spelling list is empty!"); + + for (unsigned Index = 0; Index < SpellingList.size(); ++Index) { + Record *S = SpellingList[Index]; + if (S->getValueAsString("Variety") != Spelling.getValueAsString("Variety")) + continue; + if (S->getValueAsString("Variety") == "CXX11" && + S->getValueAsString("Namespace") != + Spelling.getValueAsString("Namespace")) + continue; + if (S->getValueAsString("Name") != Spelling.getValueAsString("Name")) + continue; + + return Index; + } + + llvm_unreachable("Unknown spelling!"); +} + +static void writeAttrAccessorDefinition(Record &R, raw_ostream &OS) { + std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors"); + for (std::vector<Record*>::const_iterator I = Accessors.begin(), + E = Accessors.end(); I != E; ++I) { + Record *Accessor = *I; + std::string Name = Accessor->getValueAsString("Name"); + std::vector<Record*> Spellings = Accessor->getValueAsListOfDefs( + "Spellings"); + std::vector<Record*> SpellingList = R.getValueAsListOfDefs("Spellings"); + assert(SpellingList.size() && + "Attribute with empty spelling list can't have accessors!"); + + OS << " bool " << Name << "() const { return SpellingListIndex == "; + for (unsigned Index = 0; Index < Spellings.size(); ++Index) { + OS << getSpellingListIndex(SpellingList, *Spellings[Index]); + if (Index != Spellings.size() -1) + OS << " ||\n SpellingListIndex == "; + else + OS << "; }\n"; + } + } +} + namespace clang { // Emits the class definitions for attributes. @@ -903,6 +948,8 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { OS << " virtual void printPretty(raw_ostream &OS,\n" << " const PrintingPolicy &Policy) const;\n"; + writeAttrAccessorDefinition(R, OS); + for (ai = Args.begin(); ai != ae; ++ai) { (*ai)->writeAccessors(OS); OS << "\n\n"; |