зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
ea94bbc476
Коммит
cf807c4dfd
|
@ -18,7 +18,6 @@
|
|||
#include "clang/Basic/LangOptions.h"
|
||||
#include "clang/Basic/OperatorKinds.h"
|
||||
#include "clang/Basic/PartialDiagnostic.h"
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/NestedNameSpecifier.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
|
||||
/// 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
|
||||
/// static data members of class template specializations were instantiated.
|
||||
|
@ -322,7 +321,7 @@ public:
|
|||
}
|
||||
|
||||
/// \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.
|
||||
void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); }
|
||||
|
|
|
@ -15,9 +15,11 @@
|
|||
#define LLVM_CLANG_AST_ATTR_H
|
||||
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "clang/Basic/AttrKinds.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
@ -29,25 +31,33 @@ namespace clang {
|
|||
class ObjCInterfaceDecl;
|
||||
class Expr;
|
||||
class QualType;
|
||||
class FunctionDecl;
|
||||
class TypeSourceInfo;
|
||||
}
|
||||
|
||||
// Defined in ASTContext.h
|
||||
void *operator new(size_t Bytes, clang::ASTContext &C,
|
||||
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
|
||||
// warnings if a matching delete overload is not declared, even though the
|
||||
// throw() spec guarantees it will not be implicitly called.
|
||||
void operator delete(void *Ptr, clang::ASTContext &C, size_t)
|
||||
throw ();
|
||||
void operator delete[](void *Ptr, clang::ASTContext &C, size_t)
|
||||
throw ();
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// Attr - This represents one attribute.
|
||||
class Attr {
|
||||
private:
|
||||
Attr *Next;
|
||||
attr::Kind AttrKind;
|
||||
SourceLocation Loc;
|
||||
unsigned AttrKind : 16;
|
||||
bool Inherited : 1;
|
||||
|
||||
protected:
|
||||
|
@ -61,38 +71,36 @@ protected:
|
|||
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:
|
||||
Attr(attr::Kind AK) : Next(0), AttrKind(AK), Inherited(false) {}
|
||||
|
||||
Attr(attr::Kind AK, SourceLocation L)
|
||||
: Loc(L), AttrKind(AK) {}
|
||||
|
||||
public:
|
||||
|
||||
/// \brief Whether this attribute should be merged to new
|
||||
/// declarations.
|
||||
virtual bool isMerged() const { return true; }
|
||||
|
||||
attr::Kind getKind() const { return 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;
|
||||
attr::Kind getKind() const {
|
||||
return static_cast<attr::Kind>(AttrKind);
|
||||
}
|
||||
|
||||
SourceLocation getLocation() const { return Loc; }
|
||||
void setLocation(SourceLocation L) { Loc = L; }
|
||||
|
||||
bool isInherited() const { return Inherited; }
|
||||
void setInherited(bool value) { Inherited = value; }
|
||||
|
||||
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;
|
||||
}
|
||||
void setInherited(bool I) { Inherited = I; }
|
||||
|
||||
// Clone this attribute.
|
||||
virtual Attr* clone(ASTContext &C) const = 0;
|
||||
|
@ -102,591 +110,112 @@ public:
|
|||
};
|
||||
|
||||
#include "clang/AST/Attrs.inc"
|
||||
|
||||
class AttrWithString : public Attr {
|
||||
private:
|
||||
const char *Str;
|
||||
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) \
|
||||
class ATTR##Attr : public Attr { \
|
||||
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; } \
|
||||
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
|
||||
typedef llvm::SmallVector<Attr*, 2> AttrVec;
|
||||
typedef llvm::SmallVector<const Attr*, 2> ConstAttrVec;
|
||||
|
||||
/// DestroyAttrs - Destroy the contents of an AttrVec.
|
||||
inline void DestroyAttrs (AttrVec& V, ASTContext &C) {
|
||||
}
|
||||
|
||||
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
|
||||
/// valid on record decls.
|
||||
class MaxFieldAlignmentAttr : public Attr {
|
||||
unsigned Alignment;
|
||||
void AdvanceToNext() const {
|
||||
while (!llvm::isa<SpecificAttr>(*Current))
|
||||
++Current;
|
||||
}
|
||||
|
||||
void AdvanceToNext(AttrVec::const_iterator I) const {
|
||||
while (Current != I && !llvm::isa<SpecificAttr>(*Current))
|
||||
++Current;
|
||||
}
|
||||
|
||||
public:
|
||||
MaxFieldAlignmentAttr(unsigned alignment)
|
||||
: Attr(attr::MaxFieldAlignment), Alignment(alignment) {}
|
||||
typedef SpecificAttr* value_type;
|
||||
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.
|
||||
unsigned getAlignment() const { return Alignment; }
|
||||
specific_attr_iterator() : Current() { }
|
||||
explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
|
||||
|
||||
virtual Attr* clone(ASTContext &C) const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Attr *A) {
|
||||
return A->getKind() == attr::MaxFieldAlignment;
|
||||
reference operator*() const {
|
||||
AdvanceToNext();
|
||||
return llvm::cast<SpecificAttr>(*Current);
|
||||
}
|
||||
static bool classof(const MaxFieldAlignmentAttr *A) { return true; }
|
||||
};
|
||||
|
||||
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;
|
||||
pointer operator->() const {
|
||||
AdvanceToNext();
|
||||
return llvm::cast<SpecificAttr>(*Current);
|
||||
}
|
||||
|
||||
/// isDependent - Is the alignment a dependent expression
|
||||
bool isDependent() const {
|
||||
return getAlignmentExpr();
|
||||
specific_attr_iterator& operator++() {
|
||||
++Current;
|
||||
return *this;
|
||||
}
|
||||
specific_attr_iterator operator++(int) {
|
||||
specific_attr_iterator Tmp(*this);
|
||||
++(*this);
|
||||
return Tmp;
|
||||
}
|
||||
|
||||
/// getAlignment - The specified alignment in bits. Requires !isDependent().
|
||||
unsigned getAlignment() const {
|
||||
assert(!isDependent() && "Cannot get a value dependent alignment");
|
||||
return Alignment;
|
||||
}
|
||||
|
||||
/// 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());
|
||||
friend bool operator==(specific_attr_iterator Left,
|
||||
specific_attr_iterator Right) {
|
||||
if (Left.Current < Right.Current)
|
||||
Left.AdvanceToNext(Right.Current);
|
||||
else
|
||||
return getAlignment();
|
||||
Right.AdvanceToNext(Left.Current);
|
||||
return Left.Current == Right.Current;
|
||||
}
|
||||
|
||||
virtual Attr* clone(ASTContext &C) const;
|
||||
|
||||
// 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;
|
||||
friend bool operator!=(specific_attr_iterator Left,
|
||||
specific_attr_iterator Right) {
|
||||
return !(Left == Right);
|
||||
}
|
||||
};
|
||||
|
||||
class OwnershipTakesAttr: public OwnershipAttr {
|
||||
public:
|
||||
OwnershipTakesAttr(ASTContext &C, unsigned* arg_nums, unsigned size,
|
||||
llvm::StringRef module);
|
||||
template <typename T>
|
||||
inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) {
|
||||
return specific_attr_iterator<T>(vec.begin());
|
||||
}
|
||||
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) {
|
||||
return A->getKind() == attr::OwnershipTakes;
|
||||
}
|
||||
static bool classof(const OwnershipTakesAttr *A) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
/// getMaxAlignment - Returns the highest alignment value found among
|
||||
/// AlignedAttrs in an AttrVec, or 0 if there are none.
|
||||
inline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) {
|
||||
unsigned Align = 0;
|
||||
specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end());
|
||||
for(; i != e; ++i)
|
||||
Align = std::max(Align, i->getAlignment(Ctx));
|
||||
return Align;
|
||||
}
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
|
|
|
@ -5,6 +5,12 @@ tablegen(Attrs.inc
|
|||
add_custom_target(ClangAttrClasses
|
||||
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)
|
||||
tablegen(StmtNodes.inc
|
||||
-gen-clang-stmt-nodes)
|
||||
|
|
|
@ -308,24 +308,52 @@ public:
|
|||
}
|
||||
|
||||
bool hasAttrs() const { return HasAttrs; }
|
||||
void initAttrs(Attr *attrs);
|
||||
void addAttr(Attr *attr);
|
||||
const Attr *getAttrs() const {
|
||||
if (!HasAttrs) return 0; // common case, no attributes.
|
||||
return getAttrsImpl(); // Uncommon case, out of line hash lookup.
|
||||
void setAttrs(const AttrVec& Attrs);
|
||||
AttrVec& getAttrs() {
|
||||
return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
|
||||
}
|
||||
const AttrVec &getAttrs() const;
|
||||
void swapAttrs(Decl *D);
|
||||
void invalidateAttrs();
|
||||
void dropAttrs();
|
||||
|
||||
template<typename T> const T *getAttr() const {
|
||||
for (const Attr *attr = getAttrs(); attr; attr = attr->getNext())
|
||||
if (const T *V = dyn_cast<T>(attr))
|
||||
return V;
|
||||
return 0;
|
||||
void addAttr(Attr *A) {
|
||||
if (hasAttrs())
|
||||
getAttrs().push_back(A);
|
||||
else
|
||||
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 {
|
||||
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
|
||||
|
@ -346,16 +374,16 @@ public:
|
|||
/// (in addition to the "used" bit set by \c setUsed()) when determining
|
||||
/// whether the function is used.
|
||||
bool isUsed(bool CheckUsedAttr = true) const;
|
||||
|
||||
|
||||
void setUsed(bool U = true) { Used = U; }
|
||||
|
||||
/// \brief Retrieve the level of precompiled header from which this
|
||||
/// declaration was generated.
|
||||
///
|
||||
/// The PCH level of a declaration describes where the declaration originated
|
||||
/// from. A PCH level of 0 indicates that the declaration was not from a
|
||||
/// from. A PCH level of 0 indicates that the declaration was not from a
|
||||
/// precompiled header. A PCH level of 1 indicates that the declaration was
|
||||
/// from a top-level precompiled header; 2 indicates that the declaration
|
||||
/// from a top-level precompiled header; 2 indicates that the declaration
|
||||
/// comes from a precompiled header on which the top-level precompiled header
|
||||
/// depends, and so on.
|
||||
unsigned getPCHLevel() const { return PCHLevel; }
|
||||
|
|
|
@ -21,7 +21,6 @@ namespace clang {
|
|||
class Expr;
|
||||
class Stmt;
|
||||
class FunctionDecl;
|
||||
class AttributeList;
|
||||
class RecordDecl;
|
||||
class ObjCIvarDecl;
|
||||
class ObjCMethodDecl;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
CLANG_LEVEL := ../../..
|
||||
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
|
||||
|
||||
|
@ -12,6 +12,12 @@ $(ObjDir)/Attrs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
|
|||
$(Verb) $(TableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \
|
||||
-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)/.dir
|
||||
$(Echo) "Building Clang statement node tables with tblgen"
|
||||
|
|
|
@ -33,8 +33,8 @@ class SubsetSubject<AttrSubject base, string description, code check>
|
|||
// a possible subject.
|
||||
def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable",
|
||||
[{S->getStorageClass() != VarDecl::Register &&
|
||||
S->getKind() != Decl::ImplicitParam
|
||||
S->getKind() != Decl::ParmVar
|
||||
S->getKind() != Decl::ImplicitParam &&
|
||||
S->getKind() != Decl::ParmVar &&
|
||||
S->getKind() != Decl::NonTypeTemplateParm}]>;
|
||||
def CXXVirtualMethod : SubsetSubject<CXXRecord, "virtual member function",
|
||||
[{S->isVirtual()}]>;
|
||||
|
@ -51,18 +51,27 @@ class IntArgument<string name> : Argument<name>;
|
|||
class StringArgument<string name> : Argument<name>;
|
||||
class ExprArgument<string name> : Argument<name>;
|
||||
class FunctionArgument<string name> : Argument<name>;
|
||||
class ObjCInterfaceArgument<string name> : Argument<name>;
|
||||
class UnsignedIntArgument<string name> : Argument<name>;
|
||||
class UnsignedIntOrTypeArgument<string name> : Argument<name>;
|
||||
class TypeArgument<string name> : Argument<name>;
|
||||
class UnsignedArgument<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
|
||||
class DefaultIntArgument<string name, int default> : IntArgument<name> {
|
||||
int Default = default;
|
||||
}
|
||||
|
||||
// Zero or more arguments of a type
|
||||
class VariadicArgument<Argument arg> : Argument<arg.Name> {
|
||||
Argument VariadicArg = arg;
|
||||
// This argument is more complex, it includes the enumerator type name,
|
||||
// a list of strings to accept, and a list of enumerators to map them to.
|
||||
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 {
|
||||
|
@ -76,9 +85,8 @@ class Attr {
|
|||
// The attribute will not be permitted in C++0x attribute-specifiers if
|
||||
// this is empty; the empty string can be used as a namespace.
|
||||
list<string> Namespaces = [];
|
||||
// A temporary development bit to tell TableGen not to emit certain
|
||||
// information about the attribute.
|
||||
bit DoNotEmit = 1;
|
||||
// Any additional text that should be included verbatim in the class.
|
||||
code AdditionalMembers = [{}];
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -87,13 +95,13 @@ class Attr {
|
|||
|
||||
def Alias : Attr {
|
||||
let Spellings = ["alias"];
|
||||
let Args = [StringArgument<"AliasName">];
|
||||
let Args = [StringArgument<"Aliasee">];
|
||||
}
|
||||
|
||||
def Aligned : Attr {
|
||||
let Spellings = ["align", "aligned"];
|
||||
let Subjects = [NonBitField, NormalVar, Tag];
|
||||
let Args = [UnsignedIntOrTypeArgument<"Alignment">];
|
||||
let Args = [AlignedArgument<"Alignment">];
|
||||
let Namespaces = ["", "std"];
|
||||
}
|
||||
|
||||
|
@ -123,19 +131,17 @@ def BaseCheck : Attr {
|
|||
let Spellings = ["base_check"];
|
||||
let Subjects = [CXXRecord];
|
||||
let Namespaces = ["", "std"];
|
||||
let DoNotEmit = 0;
|
||||
}
|
||||
|
||||
def Blocks : Attr {
|
||||
let Spellings = ["blocks"];
|
||||
let Args = [IdentifierArgument<"Type">];
|
||||
let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
|
||||
}
|
||||
|
||||
def CarriesDependency : Attr {
|
||||
let Spellings = ["carries_dependency"];
|
||||
let Subjects = [ParmVar, Function];
|
||||
let Namespaces = ["", "std"];
|
||||
let DoNotEmit = 0;
|
||||
}
|
||||
|
||||
def CDecl : Attr {
|
||||
|
@ -189,7 +195,6 @@ def Final : Attr {
|
|||
let Spellings = ["final"];
|
||||
let Subjects = [CXXRecord, CXXVirtualMethod];
|
||||
let Namespaces = ["", "std"];
|
||||
let DoNotEmit = 0;
|
||||
}
|
||||
|
||||
def Format : Attr {
|
||||
|
@ -211,7 +216,6 @@ def Hiding : Attr {
|
|||
let Spellings = ["hiding"];
|
||||
let Subjects = [Field, CXXMethod];
|
||||
let Namespaces = ["", "std"];
|
||||
let DoNotEmit = 0;
|
||||
}
|
||||
|
||||
def IBAction : Attr {
|
||||
|
@ -224,7 +228,7 @@ def IBOutlet : Attr {
|
|||
|
||||
def IBOutletCollection : Attr {
|
||||
let Spellings = ["iboutletcollection"];
|
||||
let Args = [ObjCInterfaceArgument<"Class">];
|
||||
let Args = [TypeArgument<"Interface">];
|
||||
}
|
||||
|
||||
def Malloc : Attr {
|
||||
|
@ -233,12 +237,12 @@ def Malloc : Attr {
|
|||
|
||||
def MaxFieldAlignment : Attr {
|
||||
let Spellings = [];
|
||||
let Args = [UnsignedIntArgument<"Alignment">];
|
||||
let Args = [UnsignedArgument<"Alignment">];
|
||||
}
|
||||
|
||||
def MSP430Interrupt : Attr {
|
||||
let Spellings = [];
|
||||
let Args = [UnsignedIntArgument<"Number">];
|
||||
let Args = [UnsignedArgument<"Number">];
|
||||
}
|
||||
|
||||
def NoDebug : Attr {
|
||||
|
@ -251,7 +255,15 @@ def NoInline : Attr {
|
|||
|
||||
def NonNull : Attr {
|
||||
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 {
|
||||
|
@ -290,26 +302,18 @@ def Override : Attr {
|
|||
let Spellings = ["override"];
|
||||
let Subjects = [CXXVirtualMethod];
|
||||
let Namespaces = ["", "std"];
|
||||
let DoNotEmit = 0;
|
||||
}
|
||||
|
||||
def Overloadable : Attr {
|
||||
let Spellings = ["overloadable"];
|
||||
}
|
||||
|
||||
def OwnershipReturns : Attr {
|
||||
let Spellings = ["ownership_returns"];
|
||||
let Args = [StringArgument<"Module">, IntArgument<"SizeIdx">];
|
||||
}
|
||||
|
||||
def OwnershipTakes : Attr {
|
||||
let Spellings = ["ownership_takes"];
|
||||
let Args = [StringArgument<"Module">, IntArgument<"PtrIdx">];
|
||||
}
|
||||
|
||||
def OwnershipHolds : Attr {
|
||||
let Spellings = ["ownership_holds"];
|
||||
let Args = [StringArgument<"Module">, IntArgument<"PtrIdx">];
|
||||
def Ownership : Attr {
|
||||
let Spellings = ["ownership_holds", "ownership_returns", "ownership_takes"];
|
||||
let Args = [EnumArgument<"OwnKind", "OwnershipKind",
|
||||
["ownership_holds", "ownership_returns", "ownership_takes"],
|
||||
["Holds", "Returns", "Takes"]>,
|
||||
StringArgument<"Module">, VariadicUnsignedArgument<"Args">];
|
||||
}
|
||||
|
||||
def Packed : Attr {
|
||||
|
@ -322,18 +326,18 @@ def Pure : Attr {
|
|||
|
||||
def Regparm : Attr {
|
||||
let Spellings = ["regparm"];
|
||||
let Args = [UnsignedIntArgument<"NumParams">];
|
||||
let Args = [UnsignedArgument<"NumParams">];
|
||||
}
|
||||
|
||||
def ReqdWorkGroupSize : Attr {
|
||||
let Spellings = ["reqd_work_group_size"];
|
||||
let Args = [UnsignedIntArgument<"XDim">, UnsignedIntArgument<"YDim">,
|
||||
UnsignedIntArgument<"ZDim">];
|
||||
let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">,
|
||||
UnsignedArgument<"ZDim">];
|
||||
}
|
||||
|
||||
def InitPriority : Attr {
|
||||
let Spellings = ["init_priority"];
|
||||
let Args = [UnsignedIntArgument<"Priority">];
|
||||
let Args = [UnsignedArgument<"Priority">];
|
||||
}
|
||||
|
||||
def Section : Attr {
|
||||
|
@ -343,8 +347,8 @@ def Section : Attr {
|
|||
|
||||
def Sentinel : Attr {
|
||||
let Spellings = ["sentinel"];
|
||||
let Args = [DefaultIntArgument<"NulPos", 0>,
|
||||
DefaultIntArgument<"Sentinel", 0>];
|
||||
let Args = [DefaultIntArgument<"Sentinel", 0>,
|
||||
DefaultIntArgument<"NullPos", 0>];
|
||||
}
|
||||
|
||||
def StdCall : Attr {
|
||||
|
@ -373,13 +377,14 @@ def Used : Attr {
|
|||
|
||||
def Visibility : Attr {
|
||||
let Spellings = ["visibility"];
|
||||
let Args = [StringArgument<"Visibility">];
|
||||
let Args = [EnumArgument<"Visibility", "VisibilityType",
|
||||
["default", "hidden", "internal", "protected"],
|
||||
["Default", "Hidden", "Hidden", "Protected"]>];
|
||||
}
|
||||
|
||||
def VecReturn : Attr {
|
||||
let Spellings = ["vecreturn"];
|
||||
let Subjects = [CXXRecord];
|
||||
let DoNotEmit = 0;
|
||||
}
|
||||
|
||||
def WarnUnusedResult : Attr {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
add_subdirectory(AST)
|
||||
add_subdirectory(Basic)
|
||||
add_subdirectory(Driver)
|
||||
add_subdirectory(Serialization)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
CLANG_LEVEL := ../..
|
||||
DIRS := AST Basic Driver
|
||||
DIRS := AST Basic Driver Serialization
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
|
||||
|
|
|
@ -4265,7 +4265,8 @@ public:
|
|||
|
||||
/// PushPragmaVisibility - Push the top element of the visibility stack; used
|
||||
/// 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
|
||||
/// for '#pragma GCC visibility' and visibility attributes on namespaces.
|
||||
|
@ -4276,6 +4277,7 @@ public:
|
|||
|
||||
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
|
||||
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
|
||||
/// 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);
|
||||
|
||||
/// \brief Reads attributes from the current stream position.
|
||||
Attr *ReadAttributes(llvm::BitstreamCursor &DeclsCursor);
|
||||
void ReadAttributes(llvm::BitstreamCursor &DeclsCursor, AttrVec &Attrs);
|
||||
|
||||
/// \brief Reads a statement.
|
||||
Stmt *ReadStmt(llvm::BitstreamCursor &Cursor);
|
||||
|
|
|
@ -281,7 +281,7 @@ private:
|
|||
void WriteSelectors(Sema &SemaRef);
|
||||
void WriteReferencedSelectorsPool(Sema &SemaRef);
|
||||
void WriteIdentifierTable(Preprocessor &PP);
|
||||
void WriteAttributeRecord(const Attr *Attr);
|
||||
void WriteAttributeRecord(const AttrVec &Attrs);
|
||||
void WriteDeclUpdateBlock();
|
||||
|
||||
unsigned ParmVarDeclAbbrev;
|
||||
|
|
|
@ -497,8 +497,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
|
|||
CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) {
|
||||
unsigned Align = Target.getCharWidth();
|
||||
|
||||
if (const AlignedAttr* AA = D->getAttr<AlignedAttr>())
|
||||
Align = std::max(Align, AA->getMaxAlignment());
|
||||
Align = std::max(Align, D->getMaxAlignment());
|
||||
|
||||
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
|
||||
QualType T = VD->getType();
|
||||
|
@ -760,12 +759,9 @@ ASTContext::getTypeInfo(const Type *T) {
|
|||
|
||||
case Type::Typedef: {
|
||||
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
|
||||
if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
|
||||
Align = std::max(Aligned->getMaxAlignment(),
|
||||
getTypeAlign(Typedef->getUnderlyingType().getTypePtr()));
|
||||
Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
|
||||
} else
|
||||
return getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
|
||||
Align = std::max(Typedef->getMaxAlignment(),
|
||||
getTypeAlign(Typedef->getUnderlyingType().getTypePtr()));
|
||||
Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,231 +13,10 @@
|
|||
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
using namespace clang;
|
||||
|
||||
Attr::~Attr() { }
|
||||
|
||||
AttrWithString::AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s)
|
||||
: 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);
|
||||
}
|
||||
#include "clang/AST/AttrImpl.inc"
|
||||
|
|
|
@ -43,4 +43,4 @@ add_clang_library(clangAST
|
|||
)
|
||||
|
||||
add_dependencies(clangAST ClangARMNeon ClangAttrClasses ClangAttrList
|
||||
ClangDiagnosticAST ClangDeclNodes ClangStmtNodes)
|
||||
ClangAttrImpl ClangDiagnosticAST ClangDeclNodes ClangStmtNodes)
|
||||
|
|
|
@ -312,35 +312,25 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Decl::initAttrs(Attr *attrs) {
|
||||
void Decl::setAttrs(const AttrVec &attrs) {
|
||||
assert(!HasAttrs && "Decl already contains attrs.");
|
||||
|
||||
Attr *&AttrBlank = getASTContext().getDeclAttrs(this);
|
||||
assert(AttrBlank == 0 && "HasAttrs was wrong?");
|
||||
AttrVec &AttrBlank = getASTContext().getDeclAttrs(this);
|
||||
assert(AttrBlank.empty() && "HasAttrs was wrong?");
|
||||
|
||||
AttrBlank = attrs;
|
||||
HasAttrs = true;
|
||||
}
|
||||
|
||||
void Decl::addAttr(Attr *NewAttr) {
|
||||
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() {
|
||||
void Decl::dropAttrs() {
|
||||
if (!HasAttrs) return;
|
||||
|
||||
HasAttrs = false;
|
||||
getASTContext().eraseDeclAttrs(this);
|
||||
}
|
||||
|
||||
const Attr *Decl::getAttrsImpl() const {
|
||||
assert(HasAttrs && "getAttrs() should verify this!");
|
||||
const AttrVec &Decl::getAttrs() const {
|
||||
assert(HasAttrs && "No attrs to get!");
|
||||
return getASTContext().getDeclAttrs(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -1123,8 +1123,8 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
|
|||
if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
|
||||
MaxFieldAlignment = MFAA->getAlignment();
|
||||
|
||||
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
|
||||
UpdateAlignment(AA->getMaxAlignment());
|
||||
if (unsigned MaxAlign = D->getMaxAlignment())
|
||||
UpdateAlignment(MaxAlign);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1287,8 +1287,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
|
|||
|
||||
if (FieldPacked || !Context.Target.useBitFieldTypeAlignment())
|
||||
FieldAlign = 1;
|
||||
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
|
||||
FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
|
||||
FieldAlign = std::max(FieldAlign, D->getMaxAlignment());
|
||||
|
||||
// The maximum field alignment overrides the aligned attribute.
|
||||
if (MaxFieldAlignment)
|
||||
|
@ -1357,8 +1356,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
|
|||
|
||||
if (FieldPacked)
|
||||
FieldAlign = 8;
|
||||
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
|
||||
FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
|
||||
FieldAlign = std::max(FieldAlign, D->getMaxAlignment());
|
||||
|
||||
// The maximum field alignment overrides the aligned attribute.
|
||||
if (MaxFieldAlignment)
|
||||
|
|
|
@ -176,19 +176,23 @@ bool MallocChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
|
|||
// There can be multiple of these attributes.
|
||||
bool rv = false;
|
||||
if (FD->hasAttrs()) {
|
||||
for (const Attr *attr = FD->getAttrs(); attr; attr = attr->getNext()) {
|
||||
switch (attr->getKind()) {
|
||||
case attr::OwnershipReturns:
|
||||
MallocMemReturnsAttr(C, CE, cast<OwnershipAttr>(attr));
|
||||
for (specific_attr_iterator<OwnershipAttr>
|
||||
i = FD->specific_attr_begin<OwnershipAttr>(),
|
||||
e = FD->specific_attr_end<OwnershipAttr>();
|
||||
i != e; ++i) {
|
||||
switch ((*i)->getOwnKind()) {
|
||||
case OwnershipAttr::Returns: {
|
||||
MallocMemReturnsAttr(C, CE, *i);
|
||||
rv = true;
|
||||
break;
|
||||
case attr::OwnershipTakes:
|
||||
case attr::OwnershipHolds:
|
||||
FreeMemAttr(C, CE, cast<OwnershipAttr>(attr));
|
||||
}
|
||||
case OwnershipAttr::Takes:
|
||||
case OwnershipAttr::Holds: {
|
||||
FreeMemAttr(C, CE, *i);
|
||||
rv = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Ignore non-ownership attributes.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -204,10 +208,10 @@ void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
|
|||
|
||||
void MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
|
||||
const OwnershipAttr* Att) {
|
||||
if (!Att->isModule("malloc"))
|
||||
if (Att->getModule() != "malloc")
|
||||
return;
|
||||
|
||||
const unsigned *I = Att->begin(), *E = Att->end();
|
||||
OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
|
||||
if (I != E) {
|
||||
const GRState *state =
|
||||
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,
|
||||
const OwnershipAttr* Att) {
|
||||
if (!Att->isModule("malloc"))
|
||||
if (Att->getModule() != "malloc")
|
||||
return;
|
||||
|
||||
for (const unsigned *I = Att->begin(), *E = Att->end(); I != E; ++I) {
|
||||
const GRState *state =
|
||||
FreeMemAux(C, CE, C.getState(), *I, isa<OwnershipHoldsAttr>(Att));
|
||||
if (state)
|
||||
C.addTransition(state);
|
||||
for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
|
||||
I != E; ++I) {
|
||||
const GRState *state = FreeMemAux(C, CE, C.getState(), *I,
|
||||
Att->getOwnKind() == OwnershipAttr::Holds);
|
||||
if (state)
|
||||
C.addTransition(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -150,11 +150,11 @@ CodeGenModule::getDeclVisibilityMode(const Decl *D) const {
|
|||
if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) {
|
||||
switch (attr->getVisibility()) {
|
||||
default: assert(0 && "Unknown visibility!");
|
||||
case VisibilityAttr::DefaultVisibility:
|
||||
case VisibilityAttr::Default:
|
||||
return LangOptions::Default;
|
||||
case VisibilityAttr::HiddenVisibility:
|
||||
case VisibilityAttr::Hidden:
|
||||
return LangOptions::Hidden;
|
||||
case VisibilityAttr::ProtectedVisibility:
|
||||
case VisibilityAttr::Protected:
|
||||
return LangOptions::Protected;
|
||||
}
|
||||
}
|
||||
|
@ -461,12 +461,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
|
|||
else if (Features.getStackProtectorMode() == LangOptions::SSPReq)
|
||||
F->addFnAttr(llvm::Attribute::StackProtectReq);
|
||||
|
||||
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) {
|
||||
unsigned width = Context.Target.getCharWidth();
|
||||
F->setAlignment(AA->getAlignment() / width);
|
||||
while ((AA = AA->getNext<AlignedAttr>()))
|
||||
F->setAlignment(std::max(F->getAlignment(), AA->getAlignment() / width));
|
||||
}
|
||||
unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
|
||||
if (alignment)
|
||||
F->setAlignment(alignment);
|
||||
|
||||
// C++ ABI requires 2-byte alignment for member functions.
|
||||
if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D))
|
||||
F->setAlignment(2);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "clang/Sema/Sema.h"
|
||||
#include "clang/Sema/Lookup.h"
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/Basic/TargetInfo.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.
|
||||
if (unsigned Alignment = Stack->getAlignment()) {
|
||||
if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
|
||||
RD->addAttr(::new (Context) AlignMac68kAttr());
|
||||
RD->addAttr(::new (Context) AlignMac68kAttr(SourceLocation(), Context));
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (!VisContext)
|
||||
|
@ -299,9 +303,10 @@ void Sema::AddPushedVisibilityAttribute(Decl *D) {
|
|||
return;
|
||||
|
||||
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.
|
||||
|
@ -314,33 +319,34 @@ void Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
|
|||
SourceLocation PragmaLoc) {
|
||||
if (IsPush) {
|
||||
// Compute visibility to use.
|
||||
VisibilityAttr::VisibilityTypes type;
|
||||
VisibilityAttr::VisibilityType type;
|
||||
if (VisType->isStr("default"))
|
||||
type = VisibilityAttr::DefaultVisibility;
|
||||
type = VisibilityAttr::Default;
|
||||
else if (VisType->isStr("hidden"))
|
||||
type = VisibilityAttr::HiddenVisibility;
|
||||
type = VisibilityAttr::Hidden;
|
||||
else if (VisType->isStr("internal"))
|
||||
type = VisibilityAttr::HiddenVisibility; // FIXME
|
||||
type = VisibilityAttr::Hidden; // FIXME
|
||||
else if (VisType->isStr("protected"))
|
||||
type = VisibilityAttr::ProtectedVisibility;
|
||||
type = VisibilityAttr::Protected;
|
||||
else {
|
||||
Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) <<
|
||||
VisType->getName();
|
||||
return;
|
||||
}
|
||||
PushPragmaVisibility(type);
|
||||
PushPragmaVisibility(type, PragmaLoc);
|
||||
} else {
|
||||
PopPragmaVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
void Sema::PushPragmaVisibility(VisibilityAttr::VisibilityTypes type) {
|
||||
void Sema::PushPragmaVisibility(VisibilityAttr::VisibilityType type,
|
||||
SourceLocation loc) {
|
||||
// Put visibility on stack.
|
||||
if (!VisContext)
|
||||
VisContext = new VisStack;
|
||||
|
||||
VisStack *Stack = static_cast<VisStack*>(VisContext);
|
||||
Stack->push_back(type);
|
||||
Stack->push_back(std::make_pair(type, loc));
|
||||
}
|
||||
|
||||
void Sema::PopPragmaVisibility() {
|
||||
|
|
|
@ -347,9 +347,12 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
|
|||
}
|
||||
}
|
||||
|
||||
for (const NonNullAttr *NonNull = FDecl->getAttr<NonNullAttr>(); NonNull;
|
||||
NonNull = NonNull->getNext<NonNullAttr>())
|
||||
CheckNonNullArguments(NonNull, TheCall);
|
||||
specific_attr_iterator<NonNullAttr>
|
||||
i = FDecl->specific_attr_begin<NonNullAttr>(),
|
||||
e = FDecl->specific_attr_end<NonNullAttr>();
|
||||
|
||||
for (; i != e; ++i)
|
||||
CheckNonNullArguments(*i, TheCall);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1041,7 +1044,8 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
|
|||
void
|
||||
Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
|
||||
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) {
|
||||
const Expr *ArgExpr = TheCall->getArg(*i);
|
||||
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
|
||||
/// attribute.
|
||||
static bool
|
||||
DeclHasAttr(const Decl *decl, const Attr *target) {
|
||||
for (const Attr *attr = decl->getAttrs(); attr; attr = attr->getNext())
|
||||
if (attr->getKind() == target->getKind())
|
||||
DeclHasAttr(const Decl *D, const Attr *A) {
|
||||
const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A);
|
||||
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 false;
|
||||
}
|
||||
|
||||
/// MergeAttributes - append attributes from the Old decl to the New one.
|
||||
static void MergeAttributes(Decl *New, Decl *Old, ASTContext &C) {
|
||||
for (const Attr *attr = Old->getAttrs(); attr; attr = attr->getNext()) {
|
||||
if (!DeclHasAttr(New, attr) && attr->isMerged()) {
|
||||
Attr *NewAttr = attr->clone(C);
|
||||
/// MergeDeclAttributes - append attributes from the Old decl to the New one.
|
||||
static void MergeDeclAttributes(Decl *New, Decl *Old, ASTContext &C) {
|
||||
if (!Old->hasAttrs())
|
||||
return;
|
||||
// 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);
|
||||
New->addAttr(NewAttr);
|
||||
}
|
||||
|
@ -1402,7 +1415,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
|
|||
/// \returns false
|
||||
bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
|
||||
// Merge the attributes
|
||||
MergeAttributes(New, Old, Context);
|
||||
MergeDeclAttributes(New, Old, Context);
|
||||
|
||||
// Merge the storage class.
|
||||
if (Old->getStorageClass() != FunctionDecl::Extern &&
|
||||
|
@ -1447,7 +1460,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
|||
return New->setInvalidDecl();
|
||||
}
|
||||
|
||||
MergeAttributes(New, Old, Context);
|
||||
MergeDeclAttributes(New, Old, Context);
|
||||
|
||||
// Merge the types
|
||||
QualType MergedT;
|
||||
|
@ -1611,9 +1624,7 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
|
|||
}
|
||||
|
||||
if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
|
||||
// If there are attributes in the DeclSpec, apply them to the record.
|
||||
if (const AttributeList *AL = DS.getAttributes())
|
||||
ProcessDeclAttributeList(S, Record, AL);
|
||||
ProcessDeclAttributeList(S, Record, DS.getAttributes());
|
||||
|
||||
if (!Record->getDeclName() && Record->isDefinition() &&
|
||||
DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
|
||||
|
@ -2770,7 +2781,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
if (Expr *E = (Expr*) D.getAsmLabel()) {
|
||||
// The parser guarantees this is a string.
|
||||
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.
|
||||
|
@ -2810,6 +2822,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
NewVD->setInvalidDecl();
|
||||
|
||||
// attributes declared post-definition are currently ignored
|
||||
// FIXME: This should be handled in attribute merging, not
|
||||
// here.
|
||||
if (Previous.isSingleResult()) {
|
||||
VarDecl *Def = dyn_cast<VarDecl>(Previous.getFoundDecl());
|
||||
if (Def && (Def = Def->getDefinition()) &&
|
||||
|
@ -3447,7 +3461,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
if (Expr *E = (Expr*) D.getAsmLabel()) {
|
||||
// The parser guarantees this is a string.
|
||||
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
|
||||
|
@ -3673,6 +3688,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
ProcessDeclAttributes(S, NewFD, D);
|
||||
|
||||
// attributes declared post-definition are currently ignored
|
||||
// FIXME: This should happen during attribute merging
|
||||
if (Redeclaration && Previous.isSingleResult()) {
|
||||
const FunctionDecl *Def;
|
||||
FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl());
|
||||
|
@ -3684,7 +3700,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
|
||||
AddKnownFunctionAttributes(NewFD);
|
||||
|
||||
if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>()) {
|
||||
if (OverloadableAttrRequired && !NewFD->hasAttr<OverloadableAttr>()) {
|
||||
// If a function name is overloadable in C, then every function
|
||||
// with that name must be marked "overloadable".
|
||||
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
|
||||
|
@ -3692,7 +3708,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
if (!Previous.empty())
|
||||
Diag(Previous.getRepresentativeDecl()->getLocation(),
|
||||
diag::note_attribute_overloadable_prev_overload);
|
||||
NewFD->addAttr(::new (Context) OverloadableAttr());
|
||||
NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(), Context));
|
||||
}
|
||||
|
||||
if (NewFD->hasAttr<OverloadableAttr>() &&
|
||||
|
@ -4792,10 +4808,10 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
|
|||
|
||||
// Checking attributes of current function definition
|
||||
// dllimport attribute.
|
||||
if (FD->getAttr<DLLImportAttr>() &&
|
||||
(!FD->getAttr<DLLExportAttr>())) {
|
||||
// dllimport attribute cannot be applied to definition.
|
||||
if (!(FD->getAttr<DLLImportAttr>())->isInherited()) {
|
||||
DLLImportAttr *DA = FD->getAttr<DLLImportAttr>();
|
||||
if (DA && (!FD->getAttr<DLLExportAttr>())) {
|
||||
// dllimport attribute cannot be directly applied to definition.
|
||||
if (!DA->isInherited()) {
|
||||
Diag(FD->getLocation(),
|
||||
diag::err_attribute_can_be_applied_only_to_symbol_declaration)
|
||||
<< "dllimport";
|
||||
|
@ -5041,7 +5057,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
|
|||
CurContext = Context.getTranslationUnitDecl();
|
||||
|
||||
FunctionDecl *FD =
|
||||
dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D).getAs<Decl>());
|
||||
dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D).getAs<Decl>());
|
||||
FD->setImplicit();
|
||||
|
||||
CurContext = PrevDC;
|
||||
|
@ -5069,13 +5085,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
|
|||
bool HasVAListArg;
|
||||
if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) {
|
||||
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));
|
||||
}
|
||||
if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx,
|
||||
HasVAListArg)) {
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -5085,15 +5103,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
|
|||
if (!getLangOptions().MathErrno &&
|
||||
Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) {
|
||||
if (!FD->getAttr<ConstAttr>())
|
||||
FD->addAttr(::new (Context) ConstAttr());
|
||||
FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
|
||||
}
|
||||
|
||||
if (Context.BuiltinInfo.isNoReturn(BuiltinID))
|
||||
FD->setType(Context.getNoReturnType(FD->getType()));
|
||||
if (Context.BuiltinInfo.isNoThrow(BuiltinID))
|
||||
FD->addAttr(::new (Context) NoThrowAttr());
|
||||
FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context));
|
||||
if (Context.BuiltinInfo.isConst(BuiltinID))
|
||||
FD->addAttr(::new (Context) ConstAttr());
|
||||
FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
|
||||
}
|
||||
|
||||
IdentifierInfo *Name = FD->getIdentifier();
|
||||
|
@ -5115,13 +5133,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
|
|||
// FIXME: We known better than our headers.
|
||||
const_cast<FormatAttr *>(Format)->setType(Context, "printf");
|
||||
} else
|
||||
FD->addAttr(::new (Context) FormatAttr(Context, "printf", 1,
|
||||
FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
|
||||
"printf", 1,
|
||||
Name->isStr("NSLogv") ? 0 : 2));
|
||||
} else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) {
|
||||
// FIXME: asprintf and vasprintf aren't C99 functions. Should they be
|
||||
// target-specific builtins, perhaps?
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -7009,7 +7029,7 @@ void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
|
|||
Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName);
|
||||
|
||||
if (PrevDecl) {
|
||||
PrevDecl->addAttr(::new (Context) WeakAttr());
|
||||
PrevDecl->addAttr(::new (Context) WeakAttr(PragmaLoc, Context));
|
||||
} else {
|
||||
(void)WeakUndeclaredIdentifiers.insert(
|
||||
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))
|
||||
TD->addAttr(::new (S.Context) PackedAttr);
|
||||
TD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context));
|
||||
else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
|
||||
// If the alignment is less than or equal to 8 bits, the packed attribute
|
||||
// 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)
|
||||
<< Attr.getName() << FD->getType();
|
||||
else
|
||||
FD->addAttr(::new (S.Context) PackedAttr);
|
||||
FD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context));
|
||||
} else
|
||||
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.
|
||||
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
|
||||
if (MD->isInstanceMethod()) {
|
||||
d->addAttr(::new (S.Context) IBActionAttr());
|
||||
d->addAttr(::new (S.Context) IBActionAttr(Attr.getLoc(), S.Context));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -252,7 +252,7 @@ static void HandleIBOutlet(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
// The IBOutlet attributes only apply to instance variables of
|
||||
// Objective-C classes.
|
||||
if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d)) {
|
||||
d->addAttr(::new (S.Context) IBOutletAttr());
|
||||
d->addAttr(::new (S.Context) IBOutletAttr(Attr.getLoc(), S.Context));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -307,7 +307,8 @@ static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr,
|
|||
S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
|
||||
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) {
|
||||
|
@ -378,7 +379,8 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
unsigned* start = &NonNullArgs[0];
|
||||
unsigned size = NonNullArgs.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) {
|
||||
|
@ -397,24 +399,24 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
|
|||
return;
|
||||
}
|
||||
// Figure out our Kind, and check arguments while we're at it.
|
||||
attr::Kind K;
|
||||
OwnershipAttr::OwnershipKind K;
|
||||
switch (AL.getKind()) {
|
||||
case AttributeList::AT_ownership_takes:
|
||||
K = attr::OwnershipTakes;
|
||||
K = OwnershipAttr::Takes;
|
||||
if (AL.getNumArgs() < 1) {
|
||||
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case AttributeList::AT_ownership_holds:
|
||||
K = attr::OwnershipHolds;
|
||||
K = OwnershipAttr::Holds;
|
||||
if (AL.getNumArgs() < 1) {
|
||||
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case AttributeList::AT_ownership_returns:
|
||||
K = attr::OwnershipReturns;
|
||||
K = OwnershipAttr::Returns;
|
||||
if (AL.getNumArgs() > 1) {
|
||||
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
|
||||
<< AL.getNumArgs() + 1;
|
||||
|
@ -463,21 +465,21 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
|
|||
}
|
||||
--x;
|
||||
switch (K) {
|
||||
case attr::OwnershipTakes:
|
||||
case attr::OwnershipHolds: {
|
||||
case OwnershipAttr::Takes:
|
||||
case OwnershipAttr::Holds: {
|
||||
// Is the function argument a pointer type?
|
||||
QualType T = getFunctionOrMethodArgType(d, x);
|
||||
if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
|
||||
// FIXME: Should also highlight argument in decl.
|
||||
S.Diag(AL.getLoc(), diag::err_ownership_type)
|
||||
<< ((K==attr::OwnershipTakes)?"ownership_takes":"ownership_holds")
|
||||
<< ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds")
|
||||
<< "pointer"
|
||||
<< IdxExpr->getSourceRange();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case attr::OwnershipReturns: {
|
||||
case OwnershipAttr::Returns: {
|
||||
if (AL.getNumArgs() > 1) {
|
||||
// Is the function argument an integer type?
|
||||
Expr *IdxExpr = static_cast<Expr *>(AL.getArg(0));
|
||||
|
@ -497,18 +499,16 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
|
|||
} // switch
|
||||
|
||||
// Check we don't have a conflict with another ownership attribute.
|
||||
if (K != attr::OwnershipReturns && d->hasAttrs()) {
|
||||
for (const Attr *attr = d->getAttrs(); attr; attr = attr->getNext()) {
|
||||
if (const OwnershipAttr* Att = dyn_cast<OwnershipAttr>(attr)) {
|
||||
// Two ownership attributes of the same kind can't conflict,
|
||||
// except returns attributes.
|
||||
if (Att->getKind() != K) {
|
||||
for (const unsigned *I = Att->begin(), *E = Att->end(); I!=E; ++I) {
|
||||
if (x == *I) {
|
||||
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
|
||||
<< AL.getName()->getName() << "ownership_*";
|
||||
}
|
||||
}
|
||||
for (specific_attr_iterator<OwnershipAttr>
|
||||
i = d->specific_attr_begin<OwnershipAttr>(),
|
||||
e = d->specific_attr_end<OwnershipAttr>();
|
||||
i != e; ++i) {
|
||||
if ((*i)->getOwnKind() != K) {
|
||||
for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end();
|
||||
I!=E; ++I) {
|
||||
if (x == *I) {
|
||||
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
|
||||
<< AL.getName()->getName() << "ownership_*";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -519,33 +519,14 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
|
|||
unsigned* start = OwnershipArgs.data();
|
||||
unsigned size = OwnershipArgs.size();
|
||||
llvm::array_pod_sort(start, start + size);
|
||||
switch (K) {
|
||||
case attr::OwnershipTakes: {
|
||||
if (OwnershipArgs.empty()) {
|
||||
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
|
||||
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");
|
||||
|
||||
if (K != OwnershipAttr::Returns && OwnershipArgs.empty()) {
|
||||
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
|
||||
return;
|
||||
}
|
||||
|
||||
d->addAttr(::new (S.Context) OwnershipAttr(AL.getLoc(), S.Context, K, Module,
|
||||
start, size));
|
||||
}
|
||||
|
||||
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
|
||||
// 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) {
|
||||
|
@ -647,7 +628,7 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
|
||||
// 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,
|
||||
|
@ -664,7 +645,7 @@ static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
|
|||
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) {
|
||||
|
@ -677,7 +658,7 @@ static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
|
||||
QualType RetTy = FD->getResultType();
|
||||
if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
|
||||
d->addAttr(::new (S.Context) MallocAttr());
|
||||
d->addAttr(::new (S.Context) MallocAttr(Attr.getLoc(), S.Context));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -711,13 +692,13 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
|
|||
static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||
/* Diagnostics (if any) was emitted by Sema::ProcessFnAttr(). */
|
||||
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,
|
||||
Sema &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.
|
||||
|
@ -756,7 +737,7 @@ static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr,
|
|||
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) {
|
||||
|
@ -782,7 +763,7 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -803,7 +784,7 @@ static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -833,7 +814,7 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -863,7 +844,7 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -873,7 +854,7 @@ static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -883,7 +864,7 @@ static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -904,22 +885,22 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
}
|
||||
|
||||
llvm::StringRef TypeStr = Str->getString();
|
||||
VisibilityAttr::VisibilityTypes type;
|
||||
VisibilityAttr::VisibilityType type;
|
||||
|
||||
if (TypeStr == "default")
|
||||
type = VisibilityAttr::DefaultVisibility;
|
||||
type = VisibilityAttr::Default;
|
||||
else if (TypeStr == "hidden")
|
||||
type = VisibilityAttr::HiddenVisibility;
|
||||
type = VisibilityAttr::Hidden;
|
||||
else if (TypeStr == "internal")
|
||||
type = VisibilityAttr::HiddenVisibility; // FIXME
|
||||
type = VisibilityAttr::Hidden; // FIXME
|
||||
else if (TypeStr == "protected")
|
||||
type = VisibilityAttr::ProtectedVisibility;
|
||||
type = VisibilityAttr::Protected;
|
||||
else {
|
||||
S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
|
||||
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,
|
||||
|
@ -935,7 +916,7 @@ static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
|
|||
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) {
|
||||
|
@ -951,7 +932,7 @@ static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
|
|||
return;
|
||||
}
|
||||
}
|
||||
D->addAttr(::new (S.Context) ObjCNSObjectAttr());
|
||||
D->addAttr(::new (S.Context) ObjCNSObjectAttr(Attr.getLoc(), S.Context));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -966,7 +947,7 @@ HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -981,7 +962,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
return;
|
||||
}
|
||||
|
||||
BlocksAttr::BlocksAttrTypes type;
|
||||
BlocksAttr::BlockType type;
|
||||
if (Attr.getParameterName()->isStr("byref"))
|
||||
type = BlocksAttr::ByRef;
|
||||
else {
|
||||
|
@ -990,7 +971,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -1083,7 +1064,7 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
<< Attr.getName() << 6 /*function, method or block */;
|
||||
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) {
|
||||
|
@ -1111,7 +1092,7 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S)
|
|||
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) {
|
||||
|
@ -1135,7 +1116,7 @@ static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -1171,7 +1152,7 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
|||
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,
|
||||
|
@ -1194,7 +1175,8 @@ static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
|
|||
}
|
||||
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]));
|
||||
}
|
||||
|
||||
|
@ -1228,7 +1210,7 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
|||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -1249,7 +1231,7 @@ static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -1259,7 +1241,7 @@ static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -1317,7 +1299,7 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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
|
||||
|
@ -1380,7 +1362,7 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
return;
|
||||
}
|
||||
|
||||
d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue()));
|
||||
d->addAttr(::new (S.Context) FormatArgAttr(Attr.getLoc(), S.Context, Idx.getZExtValue()));
|
||||
}
|
||||
|
||||
enum FormatAttrKind {
|
||||
|
@ -1462,7 +1444,7 @@ static void HandleInitPriorityAttr(Decl *d, const AttributeList &Attr,
|
|||
Attr.setInvalid();
|
||||
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
|
||||
|
@ -1606,7 +1588,8 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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()));
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -1693,7 +1676,7 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate";
|
||||
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) {
|
||||
|
@ -1708,9 +1691,7 @@ static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
|||
// weaker alignment, rather than being silently ignored.
|
||||
|
||||
if (Attr.getNumArgs() == 0) {
|
||||
// FIXME: This should be the target specific maximum alignment.
|
||||
// (For now we just use 128 bits which is the maximum on X86).
|
||||
D->addAttr(::new (S.Context) AlignedAttr(128));
|
||||
D->addAttr(::new (S.Context) AlignedAttr(Attr.getLoc(), S.Context, true, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1720,10 +1701,11 @@ static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
|||
void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) {
|
||||
if (E->isTypeDependent() || E->isValueDependent()) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
// FIXME: Cache the number on the Attr object?
|
||||
llvm::APSInt Alignment(32);
|
||||
if (!E->isIntegerConstantExpr(Alignment, Context)) {
|
||||
Diag(AttrLoc, diag::err_attribute_argument_not_int)
|
||||
|
@ -1736,7 +1718,14 @@ void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) {
|
|||
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
|
||||
|
@ -1923,7 +1912,7 @@ static void HandleNoDebugAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -1939,7 +1928,7 @@ static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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,
|
||||
|
@ -1956,7 +1945,7 @@ static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr,
|
|||
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) {
|
||||
|
@ -1978,7 +1967,7 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -1988,15 +1977,15 @@ static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
|
||||
switch (Attr.getKind()) {
|
||||
case AttributeList::AT_fastcall:
|
||||
d->addAttr(::new (S.Context) FastCallAttr());
|
||||
d->addAttr(::new (S.Context) FastCallAttr(Attr.getLoc(), S.Context));
|
||||
return;
|
||||
case AttributeList::AT_stdcall:
|
||||
d->addAttr(::new (S.Context) StdCallAttr());
|
||||
d->addAttr(::new (S.Context) StdCallAttr(Attr.getLoc(), S.Context));
|
||||
return;
|
||||
case AttributeList::AT_thiscall:
|
||||
d->addAttr(::new (S.Context) ThisCallAttr());
|
||||
d->addAttr(::new (S.Context) ThisCallAttr(Attr.getLoc(), S.Context));
|
||||
case AttributeList::AT_cdecl:
|
||||
d->addAttr(::new (S.Context) CDeclAttr());
|
||||
d->addAttr(::new (S.Context) CDeclAttr(Attr.getLoc(), S.Context));
|
||||
return;
|
||||
default:
|
||||
llvm_unreachable("unexpected attribute kind");
|
||||
|
@ -2038,7 +2027,8 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -2064,7 +2054,7 @@ static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -2115,7 +2105,7 @@ static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -2140,7 +2130,7 @@ static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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");
|
||||
return;
|
||||
case AttributeList::AT_cf_returns_not_retained:
|
||||
d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr());
|
||||
d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(Attr.getLoc(), S.Context));
|
||||
return;
|
||||
case AttributeList::AT_ns_returns_not_retained:
|
||||
d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr());
|
||||
d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(Attr.getLoc(), S.Context));
|
||||
return;
|
||||
case AttributeList::AT_cf_returns_retained:
|
||||
d->addAttr(::new (S.Context) CFReturnsRetainedAttr());
|
||||
d->addAttr(::new (S.Context) CFReturnsRetainedAttr(Attr.getLoc(), S.Context));
|
||||
return;
|
||||
case AttributeList::AT_ns_returns_retained:
|
||||
d->addAttr(::new (S.Context) NSReturnsRetainedAttr());
|
||||
d->addAttr(::new (S.Context) NSReturnsRetainedAttr(Attr.getLoc(), S.Context));
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
@ -2369,8 +2359,9 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
|
|||
if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
|
||||
IdentifierInfo *NDId = ND->getIdentifier();
|
||||
NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias());
|
||||
NewD->addAttr(::new (Context) AliasAttr(Context, NDId->getName()));
|
||||
NewD->addAttr(::new (Context) WeakAttr());
|
||||
NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context,
|
||||
NDId->getName()));
|
||||
NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
|
||||
WeakTopLevelDecl.push_back(NewD);
|
||||
// FIXME: "hideous" code from Sema::LazilyCreateBuiltin
|
||||
// to insert Decl at TU scope, sorry.
|
||||
|
@ -2379,7 +2370,7 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
|
|||
PushOnScopeChains(NewD, S);
|
||||
CurContext = SavedContext;
|
||||
} 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);
|
||||
|
||||
if (const VisibilityAttr *attr = Namespc->getAttr<VisibilityAttr>())
|
||||
PushPragmaVisibility(attr->getVisibility());
|
||||
PushPragmaVisibility(attr->getVisibility(), attr->getLocation());
|
||||
|
||||
if (II) {
|
||||
// C++ [namespace.def]p2:
|
||||
|
|
|
@ -1454,13 +1454,14 @@ CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {
|
|||
}
|
||||
|
||||
static inline
|
||||
bool containsInvalidMethodImplAttribute(const AttributeList *A) {
|
||||
bool containsInvalidMethodImplAttribute(const AttrVec &A) {
|
||||
// The 'ibaction' attribute is allowed on method definitions because of
|
||||
// how the IBAction macro is used on both method declarations and definitions.
|
||||
// If the method definitions contains any other attributes, return true.
|
||||
while (A && A->getKind() == AttributeList::AT_IBAction)
|
||||
A = A->getNext();
|
||||
return A != NULL;
|
||||
for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i)
|
||||
if ((*i)->getKind() != attr::IBAction)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
|
||||
|
@ -1590,7 +1591,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
|
|||
}
|
||||
InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel,
|
||||
MethodType == tok::minus);
|
||||
if (containsInvalidMethodImplAttribute(AttrList))
|
||||
if (ObjCMethod->hasAttrs() &&
|
||||
containsInvalidMethodImplAttribute(ObjCMethod->getAttrs()))
|
||||
Diag(EndLoc, diag::warn_attribute_method_def);
|
||||
} else if (ObjCCategoryImplDecl *CatImpDecl =
|
||||
dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {
|
||||
|
@ -1601,7 +1603,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
|
|||
PrevMethod = CatImpDecl->getClassMethod(Sel);
|
||||
CatImpDecl->addClassMethod(ObjCMethod);
|
||||
}
|
||||
if (containsInvalidMethodImplAttribute(AttrList))
|
||||
if (ObjCMethod->hasAttrs() &&
|
||||
containsInvalidMethodImplAttribute(ObjCMethod->getAttrs()))
|
||||
Diag(EndLoc, diag::warn_attribute_method_def);
|
||||
}
|
||||
if (PrevMethod) {
|
||||
|
@ -1613,8 +1616,10 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
|
|||
|
||||
// If the interface declared this method, and it was deprecated there,
|
||||
// mark it deprecated here.
|
||||
if (InterfaceMD && InterfaceMD->hasAttr<DeprecatedAttr>())
|
||||
ObjCMethod->addAttr(::new (Context) DeprecatedAttr());
|
||||
if (InterfaceMD)
|
||||
if (Attr *DA = InterfaceMD->getAttr<DeprecatedAttr>())
|
||||
ObjCMethod->addAttr(::new (Context) DeprecatedAttr(DA->getLocation(),
|
||||
Context));
|
||||
|
||||
return DeclPtrTy::make(ObjCMethod);
|
||||
}
|
||||
|
|
|
@ -1259,7 +1259,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
|
|||
// FIXME: Do we need to check for default arguments here?
|
||||
if (Func->getNumParams() == 1 && InitialParamType == Argument) {
|
||||
if(AddMallocAttr && !Func->hasAttr<MallocAttr>())
|
||||
Func->addAttr(::new (Context) MallocAttr());
|
||||
Func->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1287,7 +1287,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
|
|||
Alloc->setImplicit();
|
||||
|
||||
if (AddMallocAttr)
|
||||
Alloc->addAttr(::new (Context) MallocAttr());
|
||||
Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
|
||||
|
||||
ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
|
||||
0, Argument, /*TInfo=*/0,
|
||||
|
|
|
@ -4031,7 +4031,7 @@ Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
|
|||
/// \brief Strips various properties off an implicit instantiation
|
||||
/// that has just been explicitly specialized.
|
||||
static void StripImplicitInstantiation(NamedDecl *D) {
|
||||
D->invalidateAttrs();
|
||||
D->dropAttrs();
|
||||
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
FD->setInlineSpecified(false);
|
||||
|
|
|
@ -140,21 +140,30 @@ bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
|
|||
// FIXME: Is this still too simple?
|
||||
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||
Decl *Tmpl, Decl *New) {
|
||||
for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr;
|
||||
TmplAttr = TmplAttr->getNext()) {
|
||||
for (AttrVec::const_iterator i = Tmpl->attr_begin(), e = Tmpl->attr_end();
|
||||
i != e; ++i) {
|
||||
const Attr *TmplAttr = *i;
|
||||
// FIXME: This should be generalized to more than just the AlignedAttr.
|
||||
if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) {
|
||||
if (Aligned->isDependent()) {
|
||||
if (Aligned->isAlignmentDependent()) {
|
||||
// The alignment expression is not potentially evaluated.
|
||||
EnterExpressionEvaluationContext Unevaluated(*this,
|
||||
Action::Unevaluated);
|
||||
|
||||
OwningExprResult Result = SubstExpr(Aligned->getAlignmentExpr(),
|
||||
TemplateArgs);
|
||||
if (!Result.isInvalid())
|
||||
// FIXME: Is this the correct source location?
|
||||
AddAlignedAttr(Aligned->getAlignmentExpr()->getExprLoc(),
|
||||
New, Result.takeAs<Expr>());
|
||||
if (Aligned->isAlignmentExpr()) {
|
||||
OwningExprResult Result = SubstExpr(Aligned->getAlignmentExpr(),
|
||||
TemplateArgs);
|
||||
if (!Result.isInvalid())
|
||||
AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>());
|
||||
}
|
||||
else {
|
||||
TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(),
|
||||
TemplateArgs,
|
||||
Aligned->getLocation(),
|
||||
DeclarationName());
|
||||
if (Result)
|
||||
AddAlignedAttr(Aligned->getLocation(), New, Result);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,8 +51,8 @@ static void HandleMSP430InterruptAttr(Decl *d,
|
|||
return;
|
||||
}
|
||||
|
||||
d->addAttr(::new (S.Context) MSP430InterruptAttr(Num));
|
||||
d->addAttr(::new (S.Context) UsedAttr());
|
||||
d->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num));
|
||||
d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -97,7 +97,7 @@ static void HandleX86ForceAlignArgPointerAttr(Decl *D,
|
|||
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) {
|
||||
|
@ -109,7 +109,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
|||
|
||||
// Attribute can be applied only to functions or variables.
|
||||
if (isa<VarDecl>(D)) {
|
||||
D->addAttr(::new (S.Context) DLLImportAttr());
|
||||
D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
|||
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) {
|
||||
|
@ -158,7 +158,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
|||
|
||||
// Attribute can be applied only to functions or variables.
|
||||
if (isa<VarDecl>(D)) {
|
||||
D->addAttr(::new (S.Context) DLLExportAttr());
|
||||
D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -177,7 +177,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
|||
return;
|
||||
}
|
||||
|
||||
D->addAttr(::new (S.Context) DLLExportAttr());
|
||||
D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
|
|
@ -13,6 +13,8 @@ add_clang_library(clangSerialization
|
|||
add_dependencies(clangSerialization
|
||||
ClangAttrClasses
|
||||
ClangAttrList
|
||||
ClangAttrPCHRead
|
||||
ClangAttrPCHWrite
|
||||
ClangDiagnosticFrontend
|
||||
ClangDiagnosticLex
|
||||
ClangDiagnosticSema
|
||||
|
|
|
@ -148,8 +148,11 @@ void PCHDeclReader::VisitDecl(Decl *D) {
|
|||
cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
|
||||
D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
D->setInvalidDecl(Record[Idx++]);
|
||||
if (Record[Idx++])
|
||||
D->initAttrs(Reader.ReadAttributes(Cursor));
|
||||
if (Record[Idx++]) {
|
||||
AttrVec Attrs;
|
||||
Reader.ReadAttributes(Cursor, Attrs);
|
||||
D->setAttrs(Attrs);
|
||||
}
|
||||
D->setImplicit(Record[Idx++]);
|
||||
D->setUsed(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.
|
||||
Attr *PCHReader::ReadAttributes(llvm::BitstreamCursor &DeclsCursor) {
|
||||
void PCHReader::ReadAttributes(llvm::BitstreamCursor &DeclsCursor,
|
||||
AttrVec &Attrs) {
|
||||
unsigned Code = DeclsCursor.ReadCode();
|
||||
assert(Code == llvm::bitc::UNABBREV_RECORD &&
|
||||
"Expected unabbreviated record"); (void)Code;
|
||||
|
@ -1102,174 +1106,18 @@ Attr *PCHReader::ReadAttributes(llvm::BitstreamCursor &DeclsCursor) {
|
|||
assert(RecCode == pch::DECL_ATTR && "Expected attribute record");
|
||||
(void)RecCode;
|
||||
|
||||
#define SIMPLE_ATTR(Name) \
|
||||
case attr::Name: \
|
||||
New = ::new (*Context) Name##Attr(); \
|
||||
break
|
||||
|
||||
#define STRING_ATTR(Name) \
|
||||
case attr::Name: \
|
||||
New = ::new (*Context) Name##Attr(*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()) {
|
||||
Attr *New = 0;
|
||||
attr::Kind Kind = (attr::Kind)Record[Idx++];
|
||||
bool IsInherited = Record[Idx++];
|
||||
SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[Idx++]);
|
||||
bool isInherited = Record[Idx++];
|
||||
|
||||
switch (Kind) {
|
||||
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);
|
||||
}
|
||||
#include "clang/Serialization/AttrPCHRead.inc"
|
||||
|
||||
assert(New && "Unable to decode attribute?");
|
||||
New->setInherited(IsInherited);
|
||||
New->setNext(Attrs);
|
||||
Attrs = New;
|
||||
New->setInherited(isInherited);
|
||||
Attrs.push_back(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.
|
||||
void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
|
||||
void PCHWriter::WriteAttributeRecord(const AttrVec &Attrs) {
|
||||
RecordData Record;
|
||||
for (; Attr; Attr = Attr->getNext()) {
|
||||
Record.push_back(Attr->getKind()); // FIXME: stable encoding, target attrs
|
||||
Record.push_back(Attr->isInherited());
|
||||
switch (Attr->getKind()) {
|
||||
default:
|
||||
assert(0 && "Does not support PCH writing for this attribute yet!");
|
||||
break;
|
||||
case attr::Alias:
|
||||
AddString(cast<AliasAttr>(Attr)->getAliasee(), Record);
|
||||
break;
|
||||
for (AttrVec::const_iterator i = Attrs.begin(), e = Attrs.end(); i != e; ++i){
|
||||
const Attr * A = *i;
|
||||
Record.push_back(A->getKind()); // FIXME: stable encoding, target attrs
|
||||
AddSourceLocation(A->getLocation(), Record);
|
||||
Record.push_back(A->isInherited());
|
||||
|
||||
case attr::AlignMac68k:
|
||||
break;
|
||||
#include "clang/Serialization/AttrPCHWrite.inc"
|
||||
|
||||
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);
|
||||
|
|
|
@ -1144,8 +1144,9 @@ bool CursorVisitor::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
|
|||
|
||||
|
||||
bool CursorVisitor::VisitAttributes(Decl *D) {
|
||||
for (const Attr *A = D->getAttrs(); A; A = A->getNext())
|
||||
if (Visit(MakeCXCursor(A, D, TU)))
|
||||
for (AttrVec::const_iterator i = D->attr_begin(), e = D->attr_end();
|
||||
i != e; ++i)
|
||||
if (Visit(MakeCXCursor(*i, D, TU)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
Загрузка…
Ссылка в новой задаче