[cfe-commits] r69225 - in /cfe/trunk: include/clang/AST/Attr.h include/clang/Frontend/PCHBitCodes.h include/clang/Frontend/PCHReader.h include/clang/Frontend/PCHWriter.h lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp test/PCH/attrs.c test/PCH/attrs.h
Douglas Gregor
dgregor at apple.com
Wed Apr 15 14:30:52 PDT 2009
Author: dgregor
Date: Wed Apr 15 16:30:51 2009
New Revision: 69225
URL: http://llvm.org/viewvc/llvm-project?rev=69225&view=rev
Log:
PCH support for declaration attributes
Added:
cfe/trunk/test/PCH/attrs.c
cfe/trunk/test/PCH/attrs.h
Modified:
cfe/trunk/include/clang/AST/Attr.h
cfe/trunk/include/clang/Frontend/PCHBitCodes.h
cfe/trunk/include/clang/Frontend/PCHReader.h
cfe/trunk/include/clang/Frontend/PCHWriter.h
cfe/trunk/lib/Frontend/PCHReader.cpp
cfe/trunk/lib/Frontend/PCHWriter.cpp
Modified: cfe/trunk/include/clang/AST/Attr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=69225&r1=69224&r2=69225&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Attr.h (original)
+++ cfe/trunk/include/clang/AST/Attr.h Wed Apr 15 16:30:51 2009
@@ -377,7 +377,12 @@
virtual ~NonNullAttr() {
delete [] ArgNums;
}
-
+
+ typedef const unsigned *iterator;
+ iterator begin() const { return ArgNums; }
+ iterator end() const { return ArgNums + Size; }
+ unsigned size() const { return Size; }
+
bool isNonNull(unsigned arg) const {
return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true;
}
Modified: cfe/trunk/include/clang/Frontend/PCHBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHBitCodes.h?rev=69225&r1=69224&r2=69225&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Wed Apr 15 16:30:51 2009
@@ -260,54 +260,59 @@
/// constant describes a record for a specific type class in the
/// AST.
enum TypeCode {
+ /// \brief Attributes attached to a type.
+ ///
+ /// Note that this has the same value as DECL_ATTR, since
+ /// attribute blocks are used for both types and declarations.
+ TYPE_ATTR = 1,
/// \brief An ExtQualType record.
- TYPE_EXT_QUAL = 1,
+ TYPE_EXT_QUAL = 2,
/// \brief A FixedWidthIntType record.
- TYPE_FIXED_WIDTH_INT = 2,
+ TYPE_FIXED_WIDTH_INT = 3,
/// \brief A ComplexType record.
- TYPE_COMPLEX = 3,
+ TYPE_COMPLEX = 4,
/// \brief A PointerType record.
- TYPE_POINTER = 4,
+ TYPE_POINTER = 5,
/// \brief A BlockPointerType record.
- TYPE_BLOCK_POINTER = 5,
+ TYPE_BLOCK_POINTER = 6,
/// \brief An LValueReferenceType record.
- TYPE_LVALUE_REFERENCE = 6,
+ TYPE_LVALUE_REFERENCE = 7,
/// \brief An RValueReferenceType record.
- TYPE_RVALUE_REFERENCE = 7,
+ TYPE_RVALUE_REFERENCE = 8,
/// \brief A MemberPointerType record.
- TYPE_MEMBER_POINTER = 8,
+ TYPE_MEMBER_POINTER = 9,
/// \brief A ConstantArrayType record.
- TYPE_CONSTANT_ARRAY = 9,
+ TYPE_CONSTANT_ARRAY = 10,
/// \brief An IncompleteArrayType record.
- TYPE_INCOMPLETE_ARRAY = 10,
+ TYPE_INCOMPLETE_ARRAY = 11,
/// \brief A VariableArrayType record.
- TYPE_VARIABLE_ARRAY = 11,
+ TYPE_VARIABLE_ARRAY = 12,
/// \brief A VectorType record.
- TYPE_VECTOR = 12,
+ TYPE_VECTOR = 13,
/// \brief An ExtVectorType record.
- TYPE_EXT_VECTOR = 13,
+ TYPE_EXT_VECTOR = 14,
/// \brief A FunctionNoProtoType record.
- TYPE_FUNCTION_NO_PROTO = 14,
+ TYPE_FUNCTION_NO_PROTO = 15,
/// \brief A FunctionProtoType record.
- TYPE_FUNCTION_PROTO = 15,
+ TYPE_FUNCTION_PROTO = 16,
/// \brief A TypedefType record.
- TYPE_TYPEDEF = 16,
+ TYPE_TYPEDEF = 17,
/// \brief A TypeOfExprType record.
- TYPE_TYPEOF_EXPR = 17,
+ TYPE_TYPEOF_EXPR = 18,
/// \brief A TypeOfType record.
- TYPE_TYPEOF = 18,
+ TYPE_TYPEOF = 19,
/// \brief A RecordType record.
- TYPE_RECORD = 19,
+ TYPE_RECORD = 20,
/// \brief An EnumType record.
- TYPE_ENUM = 20,
+ TYPE_ENUM = 21,
/// \brief An ObjCInterfaceType record.
- TYPE_OBJC_INTERFACE = 21,
+ TYPE_OBJC_INTERFACE = 22,
/// \brief An ObjCQualifiedInterfaceType record.
- TYPE_OBJC_QUALIFIED_INTERFACE = 22,
+ TYPE_OBJC_QUALIFIED_INTERFACE = 23,
/// \brief An ObjCQualifiedIdType record.
- TYPE_OBJC_QUALIFIED_ID = 23,
+ TYPE_OBJC_QUALIFIED_ID = 24,
/// \brief An ObjCQualifiedClassType record.
- TYPE_OBJC_QUALIFIED_CLASS = 24
+ TYPE_OBJC_QUALIFIED_CLASS = 25
};
/// \brief Record codes for each kind of declaration.
@@ -317,8 +322,13 @@
/// constant describes a record for a specific declaration class
/// in the AST.
enum DeclCode {
+ /// \brief Attributes attached to a declaration.
+ ///
+ /// Note that this has the same value as TYPE_ATTR, since
+ /// attribute blocks are used for both types and declarations.
+ DECL_ATTR = 1,
/// \brief A TranslationUnitDecl record.
- DECL_TRANSLATION_UNIT = 1,
+ DECL_TRANSLATION_UNIT,
/// \brief A TypedefDecl record.
DECL_TYPEDEF,
/// \brief An EnumDecl record.
Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=69225&r1=69224&r2=69225&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Wed Apr 15 16:30:51 2009
@@ -37,6 +37,7 @@
namespace clang {
class ASTContext;
+class Attr;
class Decl;
class DeclContext;
class Preprocessor;
@@ -225,6 +226,12 @@
/// \brief Read a floating-point value
llvm::APFloat ReadAPFloat(const RecordData &Record, unsigned &Idx);
+ // \brief Read a string
+ std::string ReadString(const RecordData &Record, unsigned &Idx);
+
+ /// \brief Reads attributes from the current stream position.
+ Attr *ReadAttributes();
+
/// \brief Reads an expression from the current stream position.
Expr *ReadExpr();
Modified: cfe/trunk/include/clang/Frontend/PCHWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHWriter.h?rev=69225&r1=69224&r2=69225&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Wed Apr 15 16:30:51 2009
@@ -118,6 +118,9 @@
uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
void WriteDeclsBlock(ASTContext &Context);
void WriteIdentifierTable();
+ void WriteAttributeRecord(const Attr *Attr);
+
+ void AddString(const std::string &Str, RecordData &Record);
public:
/// \brief Create a new precompiled header writer that outputs to
Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=69225&r1=69224&r2=69225&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Wed Apr 15 16:30:51 2009
@@ -74,7 +74,8 @@
cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
D->setInvalidDecl(Record[Idx++]);
- // FIXME: hasAttrs
+ if (Record[Idx++])
+ D->addAttr(Reader.ReadAttributes());
D->setImplicit(Record[Idx++]);
D->setAccess((AccessSpecifier)Record[Idx++]);
}
@@ -1074,6 +1075,10 @@
RecordData Record;
unsigned Code = Stream.ReadCode();
switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
+ case pch::TYPE_ATTR:
+ assert(false && "Should never jump to an attribute block");
+ return QualType();
+
case pch::TYPE_EXT_QUAL:
// FIXME: Deserialize ExtQualType
assert(false && "Cannot deserialize qualified types yet");
@@ -1264,6 +1269,12 @@
PCHDeclReader Reader(*this, Record, Idx);
switch ((pch::DeclCode)Stream.ReadRecord(Code, Record)) {
+ case pch::DECL_ATTR:
+ case pch::DECL_CONTEXT_LEXICAL:
+ case pch::DECL_CONTEXT_VISIBLE:
+ assert(false && "Record cannot be de-serialized with ReadDeclRecord");
+ break;
+
case pch::DECL_TRANSLATION_UNIT:
assert(Index == 0 && "Translation unit must be at index 0");
Reader.VisitTranslationUnitDecl(Context.getTranslationUnitDecl());
@@ -1372,10 +1383,6 @@
D = Block;
break;
}
-
- default:
- assert(false && "Cannot de-serialize this kind of declaration");
- break;
}
// If this declaration is also a declaration context, get the
@@ -1635,6 +1642,146 @@
return llvm::APFloat(ReadAPInt(Record, Idx));
}
+// \brief Read a string
+std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) {
+ unsigned Len = Record[Idx++];
+ std::string Result(&Record[Idx], &Record[Idx] + Len);
+ Idx += Len;
+ return Result;
+}
+
+/// \brief Reads attributes from the current stream position.
+Attr *PCHReader::ReadAttributes() {
+ unsigned Code = Stream.ReadCode();
+ assert(Code == llvm::bitc::UNABBREV_RECORD &&
+ "Expected unabbreviated record"); (void)Code;
+
+ RecordData Record;
+ unsigned Idx = 0;
+ unsigned RecCode = Stream.ReadRecord(Code, Record);
+ assert(RecCode == pch::DECL_ATTR && "Expected attribute record");
+ (void)RecCode;
+
+#define SIMPLE_ATTR(Name) \
+ case Attr::Name: \
+ New = ::new (Context) Name##Attr(); \
+ break
+
+#define STRING_ATTR(Name) \
+ case Attr::Name: \
+ New = ::new (Context) Name##Attr(ReadString(Record, Idx)); \
+ break
+
+#define UNSIGNED_ATTR(Name) \
+ case Attr::Name: \
+ New = ::new (Context) Name##Attr(Record[Idx++]); \
+ break
+
+ Attr *Attrs = 0;
+ while (Idx < Record.size()) {
+ Attr *New = 0;
+ Attr::Kind Kind = (Attr::Kind)Record[Idx++];
+ bool IsInherited = Record[Idx++];
+
+ switch (Kind) {
+ STRING_ATTR(Alias);
+ UNSIGNED_ATTR(Aligned);
+ SIMPLE_ATTR(AlwaysInline);
+ SIMPLE_ATTR(AnalyzerNoReturn);
+ STRING_ATTR(Annotate);
+ STRING_ATTR(AsmLabel);
+
+ case Attr::Blocks:
+ New = ::new (Context) BlocksAttr(
+ (BlocksAttr::BlocksAttrTypes)Record[Idx++]);
+ break;
+
+ case Attr::Cleanup:
+ New = ::new (Context) CleanupAttr(
+ cast<FunctionDecl>(GetDecl(Record[Idx++])));
+ break;
+
+ SIMPLE_ATTR(Const);
+ UNSIGNED_ATTR(Constructor);
+ SIMPLE_ATTR(DLLExport);
+ SIMPLE_ATTR(DLLImport);
+ SIMPLE_ATTR(Deprecated);
+ UNSIGNED_ATTR(Destructor);
+ SIMPLE_ATTR(FastCall);
+
+ case Attr::Format: {
+ std::string Type = ReadString(Record, Idx);
+ unsigned FormatIdx = Record[Idx++];
+ unsigned FirstArg = Record[Idx++];
+ New = ::new (Context) FormatAttr(Type, FormatIdx, FirstArg);
+ break;
+ }
+
+ SIMPLE_ATTR(GNUCInline);
+
+ case Attr::IBOutletKind:
+ New = ::new (Context) IBOutletAttr();
+ break;
+
+ SIMPLE_ATTR(NoReturn);
+ SIMPLE_ATTR(NoThrow);
+ SIMPLE_ATTR(Nodebug);
+ SIMPLE_ATTR(Noinline);
+
+ case Attr::NonNull: {
+ unsigned Size = Record[Idx++];
+ llvm::SmallVector<unsigned, 16> ArgNums;
+ ArgNums.insert(ArgNums.end(), &Record[Idx], &Record[Idx] + Size);
+ Idx += Size;
+ New = ::new (Context) NonNullAttr(&ArgNums[0], Size);
+ break;
+ }
+
+ SIMPLE_ATTR(ObjCException);
+ SIMPLE_ATTR(ObjCNSObject);
+ SIMPLE_ATTR(Overloadable);
+ UNSIGNED_ATTR(Packed);
+ SIMPLE_ATTR(Pure);
+ UNSIGNED_ATTR(Regparm);
+ STRING_ATTR(Section);
+ SIMPLE_ATTR(StdCall);
+ SIMPLE_ATTR(TransparentUnion);
+ SIMPLE_ATTR(Unavailable);
+ SIMPLE_ATTR(Unused);
+ SIMPLE_ATTR(Used);
+
+ case Attr::Visibility:
+ New = ::new (Context) VisibilityAttr(
+ (VisibilityAttr::VisibilityTypes)Record[Idx++]);
+ break;
+
+ SIMPLE_ATTR(WarnUnusedResult);
+ SIMPLE_ATTR(Weak);
+ SIMPLE_ATTR(WeakImport);
+ }
+
+ assert(New && "Unable to decode attribute?");
+ New->setInherited(IsInherited);
+ New->setNext(Attrs);
+ Attrs = New;
+ }
+#undef UNSIGNED_ATTR
+#undef STRING_ATTR
+#undef SIMPLE_ATTR
+
+ // The list of attributes was built backwards. Reverse the list
+ // before returning it.
+ Attr *PrevAttr = 0, *NextAttr = 0;
+ while (Attrs) {
+ NextAttr = Attrs->getNext();
+ Attrs->setNext(PrevAttr);
+ PrevAttr = Attrs;
+ Attrs = NextAttr;
+ }
+
+ return PrevAttr;
+}
+
Expr *PCHReader::ReadExpr() {
// Within the bitstream, expressions are stored in Reverse Polish
// Notation, with each of the subexpressions preceding the
Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=69225&r1=69224&r2=69225&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Wed Apr 15 16:30:51 2009
@@ -276,7 +276,7 @@
Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
Writer.AddSourceLocation(D->getLocation(), Record);
Record.push_back(D->isInvalidDecl());
- // FIXME: hasAttrs
+ Record.push_back(D->hasAttrs());
Record.push_back(D->isImplicit());
Record.push_back(D->getAccess());
}
@@ -1131,6 +1131,10 @@
assert(W.Code && "Unhandled declaration kind while generating PCH");
S.EmitRecord(W.Code, Record);
+ // If the declaration had any attributes, write them now.
+ if (D->hasAttrs())
+ WriteAttributeRecord(D->getAttrs());
+
// Flush any expressions that were written as part of this declaration.
FlushExprs();
@@ -1209,6 +1213,134 @@
S.EmitRecord(pch::IDENTIFIER_OFFSET, IdentOffsets);
}
+/// \brief Write a record containing the given attributes.
+void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
+ RecordData Record;
+ for (; Attr; Attr = Attr->getNext()) {
+ Record.push_back(Attr->getKind()); // FIXME: stable encoding
+ Record.push_back(Attr->isInherited());
+ switch (Attr->getKind()) {
+ case Attr::Alias:
+ AddString(cast<AliasAttr>(Attr)->getAliasee(), Record);
+ break;
+
+ case Attr::Aligned:
+ Record.push_back(cast<AlignedAttr>(Attr)->getAlignment());
+ break;
+
+ case Attr::AlwaysInline:
+ break;
+
+ case Attr::AnalyzerNoReturn:
+ break;
+
+ case Attr::Annotate:
+ AddString(cast<AnnotateAttr>(Attr)->getAnnotation(), Record);
+ break;
+
+ case Attr::AsmLabel:
+ AddString(cast<AsmLabelAttr>(Attr)->getLabel(), Record);
+ break;
+
+ case Attr::Blocks:
+ Record.push_back(cast<BlocksAttr>(Attr)->getType()); // FIXME: stable
+ break;
+
+ case Attr::Cleanup:
+ AddDeclRef(cast<CleanupAttr>(Attr)->getFunctionDecl(), Record);
+ break;
+
+ case Attr::Const:
+ break;
+
+ case Attr::Constructor:
+ Record.push_back(cast<ConstructorAttr>(Attr)->getPriority());
+ break;
+
+ case Attr::DLLExport:
+ case Attr::DLLImport:
+ case Attr::Deprecated:
+ break;
+
+ case Attr::Destructor:
+ Record.push_back(cast<DestructorAttr>(Attr)->getPriority());
+ break;
+
+ case Attr::FastCall:
+ break;
+
+ case Attr::Format: {
+ const FormatAttr *Format = cast<FormatAttr>(Attr);
+ AddString(Format->getType(), Record);
+ Record.push_back(Format->getFormatIdx());
+ Record.push_back(Format->getFirstArg());
+ break;
+ }
+
+ case Attr::GNUCInline:
+ case Attr::IBOutletKind:
+ case Attr::NoReturn:
+ case Attr::NoThrow:
+ case Attr::Nodebug:
+ case Attr::Noinline:
+ break;
+
+ case Attr::NonNull: {
+ const NonNullAttr *NonNull = cast<NonNullAttr>(Attr);
+ Record.push_back(NonNull->size());
+ Record.insert(Record.end(), NonNull->begin(), NonNull->end());
+ break;
+ }
+
+ case Attr::ObjCException:
+ case Attr::ObjCNSObject:
+ case Attr::Overloadable:
+ break;
+
+ case Attr::Packed:
+ Record.push_back(cast<PackedAttr>(Attr)->getAlignment());
+ break;
+
+ case Attr::Pure:
+ break;
+
+ case Attr::Regparm:
+ Record.push_back(cast<RegparmAttr>(Attr)->getNumParams());
+ break;
+
+ case Attr::Section:
+ AddString(cast<SectionAttr>(Attr)->getName(), Record);
+ break;
+
+ case Attr::StdCall:
+ case Attr::TransparentUnion:
+ case Attr::Unavailable:
+ case Attr::Unused:
+ case Attr::Used:
+ break;
+
+ case Attr::Visibility:
+ // FIXME: stable encoding
+ Record.push_back(cast<VisibilityAttr>(Attr)->getVisibility());
+ break;
+
+ case Attr::WarnUnusedResult:
+ case Attr::Weak:
+ case Attr::WeakImport:
+ break;
+ }
+ }
+
+ assert((int)pch::DECL_ATTR == (int)pch::TYPE_ATTR &&
+ "DECL_ATTR/TYPE_ATTR mismatch");
+ S.EmitRecord(pch::DECL_ATTR, Record);
+}
+
+void PCHWriter::AddString(const std::string &Str, RecordData &Record) {
+ Record.push_back(Str.size());
+ Record.insert(Record.end(), Str.begin(), Str.end());
+}
+
PCHWriter::PCHWriter(llvm::BitstreamWriter &S)
: S(S), NextTypeID(pch::NUM_PREDEF_TYPE_IDS) { }
Added: cfe/trunk/test/PCH/attrs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/attrs.c?rev=69225&view=auto
==============================================================================
--- cfe/trunk/test/PCH/attrs.c (added)
+++ cfe/trunk/test/PCH/attrs.c Wed Apr 15 16:30:51 2009
@@ -0,0 +1,8 @@
+// Test this without pch.
+// RUN: clang-cc -include %S/attrs.h -fsyntax-only -verify %s
+
+// Test with pch.
+// RUN: clang-cc -emit-pch -o %t %S/attrs.h &&
+// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s
+// expected-note{{previous overload}}
+double f(double); // expected-error{{overloadable}}
Added: cfe/trunk/test/PCH/attrs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/attrs.h?rev=69225&view=auto
==============================================================================
--- cfe/trunk/test/PCH/attrs.h (added)
+++ cfe/trunk/test/PCH/attrs.h Wed Apr 15 16:30:51 2009
@@ -0,0 +1,7 @@
+// Header for PCH test exprs.c
+
+
+
+
+
+int f(int) __attribute__((overloadable));
More information about the cfe-commits
mailing list