From: Michael Han Date: Fri, 1 Feb 2013 01:19:17 +0000 (+0000) Subject: [Sema][Attr]Fix alignment attribute printing. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=af02bbe84f653125d50bfded5f854baf48c307f9;p=platform%2Fupstream%2Fllvm.git [Sema][Attr]Fix alignment attribute printing. Remove "IsMSDeclspec" argument from Align attribute since the arguments in Attr.td should only model those appear in source code. Introduce attribute Accessor, and teach TableGen to generate syntax kind accessors for Align attribute, and use those accessors to decide if an alignment attribute is a declspec attribute. llvm-svn: 174133 --- diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 52ebbb4..6d70756 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -93,6 +93,11 @@ class CXX11 : Spelling { } class Keyword : Spelling; +class Accessor spellings> { + string Name = name; + list Spellings = spellings; +} + class Attr { // The various ways in which an attribute can be spelled in source list Spellings; @@ -100,8 +105,10 @@ class Attr { list Subjects; // The arguments allowed on an attribute list Args = []; - // Set to true for attributes with arguments which require delayed parsing. - bit LateParsed = 0; + // Accessors which should be generated for the attribute. + list 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/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 47b2de8..4a27792 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/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/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index cb6e898..8500bff 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/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/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index f5405ff..c146e9d 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/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(), - Aligned->getIsMSDeclSpec(), + AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs(), 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/clang/test/Sema/attr-print.c b/clang/test/Sema/attr-print.c index b523c18..2659508 100644 --- a/clang/test/Sema/attr-print.c +++ b/clang/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/clang/test/SemaCXX/attr-print.cpp b/clang/test/SemaCXX/attr-print.cpp index c7335c5..2e74789 100644 --- a/clang/test/SemaCXX/attr-print.cpp +++ b/clang/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/clang/test/SemaCXX/cxx11-attr-print.cpp b/clang/test/SemaCXX/cxx11-attr-print.cpp index b4f5859..336e7b3 100644 --- a/clang/test/SemaCXX/cxx11-attr-print.cpp +++ b/clang/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/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index 65a009c..544ec29 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -829,6 +829,51 @@ static void writePrettyPrintFunction(Record &R, std::vector &Args, OS << "}\n\n"; } +/// \brief Return the index of a spelling in a spelling list. +static unsigned getSpellingListIndex(const std::vector &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 Accessors = R.getValueAsListOfDefs("Accessors"); + for (std::vector::const_iterator I = Accessors.begin(), + E = Accessors.end(); I != E; ++I) { + Record *Accessor = *I; + std::string Name = Accessor->getValueAsString("Name"); + std::vector Spellings = Accessor->getValueAsListOfDefs( + "Spellings"); + std::vector 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";