aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/Attr.td21
-rw-r--r--include/clang/Sema/Sema.h4
-rw-r--r--lib/Sema/SemaDeclAttr.cpp38
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp4
-rw-r--r--test/Sema/attr-print.c7
-rw-r--r--test/SemaCXX/attr-print.cpp6
-rw-r--r--test/SemaCXX/cxx11-attr-print.cpp13
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp47
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";