forked from OSchip/llvm-project
parent
617482c666
commit
bc8a78d5a4
|
|
@ -378,6 +378,11 @@ public:
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -260,54 +260,59 @@ namespace clang {
|
|||
/// 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 @@ namespace clang {
|
|||
/// 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.
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ namespace llvm {
|
|||
namespace clang {
|
||||
|
||||
class ASTContext;
|
||||
class Attr;
|
||||
class Decl;
|
||||
class DeclContext;
|
||||
class Preprocessor;
|
||||
|
|
@ -225,6 +226,12 @@ public:
|
|||
/// \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();
|
||||
|
||||
|
|
|
|||
|
|
@ -118,6 +118,9 @@ private:
|
|||
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
|
||||
|
|
|
|||
|
|
@ -74,7 +74,8 @@ void PCHDeclReader::VisitDecl(Decl *D) {
|
|||
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 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
|
|||
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 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
|
|||
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 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
|
|||
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 @@ llvm::APFloat PCHReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
|
|||
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
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ void PCHDeclWriter::VisitDecl(Decl *D) {
|
|||
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 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
|
|||
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 @@ void PCHWriter::WriteIdentifierTable() {
|
|||
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) { }
|
||||
|
||||
|
|
|
|||
|
|
@ -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}}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
// Header for PCH test exprs.c
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int f(int) __attribute__((overloadable));
|
||||
Loading…
Reference in New Issue