Generate Attr subclasses with TableGen.

Now all classes derived from Attr are generated from TableGen.
Additionally, Attr* is no longer its own linked list; SmallVectors or
Attr* are used. The accompanying LLVM commit contains the updates to
TableGen necessary for this.

Some other notes about newly-generated attribute classes:

 - The constructor arguments are a SourceLocation and a Context&,
   followed by the attributes arguments in the order that they were
   defined in Attr.td

 - Every argument in Attr.td has an appropriate accessor named getFoo,
   and there are sometimes a few extra ones (such as to get the length
   of a variadic argument).

Additionally, specific_attr_iterator has been introduced, which will
iterate over an AttrVec, but only over attributes of a certain type. It
can be accessed through either Decl::specific_attr_begin/end or
the global functions of the same name.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111455 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sean Hunt 2010-08-18 23:23:40 +00:00
Родитель ea94bbc476
Коммит cf807c4dfd
35 изменённых файлов: 561 добавлений и 1459 удалений

Просмотреть файл

@ -18,7 +18,6 @@
#include "clang/Basic/LangOptions.h" #include "clang/Basic/LangOptions.h"
#include "clang/Basic/OperatorKinds.h" #include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/PartialDiagnostic.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h" #include "clang/AST/Decl.h"
#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h" #include "clang/AST/PrettyPrinter.h"
@ -199,7 +198,7 @@ class ASTContext {
/// ///
/// Since so few decls have attrs, we keep them in a hash map instead of /// Since so few decls have attrs, we keep them in a hash map instead of
/// wasting space in the Decl class. /// wasting space in the Decl class.
llvm::DenseMap<const Decl*, Attr*> DeclAttrs; llvm::DenseMap<const Decl*, AttrVec> DeclAttrs;
/// \brief Keeps track of the static data member templates from which /// \brief Keeps track of the static data member templates from which
/// static data members of class template specializations were instantiated. /// static data members of class template specializations were instantiated.
@ -322,7 +321,7 @@ public:
} }
/// \brief Retrieve the attributes for the given declaration. /// \brief Retrieve the attributes for the given declaration.
Attr*& getDeclAttrs(const Decl *D) { return DeclAttrs[D]; } AttrVec& getDeclAttrs(const Decl *D) { return DeclAttrs[D]; }
/// \brief Erase the attributes corresponding to the given declaration. /// \brief Erase the attributes corresponding to the given declaration.
void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); } void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); }

Просмотреть файл

@ -15,9 +15,11 @@
#define LLVM_CLANG_AST_ATTR_H #define LLVM_CLANG_AST_ATTR_H
#include "llvm/Support/Casting.h" #include "llvm/Support/Casting.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "clang/Basic/AttrKinds.h" #include "clang/Basic/AttrKinds.h"
#include "clang/AST/Type.h" #include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <algorithm> #include <algorithm>
@ -29,25 +31,33 @@ namespace clang {
class ObjCInterfaceDecl; class ObjCInterfaceDecl;
class Expr; class Expr;
class QualType; class QualType;
class FunctionDecl;
class TypeSourceInfo;
} }
// Defined in ASTContext.h // Defined in ASTContext.h
void *operator new(size_t Bytes, clang::ASTContext &C, void *operator new(size_t Bytes, clang::ASTContext &C,
size_t Alignment = 16) throw (); size_t Alignment = 16) throw ();
// FIXME: Being forced to not have a default argument here due to redeclaration
// rules on default arguments sucks
void *operator new[](size_t Bytes, clang::ASTContext &C,
size_t Alignment) throw ();
// It is good practice to pair new/delete operators. Also, MSVC gives many // It is good practice to pair new/delete operators. Also, MSVC gives many
// warnings if a matching delete overload is not declared, even though the // warnings if a matching delete overload is not declared, even though the
// throw() spec guarantees it will not be implicitly called. // throw() spec guarantees it will not be implicitly called.
void operator delete(void *Ptr, clang::ASTContext &C, size_t) void operator delete(void *Ptr, clang::ASTContext &C, size_t)
throw (); throw ();
void operator delete[](void *Ptr, clang::ASTContext &C, size_t)
throw ();
namespace clang { namespace clang {
/// Attr - This represents one attribute. /// Attr - This represents one attribute.
class Attr { class Attr {
private: private:
Attr *Next; SourceLocation Loc;
attr::Kind AttrKind; unsigned AttrKind : 16;
bool Inherited : 1; bool Inherited : 1;
protected: protected:
@ -61,8 +71,20 @@ protected:
assert(0 && "Attrs cannot be released with regular 'delete'."); assert(0 && "Attrs cannot be released with regular 'delete'.");
} }
public:
// Forward so that the regular new and delete do not hide global ones.
void* operator new(size_t Bytes, ASTContext &C,
size_t Alignment = 16) throw() {
return ::operator new(Bytes, C, Alignment);
}
void operator delete(void *Ptr, ASTContext &C,
size_t Alignment = 16) throw() {
return ::operator delete(Ptr, C, Alignment);
}
protected: protected:
Attr(attr::Kind AK) : Next(0), AttrKind(AK), Inherited(false) {} Attr(attr::Kind AK, SourceLocation L)
: Loc(L), AttrKind(AK) {}
public: public:
@ -70,29 +92,15 @@ public:
/// declarations. /// declarations.
virtual bool isMerged() const { return true; } virtual bool isMerged() const { return true; }
attr::Kind getKind() const { return AttrKind; } attr::Kind getKind() const {
return static_cast<attr::Kind>(AttrKind);
Attr *getNext() { return Next; }
const Attr *getNext() const { return Next; }
void setNext(Attr *next) { Next = next; }
template<typename T> const T *getNext() const {
for (const Attr *attr = getNext(); attr; attr = attr->getNext())
if (const T *V = dyn_cast<T>(attr))
return V;
return 0;
} }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
bool isInherited() const { return Inherited; } bool isInherited() const { return Inherited; }
void setInherited(bool value) { Inherited = value; } void setInherited(bool I) { Inherited = I; }
void addAttr(Attr *attr) {
assert((attr != 0) && "addAttr(): attr is null");
// FIXME: This doesn't preserve the order in any way.
attr->Next = Next;
Next = attr;
}
// Clone this attribute. // Clone this attribute.
virtual Attr* clone(ASTContext &C) const = 0; virtual Attr* clone(ASTContext &C) const = 0;
@ -103,590 +111,111 @@ public:
#include "clang/AST/Attrs.inc" #include "clang/AST/Attrs.inc"
class AttrWithString : public Attr { /// AttrVec - A vector of Attr, which is how they are stored on the AST.
private: typedef llvm::SmallVector<Attr*, 2> AttrVec;
const char *Str; typedef llvm::SmallVector<const Attr*, 2> ConstAttrVec;
unsigned StrLen;
protected:
AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s);
llvm::StringRef getString() const { return llvm::StringRef(Str, StrLen); }
void ReplaceString(ASTContext &C, llvm::StringRef newS);
};
#define DEF_SIMPLE_ATTR(ATTR) \ /// DestroyAttrs - Destroy the contents of an AttrVec.
class ATTR##Attr : public Attr { \ inline void DestroyAttrs (AttrVec& V, ASTContext &C) {
public: \
ATTR##Attr() : Attr(attr::ATTR) {} \
virtual Attr *clone(ASTContext &C) const; \
static bool classof(const Attr *A) { return A->getKind() == attr::ATTR; } \
static bool classof(const ATTR##Attr *A) { return true; } \
} }
DEF_SIMPLE_ATTR(Packed); /// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
/// providing attributes that are of a specifc type.
template <typename SpecificAttr>
class specific_attr_iterator {
/// Current - The current, underlying iterator.
/// In order to ensure we don't dereference an invalid iterator unless
/// specifically requested, we don't necessarily advance this all the
/// way. Instead, we advance it when an operation is requested; if the
/// operation is acting on what should be a past-the-end iterator,
/// then we offer no guarantees, but this way we do not dererence a
/// past-the-end iterator when we move to a past-the-end position.
mutable AttrVec::const_iterator Current;
/// \brief Attribute for specifying a maximum field alignment; this is only void AdvanceToNext() const {
/// valid on record decls. while (!llvm::isa<SpecificAttr>(*Current))
class MaxFieldAlignmentAttr : public Attr { ++Current;
unsigned Alignment; }
void AdvanceToNext(AttrVec::const_iterator I) const {
while (Current != I && !llvm::isa<SpecificAttr>(*Current))
++Current;
}
public: public:
MaxFieldAlignmentAttr(unsigned alignment) typedef SpecificAttr* value_type;
: Attr(attr::MaxFieldAlignment), Alignment(alignment) {} typedef SpecificAttr* reference;
typedef SpecificAttr* pointer;
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
/// getAlignment - The specified alignment in bits. specific_attr_iterator() : Current() { }
unsigned getAlignment() const { return Alignment; } explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
virtual Attr* clone(ASTContext &C) const; reference operator*() const {
AdvanceToNext();
// Implement isa/cast/dyncast/etc. return llvm::cast<SpecificAttr>(*Current);
static bool classof(const Attr *A) {
return A->getKind() == attr::MaxFieldAlignment;
} }
static bool classof(const MaxFieldAlignmentAttr *A) { return true; } pointer operator->() const {
}; AdvanceToNext();
return llvm::cast<SpecificAttr>(*Current);
DEF_SIMPLE_ATTR(AlignMac68k);
/// \brief Atribute for specifying the alignment of a variable or type.
///
/// This node will either contain the precise Alignment (in bits, not bytes!)
/// or will contain the expression for the alignment attribute in the case of
/// a dependent expression within a class or function template. At template
/// instantiation time these are transformed into concrete attributes.
class AlignedAttr : public Attr {
unsigned Alignment;
Expr *AlignmentExpr;
public:
AlignedAttr(unsigned alignment)
: Attr(attr::Aligned), Alignment(alignment), AlignmentExpr(0) {}
AlignedAttr(Expr *E)
: Attr(attr::Aligned), Alignment(0), AlignmentExpr(E) {}
/// getAlignmentExpr - Get a dependent alignment expression if one is present.
Expr *getAlignmentExpr() const {
return AlignmentExpr;
} }
/// isDependent - Is the alignment a dependent expression specific_attr_iterator& operator++() {
bool isDependent() const { ++Current;
return getAlignmentExpr(); return *this;
}
specific_attr_iterator operator++(int) {
specific_attr_iterator Tmp(*this);
++(*this);
return Tmp;
} }
/// getAlignment - The specified alignment in bits. Requires !isDependent(). friend bool operator==(specific_attr_iterator Left,
unsigned getAlignment() const { specific_attr_iterator Right) {
assert(!isDependent() && "Cannot get a value dependent alignment"); if (Left.Current < Right.Current)
return Alignment; Left.AdvanceToNext(Right.Current);
}
/// getMaxAlignment - Get the maximum alignment of attributes on this list.
unsigned getMaxAlignment() const {
const AlignedAttr *Next = getNext<AlignedAttr>();
if (Next)
return std::max(Next->getMaxAlignment(), getAlignment());
else else
return getAlignment(); Right.AdvanceToNext(Left.Current);
return Left.Current == Right.Current;
} }
friend bool operator!=(specific_attr_iterator Left,
virtual Attr* clone(ASTContext &C) const; specific_attr_iterator Right) {
return !(Left == Right);
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::Aligned;
}
static bool classof(const AlignedAttr *A) { return true; }
};
class AnnotateAttr : public AttrWithString {
public:
AnnotateAttr(ASTContext &C, llvm::StringRef ann)
: AttrWithString(attr::Annotate, C, ann) {}
llvm::StringRef getAnnotation() const { return getString(); }
virtual Attr* clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::Annotate;
}
static bool classof(const AnnotateAttr *A) { return true; }
};
class AsmLabelAttr : public AttrWithString {
public:
AsmLabelAttr(ASTContext &C, llvm::StringRef L)
: AttrWithString(attr::AsmLabel, C, L) {}
llvm::StringRef getLabel() const { return getString(); }
virtual Attr* clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::AsmLabel;
}
static bool classof(const AsmLabelAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(AlwaysInline);
class AliasAttr : public AttrWithString {
public:
AliasAttr(ASTContext &C, llvm::StringRef aliasee)
: AttrWithString(attr::Alias, C, aliasee) {}
llvm::StringRef getAliasee() const { return getString(); }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == attr::Alias; }
static bool classof(const AliasAttr *A) { return true; }
};
class ConstructorAttr : public Attr {
int priority;
public:
ConstructorAttr(int p) : Attr(attr::Constructor), priority(p) {}
int getPriority() const { return priority; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A)
{ return A->getKind() == attr::Constructor; }
static bool classof(const ConstructorAttr *A) { return true; }
};
class DestructorAttr : public Attr {
int priority;
public:
DestructorAttr(int p) : Attr(attr::Destructor), priority(p) {}
int getPriority() const { return priority; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A)
{ return A->getKind() == attr::Destructor; }
static bool classof(const DestructorAttr *A) { return true; }
};
class IBOutletAttr : public Attr {
public:
IBOutletAttr() : Attr(attr::IBOutlet) {}
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::IBOutlet;
}
static bool classof(const IBOutletAttr *A) { return true; }
};
class IBOutletCollectionAttr : public Attr {
QualType QT;
public:
IBOutletCollectionAttr(QualType qt = QualType())
: Attr(attr::IBOutletCollection), QT(qt) {}
QualType getType() const { return QT; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::IBOutletCollection;
}
static bool classof(const IBOutletCollectionAttr *A) { return true; }
};
class IBActionAttr : public Attr {
public:
IBActionAttr() : Attr(attr::IBAction) {}
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::IBAction;
}
static bool classof(const IBActionAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(AnalyzerNoReturn);
DEF_SIMPLE_ATTR(Deprecated);
DEF_SIMPLE_ATTR(GNUInline);
DEF_SIMPLE_ATTR(Malloc);
DEF_SIMPLE_ATTR(NoReturn);
DEF_SIMPLE_ATTR(NoInstrumentFunction);
class SectionAttr : public AttrWithString {
public:
SectionAttr(ASTContext &C, llvm::StringRef N)
: AttrWithString(attr::Section, C, N) {}
llvm::StringRef getName() const { return getString(); }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::Section;
}
static bool classof(const SectionAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(Unavailable);
DEF_SIMPLE_ATTR(Unused);
DEF_SIMPLE_ATTR(Used);
DEF_SIMPLE_ATTR(Weak);
DEF_SIMPLE_ATTR(WeakImport);
DEF_SIMPLE_ATTR(WeakRef);
DEF_SIMPLE_ATTR(NoThrow);
DEF_SIMPLE_ATTR(Const);
DEF_SIMPLE_ATTR(Pure);
class NonNullAttr : public Attr {
unsigned* ArgNums;
unsigned Size;
public:
NonNullAttr(ASTContext &C, unsigned* arg_nums = 0, unsigned size = 0);
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;
}
virtual Attr *clone(ASTContext &C) const;
static bool classof(const Attr *A) { return A->getKind() == attr::NonNull; }
static bool classof(const NonNullAttr *A) { return true; }
};
/// OwnershipAttr
/// Ownership attributes are used to annotate pointers that own a resource
/// in order for the analyzer to check correct allocation and deallocation.
/// There are three attributes, ownership_returns, ownership_holds and
/// ownership_takes, represented by subclasses of OwnershipAttr
class OwnershipAttr: public AttrWithString {
protected:
unsigned* ArgNums;
unsigned Size;
public:
attr::Kind AKind;
public:
OwnershipAttr(attr::Kind AK, ASTContext &C, unsigned* arg_nums, unsigned size,
llvm::StringRef module);
virtual void Destroy(ASTContext &C);
/// Ownership attributes have a 'module', which is the name of a kind of
/// resource that can be checked.
/// The Malloc checker uses the module 'malloc'.
llvm::StringRef getModule() const {
return getString();
}
void setModule(ASTContext &C, llvm::StringRef module) {
ReplaceString(C, module);
}
bool isModule(const char *m) const {
return getModule().equals(m);
}
typedef const unsigned *iterator;
iterator begin() const {
return ArgNums;
}
iterator end() const {
return ArgNums + Size;
}
unsigned size() const {
return Size;
}
virtual Attr *clone(ASTContext &C) const;
static bool classof(const Attr *A) {
switch (A->getKind()) {
case attr::OwnershipTakes:
case attr::OwnershipHolds:
case attr::OwnershipReturns:
return true;
default:
return false;
}
}
static bool classof(const OwnershipAttr *A) {
return true;
} }
}; };
class OwnershipTakesAttr: public OwnershipAttr { template <typename T>
public: inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) {
OwnershipTakesAttr(ASTContext &C, unsigned* arg_nums, unsigned size, return specific_attr_iterator<T>(vec.begin());
llvm::StringRef module); }
template <typename T>
inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) {
return specific_attr_iterator<T>(vec.end());
}
virtual Attr *clone(ASTContext &C) const; template <typename T>
inline bool hasSpecificAttr(const AttrVec& vec) {
return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec);
}
template <typename T>
inline T *getSpecificAttr(const AttrVec& vec) {
specific_attr_iterator<T> i = specific_attr_begin<T>(vec);
if (i != specific_attr_end<T>(vec))
return *i;
else
return 0;
}
static bool classof(const Attr *A) { /// getMaxAlignment - Returns the highest alignment value found among
return A->getKind() == attr::OwnershipTakes; /// AlignedAttrs in an AttrVec, or 0 if there are none.
} inline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) {
static bool classof(const OwnershipTakesAttr *A) { unsigned Align = 0;
return true; specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end());
} for(; i != e; ++i)
}; Align = std::max(Align, i->getAlignment(Ctx));
return Align;
class OwnershipHoldsAttr: public OwnershipAttr { }
public:
OwnershipHoldsAttr(ASTContext &C, unsigned* arg_nums, unsigned size,
llvm::StringRef module);
virtual Attr *clone(ASTContext &C) const;
static bool classof(const Attr *A) {
return A->getKind() == attr::OwnershipHolds;
}
static bool classof(const OwnershipHoldsAttr *A) {
return true;
}
};
class OwnershipReturnsAttr: public OwnershipAttr {
public:
OwnershipReturnsAttr(ASTContext &C, unsigned* arg_nums, unsigned size,
llvm::StringRef module);
virtual Attr *clone(ASTContext &C) const;
static bool classof(const Attr *A) {
return A->getKind() == attr::OwnershipReturns;
}
static bool classof(const OwnershipReturnsAttr *A) {
return true;
}
};
class FormatAttr : public AttrWithString {
int formatIdx, firstArg;
public:
FormatAttr(ASTContext &C, llvm::StringRef type, int idx, int first)
: AttrWithString(attr::Format, C, type), formatIdx(idx), firstArg(first) {}
llvm::StringRef getType() const { return getString(); }
void setType(ASTContext &C, llvm::StringRef type);
int getFormatIdx() const { return formatIdx; }
int getFirstArg() const { return firstArg; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == attr::Format; }
static bool classof(const FormatAttr *A) { return true; }
};
class FormatArgAttr : public Attr {
int formatIdx;
public:
FormatArgAttr(int idx) : Attr(attr::FormatArg), formatIdx(idx) {}
int getFormatIdx() const { return formatIdx; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == attr::FormatArg; }
static bool classof(const FormatArgAttr *A) { return true; }
};
class SentinelAttr : public Attr {
int sentinel, NullPos;
public:
SentinelAttr(int sentinel_val, int nullPos) : Attr(attr::Sentinel),
sentinel(sentinel_val), NullPos(nullPos) {}
int getSentinel() const { return sentinel; }
int getNullPos() const { return NullPos; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == attr::Sentinel; }
static bool classof(const SentinelAttr *A) { return true; }
};
class VisibilityAttr : public Attr {
public:
/// @brief An enumeration for the kinds of visibility of symbols.
enum VisibilityTypes {
DefaultVisibility = 0,
HiddenVisibility,
ProtectedVisibility
};
private:
VisibilityTypes VisibilityType;
bool FromPragma;
public:
VisibilityAttr(VisibilityTypes v, bool fp) : Attr(attr::Visibility),
VisibilityType(v), FromPragma(fp) {}
VisibilityTypes getVisibility() const { return VisibilityType; }
bool isFromPragma() const { return FromPragma; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A)
{ return A->getKind() == attr::Visibility; }
static bool classof(const VisibilityAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(FastCall);
DEF_SIMPLE_ATTR(StdCall);
DEF_SIMPLE_ATTR(ThisCall);
DEF_SIMPLE_ATTR(CDecl);
DEF_SIMPLE_ATTR(TransparentUnion);
DEF_SIMPLE_ATTR(ObjCNSObject);
DEF_SIMPLE_ATTR(ObjCException);
class OverloadableAttr : public Attr {
public:
OverloadableAttr() : Attr(attr::Overloadable) { }
virtual bool isMerged() const { return false; }
virtual Attr *clone(ASTContext &C) const;
static bool classof(const Attr *A)
{ return A->getKind() == attr::Overloadable; }
static bool classof(const OverloadableAttr *) { return true; }
};
class BlocksAttr : public Attr {
public:
enum BlocksAttrTypes {
ByRef = 0
};
private:
BlocksAttrTypes BlocksAttrType;
public:
BlocksAttr(BlocksAttrTypes t) : Attr(attr::Blocks), BlocksAttrType(t) {}
BlocksAttrTypes getType() const { return BlocksAttrType; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == attr::Blocks; }
static bool classof(const BlocksAttr *A) { return true; }
};
class FunctionDecl;
class CleanupAttr : public Attr {
FunctionDecl *FD;
public:
CleanupAttr(FunctionDecl *fd) : Attr(attr::Cleanup), FD(fd) {}
const FunctionDecl *getFunctionDecl() const { return FD; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == attr::Cleanup; }
static bool classof(const CleanupAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(NoDebug);
DEF_SIMPLE_ATTR(WarnUnusedResult);
DEF_SIMPLE_ATTR(NoInline);
class RegparmAttr : public Attr {
unsigned NumParams;
public:
RegparmAttr(unsigned np) : Attr(attr::Regparm), NumParams(np) {}
unsigned getNumParams() const { return NumParams; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == attr::Regparm; }
static bool classof(const RegparmAttr *A) { return true; }
};
class ReqdWorkGroupSizeAttr : public Attr {
unsigned X, Y, Z;
public:
ReqdWorkGroupSizeAttr(unsigned X, unsigned Y, unsigned Z)
: Attr(attr::ReqdWorkGroupSize), X(X), Y(Y), Z(Z) {}
unsigned getXDim() const { return X; }
unsigned getYDim() const { return Y; }
unsigned getZDim() const { return Z; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::ReqdWorkGroupSize;
}
static bool classof(const ReqdWorkGroupSizeAttr *A) { return true; }
};
class InitPriorityAttr : public Attr {
unsigned Priority;
public:
InitPriorityAttr(unsigned priority)
: Attr(attr::InitPriority), Priority(priority) {}
unsigned getPriority() const { return Priority; }
virtual Attr *clone(ASTContext &C) const;
static bool classof(const Attr *A)
{ return A->getKind() == attr::InitPriority; }
static bool classof(const InitPriorityAttr *A) { return true; }
};
// Checker-specific attributes.
DEF_SIMPLE_ATTR(CFReturnsNotRetained);
DEF_SIMPLE_ATTR(CFReturnsRetained);
DEF_SIMPLE_ATTR(NSReturnsNotRetained);
DEF_SIMPLE_ATTR(NSReturnsRetained);
// Target-specific attributes
DEF_SIMPLE_ATTR(DLLImport);
DEF_SIMPLE_ATTR(DLLExport);
class MSP430InterruptAttr : public Attr {
unsigned Number;
public:
MSP430InterruptAttr(unsigned n) : Attr(attr::MSP430Interrupt), Number(n) {}
unsigned getNumber() const { return Number; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A)
{ return A->getKind() == attr::MSP430Interrupt; }
static bool classof(const MSP430InterruptAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(X86ForceAlignArgPointer);
#undef DEF_SIMPLE_ATTR
} // end namespace clang } // end namespace clang

Просмотреть файл

@ -5,6 +5,12 @@ tablegen(Attrs.inc
add_custom_target(ClangAttrClasses add_custom_target(ClangAttrClasses
DEPENDS Attrs.inc) DEPENDS Attrs.inc)
tablegen(AttrImpl.inc
-gen-clang-attr-impl
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
add_custom_target(ClangAttrImpl
DEPENDS AttrImpl.inc)
set(LLVM_TARGET_DEFINITIONS ../Basic/StmtNodes.td) set(LLVM_TARGET_DEFINITIONS ../Basic/StmtNodes.td)
tablegen(StmtNodes.inc tablegen(StmtNodes.inc
-gen-clang-stmt-nodes) -gen-clang-stmt-nodes)

Просмотреть файл

@ -308,24 +308,52 @@ public:
} }
bool hasAttrs() const { return HasAttrs; } bool hasAttrs() const { return HasAttrs; }
void initAttrs(Attr *attrs); void setAttrs(const AttrVec& Attrs);
void addAttr(Attr *attr); AttrVec& getAttrs() {
const Attr *getAttrs() const { return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
if (!HasAttrs) return 0; // common case, no attributes.
return getAttrsImpl(); // Uncommon case, out of line hash lookup.
} }
const AttrVec &getAttrs() const;
void swapAttrs(Decl *D); void swapAttrs(Decl *D);
void invalidateAttrs(); void dropAttrs();
template<typename T> const T *getAttr() const { void addAttr(Attr *A) {
for (const Attr *attr = getAttrs(); attr; attr = attr->getNext()) if (hasAttrs())
if (const T *V = dyn_cast<T>(attr)) getAttrs().push_back(A);
return V; else
return 0; setAttrs(AttrVec(1, A));
} }
typedef AttrVec::const_iterator attr_iterator;
// FIXME: Do not rely on iterators having comparable singular values.
// Note that this should error out if they do not.
attr_iterator attr_begin() const {
return hasAttrs() ? getAttrs().begin() : 0;
}
attr_iterator attr_end() const {
return hasAttrs() ? getAttrs().end() : 0;
}
template <typename T>
specific_attr_iterator<T> specific_attr_begin() const {
return specific_attr_iterator<T>(attr_begin());
}
template <typename T>
specific_attr_iterator<T> specific_attr_end() const {
return specific_attr_iterator<T>(attr_end());
}
template<typename T> T *getAttr() const {
return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : 0;
}
template<typename T> bool hasAttr() const { template<typename T> bool hasAttr() const {
return getAttr<T>() != 0; return hasAttrs() && hasSpecificAttr<T>(getAttrs());
}
/// getMaxAlignment - return the maximum alignment specified by attributes
/// on this decl, 0 if there are none.
unsigned getMaxAlignment() const {
return hasAttrs() ? getMaxAttrAlignment(getAttrs(), getASTContext()) : 0;
} }
/// setInvalidDecl - Indicates the Decl had a semantic error. This /// setInvalidDecl - Indicates the Decl had a semantic error. This

Просмотреть файл

@ -21,7 +21,6 @@ namespace clang {
class Expr; class Expr;
class Stmt; class Stmt;
class FunctionDecl; class FunctionDecl;
class AttributeList;
class RecordDecl; class RecordDecl;
class ObjCIvarDecl; class ObjCIvarDecl;
class ObjCMethodDecl; class ObjCMethodDecl;

Просмотреть файл

@ -1,6 +1,6 @@
CLANG_LEVEL := ../../.. CLANG_LEVEL := ../../..
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
BUILT_SOURCES = Attrs.inc StmtNodes.inc DeclNodes.inc BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc
TABLEGEN_INC_FILES_COMMON = 1 TABLEGEN_INC_FILES_COMMON = 1
@ -12,6 +12,12 @@ $(ObjDir)/Attrs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
$(Verb) $(TableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \ $(Verb) $(TableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $< -I $(PROJ_SRC_DIR)/../../ $<
$(ObjDir)/AttrImpl.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang attribute implementations with tblgen"
$(Verb) $(TableGen) -gen-clang-attr-impl -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $<
$(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(TBLGEN) \ $(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(TBLGEN) \
$(ObjDir)/.dir $(ObjDir)/.dir
$(Echo) "Building Clang statement node tables with tblgen" $(Echo) "Building Clang statement node tables with tblgen"

Просмотреть файл

@ -33,8 +33,8 @@ class SubsetSubject<AttrSubject base, string description, code check>
// a possible subject. // a possible subject.
def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable", def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable",
[{S->getStorageClass() != VarDecl::Register && [{S->getStorageClass() != VarDecl::Register &&
S->getKind() != Decl::ImplicitParam S->getKind() != Decl::ImplicitParam &&
S->getKind() != Decl::ParmVar S->getKind() != Decl::ParmVar &&
S->getKind() != Decl::NonTypeTemplateParm}]>; S->getKind() != Decl::NonTypeTemplateParm}]>;
def CXXVirtualMethod : SubsetSubject<CXXRecord, "virtual member function", def CXXVirtualMethod : SubsetSubject<CXXRecord, "virtual member function",
[{S->isVirtual()}]>; [{S->isVirtual()}]>;
@ -51,18 +51,27 @@ class IntArgument<string name> : Argument<name>;
class StringArgument<string name> : Argument<name>; class StringArgument<string name> : Argument<name>;
class ExprArgument<string name> : Argument<name>; class ExprArgument<string name> : Argument<name>;
class FunctionArgument<string name> : Argument<name>; class FunctionArgument<string name> : Argument<name>;
class ObjCInterfaceArgument<string name> : Argument<name>; class TypeArgument<string name> : Argument<name>;
class UnsignedIntArgument<string name> : Argument<name>; class UnsignedArgument<string name> : Argument<name>;
class UnsignedIntOrTypeArgument<string name> : Argument<name>; class VariadicUnsignedArgument<string name> : Argument<name>;
// This one's a doozy, so it gets its own special type
// It can be an unsigned integer, or a type. Either can
// be dependent.
class AlignedArgument<string name> : Argument<name>;
// An integer argument with a default value // An integer argument with a default value
class DefaultIntArgument<string name, int default> : IntArgument<name> { class DefaultIntArgument<string name, int default> : IntArgument<name> {
int Default = default; int Default = default;
} }
// Zero or more arguments of a type // This argument is more complex, it includes the enumerator type name,
class VariadicArgument<Argument arg> : Argument<arg.Name> { // a list of strings to accept, and a list of enumerators to map them to.
Argument VariadicArg = arg; class EnumArgument<string name, string type, list<string> values,
list<string> enums> : Argument<name> {
string Type = type;
list<string> Values = values;
list<string> Enums = enums;
} }
class Attr { class Attr {
@ -76,9 +85,8 @@ class Attr {
// The attribute will not be permitted in C++0x attribute-specifiers if // The attribute will not be permitted in C++0x attribute-specifiers if
// this is empty; the empty string can be used as a namespace. // this is empty; the empty string can be used as a namespace.
list<string> Namespaces = []; list<string> Namespaces = [];
// A temporary development bit to tell TableGen not to emit certain // Any additional text that should be included verbatim in the class.
// information about the attribute. code AdditionalMembers = [{}];
bit DoNotEmit = 1;
} }
// //
@ -87,13 +95,13 @@ class Attr {
def Alias : Attr { def Alias : Attr {
let Spellings = ["alias"]; let Spellings = ["alias"];
let Args = [StringArgument<"AliasName">]; let Args = [StringArgument<"Aliasee">];
} }
def Aligned : Attr { def Aligned : Attr {
let Spellings = ["align", "aligned"]; let Spellings = ["align", "aligned"];
let Subjects = [NonBitField, NormalVar, Tag]; let Subjects = [NonBitField, NormalVar, Tag];
let Args = [UnsignedIntOrTypeArgument<"Alignment">]; let Args = [AlignedArgument<"Alignment">];
let Namespaces = ["", "std"]; let Namespaces = ["", "std"];
} }
@ -123,19 +131,17 @@ def BaseCheck : Attr {
let Spellings = ["base_check"]; let Spellings = ["base_check"];
let Subjects = [CXXRecord]; let Subjects = [CXXRecord];
let Namespaces = ["", "std"]; let Namespaces = ["", "std"];
let DoNotEmit = 0;
} }
def Blocks : Attr { def Blocks : Attr {
let Spellings = ["blocks"]; let Spellings = ["blocks"];
let Args = [IdentifierArgument<"Type">]; let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
} }
def CarriesDependency : Attr { def CarriesDependency : Attr {
let Spellings = ["carries_dependency"]; let Spellings = ["carries_dependency"];
let Subjects = [ParmVar, Function]; let Subjects = [ParmVar, Function];
let Namespaces = ["", "std"]; let Namespaces = ["", "std"];
let DoNotEmit = 0;
} }
def CDecl : Attr { def CDecl : Attr {
@ -189,7 +195,6 @@ def Final : Attr {
let Spellings = ["final"]; let Spellings = ["final"];
let Subjects = [CXXRecord, CXXVirtualMethod]; let Subjects = [CXXRecord, CXXVirtualMethod];
let Namespaces = ["", "std"]; let Namespaces = ["", "std"];
let DoNotEmit = 0;
} }
def Format : Attr { def Format : Attr {
@ -211,7 +216,6 @@ def Hiding : Attr {
let Spellings = ["hiding"]; let Spellings = ["hiding"];
let Subjects = [Field, CXXMethod]; let Subjects = [Field, CXXMethod];
let Namespaces = ["", "std"]; let Namespaces = ["", "std"];
let DoNotEmit = 0;
} }
def IBAction : Attr { def IBAction : Attr {
@ -224,7 +228,7 @@ def IBOutlet : Attr {
def IBOutletCollection : Attr { def IBOutletCollection : Attr {
let Spellings = ["iboutletcollection"]; let Spellings = ["iboutletcollection"];
let Args = [ObjCInterfaceArgument<"Class">]; let Args = [TypeArgument<"Interface">];
} }
def Malloc : Attr { def Malloc : Attr {
@ -233,12 +237,12 @@ def Malloc : Attr {
def MaxFieldAlignment : Attr { def MaxFieldAlignment : Attr {
let Spellings = []; let Spellings = [];
let Args = [UnsignedIntArgument<"Alignment">]; let Args = [UnsignedArgument<"Alignment">];
} }
def MSP430Interrupt : Attr { def MSP430Interrupt : Attr {
let Spellings = []; let Spellings = [];
let Args = [UnsignedIntArgument<"Number">]; let Args = [UnsignedArgument<"Number">];
} }
def NoDebug : Attr { def NoDebug : Attr {
@ -251,7 +255,15 @@ def NoInline : Attr {
def NonNull : Attr { def NonNull : Attr {
let Spellings = ["nonnull"]; let Spellings = ["nonnull"];
let Args = [VariadicArgument<UnsignedIntArgument<"Args">>]; let Args = [VariadicUnsignedArgument<"Args">];
let AdditionalMembers =
[{bool isNonNull(unsigned idx) const {
for (args_iterator i = args_begin(), e = args_end();
i != e; ++i)
if (*i == idx)
return true;
return false;
} }];
} }
def NoReturn : Attr { def NoReturn : Attr {
@ -290,26 +302,18 @@ def Override : Attr {
let Spellings = ["override"]; let Spellings = ["override"];
let Subjects = [CXXVirtualMethod]; let Subjects = [CXXVirtualMethod];
let Namespaces = ["", "std"]; let Namespaces = ["", "std"];
let DoNotEmit = 0;
} }
def Overloadable : Attr { def Overloadable : Attr {
let Spellings = ["overloadable"]; let Spellings = ["overloadable"];
} }
def OwnershipReturns : Attr { def Ownership : Attr {
let Spellings = ["ownership_returns"]; let Spellings = ["ownership_holds", "ownership_returns", "ownership_takes"];
let Args = [StringArgument<"Module">, IntArgument<"SizeIdx">]; let Args = [EnumArgument<"OwnKind", "OwnershipKind",
} ["ownership_holds", "ownership_returns", "ownership_takes"],
["Holds", "Returns", "Takes"]>,
def OwnershipTakes : Attr { StringArgument<"Module">, VariadicUnsignedArgument<"Args">];
let Spellings = ["ownership_takes"];
let Args = [StringArgument<"Module">, IntArgument<"PtrIdx">];
}
def OwnershipHolds : Attr {
let Spellings = ["ownership_holds"];
let Args = [StringArgument<"Module">, IntArgument<"PtrIdx">];
} }
def Packed : Attr { def Packed : Attr {
@ -322,18 +326,18 @@ def Pure : Attr {
def Regparm : Attr { def Regparm : Attr {
let Spellings = ["regparm"]; let Spellings = ["regparm"];
let Args = [UnsignedIntArgument<"NumParams">]; let Args = [UnsignedArgument<"NumParams">];
} }
def ReqdWorkGroupSize : Attr { def ReqdWorkGroupSize : Attr {
let Spellings = ["reqd_work_group_size"]; let Spellings = ["reqd_work_group_size"];
let Args = [UnsignedIntArgument<"XDim">, UnsignedIntArgument<"YDim">, let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">,
UnsignedIntArgument<"ZDim">]; UnsignedArgument<"ZDim">];
} }
def InitPriority : Attr { def InitPriority : Attr {
let Spellings = ["init_priority"]; let Spellings = ["init_priority"];
let Args = [UnsignedIntArgument<"Priority">]; let Args = [UnsignedArgument<"Priority">];
} }
def Section : Attr { def Section : Attr {
@ -343,8 +347,8 @@ def Section : Attr {
def Sentinel : Attr { def Sentinel : Attr {
let Spellings = ["sentinel"]; let Spellings = ["sentinel"];
let Args = [DefaultIntArgument<"NulPos", 0>, let Args = [DefaultIntArgument<"Sentinel", 0>,
DefaultIntArgument<"Sentinel", 0>]; DefaultIntArgument<"NullPos", 0>];
} }
def StdCall : Attr { def StdCall : Attr {
@ -373,13 +377,14 @@ def Used : Attr {
def Visibility : Attr { def Visibility : Attr {
let Spellings = ["visibility"]; let Spellings = ["visibility"];
let Args = [StringArgument<"Visibility">]; let Args = [EnumArgument<"Visibility", "VisibilityType",
["default", "hidden", "internal", "protected"],
["Default", "Hidden", "Hidden", "Protected"]>];
} }
def VecReturn : Attr { def VecReturn : Attr {
let Spellings = ["vecreturn"]; let Spellings = ["vecreturn"];
let Subjects = [CXXRecord]; let Subjects = [CXXRecord];
let DoNotEmit = 0;
} }
def WarnUnusedResult : Attr { def WarnUnusedResult : Attr {

Просмотреть файл

@ -1,3 +1,4 @@
add_subdirectory(AST) add_subdirectory(AST)
add_subdirectory(Basic) add_subdirectory(Basic)
add_subdirectory(Driver) add_subdirectory(Driver)
add_subdirectory(Serialization)

Просмотреть файл

@ -1,5 +1,5 @@
CLANG_LEVEL := ../.. CLANG_LEVEL := ../..
DIRS := AST Basic Driver DIRS := AST Basic Driver Serialization
include $(CLANG_LEVEL)/Makefile include $(CLANG_LEVEL)/Makefile

Просмотреть файл

@ -4265,7 +4265,8 @@ public:
/// PushPragmaVisibility - Push the top element of the visibility stack; used /// PushPragmaVisibility - Push the top element of the visibility stack; used
/// for '#pragma GCC visibility' and visibility attributes on namespaces. /// for '#pragma GCC visibility' and visibility attributes on namespaces.
void PushPragmaVisibility(VisibilityAttr::VisibilityTypes type); void PushPragmaVisibility(VisibilityAttr::VisibilityType type,
SourceLocation loc);
/// PopPragmaVisibility - Pop the top element of the visibility stack; used /// PopPragmaVisibility - Pop the top element of the visibility stack; used
/// for '#pragma GCC visibility' and visibility attributes on namespaces. /// for '#pragma GCC visibility' and visibility attributes on namespaces.
@ -4276,6 +4277,7 @@ public:
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration. /// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E); void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E);
void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, TypeSourceInfo *T);
/// CastCategory - Get the correct forwarded implicit cast result category /// CastCategory - Get the correct forwarded implicit cast result category
/// from the inner expression. /// from the inner expression.

Просмотреть файл

@ -0,0 +1,12 @@
set(LLVM_TARGET_DEFINITIONS ../Basic/Attr.td)
tablegen(AttrPCHRead.inc
-gen-clang-attr-pch-read
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
add_custom_target(ClangAttrPCHRead
DEPENDS AttrPCHRead.inc)
tablegen(AttrPCHWrite.inc
-gen-clang-attr-pch-write
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
add_custom_target(ClangAttrPCHWrite
DEPENDS AttrPCHWrite.inc)

Просмотреть файл

@ -0,0 +1,19 @@
CLANG_LEVEL := ../../..
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
BUILT_SOURCES = AttrPCHRead.inc AttrPCHWrite.inc
TABLEGEN_INC_FILES_COMMON = 1
include $(CLANG_LEVEL)/Makefile
$(ObjDir)/AttrPCHRead.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang PCH reader with tblgen"
$(Verb) $(TableGen) -gen-clang-attr-pch-read -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $<
$(ObjDir)/AttrPCHWrite.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang PCH writer with tblgen"
$(Verb) $(TableGen) -gen-clang-attr-pch-write -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $<

Просмотреть файл

@ -908,7 +908,7 @@ public:
CXXTemporary *ReadCXXTemporary(const RecordData &Record, unsigned &Idx); CXXTemporary *ReadCXXTemporary(const RecordData &Record, unsigned &Idx);
/// \brief Reads attributes from the current stream position. /// \brief Reads attributes from the current stream position.
Attr *ReadAttributes(llvm::BitstreamCursor &DeclsCursor); void ReadAttributes(llvm::BitstreamCursor &DeclsCursor, AttrVec &Attrs);
/// \brief Reads a statement. /// \brief Reads a statement.
Stmt *ReadStmt(llvm::BitstreamCursor &Cursor); Stmt *ReadStmt(llvm::BitstreamCursor &Cursor);

Просмотреть файл

@ -281,7 +281,7 @@ private:
void WriteSelectors(Sema &SemaRef); void WriteSelectors(Sema &SemaRef);
void WriteReferencedSelectorsPool(Sema &SemaRef); void WriteReferencedSelectorsPool(Sema &SemaRef);
void WriteIdentifierTable(Preprocessor &PP); void WriteIdentifierTable(Preprocessor &PP);
void WriteAttributeRecord(const Attr *Attr); void WriteAttributeRecord(const AttrVec &Attrs);
void WriteDeclUpdateBlock(); void WriteDeclUpdateBlock();
unsigned ParmVarDeclAbbrev; unsigned ParmVarDeclAbbrev;

Просмотреть файл

@ -497,8 +497,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) { CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) {
unsigned Align = Target.getCharWidth(); unsigned Align = Target.getCharWidth();
if (const AlignedAttr* AA = D->getAttr<AlignedAttr>()) Align = std::max(Align, D->getMaxAlignment());
Align = std::max(Align, AA->getMaxAlignment());
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) { if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
QualType T = VD->getType(); QualType T = VD->getType();
@ -760,12 +759,9 @@ ASTContext::getTypeInfo(const Type *T) {
case Type::Typedef: { case Type::Typedef: {
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl(); const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) { Align = std::max(Typedef->getMaxAlignment(),
Align = std::max(Aligned->getMaxAlignment(), getTypeAlign(Typedef->getUnderlyingType().getTypePtr()));
getTypeAlign(Typedef->getUnderlyingType().getTypePtr())); Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
} else
return getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
break; break;
} }

Просмотреть файл

@ -13,231 +13,10 @@
#include "clang/AST/Attr.h" #include "clang/AST/Attr.h"
#include "clang/AST/ASTContext.h" #include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "clang/AST/Expr.h"
using namespace clang; using namespace clang;
Attr::~Attr() { } Attr::~Attr() { }
AttrWithString::AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s) #include "clang/AST/AttrImpl.inc"
: Attr(AK) {
assert(!s.empty());
StrLen = s.size();
Str = new (C) char[StrLen];
memcpy(const_cast<char*>(Str), s.data(), StrLen);
}
void AttrWithString::ReplaceString(ASTContext &C, llvm::StringRef newS) {
if (newS.size() > StrLen) {
C.Deallocate(const_cast<char*>(Str));
Str = new (C) char[newS.size()];
}
StrLen = newS.size();
memcpy(const_cast<char*>(Str), newS.data(), StrLen);
}
void FormatAttr::setType(ASTContext &C, llvm::StringRef type) {
ReplaceString(C, type);
}
NonNullAttr::NonNullAttr(ASTContext &C, unsigned* arg_nums, unsigned size)
: Attr(attr::NonNull), ArgNums(0), Size(0) {
if (size == 0)
return;
assert(arg_nums);
ArgNums = new (C) unsigned[size];
Size = size;
memcpy(ArgNums, arg_nums, sizeof(*ArgNums)*size);
}
OwnershipAttr::OwnershipAttr(attr::Kind AK, ASTContext &C, unsigned* arg_nums,
unsigned size, llvm::StringRef module)
: AttrWithString(AK, C, module), ArgNums(0), Size(0) {
if (size == 0)
return;
assert(arg_nums);
ArgNums = new (C) unsigned[size];
Size = size;
memcpy(ArgNums, arg_nums, sizeof(*ArgNums) * size);
}
void OwnershipAttr::Destroy(ASTContext &C) {
if (ArgNums)
C.Deallocate(ArgNums);
}
OwnershipTakesAttr::OwnershipTakesAttr(ASTContext &C, unsigned* arg_nums,
unsigned size, llvm::StringRef module)
: OwnershipAttr(attr::OwnershipTakes, C, arg_nums, size, module) {
}
OwnershipHoldsAttr::OwnershipHoldsAttr(ASTContext &C, unsigned* arg_nums,
unsigned size, llvm::StringRef module)
: OwnershipAttr(attr::OwnershipHolds, C, arg_nums, size, module) {
}
OwnershipReturnsAttr::OwnershipReturnsAttr(ASTContext &C, unsigned* arg_nums,
unsigned size,
llvm::StringRef module)
: OwnershipAttr(attr::OwnershipReturns, C, arg_nums, size, module) {
}
#define DEF_SIMPLE_ATTR_CLONE(ATTR) \
Attr *ATTR##Attr::clone(ASTContext &C) const { \
return ::new (C) ATTR##Attr; \
}
// FIXME: Can we use variadic macro to define DEF_SIMPLE_ATTR_CLONE for
// "non-simple" classes?
DEF_SIMPLE_ATTR_CLONE(AlignMac68k)
DEF_SIMPLE_ATTR_CLONE(AlwaysInline)
DEF_SIMPLE_ATTR_CLONE(AnalyzerNoReturn)
DEF_SIMPLE_ATTR_CLONE(BaseCheck)
DEF_SIMPLE_ATTR_CLONE(CDecl)
DEF_SIMPLE_ATTR_CLONE(CFReturnsNotRetained)
DEF_SIMPLE_ATTR_CLONE(CFReturnsRetained)
DEF_SIMPLE_ATTR_CLONE(Const)
DEF_SIMPLE_ATTR_CLONE(DLLExport)
DEF_SIMPLE_ATTR_CLONE(DLLImport)
DEF_SIMPLE_ATTR_CLONE(Deprecated)
DEF_SIMPLE_ATTR_CLONE(FastCall)
DEF_SIMPLE_ATTR_CLONE(Final)
DEF_SIMPLE_ATTR_CLONE(Hiding)
DEF_SIMPLE_ATTR_CLONE(Malloc)
DEF_SIMPLE_ATTR_CLONE(NSReturnsNotRetained)
DEF_SIMPLE_ATTR_CLONE(NSReturnsRetained)
DEF_SIMPLE_ATTR_CLONE(NoDebug)
DEF_SIMPLE_ATTR_CLONE(NoInline)
DEF_SIMPLE_ATTR_CLONE(NoInstrumentFunction)
DEF_SIMPLE_ATTR_CLONE(NoReturn)
DEF_SIMPLE_ATTR_CLONE(NoThrow)
DEF_SIMPLE_ATTR_CLONE(ObjCException)
DEF_SIMPLE_ATTR_CLONE(ObjCNSObject)
DEF_SIMPLE_ATTR_CLONE(Override)
DEF_SIMPLE_ATTR_CLONE(Packed)
DEF_SIMPLE_ATTR_CLONE(Pure)
DEF_SIMPLE_ATTR_CLONE(StdCall)
DEF_SIMPLE_ATTR_CLONE(ThisCall)
DEF_SIMPLE_ATTR_CLONE(TransparentUnion)
DEF_SIMPLE_ATTR_CLONE(Unavailable)
DEF_SIMPLE_ATTR_CLONE(Unused)
DEF_SIMPLE_ATTR_CLONE(Used)
DEF_SIMPLE_ATTR_CLONE(VecReturn)
DEF_SIMPLE_ATTR_CLONE(WarnUnusedResult)
DEF_SIMPLE_ATTR_CLONE(Weak)
DEF_SIMPLE_ATTR_CLONE(WeakImport)
DEF_SIMPLE_ATTR_CLONE(WeakRef)
DEF_SIMPLE_ATTR_CLONE(X86ForceAlignArgPointer)
Attr* MaxFieldAlignmentAttr::clone(ASTContext &C) const {
return ::new (C) MaxFieldAlignmentAttr(Alignment);
}
Attr* AlignedAttr::clone(ASTContext &C) const {
return ::new (C) AlignedAttr(Alignment);
}
Attr* AnnotateAttr::clone(ASTContext &C) const {
return ::new (C) AnnotateAttr(C, getAnnotation());
}
Attr *AsmLabelAttr::clone(ASTContext &C) const {
return ::new (C) AsmLabelAttr(C, getLabel());
}
Attr *AliasAttr::clone(ASTContext &C) const {
return ::new (C) AliasAttr(C, getAliasee());
}
Attr *ConstructorAttr::clone(ASTContext &C) const {
return ::new (C) ConstructorAttr(priority);
}
Attr *DestructorAttr::clone(ASTContext &C) const {
return ::new (C) DestructorAttr(priority);
}
Attr *IBOutletAttr::clone(ASTContext &C) const {
return ::new (C) IBOutletAttr;
}
Attr *IBOutletCollectionAttr::clone(ASTContext &C) const {
return ::new (C) IBOutletCollectionAttr(QT);
}
Attr *IBActionAttr::clone(ASTContext &C) const {
return ::new (C) IBActionAttr;
}
Attr *GNUInlineAttr::clone(ASTContext &C) const {
return ::new (C) GNUInlineAttr;
}
Attr *SectionAttr::clone(ASTContext &C) const {
return ::new (C) SectionAttr(C, getName());
}
Attr *NonNullAttr::clone(ASTContext &C) const {
return ::new (C) NonNullAttr(C, ArgNums, Size);
}
Attr *OwnershipAttr::clone(ASTContext &C) const {
return ::new (C) OwnershipAttr(AKind, C, ArgNums, Size, getModule());
}
Attr *OwnershipReturnsAttr::clone(ASTContext &C) const {
return ::new (C) OwnershipReturnsAttr(C, ArgNums, Size, getModule());
}
Attr *OwnershipTakesAttr::clone(ASTContext &C) const {
return ::new (C) OwnershipTakesAttr(C, ArgNums, Size, getModule());
}
Attr *OwnershipHoldsAttr::clone(ASTContext &C) const {
return ::new (C) OwnershipHoldsAttr(C, ArgNums, Size, getModule());
}
Attr *FormatAttr::clone(ASTContext &C) const {
return ::new (C) FormatAttr(C, getType(), formatIdx, firstArg);
}
Attr *FormatArgAttr::clone(ASTContext &C) const {
return ::new (C) FormatArgAttr(formatIdx);
}
Attr *SentinelAttr::clone(ASTContext &C) const {
return ::new (C) SentinelAttr(sentinel, NullPos);
}
Attr *VisibilityAttr::clone(ASTContext &C) const {
return ::new (C) VisibilityAttr(VisibilityType, FromPragma);
}
Attr *OverloadableAttr::clone(ASTContext &C) const {
return ::new (C) OverloadableAttr;
}
Attr *BlocksAttr::clone(ASTContext &C) const {
return ::new (C) BlocksAttr(BlocksAttrType);
}
Attr *CleanupAttr::clone(ASTContext &C) const {
return ::new (C) CleanupAttr(FD);
}
Attr *RegparmAttr::clone(ASTContext &C) const {
return ::new (C) RegparmAttr(NumParams);
}
Attr *ReqdWorkGroupSizeAttr::clone(ASTContext &C) const {
return ::new (C) ReqdWorkGroupSizeAttr(X, Y, Z);
}
Attr *InitPriorityAttr::clone(ASTContext &C) const {
return ::new (C) InitPriorityAttr(Priority);
}
Attr *MSP430InterruptAttr::clone(ASTContext &C) const {
return ::new (C) MSP430InterruptAttr(Number);
}

Просмотреть файл

@ -43,4 +43,4 @@ add_clang_library(clangAST
) )
add_dependencies(clangAST ClangARMNeon ClangAttrClasses ClangAttrList add_dependencies(clangAST ClangARMNeon ClangAttrClasses ClangAttrList
ClangDiagnosticAST ClangDeclNodes ClangStmtNodes) ClangAttrImpl ClangDiagnosticAST ClangDeclNodes ClangStmtNodes)

Просмотреть файл

@ -312,35 +312,25 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
return 0; return 0;
} }
void Decl::initAttrs(Attr *attrs) { void Decl::setAttrs(const AttrVec &attrs) {
assert(!HasAttrs && "Decl already contains attrs."); assert(!HasAttrs && "Decl already contains attrs.");
Attr *&AttrBlank = getASTContext().getDeclAttrs(this); AttrVec &AttrBlank = getASTContext().getDeclAttrs(this);
assert(AttrBlank == 0 && "HasAttrs was wrong?"); assert(AttrBlank.empty() && "HasAttrs was wrong?");
AttrBlank = attrs; AttrBlank = attrs;
HasAttrs = true; HasAttrs = true;
} }
void Decl::addAttr(Attr *NewAttr) { void Decl::dropAttrs() {
Attr *&ExistingAttr = getASTContext().getDeclAttrs(this);
assert(NewAttr->getNext() == 0 && "Chain of attributes will be truncated!");
NewAttr->setNext(ExistingAttr);
ExistingAttr = NewAttr;
HasAttrs = true;
}
void Decl::invalidateAttrs() {
if (!HasAttrs) return; if (!HasAttrs) return;
HasAttrs = false; HasAttrs = false;
getASTContext().eraseDeclAttrs(this); getASTContext().eraseDeclAttrs(this);
} }
const Attr *Decl::getAttrsImpl() const { const AttrVec &Decl::getAttrs() const {
assert(HasAttrs && "getAttrs() should verify this!"); assert(HasAttrs && "No attrs to get!");
return getASTContext().getDeclAttrs(this); return getASTContext().getDeclAttrs(this);
} }

Просмотреть файл

@ -1123,8 +1123,8 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>()) if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
MaxFieldAlignment = MFAA->getAlignment(); MaxFieldAlignment = MFAA->getAlignment();
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) if (unsigned MaxAlign = D->getMaxAlignment())
UpdateAlignment(AA->getMaxAlignment()); UpdateAlignment(MaxAlign);
} }
} }
@ -1287,8 +1287,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
if (FieldPacked || !Context.Target.useBitFieldTypeAlignment()) if (FieldPacked || !Context.Target.useBitFieldTypeAlignment())
FieldAlign = 1; FieldAlign = 1;
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) FieldAlign = std::max(FieldAlign, D->getMaxAlignment());
FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
// The maximum field alignment overrides the aligned attribute. // The maximum field alignment overrides the aligned attribute.
if (MaxFieldAlignment) if (MaxFieldAlignment)
@ -1357,8 +1356,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
if (FieldPacked) if (FieldPacked)
FieldAlign = 8; FieldAlign = 8;
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) FieldAlign = std::max(FieldAlign, D->getMaxAlignment());
FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
// The maximum field alignment overrides the aligned attribute. // The maximum field alignment overrides the aligned attribute.
if (MaxFieldAlignment) if (MaxFieldAlignment)

Просмотреть файл

@ -176,19 +176,23 @@ bool MallocChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
// There can be multiple of these attributes. // There can be multiple of these attributes.
bool rv = false; bool rv = false;
if (FD->hasAttrs()) { if (FD->hasAttrs()) {
for (const Attr *attr = FD->getAttrs(); attr; attr = attr->getNext()) { for (specific_attr_iterator<OwnershipAttr>
switch (attr->getKind()) { i = FD->specific_attr_begin<OwnershipAttr>(),
case attr::OwnershipReturns: e = FD->specific_attr_end<OwnershipAttr>();
MallocMemReturnsAttr(C, CE, cast<OwnershipAttr>(attr)); i != e; ++i) {
switch ((*i)->getOwnKind()) {
case OwnershipAttr::Returns: {
MallocMemReturnsAttr(C, CE, *i);
rv = true; rv = true;
break; break;
case attr::OwnershipTakes: }
case attr::OwnershipHolds: case OwnershipAttr::Takes:
FreeMemAttr(C, CE, cast<OwnershipAttr>(attr)); case OwnershipAttr::Holds: {
FreeMemAttr(C, CE, *i);
rv = true; rv = true;
break; break;
}
default: default:
// Ignore non-ownership attributes.
break; break;
} }
} }
@ -204,10 +208,10 @@ void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
void MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, void MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
const OwnershipAttr* Att) { const OwnershipAttr* Att) {
if (!Att->isModule("malloc")) if (Att->getModule() != "malloc")
return; return;
const unsigned *I = Att->begin(), *E = Att->end(); OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
if (I != E) { if (I != E) {
const GRState *state = const GRState *state =
MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState()); MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState());
@ -258,14 +262,15 @@ void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) {
void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE, void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE,
const OwnershipAttr* Att) { const OwnershipAttr* Att) {
if (!Att->isModule("malloc")) if (Att->getModule() != "malloc")
return; return;
for (const unsigned *I = Att->begin(), *E = Att->end(); I != E; ++I) { for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
const GRState *state = I != E; ++I) {
FreeMemAux(C, CE, C.getState(), *I, isa<OwnershipHoldsAttr>(Att)); const GRState *state = FreeMemAux(C, CE, C.getState(), *I,
if (state) Att->getOwnKind() == OwnershipAttr::Holds);
C.addTransition(state); if (state)
C.addTransition(state);
} }
} }

Просмотреть файл

@ -150,11 +150,11 @@ CodeGenModule::getDeclVisibilityMode(const Decl *D) const {
if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) { if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) {
switch (attr->getVisibility()) { switch (attr->getVisibility()) {
default: assert(0 && "Unknown visibility!"); default: assert(0 && "Unknown visibility!");
case VisibilityAttr::DefaultVisibility: case VisibilityAttr::Default:
return LangOptions::Default; return LangOptions::Default;
case VisibilityAttr::HiddenVisibility: case VisibilityAttr::Hidden:
return LangOptions::Hidden; return LangOptions::Hidden;
case VisibilityAttr::ProtectedVisibility: case VisibilityAttr::Protected:
return LangOptions::Protected; return LangOptions::Protected;
} }
} }
@ -461,12 +461,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
else if (Features.getStackProtectorMode() == LangOptions::SSPReq) else if (Features.getStackProtectorMode() == LangOptions::SSPReq)
F->addFnAttr(llvm::Attribute::StackProtectReq); F->addFnAttr(llvm::Attribute::StackProtectReq);
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) { unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
unsigned width = Context.Target.getCharWidth(); if (alignment)
F->setAlignment(AA->getAlignment() / width); F->setAlignment(alignment);
while ((AA = AA->getNext<AlignedAttr>()))
F->setAlignment(std::max(F->getAlignment(), AA->getAlignment() / width));
}
// C++ ABI requires 2-byte alignment for member functions. // C++ ABI requires 2-byte alignment for member functions.
if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D)) if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D))
F->setAlignment(2); F->setAlignment(2);

Просмотреть файл

@ -14,6 +14,7 @@
#include "clang/Sema/Sema.h" #include "clang/Sema/Sema.h"
#include "clang/Sema/Lookup.h" #include "clang/Sema/Lookup.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Expr.h" #include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h" #include "clang/Lex/Preprocessor.h"
@ -120,9 +121,11 @@ void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
// Otherwise, check to see if we need a max field alignment attribute. // Otherwise, check to see if we need a max field alignment attribute.
if (unsigned Alignment = Stack->getAlignment()) { if (unsigned Alignment = Stack->getAlignment()) {
if (Alignment == PackStackEntry::kMac68kAlignmentSentinel) if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
RD->addAttr(::new (Context) AlignMac68kAttr()); RD->addAttr(::new (Context) AlignMac68kAttr(SourceLocation(), Context));
else else
RD->addAttr(::new (Context) MaxFieldAlignmentAttr(Alignment * 8)); RD->addAttr(::new (Context) MaxFieldAlignmentAttr(SourceLocation(),
Context,
Alignment * 8));
} }
} }
@ -285,11 +288,12 @@ void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
continue; continue;
} }
VD->addAttr(::new (Context) UnusedAttr()); VD->addAttr(::new (Context) UnusedAttr(Tok.getLocation(), Context));
} }
} }
typedef std::vector<VisibilityAttr::VisibilityTypes> VisStack; typedef std::vector<std::pair<VisibilityAttr::VisibilityType,
SourceLocation> > VisStack;
void Sema::AddPushedVisibilityAttribute(Decl *D) { void Sema::AddPushedVisibilityAttribute(Decl *D) {
if (!VisContext) if (!VisContext)
@ -299,9 +303,10 @@ void Sema::AddPushedVisibilityAttribute(Decl *D) {
return; return;
VisStack *Stack = static_cast<VisStack*>(VisContext); VisStack *Stack = static_cast<VisStack*>(VisContext);
VisibilityAttr::VisibilityTypes type = Stack->back(); VisibilityAttr::VisibilityType type = Stack->back().first;
SourceLocation loc = Stack->back().second;
D->addAttr(::new (Context) VisibilityAttr(type, true)); D->addAttr(::new (Context) VisibilityAttr(loc, Context, type));
} }
/// FreeVisContext - Deallocate and null out VisContext. /// FreeVisContext - Deallocate and null out VisContext.
@ -314,33 +319,34 @@ void Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
SourceLocation PragmaLoc) { SourceLocation PragmaLoc) {
if (IsPush) { if (IsPush) {
// Compute visibility to use. // Compute visibility to use.
VisibilityAttr::VisibilityTypes type; VisibilityAttr::VisibilityType type;
if (VisType->isStr("default")) if (VisType->isStr("default"))
type = VisibilityAttr::DefaultVisibility; type = VisibilityAttr::Default;
else if (VisType->isStr("hidden")) else if (VisType->isStr("hidden"))
type = VisibilityAttr::HiddenVisibility; type = VisibilityAttr::Hidden;
else if (VisType->isStr("internal")) else if (VisType->isStr("internal"))
type = VisibilityAttr::HiddenVisibility; // FIXME type = VisibilityAttr::Hidden; // FIXME
else if (VisType->isStr("protected")) else if (VisType->isStr("protected"))
type = VisibilityAttr::ProtectedVisibility; type = VisibilityAttr::Protected;
else { else {
Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) <<
VisType->getName(); VisType->getName();
return; return;
} }
PushPragmaVisibility(type); PushPragmaVisibility(type, PragmaLoc);
} else { } else {
PopPragmaVisibility(); PopPragmaVisibility();
} }
} }
void Sema::PushPragmaVisibility(VisibilityAttr::VisibilityTypes type) { void Sema::PushPragmaVisibility(VisibilityAttr::VisibilityType type,
SourceLocation loc) {
// Put visibility on stack. // Put visibility on stack.
if (!VisContext) if (!VisContext)
VisContext = new VisStack; VisContext = new VisStack;
VisStack *Stack = static_cast<VisStack*>(VisContext); VisStack *Stack = static_cast<VisStack*>(VisContext);
Stack->push_back(type); Stack->push_back(std::make_pair(type, loc));
} }
void Sema::PopPragmaVisibility() { void Sema::PopPragmaVisibility() {

Просмотреть файл

@ -347,9 +347,12 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
} }
} }
for (const NonNullAttr *NonNull = FDecl->getAttr<NonNullAttr>(); NonNull; specific_attr_iterator<NonNullAttr>
NonNull = NonNull->getNext<NonNullAttr>()) i = FDecl->specific_attr_begin<NonNullAttr>(),
CheckNonNullArguments(NonNull, TheCall); e = FDecl->specific_attr_end<NonNullAttr>();
for (; i != e; ++i)
CheckNonNullArguments(*i, TheCall);
return false; return false;
} }
@ -1041,7 +1044,8 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
void void
Sema::CheckNonNullArguments(const NonNullAttr *NonNull, Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
const CallExpr *TheCall) { const CallExpr *TheCall) {
for (NonNullAttr::iterator i = NonNull->begin(), e = NonNull->end(); for (NonNullAttr::args_iterator i = NonNull->args_begin(),
e = NonNull->args_end();
i != e; ++i) { i != e; ++i) {
const Expr *ArgExpr = TheCall->getArg(*i); const Expr *ArgExpr = TheCall->getArg(*i);
if (ArgExpr->isNullPointerConstant(Context, if (ArgExpr->isNullPointerConstant(Context,

Просмотреть файл

@ -997,19 +997,32 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
/// DeclhasAttr - returns true if decl Declaration already has the target /// DeclhasAttr - returns true if decl Declaration already has the target
/// attribute. /// attribute.
static bool static bool
DeclHasAttr(const Decl *decl, const Attr *target) { DeclHasAttr(const Decl *D, const Attr *A) {
for (const Attr *attr = decl->getAttrs(); attr; attr = attr->getNext()) const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A);
if (attr->getKind() == target->getKind()) for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i)
if ((*i)->getKind() == A->getKind()) {
// FIXME: Don't hardcode this check
if (OA && isa<OwnershipAttr>(*i))
return OA->getOwnKind() == cast<OwnershipAttr>(*i)->getOwnKind();
return true; return true;
}
return false; return false;
} }
/// MergeAttributes - append attributes from the Old decl to the New one. /// MergeDeclAttributes - append attributes from the Old decl to the New one.
static void MergeAttributes(Decl *New, Decl *Old, ASTContext &C) { static void MergeDeclAttributes(Decl *New, Decl *Old, ASTContext &C) {
for (const Attr *attr = Old->getAttrs(); attr; attr = attr->getNext()) { if (!Old->hasAttrs())
if (!DeclHasAttr(New, attr) && attr->isMerged()) { return;
Attr *NewAttr = attr->clone(C); // Ensure that any moving of objects within the allocated map is done before
// we process them.
if (!New->hasAttrs())
New->setAttrs(AttrVec());
for (Decl::attr_iterator i = Old->attr_begin(), e = Old->attr_end(); i != e;
++i) {
// FIXME: Make this more general than just checking for Overloadable.
if (!DeclHasAttr(New, *i) && (*i)->getKind() != attr::Overloadable) {
Attr *NewAttr = (*i)->clone(C);
NewAttr->setInherited(true); NewAttr->setInherited(true);
New->addAttr(NewAttr); New->addAttr(NewAttr);
} }
@ -1402,7 +1415,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
/// \returns false /// \returns false
bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
// Merge the attributes // Merge the attributes
MergeAttributes(New, Old, Context); MergeDeclAttributes(New, Old, Context);
// Merge the storage class. // Merge the storage class.
if (Old->getStorageClass() != FunctionDecl::Extern && if (Old->getStorageClass() != FunctionDecl::Extern &&
@ -1447,7 +1460,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
return New->setInvalidDecl(); return New->setInvalidDecl();
} }
MergeAttributes(New, Old, Context); MergeDeclAttributes(New, Old, Context);
// Merge the types // Merge the types
QualType MergedT; QualType MergedT;
@ -1611,9 +1624,7 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
} }
if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) { if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
// If there are attributes in the DeclSpec, apply them to the record. ProcessDeclAttributeList(S, Record, DS.getAttributes());
if (const AttributeList *AL = DS.getAttributes())
ProcessDeclAttributeList(S, Record, AL);
if (!Record->getDeclName() && Record->isDefinition() && if (!Record->getDeclName() && Record->isDefinition() &&
DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
@ -2770,7 +2781,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (Expr *E = (Expr*) D.getAsmLabel()) { if (Expr *E = (Expr*) D.getAsmLabel()) {
// The parser guarantees this is a string. // The parser guarantees this is a string.
StringLiteral *SE = cast<StringLiteral>(E); StringLiteral *SE = cast<StringLiteral>(E);
NewVD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString())); NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0),
Context, SE->getString()));
} }
// Diagnose shadowed variables before filtering for scope. // Diagnose shadowed variables before filtering for scope.
@ -2810,6 +2822,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
NewVD->setInvalidDecl(); NewVD->setInvalidDecl();
// attributes declared post-definition are currently ignored // attributes declared post-definition are currently ignored
// FIXME: This should be handled in attribute merging, not
// here.
if (Previous.isSingleResult()) { if (Previous.isSingleResult()) {
VarDecl *Def = dyn_cast<VarDecl>(Previous.getFoundDecl()); VarDecl *Def = dyn_cast<VarDecl>(Previous.getFoundDecl());
if (Def && (Def = Def->getDefinition()) && if (Def && (Def = Def->getDefinition()) &&
@ -3447,7 +3461,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (Expr *E = (Expr*) D.getAsmLabel()) { if (Expr *E = (Expr*) D.getAsmLabel()) {
// The parser guarantees this is a string. // The parser guarantees this is a string.
StringLiteral *SE = cast<StringLiteral>(E); StringLiteral *SE = cast<StringLiteral>(E);
NewFD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString())); NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context,
SE->getString()));
} }
// Copy the parameter declarations from the declarator D to the function // Copy the parameter declarations from the declarator D to the function
@ -3673,6 +3688,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
ProcessDeclAttributes(S, NewFD, D); ProcessDeclAttributes(S, NewFD, D);
// attributes declared post-definition are currently ignored // attributes declared post-definition are currently ignored
// FIXME: This should happen during attribute merging
if (Redeclaration && Previous.isSingleResult()) { if (Redeclaration && Previous.isSingleResult()) {
const FunctionDecl *Def; const FunctionDecl *Def;
FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl()); FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl());
@ -3684,7 +3700,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
AddKnownFunctionAttributes(NewFD); AddKnownFunctionAttributes(NewFD);
if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>()) { if (OverloadableAttrRequired && !NewFD->hasAttr<OverloadableAttr>()) {
// If a function name is overloadable in C, then every function // If a function name is overloadable in C, then every function
// with that name must be marked "overloadable". // with that name must be marked "overloadable".
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing) Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
@ -3692,7 +3708,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (!Previous.empty()) if (!Previous.empty())
Diag(Previous.getRepresentativeDecl()->getLocation(), Diag(Previous.getRepresentativeDecl()->getLocation(),
diag::note_attribute_overloadable_prev_overload); diag::note_attribute_overloadable_prev_overload);
NewFD->addAttr(::new (Context) OverloadableAttr()); NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(), Context));
} }
if (NewFD->hasAttr<OverloadableAttr>() && if (NewFD->hasAttr<OverloadableAttr>() &&
@ -4792,10 +4808,10 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
// Checking attributes of current function definition // Checking attributes of current function definition
// dllimport attribute. // dllimport attribute.
if (FD->getAttr<DLLImportAttr>() && DLLImportAttr *DA = FD->getAttr<DLLImportAttr>();
(!FD->getAttr<DLLExportAttr>())) { if (DA && (!FD->getAttr<DLLExportAttr>())) {
// dllimport attribute cannot be applied to definition. // dllimport attribute cannot be directly applied to definition.
if (!(FD->getAttr<DLLImportAttr>())->isInherited()) { if (!DA->isInherited()) {
Diag(FD->getLocation(), Diag(FD->getLocation(),
diag::err_attribute_can_be_applied_only_to_symbol_declaration) diag::err_attribute_can_be_applied_only_to_symbol_declaration)
<< "dllimport"; << "dllimport";
@ -5041,7 +5057,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
CurContext = Context.getTranslationUnitDecl(); CurContext = Context.getTranslationUnitDecl();
FunctionDecl *FD = FunctionDecl *FD =
dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D).getAs<Decl>()); dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D).getAs<Decl>());
FD->setImplicit(); FD->setImplicit();
CurContext = PrevDC; CurContext = PrevDC;
@ -5069,13 +5085,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
bool HasVAListArg; bool HasVAListArg;
if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) { if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) {
if (!FD->getAttr<FormatAttr>()) if (!FD->getAttr<FormatAttr>())
FD->addAttr(::new (Context) FormatAttr(Context, "printf", FormatIdx+1, FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
"printf", FormatIdx+1,
HasVAListArg ? 0 : FormatIdx+2)); HasVAListArg ? 0 : FormatIdx+2));
} }
if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx, if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx,
HasVAListArg)) { HasVAListArg)) {
if (!FD->getAttr<FormatAttr>()) if (!FD->getAttr<FormatAttr>())
FD->addAttr(::new (Context) FormatAttr(Context, "scanf", FormatIdx+1, FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
"scanf", FormatIdx+1,
HasVAListArg ? 0 : FormatIdx+2)); HasVAListArg ? 0 : FormatIdx+2));
} }
@ -5085,15 +5103,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
if (!getLangOptions().MathErrno && if (!getLangOptions().MathErrno &&
Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) { Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) {
if (!FD->getAttr<ConstAttr>()) if (!FD->getAttr<ConstAttr>())
FD->addAttr(::new (Context) ConstAttr()); FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
} }
if (Context.BuiltinInfo.isNoReturn(BuiltinID)) if (Context.BuiltinInfo.isNoReturn(BuiltinID))
FD->setType(Context.getNoReturnType(FD->getType())); FD->setType(Context.getNoReturnType(FD->getType()));
if (Context.BuiltinInfo.isNoThrow(BuiltinID)) if (Context.BuiltinInfo.isNoThrow(BuiltinID))
FD->addAttr(::new (Context) NoThrowAttr()); FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context));
if (Context.BuiltinInfo.isConst(BuiltinID)) if (Context.BuiltinInfo.isConst(BuiltinID))
FD->addAttr(::new (Context) ConstAttr()); FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
} }
IdentifierInfo *Name = FD->getIdentifier(); IdentifierInfo *Name = FD->getIdentifier();
@ -5115,13 +5133,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
// FIXME: We known better than our headers. // FIXME: We known better than our headers.
const_cast<FormatAttr *>(Format)->setType(Context, "printf"); const_cast<FormatAttr *>(Format)->setType(Context, "printf");
} else } else
FD->addAttr(::new (Context) FormatAttr(Context, "printf", 1, FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
"printf", 1,
Name->isStr("NSLogv") ? 0 : 2)); Name->isStr("NSLogv") ? 0 : 2));
} else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) { } else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) {
// FIXME: asprintf and vasprintf aren't C99 functions. Should they be // FIXME: asprintf and vasprintf aren't C99 functions. Should they be
// target-specific builtins, perhaps? // target-specific builtins, perhaps?
if (!FD->getAttr<FormatAttr>()) if (!FD->getAttr<FormatAttr>())
FD->addAttr(::new (Context) FormatAttr(Context, "printf", 2, FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
"printf", 2,
Name->isStr("vasprintf") ? 0 : 3)); Name->isStr("vasprintf") ? 0 : 3));
} }
} }
@ -7009,7 +7029,7 @@ void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName); Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName);
if (PrevDecl) { if (PrevDecl) {
PrevDecl->addAttr(::new (Context) WeakAttr()); PrevDecl->addAttr(::new (Context) WeakAttr(PragmaLoc, Context));
} else { } else {
(void)WeakUndeclaredIdentifiers.insert( (void)WeakUndeclaredIdentifiers.insert(
std::pair<IdentifierInfo*,WeakInfo> std::pair<IdentifierInfo*,WeakInfo>

Просмотреть файл

@ -211,7 +211,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
} }
if (TagDecl *TD = dyn_cast<TagDecl>(d)) if (TagDecl *TD = dyn_cast<TagDecl>(d))
TD->addAttr(::new (S.Context) PackedAttr); TD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context));
else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) { else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
// If the alignment is less than or equal to 8 bits, the packed attribute // If the alignment is less than or equal to 8 bits, the packed attribute
// has no effect. // has no effect.
@ -220,7 +220,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
<< Attr.getName() << FD->getType(); << Attr.getName() << FD->getType();
else else
FD->addAttr(::new (S.Context) PackedAttr); FD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context));
} else } else
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
} }
@ -235,7 +235,7 @@ static void HandleIBAction(Decl *d, const AttributeList &Attr, Sema &S) {
// The IBAction attributes only apply to instance methods. // The IBAction attributes only apply to instance methods.
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
if (MD->isInstanceMethod()) { if (MD->isInstanceMethod()) {
d->addAttr(::new (S.Context) IBActionAttr()); d->addAttr(::new (S.Context) IBActionAttr(Attr.getLoc(), S.Context));
return; return;
} }
@ -252,7 +252,7 @@ static void HandleIBOutlet(Decl *d, const AttributeList &Attr, Sema &S) {
// The IBOutlet attributes only apply to instance variables of // The IBOutlet attributes only apply to instance variables of
// Objective-C classes. // Objective-C classes.
if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d)) { if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d)) {
d->addAttr(::new (S.Context) IBOutletAttr()); d->addAttr(::new (S.Context) IBOutletAttr(Attr.getLoc(), S.Context));
return; return;
} }
@ -307,7 +307,8 @@ static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr,
S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
return; return;
} }
d->addAttr(::new (S.Context) IBOutletCollectionAttr(QT)); d->addAttr(::new (S.Context) IBOutletCollectionAttr(Attr.getLoc(), S.Context,
QT));
} }
static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -378,7 +379,8 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
unsigned* start = &NonNullArgs[0]; unsigned* start = &NonNullArgs[0];
unsigned size = NonNullArgs.size(); unsigned size = NonNullArgs.size();
llvm::array_pod_sort(start, start + size); llvm::array_pod_sort(start, start + size);
d->addAttr(::new (S.Context) NonNullAttr(S.Context, start, size)); d->addAttr(::new (S.Context) NonNullAttr(Attr.getLoc(), S.Context, start,
size));
} }
static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) { static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
@ -397,24 +399,24 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
return; return;
} }
// Figure out our Kind, and check arguments while we're at it. // Figure out our Kind, and check arguments while we're at it.
attr::Kind K; OwnershipAttr::OwnershipKind K;
switch (AL.getKind()) { switch (AL.getKind()) {
case AttributeList::AT_ownership_takes: case AttributeList::AT_ownership_takes:
K = attr::OwnershipTakes; K = OwnershipAttr::Takes;
if (AL.getNumArgs() < 1) { if (AL.getNumArgs() < 1) {
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
return; return;
} }
break; break;
case AttributeList::AT_ownership_holds: case AttributeList::AT_ownership_holds:
K = attr::OwnershipHolds; K = OwnershipAttr::Holds;
if (AL.getNumArgs() < 1) { if (AL.getNumArgs() < 1) {
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
return; return;
} }
break; break;
case AttributeList::AT_ownership_returns: case AttributeList::AT_ownership_returns:
K = attr::OwnershipReturns; K = OwnershipAttr::Returns;
if (AL.getNumArgs() > 1) { if (AL.getNumArgs() > 1) {
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
<< AL.getNumArgs() + 1; << AL.getNumArgs() + 1;
@ -463,21 +465,21 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
} }
--x; --x;
switch (K) { switch (K) {
case attr::OwnershipTakes: case OwnershipAttr::Takes:
case attr::OwnershipHolds: { case OwnershipAttr::Holds: {
// Is the function argument a pointer type? // Is the function argument a pointer type?
QualType T = getFunctionOrMethodArgType(d, x); QualType T = getFunctionOrMethodArgType(d, x);
if (!T->isAnyPointerType() && !T->isBlockPointerType()) { if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
// FIXME: Should also highlight argument in decl. // FIXME: Should also highlight argument in decl.
S.Diag(AL.getLoc(), diag::err_ownership_type) S.Diag(AL.getLoc(), diag::err_ownership_type)
<< ((K==attr::OwnershipTakes)?"ownership_takes":"ownership_holds") << ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds")
<< "pointer" << "pointer"
<< IdxExpr->getSourceRange(); << IdxExpr->getSourceRange();
continue; continue;
} }
break; break;
} }
case attr::OwnershipReturns: { case OwnershipAttr::Returns: {
if (AL.getNumArgs() > 1) { if (AL.getNumArgs() > 1) {
// Is the function argument an integer type? // Is the function argument an integer type?
Expr *IdxExpr = static_cast<Expr *>(AL.getArg(0)); Expr *IdxExpr = static_cast<Expr *>(AL.getArg(0));
@ -497,18 +499,16 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
} // switch } // switch
// Check we don't have a conflict with another ownership attribute. // Check we don't have a conflict with another ownership attribute.
if (K != attr::OwnershipReturns && d->hasAttrs()) { for (specific_attr_iterator<OwnershipAttr>
for (const Attr *attr = d->getAttrs(); attr; attr = attr->getNext()) { i = d->specific_attr_begin<OwnershipAttr>(),
if (const OwnershipAttr* Att = dyn_cast<OwnershipAttr>(attr)) { e = d->specific_attr_end<OwnershipAttr>();
// Two ownership attributes of the same kind can't conflict, i != e; ++i) {
// except returns attributes. if ((*i)->getOwnKind() != K) {
if (Att->getKind() != K) { for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end();
for (const unsigned *I = Att->begin(), *E = Att->end(); I!=E; ++I) { I!=E; ++I) {
if (x == *I) { if (x == *I) {
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
<< AL.getName()->getName() << "ownership_*"; << AL.getName()->getName() << "ownership_*";
}
}
} }
} }
} }
@ -519,33 +519,14 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
unsigned* start = OwnershipArgs.data(); unsigned* start = OwnershipArgs.data();
unsigned size = OwnershipArgs.size(); unsigned size = OwnershipArgs.size();
llvm::array_pod_sort(start, start + size); llvm::array_pod_sort(start, start + size);
switch (K) {
case attr::OwnershipTakes: { if (K != OwnershipAttr::Returns && OwnershipArgs.empty()) {
if (OwnershipArgs.empty()) { S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; return;
return;
}
d->addAttr(::new (S.Context) OwnershipTakesAttr(S.Context, start, size,
Module));
break;
}
case attr::OwnershipHolds: {
if (OwnershipArgs.empty()) {
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
return;
}
d->addAttr(::new (S.Context) OwnershipHoldsAttr(S.Context, start, size,
Module));
break;
}
case attr::OwnershipReturns: {
d->addAttr(::new (S.Context) OwnershipReturnsAttr(S.Context, start, size,
Module));
break;
}
default:
llvm_unreachable("Unknown ownership attribute");
} }
d->addAttr(::new (S.Context) OwnershipAttr(AL.getLoc(), S.Context, K, Module,
start, size));
} }
static bool isStaticVarOrStaticFunciton(Decl *D) { static bool isStaticVarOrStaticFunciton(Decl *D) {
@ -622,10 +603,10 @@ static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) {
} }
// GCC will accept anything as the argument of weakref. Should we // GCC will accept anything as the argument of weakref. Should we
// check for an existing decl? // check for an existing decl?
d->addAttr(::new (S.Context) AliasAttr(S.Context, Str->getString())); d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, Str->getString()));
} }
d->addAttr(::new (S.Context) WeakRefAttr()); d->addAttr(::new (S.Context) WeakRefAttr(Attr.getLoc(), S.Context));
} }
static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -647,7 +628,7 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// FIXME: check if target symbol exists in current file // FIXME: check if target symbol exists in current file
d->addAttr(::new (S.Context) AliasAttr(S.Context, Str->getString())); d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, Str->getString()));
} }
static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
@ -664,7 +645,7 @@ static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
return; return;
} }
d->addAttr(::new (S.Context) AlwaysInlineAttr()); d->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getLoc(), S.Context));
} }
static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -677,7 +658,7 @@ static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
QualType RetTy = FD->getResultType(); QualType RetTy = FD->getResultType();
if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) { if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
d->addAttr(::new (S.Context) MallocAttr()); d->addAttr(::new (S.Context) MallocAttr(Attr.getLoc(), S.Context));
return; return;
} }
} }
@ -711,13 +692,13 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
/* Diagnostics (if any) was emitted by Sema::ProcessFnAttr(). */ /* Diagnostics (if any) was emitted by Sema::ProcessFnAttr(). */
assert(Attr.isInvalid() == false); assert(Attr.isInvalid() == false);
d->addAttr(::new (S.Context) NoReturnAttr()); d->addAttr(::new (S.Context) NoReturnAttr(Attr.getLoc(), S.Context));
} }
static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
Sema &S) { Sema &S) {
if (HandleCommonNoReturnAttr(d, Attr, S)) if (HandleCommonNoReturnAttr(d, Attr, S))
d->addAttr(::new (S.Context) AnalyzerNoReturnAttr()); d->addAttr(::new (S.Context) AnalyzerNoReturnAttr(Attr.getLoc(), S.Context));
} }
// PS3 PPU-specific. // PS3 PPU-specific.
@ -756,7 +737,7 @@ static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr,
return; return;
} }
d->addAttr(::new (S.Context) VecReturnAttr()); d->addAttr(::new (S.Context) VecReturnAttr(Attr.getLoc(), S.Context));
} }
static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -782,7 +763,7 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) UnusedAttr()); d->addAttr(::new (S.Context) UnusedAttr(Attr.getLoc(), S.Context));
} }
static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -803,7 +784,7 @@ static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) UsedAttr()); d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
} }
static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -833,7 +814,7 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) ConstructorAttr(priority)); d->addAttr(::new (S.Context) ConstructorAttr(Attr.getLoc(), S.Context, priority));
} }
static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -863,7 +844,7 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) DestructorAttr(priority)); d->addAttr(::new (S.Context) DestructorAttr(Attr.getLoc(), S.Context, priority));
} }
static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -873,7 +854,7 @@ static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) DeprecatedAttr()); d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context));
} }
static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -883,7 +864,7 @@ static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) UnavailableAttr()); d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context));
} }
static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -904,22 +885,22 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
} }
llvm::StringRef TypeStr = Str->getString(); llvm::StringRef TypeStr = Str->getString();
VisibilityAttr::VisibilityTypes type; VisibilityAttr::VisibilityType type;
if (TypeStr == "default") if (TypeStr == "default")
type = VisibilityAttr::DefaultVisibility; type = VisibilityAttr::Default;
else if (TypeStr == "hidden") else if (TypeStr == "hidden")
type = VisibilityAttr::HiddenVisibility; type = VisibilityAttr::Hidden;
else if (TypeStr == "internal") else if (TypeStr == "internal")
type = VisibilityAttr::HiddenVisibility; // FIXME type = VisibilityAttr::Hidden; // FIXME
else if (TypeStr == "protected") else if (TypeStr == "protected")
type = VisibilityAttr::ProtectedVisibility; type = VisibilityAttr::Protected;
else { else {
S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr; S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
return; return;
} }
d->addAttr(::new (S.Context) VisibilityAttr(type, false)); d->addAttr(::new (S.Context) VisibilityAttr(Attr.getLoc(), S.Context, type));
} }
static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr, static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
@ -935,7 +916,7 @@ static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
return; return;
} }
D->addAttr(::new (S.Context) ObjCExceptionAttr()); D->addAttr(::new (S.Context) ObjCExceptionAttr(Attr.getLoc(), S.Context));
} }
static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) { static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
@ -951,7 +932,7 @@ static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
return; return;
} }
} }
D->addAttr(::new (S.Context) ObjCNSObjectAttr()); D->addAttr(::new (S.Context) ObjCNSObjectAttr(Attr.getLoc(), S.Context));
} }
static void static void
@ -966,7 +947,7 @@ HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return; return;
} }
D->addAttr(::new (S.Context) OverloadableAttr()); D->addAttr(::new (S.Context) OverloadableAttr(Attr.getLoc(), S.Context));
} }
static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -981,7 +962,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
BlocksAttr::BlocksAttrTypes type; BlocksAttr::BlockType type;
if (Attr.getParameterName()->isStr("byref")) if (Attr.getParameterName()->isStr("byref"))
type = BlocksAttr::ByRef; type = BlocksAttr::ByRef;
else { else {
@ -990,7 +971,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) BlocksAttr(type)); d->addAttr(::new (S.Context) BlocksAttr(Attr.getLoc(), S.Context, type));
} }
static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -1083,7 +1064,7 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
<< Attr.getName() << 6 /*function, method or block */; << Attr.getName() << 6 /*function, method or block */;
return; return;
} }
d->addAttr(::new (S.Context) SentinelAttr(sentinel, nullPos)); d->addAttr(::new (S.Context) SentinelAttr(Attr.getLoc(), S.Context, sentinel, nullPos));
} }
static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) { static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) {
@ -1111,7 +1092,7 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S)
return; return;
} }
D->addAttr(::new (S.Context) WarnUnusedResultAttr()); D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getLoc(), S.Context));
} }
static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) { static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@ -1135,7 +1116,7 @@ static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return; return;
} }
D->addAttr(::new (S.Context) WeakAttr()); D->addAttr(::new (S.Context) WeakAttr(Attr.getLoc(), S.Context));
} }
static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@ -1171,7 +1152,7 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return; return;
} }
D->addAttr(::new (S.Context) WeakImportAttr()); D->addAttr(::new (S.Context) WeakImportAttr(Attr.getLoc(), S.Context));
} }
static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr, static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
@ -1194,7 +1175,8 @@ static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
} }
WGSize[i] = (unsigned) ArgNum.getZExtValue(); WGSize[i] = (unsigned) ArgNum.getZExtValue();
} }
D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(WGSize[0], WGSize[1], D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(Attr.getLoc(), S.Context,
WGSize[0], WGSize[1],
WGSize[2])); WGSize[2]));
} }
@ -1228,7 +1210,7 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return; return;
} }
D->addAttr(::new (S.Context) SectionAttr(S.Context, SE->getString())); D->addAttr(::new (S.Context) SectionAttr(Attr.getLoc(), S.Context, SE->getString()));
} }
@ -1239,7 +1221,7 @@ static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) NoThrowAttr()); d->addAttr(::new (S.Context) NoThrowAttr(Attr.getLoc(), S.Context));
} }
static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -1249,7 +1231,7 @@ static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) ConstAttr()); d->addAttr(::new (S.Context) ConstAttr(Attr.getLoc(), S.Context));
} }
static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -1259,7 +1241,7 @@ static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) PureAttr()); d->addAttr(::new (S.Context) PureAttr(Attr.getLoc(), S.Context));
} }
static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -1317,7 +1299,7 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) CleanupAttr(FD)); d->addAttr(::new (S.Context) CleanupAttr(Attr.getLoc(), S.Context, FD));
} }
/// Handle __attribute__((format_arg((idx)))) attribute based on /// Handle __attribute__((format_arg((idx)))) attribute based on
@ -1380,7 +1362,7 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue())); d->addAttr(::new (S.Context) FormatArgAttr(Attr.getLoc(), S.Context, Idx.getZExtValue()));
} }
enum FormatAttrKind { enum FormatAttrKind {
@ -1462,7 +1444,7 @@ static void HandleInitPriorityAttr(Decl *d, const AttributeList &Attr,
Attr.setInvalid(); Attr.setInvalid();
return; return;
} }
d->addAttr(::new (S.Context) InitPriorityAttr(prioritynum)); d->addAttr(::new (S.Context) InitPriorityAttr(Attr.getLoc(), S.Context, prioritynum));
} }
/// Handle __attribute__((format(type,idx,firstarg))) attributes based on /// Handle __attribute__((format(type,idx,firstarg))) attributes based on
@ -1606,7 +1588,8 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) FormatAttr(S.Context, Format, Idx.getZExtValue(), d->addAttr(::new (S.Context) FormatAttr(Attr.getLoc(), S.Context, Format,
Idx.getZExtValue(),
FirstArg.getZExtValue())); FirstArg.getZExtValue()));
} }
@ -1675,7 +1658,7 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
} }
} }
RD->addAttr(::new (S.Context) TransparentUnionAttr()); RD->addAttr(::new (S.Context) TransparentUnionAttr(Attr.getLoc(), S.Context));
} }
static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -1693,7 +1676,7 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate"; S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate";
return; return;
} }
d->addAttr(::new (S.Context) AnnotateAttr(S.Context, SE->getString())); d->addAttr(::new (S.Context) AnnotateAttr(Attr.getLoc(), S.Context, SE->getString()));
} }
static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) { static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@ -1708,9 +1691,7 @@ static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// weaker alignment, rather than being silently ignored. // weaker alignment, rather than being silently ignored.
if (Attr.getNumArgs() == 0) { if (Attr.getNumArgs() == 0) {
// FIXME: This should be the target specific maximum alignment. D->addAttr(::new (S.Context) AlignedAttr(Attr.getLoc(), S.Context, true, 0));
// (For now we just use 128 bits which is the maximum on X86).
D->addAttr(::new (S.Context) AlignedAttr(128));
return; return;
} }
@ -1720,10 +1701,11 @@ static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) { void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) {
if (E->isTypeDependent() || E->isValueDependent()) { if (E->isTypeDependent() || E->isValueDependent()) {
// Save dependent expressions in the AST to be instantiated. // Save dependent expressions in the AST to be instantiated.
D->addAttr(::new (Context) AlignedAttr(E)); D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E));
return; return;
} }
// FIXME: Cache the number on the Attr object?
llvm::APSInt Alignment(32); llvm::APSInt Alignment(32);
if (!E->isIntegerConstantExpr(Alignment, Context)) { if (!E->isIntegerConstantExpr(Alignment, Context)) {
Diag(AttrLoc, diag::err_attribute_argument_not_int) Diag(AttrLoc, diag::err_attribute_argument_not_int)
@ -1736,7 +1718,14 @@ void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) {
return; return;
} }
D->addAttr(::new (Context) AlignedAttr(Alignment.getZExtValue() * 8)); D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E));
}
void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, TypeSourceInfo *TS) {
// FIXME: Cache the number on the Attr object if non-dependent?
// FIXME: Perform checking of type validity
D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, false, TS));
return;
} }
/// HandleModeAttr - This attribute modifies the width of a decl with primitive /// HandleModeAttr - This attribute modifies the width of a decl with primitive
@ -1923,7 +1912,7 @@ static void HandleNoDebugAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) NoDebugAttr()); d->addAttr(::new (S.Context) NoDebugAttr(Attr.getLoc(), S.Context));
} }
static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -1939,7 +1928,7 @@ static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) NoInlineAttr()); d->addAttr(::new (S.Context) NoInlineAttr(Attr.getLoc(), S.Context));
} }
static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr, static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr,
@ -1956,7 +1945,7 @@ static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr,
return; return;
} }
d->addAttr(::new (S.Context) NoInstrumentFunctionAttr()); d->addAttr(::new (S.Context) NoInstrumentFunctionAttr(Attr.getLoc(), S.Context));
} }
static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -1978,7 +1967,7 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) GNUInlineAttr()); d->addAttr(::new (S.Context) GNUInlineAttr(Attr.getLoc(), S.Context));
} }
static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -1988,15 +1977,15 @@ static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) {
switch (Attr.getKind()) { switch (Attr.getKind()) {
case AttributeList::AT_fastcall: case AttributeList::AT_fastcall:
d->addAttr(::new (S.Context) FastCallAttr()); d->addAttr(::new (S.Context) FastCallAttr(Attr.getLoc(), S.Context));
return; return;
case AttributeList::AT_stdcall: case AttributeList::AT_stdcall:
d->addAttr(::new (S.Context) StdCallAttr()); d->addAttr(::new (S.Context) StdCallAttr(Attr.getLoc(), S.Context));
return; return;
case AttributeList::AT_thiscall: case AttributeList::AT_thiscall:
d->addAttr(::new (S.Context) ThisCallAttr()); d->addAttr(::new (S.Context) ThisCallAttr(Attr.getLoc(), S.Context));
case AttributeList::AT_cdecl: case AttributeList::AT_cdecl:
d->addAttr(::new (S.Context) CDeclAttr()); d->addAttr(::new (S.Context) CDeclAttr(Attr.getLoc(), S.Context));
return; return;
default: default:
llvm_unreachable("unexpected attribute kind"); llvm_unreachable("unexpected attribute kind");
@ -2038,7 +2027,8 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue())); d->addAttr(::new (S.Context) RegparmAttr(Attr.getLoc(), S.Context,
NumParams.getZExtValue()));
} }
static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -2064,7 +2054,7 @@ static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) FinalAttr()); d->addAttr(::new (S.Context) FinalAttr(Attr.getLoc(), S.Context));
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -2090,7 +2080,7 @@ static void HandleBaseCheckAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) BaseCheckAttr()); d->addAttr(::new (S.Context) BaseCheckAttr(Attr.getLoc(), S.Context));
} }
static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -2115,7 +2105,7 @@ static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) HidingAttr()); d->addAttr(::new (S.Context) HidingAttr(Attr.getLoc(), S.Context));
} }
static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -2140,7 +2130,7 @@ static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) OverrideAttr()); d->addAttr(::new (S.Context) OverrideAttr(Attr.getLoc(), S.Context));
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -2176,16 +2166,16 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr,
assert(0 && "invalid ownership attribute"); assert(0 && "invalid ownership attribute");
return; return;
case AttributeList::AT_cf_returns_not_retained: case AttributeList::AT_cf_returns_not_retained:
d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr()); d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(Attr.getLoc(), S.Context));
return; return;
case AttributeList::AT_ns_returns_not_retained: case AttributeList::AT_ns_returns_not_retained:
d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr()); d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(Attr.getLoc(), S.Context));
return; return;
case AttributeList::AT_cf_returns_retained: case AttributeList::AT_cf_returns_retained:
d->addAttr(::new (S.Context) CFReturnsRetainedAttr()); d->addAttr(::new (S.Context) CFReturnsRetainedAttr(Attr.getLoc(), S.Context));
return; return;
case AttributeList::AT_ns_returns_retained: case AttributeList::AT_ns_returns_retained:
d->addAttr(::new (S.Context) NSReturnsRetainedAttr()); d->addAttr(::new (S.Context) NSReturnsRetainedAttr(Attr.getLoc(), S.Context));
return; return;
}; };
} }
@ -2369,8 +2359,9 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...)) if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
IdentifierInfo *NDId = ND->getIdentifier(); IdentifierInfo *NDId = ND->getIdentifier();
NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias()); NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias());
NewD->addAttr(::new (Context) AliasAttr(Context, NDId->getName())); NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context,
NewD->addAttr(::new (Context) WeakAttr()); NDId->getName()));
NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
WeakTopLevelDecl.push_back(NewD); WeakTopLevelDecl.push_back(NewD);
// FIXME: "hideous" code from Sema::LazilyCreateBuiltin // FIXME: "hideous" code from Sema::LazilyCreateBuiltin
// to insert Decl at TU scope, sorry. // to insert Decl at TU scope, sorry.
@ -2379,7 +2370,7 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
PushOnScopeChains(NewD, S); PushOnScopeChains(NewD, S);
CurContext = SavedContext; CurContext = SavedContext;
} else { // just add weak to existing } else { // just add weak to existing
ND->addAttr(::new (Context) WeakAttr()); ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
} }
} }

Просмотреть файл

@ -3292,7 +3292,7 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList); ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
if (const VisibilityAttr *attr = Namespc->getAttr<VisibilityAttr>()) if (const VisibilityAttr *attr = Namespc->getAttr<VisibilityAttr>())
PushPragmaVisibility(attr->getVisibility()); PushPragmaVisibility(attr->getVisibility(), attr->getLocation());
if (II) { if (II) {
// C++ [namespace.def]p2: // C++ [namespace.def]p2:

Просмотреть файл

@ -1454,13 +1454,14 @@ CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {
} }
static inline static inline
bool containsInvalidMethodImplAttribute(const AttributeList *A) { bool containsInvalidMethodImplAttribute(const AttrVec &A) {
// The 'ibaction' attribute is allowed on method definitions because of // The 'ibaction' attribute is allowed on method definitions because of
// how the IBAction macro is used on both method declarations and definitions. // how the IBAction macro is used on both method declarations and definitions.
// If the method definitions contains any other attributes, return true. // If the method definitions contains any other attributes, return true.
while (A && A->getKind() == AttributeList::AT_IBAction) for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i)
A = A->getNext(); if ((*i)->getKind() != attr::IBAction)
return A != NULL; return true;
return false;
} }
Sema::DeclPtrTy Sema::ActOnMethodDeclaration( Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
@ -1590,7 +1591,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
} }
InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel, InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel,
MethodType == tok::minus); MethodType == tok::minus);
if (containsInvalidMethodImplAttribute(AttrList)) if (ObjCMethod->hasAttrs() &&
containsInvalidMethodImplAttribute(ObjCMethod->getAttrs()))
Diag(EndLoc, diag::warn_attribute_method_def); Diag(EndLoc, diag::warn_attribute_method_def);
} else if (ObjCCategoryImplDecl *CatImpDecl = } else if (ObjCCategoryImplDecl *CatImpDecl =
dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) { dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {
@ -1601,7 +1603,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
PrevMethod = CatImpDecl->getClassMethod(Sel); PrevMethod = CatImpDecl->getClassMethod(Sel);
CatImpDecl->addClassMethod(ObjCMethod); CatImpDecl->addClassMethod(ObjCMethod);
} }
if (containsInvalidMethodImplAttribute(AttrList)) if (ObjCMethod->hasAttrs() &&
containsInvalidMethodImplAttribute(ObjCMethod->getAttrs()))
Diag(EndLoc, diag::warn_attribute_method_def); Diag(EndLoc, diag::warn_attribute_method_def);
} }
if (PrevMethod) { if (PrevMethod) {
@ -1613,8 +1616,10 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
// If the interface declared this method, and it was deprecated there, // If the interface declared this method, and it was deprecated there,
// mark it deprecated here. // mark it deprecated here.
if (InterfaceMD && InterfaceMD->hasAttr<DeprecatedAttr>()) if (InterfaceMD)
ObjCMethod->addAttr(::new (Context) DeprecatedAttr()); if (Attr *DA = InterfaceMD->getAttr<DeprecatedAttr>())
ObjCMethod->addAttr(::new (Context) DeprecatedAttr(DA->getLocation(),
Context));
return DeclPtrTy::make(ObjCMethod); return DeclPtrTy::make(ObjCMethod);
} }

Просмотреть файл

@ -1259,7 +1259,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
// FIXME: Do we need to check for default arguments here? // FIXME: Do we need to check for default arguments here?
if (Func->getNumParams() == 1 && InitialParamType == Argument) { if (Func->getNumParams() == 1 && InitialParamType == Argument) {
if(AddMallocAttr && !Func->hasAttr<MallocAttr>()) if(AddMallocAttr && !Func->hasAttr<MallocAttr>())
Func->addAttr(::new (Context) MallocAttr()); Func->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
return; return;
} }
} }
@ -1287,7 +1287,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
Alloc->setImplicit(); Alloc->setImplicit();
if (AddMallocAttr) if (AddMallocAttr)
Alloc->addAttr(::new (Context) MallocAttr()); Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(), ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
0, Argument, /*TInfo=*/0, 0, Argument, /*TInfo=*/0,

Просмотреть файл

@ -4031,7 +4031,7 @@ Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
/// \brief Strips various properties off an implicit instantiation /// \brief Strips various properties off an implicit instantiation
/// that has just been explicitly specialized. /// that has just been explicitly specialized.
static void StripImplicitInstantiation(NamedDecl *D) { static void StripImplicitInstantiation(NamedDecl *D) {
D->invalidateAttrs(); D->dropAttrs();
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
FD->setInlineSpecified(false); FD->setInlineSpecified(false);

Просмотреть файл

@ -140,21 +140,30 @@ bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
// FIXME: Is this still too simple? // FIXME: Is this still too simple?
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
Decl *Tmpl, Decl *New) { Decl *Tmpl, Decl *New) {
for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr; for (AttrVec::const_iterator i = Tmpl->attr_begin(), e = Tmpl->attr_end();
TmplAttr = TmplAttr->getNext()) { i != e; ++i) {
const Attr *TmplAttr = *i;
// FIXME: This should be generalized to more than just the AlignedAttr. // FIXME: This should be generalized to more than just the AlignedAttr.
if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) { if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) {
if (Aligned->isDependent()) { if (Aligned->isAlignmentDependent()) {
// The alignment expression is not potentially evaluated. // The alignment expression is not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(*this, EnterExpressionEvaluationContext Unevaluated(*this,
Action::Unevaluated); Action::Unevaluated);
OwningExprResult Result = SubstExpr(Aligned->getAlignmentExpr(), if (Aligned->isAlignmentExpr()) {
TemplateArgs); OwningExprResult Result = SubstExpr(Aligned->getAlignmentExpr(),
if (!Result.isInvalid()) TemplateArgs);
// FIXME: Is this the correct source location? if (!Result.isInvalid())
AddAlignedAttr(Aligned->getAlignmentExpr()->getExprLoc(), AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>());
New, Result.takeAs<Expr>()); }
else {
TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(),
TemplateArgs,
Aligned->getLocation(),
DeclarationName());
if (Result)
AddAlignedAttr(Aligned->getLocation(), New, Result);
}
continue; continue;
} }
} }

Просмотреть файл

@ -51,8 +51,8 @@ static void HandleMSP430InterruptAttr(Decl *d,
return; return;
} }
d->addAttr(::new (S.Context) MSP430InterruptAttr(Num)); d->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num));
d->addAttr(::new (S.Context) UsedAttr()); d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
} }
namespace { namespace {
@ -97,7 +97,7 @@ static void HandleX86ForceAlignArgPointerAttr(Decl *D,
return; return;
} }
D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr()); D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getLoc(), S.Context));
} }
static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@ -109,7 +109,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// Attribute can be applied only to functions or variables. // Attribute can be applied only to functions or variables.
if (isa<VarDecl>(D)) { if (isa<VarDecl>(D)) {
D->addAttr(::new (S.Context) DLLImportAttr()); D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context));
return; return;
} }
@ -146,7 +146,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return; return;
} }
D->addAttr(::new (S.Context) DLLImportAttr()); D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context));
} }
static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@ -158,7 +158,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// Attribute can be applied only to functions or variables. // Attribute can be applied only to functions or variables.
if (isa<VarDecl>(D)) { if (isa<VarDecl>(D)) {
D->addAttr(::new (S.Context) DLLExportAttr()); D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
return; return;
} }
@ -177,7 +177,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return; return;
} }
D->addAttr(::new (S.Context) DLLExportAttr()); D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
} }
namespace { namespace {

Просмотреть файл

@ -13,6 +13,8 @@ add_clang_library(clangSerialization
add_dependencies(clangSerialization add_dependencies(clangSerialization
ClangAttrClasses ClangAttrClasses
ClangAttrList ClangAttrList
ClangAttrPCHRead
ClangAttrPCHWrite
ClangDiagnosticFrontend ClangDiagnosticFrontend
ClangDiagnosticLex ClangDiagnosticLex
ClangDiagnosticSema ClangDiagnosticSema

Просмотреть файл

@ -148,8 +148,11 @@ void PCHDeclReader::VisitDecl(Decl *D) {
cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++]))); cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
D->setInvalidDecl(Record[Idx++]); D->setInvalidDecl(Record[Idx++]);
if (Record[Idx++]) if (Record[Idx++]) {
D->initAttrs(Reader.ReadAttributes(Cursor)); AttrVec Attrs;
Reader.ReadAttributes(Cursor, Attrs);
D->setAttrs(Attrs);
}
D->setImplicit(Record[Idx++]); D->setImplicit(Record[Idx++]);
D->setUsed(Record[Idx++]); D->setUsed(Record[Idx++]);
D->setAccess((AccessSpecifier)Record[Idx++]); D->setAccess((AccessSpecifier)Record[Idx++]);
@ -1091,7 +1094,8 @@ void PCHDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// \brief Reads attributes from the current stream position. /// \brief Reads attributes from the current stream position.
Attr *PCHReader::ReadAttributes(llvm::BitstreamCursor &DeclsCursor) { void PCHReader::ReadAttributes(llvm::BitstreamCursor &DeclsCursor,
AttrVec &Attrs) {
unsigned Code = DeclsCursor.ReadCode(); unsigned Code = DeclsCursor.ReadCode();
assert(Code == llvm::bitc::UNABBREV_RECORD && assert(Code == llvm::bitc::UNABBREV_RECORD &&
"Expected unabbreviated record"); (void)Code; "Expected unabbreviated record"); (void)Code;
@ -1102,174 +1106,18 @@ Attr *PCHReader::ReadAttributes(llvm::BitstreamCursor &DeclsCursor) {
assert(RecCode == pch::DECL_ATTR && "Expected attribute record"); assert(RecCode == pch::DECL_ATTR && "Expected attribute record");
(void)RecCode; (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(*Context, 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()) { while (Idx < Record.size()) {
Attr *New = 0; Attr *New = 0;
attr::Kind Kind = (attr::Kind)Record[Idx++]; attr::Kind Kind = (attr::Kind)Record[Idx++];
bool IsInherited = Record[Idx++]; SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[Idx++]);
bool isInherited = Record[Idx++];
switch (Kind) { #include "clang/Serialization/AttrPCHRead.inc"
default:
assert(0 && "Unknown attribute!");
break;
STRING_ATTR(Alias);
SIMPLE_ATTR(AlignMac68k);
UNSIGNED_ATTR(Aligned);
SIMPLE_ATTR(AlwaysInline);
SIMPLE_ATTR(AnalyzerNoReturn);
STRING_ATTR(Annotate);
STRING_ATTR(AsmLabel);
SIMPLE_ATTR(BaseCheck);
case attr::Blocks:
New = ::new (*Context) BlocksAttr(
(BlocksAttr::BlocksAttrTypes)Record[Idx++]);
break;
SIMPLE_ATTR(CDecl);
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);
SIMPLE_ATTR(Final);
case attr::Format: {
std::string Type = ReadString(Record, Idx);
unsigned FormatIdx = Record[Idx++];
unsigned FirstArg = Record[Idx++];
New = ::new (*Context) FormatAttr(*Context, Type, FormatIdx, FirstArg);
break;
}
case attr::FormatArg: {
unsigned FormatIdx = Record[Idx++];
New = ::new (*Context) FormatArgAttr(FormatIdx);
break;
}
case attr::Sentinel: {
int sentinel = Record[Idx++];
int nullPos = Record[Idx++];
New = ::new (*Context) SentinelAttr(sentinel, nullPos);
break;
}
SIMPLE_ATTR(GNUInline);
SIMPLE_ATTR(Hiding);
case attr::IBAction:
New = ::new (*Context) IBActionAttr();
break;
case attr::IBOutlet:
New = ::new (*Context) IBOutletAttr();
break;
case attr::IBOutletCollection: {
QualType QT = GetType(Record[Idx++]);
New = ::new (*Context) IBOutletCollectionAttr(QT);
break;
}
SIMPLE_ATTR(Malloc);
SIMPLE_ATTR(NoDebug);
SIMPLE_ATTR(NoInline);
SIMPLE_ATTR(NoReturn);
SIMPLE_ATTR(NoThrow);
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(*Context, ArgNums.data(), Size);
break;
}
case attr::ReqdWorkGroupSize: {
unsigned X = Record[Idx++];
unsigned Y = Record[Idx++];
unsigned Z = Record[Idx++];
New = ::new (*Context) ReqdWorkGroupSizeAttr(X, Y, Z);
break;
}
SIMPLE_ATTR(ObjCException);
SIMPLE_ATTR(ObjCNSObject);
SIMPLE_ATTR(CFReturnsNotRetained);
SIMPLE_ATTR(CFReturnsRetained);
SIMPLE_ATTR(NSReturnsNotRetained);
SIMPLE_ATTR(NSReturnsRetained);
SIMPLE_ATTR(Overloadable);
SIMPLE_ATTR(Override);
SIMPLE_ATTR(Packed);
UNSIGNED_ATTR(MaxFieldAlignment);
SIMPLE_ATTR(Pure);
UNSIGNED_ATTR(Regparm);
STRING_ATTR(Section);
SIMPLE_ATTR(StdCall);
SIMPLE_ATTR(ThisCall);
SIMPLE_ATTR(TransparentUnion);
SIMPLE_ATTR(Unavailable);
SIMPLE_ATTR(Unused);
SIMPLE_ATTR(Used);
case attr::Visibility:
New = ::new (*Context) VisibilityAttr(
(VisibilityAttr::VisibilityTypes)Record[Idx++],
(bool)Record[Idx++]);
break;
SIMPLE_ATTR(WarnUnusedResult);
SIMPLE_ATTR(Weak);
SIMPLE_ATTR(WeakRef);
SIMPLE_ATTR(WeakImport);
}
assert(New && "Unable to decode attribute?"); assert(New && "Unable to decode attribute?");
New->setInherited(IsInherited); New->setInherited(isInherited);
New->setNext(Attrs); Attrs.push_back(New);
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;
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

Просмотреть файл

@ -1949,172 +1949,16 @@ void PCHWriter::WriteIdentifierTable(Preprocessor &PP) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// \brief Write a record containing the given attributes. /// \brief Write a record containing the given attributes.
void PCHWriter::WriteAttributeRecord(const Attr *Attr) { void PCHWriter::WriteAttributeRecord(const AttrVec &Attrs) {
RecordData Record; RecordData Record;
for (; Attr; Attr = Attr->getNext()) { for (AttrVec::const_iterator i = Attrs.begin(), e = Attrs.end(); i != e; ++i){
Record.push_back(Attr->getKind()); // FIXME: stable encoding, target attrs const Attr * A = *i;
Record.push_back(Attr->isInherited()); Record.push_back(A->getKind()); // FIXME: stable encoding, target attrs
switch (Attr->getKind()) { AddSourceLocation(A->getLocation(), Record);
default: Record.push_back(A->isInherited());
assert(0 && "Does not support PCH writing for this attribute yet!");
break;
case attr::Alias:
AddString(cast<AliasAttr>(Attr)->getAliasee(), Record);
break;
case attr::AlignMac68k: #include "clang/Serialization/AttrPCHWrite.inc"
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::BaseCheck:
break;
case attr::Blocks:
Record.push_back(cast<BlocksAttr>(Attr)->getType()); // FIXME: stable
break;
case attr::CDecl:
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:
case attr::Final:
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::FormatArg: {
const FormatArgAttr *Format = cast<FormatArgAttr>(Attr);
Record.push_back(Format->getFormatIdx());
break;
}
case attr::Sentinel : {
const SentinelAttr *Sentinel = cast<SentinelAttr>(Attr);
Record.push_back(Sentinel->getSentinel());
Record.push_back(Sentinel->getNullPos());
break;
}
case attr::GNUInline:
case attr::Hiding:
case attr::IBAction:
case attr::IBOutlet:
case attr::Malloc:
case attr::NoDebug:
case attr::NoInline:
case attr::NoReturn:
case attr::NoThrow:
break;
case attr::IBOutletCollection: {
const IBOutletCollectionAttr *ICA = cast<IBOutletCollectionAttr>(Attr);
AddTypeRef(ICA->getType(), Record);
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::CFReturnsNotRetained:
case attr::CFReturnsRetained:
case attr::NSReturnsNotRetained:
case attr::NSReturnsRetained:
case attr::ObjCException:
case attr::ObjCNSObject:
case attr::Overloadable:
case attr::Override:
break;
case attr::MaxFieldAlignment:
Record.push_back(cast<MaxFieldAlignmentAttr>(Attr)->getAlignment());
break;
case attr::Packed:
break;
case attr::Pure:
break;
case attr::Regparm:
Record.push_back(cast<RegparmAttr>(Attr)->getNumParams());
break;
case attr::ReqdWorkGroupSize:
Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getXDim());
Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getYDim());
Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getZDim());
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());
Record.push_back(cast<VisibilityAttr>(Attr)->isFromPragma());
break;
case attr::WarnUnusedResult:
case attr::Weak:
case attr::WeakRef:
case attr::WeakImport:
break;
}
} }
Stream.EmitRecord(pch::DECL_ATTR, Record); Stream.EmitRecord(pch::DECL_ATTR, Record);

Просмотреть файл

@ -1144,8 +1144,9 @@ bool CursorVisitor::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
bool CursorVisitor::VisitAttributes(Decl *D) { bool CursorVisitor::VisitAttributes(Decl *D) {
for (const Attr *A = D->getAttrs(); A; A = A->getNext()) for (AttrVec::const_iterator i = D->attr_begin(), e = D->attr_end();
if (Visit(MakeCXCursor(A, D, TU))) i != e; ++i)
if (Visit(MakeCXCursor(*i, D, TU)))
return true; return true;
return false; return false;