зеркало из 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/LangOptions.h"
|
||||||
#include "clang/Basic/OperatorKinds.h"
|
#include "clang/Basic/OperatorKinds.h"
|
||||||
#include "clang/Basic/PartialDiagnostic.h"
|
#include "clang/Basic/PartialDiagnostic.h"
|
||||||
#include "clang/AST/Attr.h"
|
|
||||||
#include "clang/AST/Decl.h"
|
#include "clang/AST/Decl.h"
|
||||||
#include "clang/AST/NestedNameSpecifier.h"
|
#include "clang/AST/NestedNameSpecifier.h"
|
||||||
#include "clang/AST/PrettyPrinter.h"
|
#include "clang/AST/PrettyPrinter.h"
|
||||||
|
@ -199,7 +198,7 @@ class ASTContext {
|
||||||
///
|
///
|
||||||
/// Since so few decls have attrs, we keep them in a hash map instead of
|
/// Since so few decls have attrs, we keep them in a hash map instead of
|
||||||
/// wasting space in the Decl class.
|
/// wasting space in the Decl class.
|
||||||
llvm::DenseMap<const Decl*, Attr*> DeclAttrs;
|
llvm::DenseMap<const Decl*, AttrVec> DeclAttrs;
|
||||||
|
|
||||||
/// \brief Keeps track of the static data member templates from which
|
/// \brief Keeps track of the static data member templates from which
|
||||||
/// static data members of class template specializations were instantiated.
|
/// static data members of class template specializations were instantiated.
|
||||||
|
@ -322,7 +321,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Retrieve the attributes for the given declaration.
|
/// \brief Retrieve the attributes for the given declaration.
|
||||||
Attr*& getDeclAttrs(const Decl *D) { return DeclAttrs[D]; }
|
AttrVec& getDeclAttrs(const Decl *D) { return DeclAttrs[D]; }
|
||||||
|
|
||||||
/// \brief Erase the attributes corresponding to the given declaration.
|
/// \brief Erase the attributes corresponding to the given declaration.
|
||||||
void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); }
|
void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); }
|
||||||
|
|
|
@ -15,9 +15,11 @@
|
||||||
#define LLVM_CLANG_AST_ATTR_H
|
#define LLVM_CLANG_AST_ATTR_H
|
||||||
|
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "clang/Basic/AttrKinds.h"
|
#include "clang/Basic/AttrKinds.h"
|
||||||
#include "clang/AST/Type.h"
|
#include "clang/AST/Type.h"
|
||||||
|
#include "clang/Basic/SourceLocation.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -29,25 +31,33 @@ namespace clang {
|
||||||
class ObjCInterfaceDecl;
|
class ObjCInterfaceDecl;
|
||||||
class Expr;
|
class Expr;
|
||||||
class QualType;
|
class QualType;
|
||||||
|
class FunctionDecl;
|
||||||
|
class TypeSourceInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defined in ASTContext.h
|
// Defined in ASTContext.h
|
||||||
void *operator new(size_t Bytes, clang::ASTContext &C,
|
void *operator new(size_t Bytes, clang::ASTContext &C,
|
||||||
size_t Alignment = 16) throw ();
|
size_t Alignment = 16) throw ();
|
||||||
|
// FIXME: Being forced to not have a default argument here due to redeclaration
|
||||||
|
// rules on default arguments sucks
|
||||||
|
void *operator new[](size_t Bytes, clang::ASTContext &C,
|
||||||
|
size_t Alignment) throw ();
|
||||||
|
|
||||||
// It is good practice to pair new/delete operators. Also, MSVC gives many
|
// It is good practice to pair new/delete operators. Also, MSVC gives many
|
||||||
// warnings if a matching delete overload is not declared, even though the
|
// warnings if a matching delete overload is not declared, even though the
|
||||||
// throw() spec guarantees it will not be implicitly called.
|
// throw() spec guarantees it will not be implicitly called.
|
||||||
void operator delete(void *Ptr, clang::ASTContext &C, size_t)
|
void operator delete(void *Ptr, clang::ASTContext &C, size_t)
|
||||||
throw ();
|
throw ();
|
||||||
|
void operator delete[](void *Ptr, clang::ASTContext &C, size_t)
|
||||||
|
throw ();
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
/// Attr - This represents one attribute.
|
/// Attr - This represents one attribute.
|
||||||
class Attr {
|
class Attr {
|
||||||
private:
|
private:
|
||||||
Attr *Next;
|
SourceLocation Loc;
|
||||||
attr::Kind AttrKind;
|
unsigned AttrKind : 16;
|
||||||
bool Inherited : 1;
|
bool Inherited : 1;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -61,8 +71,20 @@ protected:
|
||||||
assert(0 && "Attrs cannot be released with regular 'delete'.");
|
assert(0 && "Attrs cannot be released with regular 'delete'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Forward so that the regular new and delete do not hide global ones.
|
||||||
|
void* operator new(size_t Bytes, ASTContext &C,
|
||||||
|
size_t Alignment = 16) throw() {
|
||||||
|
return ::operator new(Bytes, C, Alignment);
|
||||||
|
}
|
||||||
|
void operator delete(void *Ptr, ASTContext &C,
|
||||||
|
size_t Alignment = 16) throw() {
|
||||||
|
return ::operator delete(Ptr, C, Alignment);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Attr(attr::Kind AK) : Next(0), AttrKind(AK), Inherited(false) {}
|
Attr(attr::Kind AK, SourceLocation L)
|
||||||
|
: Loc(L), AttrKind(AK) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -70,29 +92,15 @@ public:
|
||||||
/// declarations.
|
/// declarations.
|
||||||
virtual bool isMerged() const { return true; }
|
virtual bool isMerged() const { return true; }
|
||||||
|
|
||||||
attr::Kind getKind() const { return AttrKind; }
|
attr::Kind getKind() const {
|
||||||
|
return static_cast<attr::Kind>(AttrKind);
|
||||||
Attr *getNext() { return Next; }
|
|
||||||
const Attr *getNext() const { return Next; }
|
|
||||||
void setNext(Attr *next) { Next = next; }
|
|
||||||
|
|
||||||
template<typename T> const T *getNext() const {
|
|
||||||
for (const Attr *attr = getNext(); attr; attr = attr->getNext())
|
|
||||||
if (const T *V = dyn_cast<T>(attr))
|
|
||||||
return V;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SourceLocation getLocation() const { return Loc; }
|
||||||
|
void setLocation(SourceLocation L) { Loc = L; }
|
||||||
|
|
||||||
bool isInherited() const { return Inherited; }
|
bool isInherited() const { return Inherited; }
|
||||||
void setInherited(bool value) { Inherited = value; }
|
void setInherited(bool I) { Inherited = I; }
|
||||||
|
|
||||||
void addAttr(Attr *attr) {
|
|
||||||
assert((attr != 0) && "addAttr(): attr is null");
|
|
||||||
|
|
||||||
// FIXME: This doesn't preserve the order in any way.
|
|
||||||
attr->Next = Next;
|
|
||||||
Next = attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clone this attribute.
|
// Clone this attribute.
|
||||||
virtual Attr* clone(ASTContext &C) const = 0;
|
virtual Attr* clone(ASTContext &C) const = 0;
|
||||||
|
@ -103,590 +111,111 @@ public:
|
||||||
|
|
||||||
#include "clang/AST/Attrs.inc"
|
#include "clang/AST/Attrs.inc"
|
||||||
|
|
||||||
class AttrWithString : public Attr {
|
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
|
||||||
private:
|
typedef llvm::SmallVector<Attr*, 2> AttrVec;
|
||||||
const char *Str;
|
typedef llvm::SmallVector<const Attr*, 2> ConstAttrVec;
|
||||||
unsigned StrLen;
|
|
||||||
protected:
|
|
||||||
AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s);
|
|
||||||
llvm::StringRef getString() const { return llvm::StringRef(Str, StrLen); }
|
|
||||||
void ReplaceString(ASTContext &C, llvm::StringRef newS);
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DEF_SIMPLE_ATTR(ATTR) \
|
/// DestroyAttrs - Destroy the contents of an AttrVec.
|
||||||
class ATTR##Attr : public Attr { \
|
inline void DestroyAttrs (AttrVec& V, ASTContext &C) {
|
||||||
public: \
|
|
||||||
ATTR##Attr() : Attr(attr::ATTR) {} \
|
|
||||||
virtual Attr *clone(ASTContext &C) const; \
|
|
||||||
static bool classof(const Attr *A) { return A->getKind() == attr::ATTR; } \
|
|
||||||
static bool classof(const ATTR##Attr *A) { return true; } \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_SIMPLE_ATTR(Packed);
|
/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
|
||||||
|
/// providing attributes that are of a specifc type.
|
||||||
|
template <typename SpecificAttr>
|
||||||
|
class specific_attr_iterator {
|
||||||
|
/// Current - The current, underlying iterator.
|
||||||
|
/// In order to ensure we don't dereference an invalid iterator unless
|
||||||
|
/// specifically requested, we don't necessarily advance this all the
|
||||||
|
/// way. Instead, we advance it when an operation is requested; if the
|
||||||
|
/// operation is acting on what should be a past-the-end iterator,
|
||||||
|
/// then we offer no guarantees, but this way we do not dererence a
|
||||||
|
/// past-the-end iterator when we move to a past-the-end position.
|
||||||
|
mutable AttrVec::const_iterator Current;
|
||||||
|
|
||||||
/// \brief Attribute for specifying a maximum field alignment; this is only
|
void AdvanceToNext() const {
|
||||||
/// valid on record decls.
|
while (!llvm::isa<SpecificAttr>(*Current))
|
||||||
class MaxFieldAlignmentAttr : public Attr {
|
++Current;
|
||||||
unsigned Alignment;
|
}
|
||||||
|
|
||||||
|
void AdvanceToNext(AttrVec::const_iterator I) const {
|
||||||
|
while (Current != I && !llvm::isa<SpecificAttr>(*Current))
|
||||||
|
++Current;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MaxFieldAlignmentAttr(unsigned alignment)
|
typedef SpecificAttr* value_type;
|
||||||
: Attr(attr::MaxFieldAlignment), Alignment(alignment) {}
|
typedef SpecificAttr* reference;
|
||||||
|
typedef SpecificAttr* pointer;
|
||||||
|
typedef std::forward_iterator_tag iterator_category;
|
||||||
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
|
||||||
/// getAlignment - The specified alignment in bits.
|
specific_attr_iterator() : Current() { }
|
||||||
unsigned getAlignment() const { return Alignment; }
|
explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
|
||||||
|
|
||||||
virtual Attr* clone(ASTContext &C) const;
|
reference operator*() const {
|
||||||
|
AdvanceToNext();
|
||||||
// Implement isa/cast/dyncast/etc.
|
return llvm::cast<SpecificAttr>(*Current);
|
||||||
static bool classof(const Attr *A) {
|
|
||||||
return A->getKind() == attr::MaxFieldAlignment;
|
|
||||||
}
|
}
|
||||||
static bool classof(const MaxFieldAlignmentAttr *A) { return true; }
|
pointer operator->() const {
|
||||||
};
|
AdvanceToNext();
|
||||||
|
return llvm::cast<SpecificAttr>(*Current);
|
||||||
DEF_SIMPLE_ATTR(AlignMac68k);
|
|
||||||
|
|
||||||
/// \brief Atribute for specifying the alignment of a variable or type.
|
|
||||||
///
|
|
||||||
/// This node will either contain the precise Alignment (in bits, not bytes!)
|
|
||||||
/// or will contain the expression for the alignment attribute in the case of
|
|
||||||
/// a dependent expression within a class or function template. At template
|
|
||||||
/// instantiation time these are transformed into concrete attributes.
|
|
||||||
class AlignedAttr : public Attr {
|
|
||||||
unsigned Alignment;
|
|
||||||
Expr *AlignmentExpr;
|
|
||||||
public:
|
|
||||||
AlignedAttr(unsigned alignment)
|
|
||||||
: Attr(attr::Aligned), Alignment(alignment), AlignmentExpr(0) {}
|
|
||||||
AlignedAttr(Expr *E)
|
|
||||||
: Attr(attr::Aligned), Alignment(0), AlignmentExpr(E) {}
|
|
||||||
|
|
||||||
/// getAlignmentExpr - Get a dependent alignment expression if one is present.
|
|
||||||
Expr *getAlignmentExpr() const {
|
|
||||||
return AlignmentExpr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isDependent - Is the alignment a dependent expression
|
specific_attr_iterator& operator++() {
|
||||||
bool isDependent() const {
|
++Current;
|
||||||
return getAlignmentExpr();
|
return *this;
|
||||||
|
}
|
||||||
|
specific_attr_iterator operator++(int) {
|
||||||
|
specific_attr_iterator Tmp(*this);
|
||||||
|
++(*this);
|
||||||
|
return Tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getAlignment - The specified alignment in bits. Requires !isDependent().
|
friend bool operator==(specific_attr_iterator Left,
|
||||||
unsigned getAlignment() const {
|
specific_attr_iterator Right) {
|
||||||
assert(!isDependent() && "Cannot get a value dependent alignment");
|
if (Left.Current < Right.Current)
|
||||||
return Alignment;
|
Left.AdvanceToNext(Right.Current);
|
||||||
}
|
|
||||||
|
|
||||||
/// getMaxAlignment - Get the maximum alignment of attributes on this list.
|
|
||||||
unsigned getMaxAlignment() const {
|
|
||||||
const AlignedAttr *Next = getNext<AlignedAttr>();
|
|
||||||
if (Next)
|
|
||||||
return std::max(Next->getMaxAlignment(), getAlignment());
|
|
||||||
else
|
else
|
||||||
return getAlignment();
|
Right.AdvanceToNext(Left.Current);
|
||||||
|
return Left.Current == Right.Current;
|
||||||
}
|
}
|
||||||
|
friend bool operator!=(specific_attr_iterator Left,
|
||||||
virtual Attr* clone(ASTContext &C) const;
|
specific_attr_iterator Right) {
|
||||||
|
return !(Left == Right);
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A) {
|
|
||||||
return A->getKind() == attr::Aligned;
|
|
||||||
}
|
|
||||||
static bool classof(const AlignedAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class AnnotateAttr : public AttrWithString {
|
|
||||||
public:
|
|
||||||
AnnotateAttr(ASTContext &C, llvm::StringRef ann)
|
|
||||||
: AttrWithString(attr::Annotate, C, ann) {}
|
|
||||||
|
|
||||||
llvm::StringRef getAnnotation() const { return getString(); }
|
|
||||||
|
|
||||||
virtual Attr* clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A) {
|
|
||||||
return A->getKind() == attr::Annotate;
|
|
||||||
}
|
|
||||||
static bool classof(const AnnotateAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class AsmLabelAttr : public AttrWithString {
|
|
||||||
public:
|
|
||||||
AsmLabelAttr(ASTContext &C, llvm::StringRef L)
|
|
||||||
: AttrWithString(attr::AsmLabel, C, L) {}
|
|
||||||
|
|
||||||
llvm::StringRef getLabel() const { return getString(); }
|
|
||||||
|
|
||||||
virtual Attr* clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A) {
|
|
||||||
return A->getKind() == attr::AsmLabel;
|
|
||||||
}
|
|
||||||
static bool classof(const AsmLabelAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
DEF_SIMPLE_ATTR(AlwaysInline);
|
|
||||||
|
|
||||||
class AliasAttr : public AttrWithString {
|
|
||||||
public:
|
|
||||||
AliasAttr(ASTContext &C, llvm::StringRef aliasee)
|
|
||||||
: AttrWithString(attr::Alias, C, aliasee) {}
|
|
||||||
|
|
||||||
llvm::StringRef getAliasee() const { return getString(); }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A) { return A->getKind() == attr::Alias; }
|
|
||||||
static bool classof(const AliasAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class ConstructorAttr : public Attr {
|
|
||||||
int priority;
|
|
||||||
public:
|
|
||||||
ConstructorAttr(int p) : Attr(attr::Constructor), priority(p) {}
|
|
||||||
|
|
||||||
int getPriority() const { return priority; }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A)
|
|
||||||
{ return A->getKind() == attr::Constructor; }
|
|
||||||
static bool classof(const ConstructorAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class DestructorAttr : public Attr {
|
|
||||||
int priority;
|
|
||||||
public:
|
|
||||||
DestructorAttr(int p) : Attr(attr::Destructor), priority(p) {}
|
|
||||||
|
|
||||||
int getPriority() const { return priority; }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A)
|
|
||||||
{ return A->getKind() == attr::Destructor; }
|
|
||||||
static bool classof(const DestructorAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class IBOutletAttr : public Attr {
|
|
||||||
public:
|
|
||||||
IBOutletAttr() : Attr(attr::IBOutlet) {}
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A) {
|
|
||||||
return A->getKind() == attr::IBOutlet;
|
|
||||||
}
|
|
||||||
static bool classof(const IBOutletAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class IBOutletCollectionAttr : public Attr {
|
|
||||||
QualType QT;
|
|
||||||
public:
|
|
||||||
IBOutletCollectionAttr(QualType qt = QualType())
|
|
||||||
: Attr(attr::IBOutletCollection), QT(qt) {}
|
|
||||||
|
|
||||||
QualType getType() const { return QT; }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A) {
|
|
||||||
return A->getKind() == attr::IBOutletCollection;
|
|
||||||
}
|
|
||||||
static bool classof(const IBOutletCollectionAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class IBActionAttr : public Attr {
|
|
||||||
public:
|
|
||||||
IBActionAttr() : Attr(attr::IBAction) {}
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A) {
|
|
||||||
return A->getKind() == attr::IBAction;
|
|
||||||
}
|
|
||||||
static bool classof(const IBActionAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
DEF_SIMPLE_ATTR(AnalyzerNoReturn);
|
|
||||||
DEF_SIMPLE_ATTR(Deprecated);
|
|
||||||
DEF_SIMPLE_ATTR(GNUInline);
|
|
||||||
DEF_SIMPLE_ATTR(Malloc);
|
|
||||||
DEF_SIMPLE_ATTR(NoReturn);
|
|
||||||
DEF_SIMPLE_ATTR(NoInstrumentFunction);
|
|
||||||
|
|
||||||
class SectionAttr : public AttrWithString {
|
|
||||||
public:
|
|
||||||
SectionAttr(ASTContext &C, llvm::StringRef N)
|
|
||||||
: AttrWithString(attr::Section, C, N) {}
|
|
||||||
|
|
||||||
llvm::StringRef getName() const { return getString(); }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A) {
|
|
||||||
return A->getKind() == attr::Section;
|
|
||||||
}
|
|
||||||
static bool classof(const SectionAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
DEF_SIMPLE_ATTR(Unavailable);
|
|
||||||
DEF_SIMPLE_ATTR(Unused);
|
|
||||||
DEF_SIMPLE_ATTR(Used);
|
|
||||||
DEF_SIMPLE_ATTR(Weak);
|
|
||||||
DEF_SIMPLE_ATTR(WeakImport);
|
|
||||||
DEF_SIMPLE_ATTR(WeakRef);
|
|
||||||
DEF_SIMPLE_ATTR(NoThrow);
|
|
||||||
DEF_SIMPLE_ATTR(Const);
|
|
||||||
DEF_SIMPLE_ATTR(Pure);
|
|
||||||
|
|
||||||
class NonNullAttr : public Attr {
|
|
||||||
unsigned* ArgNums;
|
|
||||||
unsigned Size;
|
|
||||||
public:
|
|
||||||
NonNullAttr(ASTContext &C, unsigned* arg_nums = 0, unsigned size = 0);
|
|
||||||
|
|
||||||
typedef const unsigned *iterator;
|
|
||||||
iterator begin() const { return ArgNums; }
|
|
||||||
iterator end() const { return ArgNums + Size; }
|
|
||||||
unsigned size() const { return Size; }
|
|
||||||
|
|
||||||
bool isNonNull(unsigned arg) const {
|
|
||||||
return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
static bool classof(const Attr *A) { return A->getKind() == attr::NonNull; }
|
|
||||||
static bool classof(const NonNullAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/// OwnershipAttr
|
|
||||||
/// Ownership attributes are used to annotate pointers that own a resource
|
|
||||||
/// in order for the analyzer to check correct allocation and deallocation.
|
|
||||||
/// There are three attributes, ownership_returns, ownership_holds and
|
|
||||||
/// ownership_takes, represented by subclasses of OwnershipAttr
|
|
||||||
class OwnershipAttr: public AttrWithString {
|
|
||||||
protected:
|
|
||||||
unsigned* ArgNums;
|
|
||||||
unsigned Size;
|
|
||||||
public:
|
|
||||||
attr::Kind AKind;
|
|
||||||
public:
|
|
||||||
OwnershipAttr(attr::Kind AK, ASTContext &C, unsigned* arg_nums, unsigned size,
|
|
||||||
llvm::StringRef module);
|
|
||||||
|
|
||||||
|
|
||||||
virtual void Destroy(ASTContext &C);
|
|
||||||
|
|
||||||
/// Ownership attributes have a 'module', which is the name of a kind of
|
|
||||||
/// resource that can be checked.
|
|
||||||
/// The Malloc checker uses the module 'malloc'.
|
|
||||||
llvm::StringRef getModule() const {
|
|
||||||
return getString();
|
|
||||||
}
|
|
||||||
void setModule(ASTContext &C, llvm::StringRef module) {
|
|
||||||
ReplaceString(C, module);
|
|
||||||
}
|
|
||||||
bool isModule(const char *m) const {
|
|
||||||
return getModule().equals(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef const unsigned *iterator;
|
|
||||||
iterator begin() const {
|
|
||||||
return ArgNums;
|
|
||||||
}
|
|
||||||
iterator end() const {
|
|
||||||
return ArgNums + Size;
|
|
||||||
}
|
|
||||||
unsigned size() const {
|
|
||||||
return Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
static bool classof(const Attr *A) {
|
|
||||||
switch (A->getKind()) {
|
|
||||||
case attr::OwnershipTakes:
|
|
||||||
case attr::OwnershipHolds:
|
|
||||||
case attr::OwnershipReturns:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static bool classof(const OwnershipAttr *A) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class OwnershipTakesAttr: public OwnershipAttr {
|
template <typename T>
|
||||||
public:
|
inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) {
|
||||||
OwnershipTakesAttr(ASTContext &C, unsigned* arg_nums, unsigned size,
|
return specific_attr_iterator<T>(vec.begin());
|
||||||
llvm::StringRef module);
|
}
|
||||||
|
template <typename T>
|
||||||
|
inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) {
|
||||||
|
return specific_attr_iterator<T>(vec.end());
|
||||||
|
}
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
template <typename T>
|
||||||
|
inline bool hasSpecificAttr(const AttrVec& vec) {
|
||||||
|
return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
inline T *getSpecificAttr(const AttrVec& vec) {
|
||||||
|
specific_attr_iterator<T> i = specific_attr_begin<T>(vec);
|
||||||
|
if (i != specific_attr_end<T>(vec))
|
||||||
|
return *i;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static bool classof(const Attr *A) {
|
/// getMaxAlignment - Returns the highest alignment value found among
|
||||||
return A->getKind() == attr::OwnershipTakes;
|
/// AlignedAttrs in an AttrVec, or 0 if there are none.
|
||||||
}
|
inline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) {
|
||||||
static bool classof(const OwnershipTakesAttr *A) {
|
unsigned Align = 0;
|
||||||
return true;
|
specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end());
|
||||||
}
|
for(; i != e; ++i)
|
||||||
};
|
Align = std::max(Align, i->getAlignment(Ctx));
|
||||||
|
return Align;
|
||||||
class OwnershipHoldsAttr: public OwnershipAttr {
|
}
|
||||||
public:
|
|
||||||
OwnershipHoldsAttr(ASTContext &C, unsigned* arg_nums, unsigned size,
|
|
||||||
llvm::StringRef module);
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
static bool classof(const Attr *A) {
|
|
||||||
return A->getKind() == attr::OwnershipHolds;
|
|
||||||
}
|
|
||||||
static bool classof(const OwnershipHoldsAttr *A) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class OwnershipReturnsAttr: public OwnershipAttr {
|
|
||||||
public:
|
|
||||||
OwnershipReturnsAttr(ASTContext &C, unsigned* arg_nums, unsigned size,
|
|
||||||
llvm::StringRef module);
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
static bool classof(const Attr *A) {
|
|
||||||
return A->getKind() == attr::OwnershipReturns;
|
|
||||||
}
|
|
||||||
static bool classof(const OwnershipReturnsAttr *A) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class FormatAttr : public AttrWithString {
|
|
||||||
int formatIdx, firstArg;
|
|
||||||
public:
|
|
||||||
FormatAttr(ASTContext &C, llvm::StringRef type, int idx, int first)
|
|
||||||
: AttrWithString(attr::Format, C, type), formatIdx(idx), firstArg(first) {}
|
|
||||||
|
|
||||||
llvm::StringRef getType() const { return getString(); }
|
|
||||||
void setType(ASTContext &C, llvm::StringRef type);
|
|
||||||
int getFormatIdx() const { return formatIdx; }
|
|
||||||
int getFirstArg() const { return firstArg; }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A) { return A->getKind() == attr::Format; }
|
|
||||||
static bool classof(const FormatAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class FormatArgAttr : public Attr {
|
|
||||||
int formatIdx;
|
|
||||||
public:
|
|
||||||
FormatArgAttr(int idx) : Attr(attr::FormatArg), formatIdx(idx) {}
|
|
||||||
int getFormatIdx() const { return formatIdx; }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A) { return A->getKind() == attr::FormatArg; }
|
|
||||||
static bool classof(const FormatArgAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class SentinelAttr : public Attr {
|
|
||||||
int sentinel, NullPos;
|
|
||||||
public:
|
|
||||||
SentinelAttr(int sentinel_val, int nullPos) : Attr(attr::Sentinel),
|
|
||||||
sentinel(sentinel_val), NullPos(nullPos) {}
|
|
||||||
int getSentinel() const { return sentinel; }
|
|
||||||
int getNullPos() const { return NullPos; }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A) { return A->getKind() == attr::Sentinel; }
|
|
||||||
static bool classof(const SentinelAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class VisibilityAttr : public Attr {
|
|
||||||
public:
|
|
||||||
/// @brief An enumeration for the kinds of visibility of symbols.
|
|
||||||
enum VisibilityTypes {
|
|
||||||
DefaultVisibility = 0,
|
|
||||||
HiddenVisibility,
|
|
||||||
ProtectedVisibility
|
|
||||||
};
|
|
||||||
private:
|
|
||||||
VisibilityTypes VisibilityType;
|
|
||||||
bool FromPragma;
|
|
||||||
public:
|
|
||||||
VisibilityAttr(VisibilityTypes v, bool fp) : Attr(attr::Visibility),
|
|
||||||
VisibilityType(v), FromPragma(fp) {}
|
|
||||||
|
|
||||||
VisibilityTypes getVisibility() const { return VisibilityType; }
|
|
||||||
|
|
||||||
bool isFromPragma() const { return FromPragma; }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A)
|
|
||||||
{ return A->getKind() == attr::Visibility; }
|
|
||||||
static bool classof(const VisibilityAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
DEF_SIMPLE_ATTR(FastCall);
|
|
||||||
DEF_SIMPLE_ATTR(StdCall);
|
|
||||||
DEF_SIMPLE_ATTR(ThisCall);
|
|
||||||
DEF_SIMPLE_ATTR(CDecl);
|
|
||||||
DEF_SIMPLE_ATTR(TransparentUnion);
|
|
||||||
DEF_SIMPLE_ATTR(ObjCNSObject);
|
|
||||||
DEF_SIMPLE_ATTR(ObjCException);
|
|
||||||
|
|
||||||
class OverloadableAttr : public Attr {
|
|
||||||
public:
|
|
||||||
OverloadableAttr() : Attr(attr::Overloadable) { }
|
|
||||||
|
|
||||||
virtual bool isMerged() const { return false; }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
static bool classof(const Attr *A)
|
|
||||||
{ return A->getKind() == attr::Overloadable; }
|
|
||||||
static bool classof(const OverloadableAttr *) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class BlocksAttr : public Attr {
|
|
||||||
public:
|
|
||||||
enum BlocksAttrTypes {
|
|
||||||
ByRef = 0
|
|
||||||
};
|
|
||||||
private:
|
|
||||||
BlocksAttrTypes BlocksAttrType;
|
|
||||||
public:
|
|
||||||
BlocksAttr(BlocksAttrTypes t) : Attr(attr::Blocks), BlocksAttrType(t) {}
|
|
||||||
|
|
||||||
BlocksAttrTypes getType() const { return BlocksAttrType; }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A) { return A->getKind() == attr::Blocks; }
|
|
||||||
static bool classof(const BlocksAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class FunctionDecl;
|
|
||||||
|
|
||||||
class CleanupAttr : public Attr {
|
|
||||||
FunctionDecl *FD;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CleanupAttr(FunctionDecl *fd) : Attr(attr::Cleanup), FD(fd) {}
|
|
||||||
|
|
||||||
const FunctionDecl *getFunctionDecl() const { return FD; }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A) { return A->getKind() == attr::Cleanup; }
|
|
||||||
static bool classof(const CleanupAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
DEF_SIMPLE_ATTR(NoDebug);
|
|
||||||
DEF_SIMPLE_ATTR(WarnUnusedResult);
|
|
||||||
DEF_SIMPLE_ATTR(NoInline);
|
|
||||||
|
|
||||||
class RegparmAttr : public Attr {
|
|
||||||
unsigned NumParams;
|
|
||||||
|
|
||||||
public:
|
|
||||||
RegparmAttr(unsigned np) : Attr(attr::Regparm), NumParams(np) {}
|
|
||||||
|
|
||||||
unsigned getNumParams() const { return NumParams; }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A) { return A->getKind() == attr::Regparm; }
|
|
||||||
static bool classof(const RegparmAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class ReqdWorkGroupSizeAttr : public Attr {
|
|
||||||
unsigned X, Y, Z;
|
|
||||||
public:
|
|
||||||
ReqdWorkGroupSizeAttr(unsigned X, unsigned Y, unsigned Z)
|
|
||||||
: Attr(attr::ReqdWorkGroupSize), X(X), Y(Y), Z(Z) {}
|
|
||||||
|
|
||||||
unsigned getXDim() const { return X; }
|
|
||||||
unsigned getYDim() const { return Y; }
|
|
||||||
unsigned getZDim() const { return Z; }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A) {
|
|
||||||
return A->getKind() == attr::ReqdWorkGroupSize;
|
|
||||||
}
|
|
||||||
static bool classof(const ReqdWorkGroupSizeAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class InitPriorityAttr : public Attr {
|
|
||||||
unsigned Priority;
|
|
||||||
public:
|
|
||||||
InitPriorityAttr(unsigned priority)
|
|
||||||
: Attr(attr::InitPriority), Priority(priority) {}
|
|
||||||
|
|
||||||
unsigned getPriority() const { return Priority; }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
static bool classof(const Attr *A)
|
|
||||||
{ return A->getKind() == attr::InitPriority; }
|
|
||||||
static bool classof(const InitPriorityAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Checker-specific attributes.
|
|
||||||
DEF_SIMPLE_ATTR(CFReturnsNotRetained);
|
|
||||||
DEF_SIMPLE_ATTR(CFReturnsRetained);
|
|
||||||
DEF_SIMPLE_ATTR(NSReturnsNotRetained);
|
|
||||||
DEF_SIMPLE_ATTR(NSReturnsRetained);
|
|
||||||
|
|
||||||
// Target-specific attributes
|
|
||||||
DEF_SIMPLE_ATTR(DLLImport);
|
|
||||||
DEF_SIMPLE_ATTR(DLLExport);
|
|
||||||
|
|
||||||
class MSP430InterruptAttr : public Attr {
|
|
||||||
unsigned Number;
|
|
||||||
|
|
||||||
public:
|
|
||||||
MSP430InterruptAttr(unsigned n) : Attr(attr::MSP430Interrupt), Number(n) {}
|
|
||||||
|
|
||||||
unsigned getNumber() const { return Number; }
|
|
||||||
|
|
||||||
virtual Attr *clone(ASTContext &C) const;
|
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
|
||||||
static bool classof(const Attr *A)
|
|
||||||
{ return A->getKind() == attr::MSP430Interrupt; }
|
|
||||||
static bool classof(const MSP430InterruptAttr *A) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
DEF_SIMPLE_ATTR(X86ForceAlignArgPointer);
|
|
||||||
|
|
||||||
#undef DEF_SIMPLE_ATTR
|
|
||||||
|
|
||||||
} // end namespace clang
|
} // end namespace clang
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,12 @@ tablegen(Attrs.inc
|
||||||
add_custom_target(ClangAttrClasses
|
add_custom_target(ClangAttrClasses
|
||||||
DEPENDS Attrs.inc)
|
DEPENDS Attrs.inc)
|
||||||
|
|
||||||
|
tablegen(AttrImpl.inc
|
||||||
|
-gen-clang-attr-impl
|
||||||
|
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
|
||||||
|
add_custom_target(ClangAttrImpl
|
||||||
|
DEPENDS AttrImpl.inc)
|
||||||
|
|
||||||
set(LLVM_TARGET_DEFINITIONS ../Basic/StmtNodes.td)
|
set(LLVM_TARGET_DEFINITIONS ../Basic/StmtNodes.td)
|
||||||
tablegen(StmtNodes.inc
|
tablegen(StmtNodes.inc
|
||||||
-gen-clang-stmt-nodes)
|
-gen-clang-stmt-nodes)
|
||||||
|
|
|
@ -308,24 +308,52 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasAttrs() const { return HasAttrs; }
|
bool hasAttrs() const { return HasAttrs; }
|
||||||
void initAttrs(Attr *attrs);
|
void setAttrs(const AttrVec& Attrs);
|
||||||
void addAttr(Attr *attr);
|
AttrVec& getAttrs() {
|
||||||
const Attr *getAttrs() const {
|
return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
|
||||||
if (!HasAttrs) return 0; // common case, no attributes.
|
|
||||||
return getAttrsImpl(); // Uncommon case, out of line hash lookup.
|
|
||||||
}
|
}
|
||||||
|
const AttrVec &getAttrs() const;
|
||||||
void swapAttrs(Decl *D);
|
void swapAttrs(Decl *D);
|
||||||
void invalidateAttrs();
|
void dropAttrs();
|
||||||
|
|
||||||
template<typename T> const T *getAttr() const {
|
void addAttr(Attr *A) {
|
||||||
for (const Attr *attr = getAttrs(); attr; attr = attr->getNext())
|
if (hasAttrs())
|
||||||
if (const T *V = dyn_cast<T>(attr))
|
getAttrs().push_back(A);
|
||||||
return V;
|
else
|
||||||
return 0;
|
setAttrs(AttrVec(1, A));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef AttrVec::const_iterator attr_iterator;
|
||||||
|
|
||||||
|
// FIXME: Do not rely on iterators having comparable singular values.
|
||||||
|
// Note that this should error out if they do not.
|
||||||
|
attr_iterator attr_begin() const {
|
||||||
|
return hasAttrs() ? getAttrs().begin() : 0;
|
||||||
|
}
|
||||||
|
attr_iterator attr_end() const {
|
||||||
|
return hasAttrs() ? getAttrs().end() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
specific_attr_iterator<T> specific_attr_begin() const {
|
||||||
|
return specific_attr_iterator<T>(attr_begin());
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
specific_attr_iterator<T> specific_attr_end() const {
|
||||||
|
return specific_attr_iterator<T>(attr_end());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> T *getAttr() const {
|
||||||
|
return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : 0;
|
||||||
|
}
|
||||||
template<typename T> bool hasAttr() const {
|
template<typename T> bool hasAttr() const {
|
||||||
return getAttr<T>() != 0;
|
return hasAttrs() && hasSpecificAttr<T>(getAttrs());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getMaxAlignment - return the maximum alignment specified by attributes
|
||||||
|
/// on this decl, 0 if there are none.
|
||||||
|
unsigned getMaxAlignment() const {
|
||||||
|
return hasAttrs() ? getMaxAttrAlignment(getAttrs(), getASTContext()) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// setInvalidDecl - Indicates the Decl had a semantic error. This
|
/// setInvalidDecl - Indicates the Decl had a semantic error. This
|
||||||
|
|
|
@ -21,7 +21,6 @@ namespace clang {
|
||||||
class Expr;
|
class Expr;
|
||||||
class Stmt;
|
class Stmt;
|
||||||
class FunctionDecl;
|
class FunctionDecl;
|
||||||
class AttributeList;
|
|
||||||
class RecordDecl;
|
class RecordDecl;
|
||||||
class ObjCIvarDecl;
|
class ObjCIvarDecl;
|
||||||
class ObjCMethodDecl;
|
class ObjCMethodDecl;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
CLANG_LEVEL := ../../..
|
CLANG_LEVEL := ../../..
|
||||||
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
|
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
|
||||||
BUILT_SOURCES = Attrs.inc StmtNodes.inc DeclNodes.inc
|
BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc
|
||||||
|
|
||||||
TABLEGEN_INC_FILES_COMMON = 1
|
TABLEGEN_INC_FILES_COMMON = 1
|
||||||
|
|
||||||
|
@ -12,6 +12,12 @@ $(ObjDir)/Attrs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
|
||||||
$(Verb) $(TableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \
|
$(Verb) $(TableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \
|
||||||
-I $(PROJ_SRC_DIR)/../../ $<
|
-I $(PROJ_SRC_DIR)/../../ $<
|
||||||
|
|
||||||
|
$(ObjDir)/AttrImpl.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
|
||||||
|
$(ObjDir)/.dir
|
||||||
|
$(Echo) "Building Clang attribute implementations with tblgen"
|
||||||
|
$(Verb) $(TableGen) -gen-clang-attr-impl -o $(call SYSPATH, $@) \
|
||||||
|
-I $(PROJ_SRC_DIR)/../../ $<
|
||||||
|
|
||||||
$(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(TBLGEN) \
|
$(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(TBLGEN) \
|
||||||
$(ObjDir)/.dir
|
$(ObjDir)/.dir
|
||||||
$(Echo) "Building Clang statement node tables with tblgen"
|
$(Echo) "Building Clang statement node tables with tblgen"
|
||||||
|
|
|
@ -33,8 +33,8 @@ class SubsetSubject<AttrSubject base, string description, code check>
|
||||||
// a possible subject.
|
// a possible subject.
|
||||||
def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable",
|
def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable",
|
||||||
[{S->getStorageClass() != VarDecl::Register &&
|
[{S->getStorageClass() != VarDecl::Register &&
|
||||||
S->getKind() != Decl::ImplicitParam
|
S->getKind() != Decl::ImplicitParam &&
|
||||||
S->getKind() != Decl::ParmVar
|
S->getKind() != Decl::ParmVar &&
|
||||||
S->getKind() != Decl::NonTypeTemplateParm}]>;
|
S->getKind() != Decl::NonTypeTemplateParm}]>;
|
||||||
def CXXVirtualMethod : SubsetSubject<CXXRecord, "virtual member function",
|
def CXXVirtualMethod : SubsetSubject<CXXRecord, "virtual member function",
|
||||||
[{S->isVirtual()}]>;
|
[{S->isVirtual()}]>;
|
||||||
|
@ -51,18 +51,27 @@ class IntArgument<string name> : Argument<name>;
|
||||||
class StringArgument<string name> : Argument<name>;
|
class StringArgument<string name> : Argument<name>;
|
||||||
class ExprArgument<string name> : Argument<name>;
|
class ExprArgument<string name> : Argument<name>;
|
||||||
class FunctionArgument<string name> : Argument<name>;
|
class FunctionArgument<string name> : Argument<name>;
|
||||||
class ObjCInterfaceArgument<string name> : Argument<name>;
|
class TypeArgument<string name> : Argument<name>;
|
||||||
class UnsignedIntArgument<string name> : Argument<name>;
|
class UnsignedArgument<string name> : Argument<name>;
|
||||||
class UnsignedIntOrTypeArgument<string name> : Argument<name>;
|
class VariadicUnsignedArgument<string name> : Argument<name>;
|
||||||
|
|
||||||
|
// This one's a doozy, so it gets its own special type
|
||||||
|
// It can be an unsigned integer, or a type. Either can
|
||||||
|
// be dependent.
|
||||||
|
class AlignedArgument<string name> : Argument<name>;
|
||||||
|
|
||||||
// An integer argument with a default value
|
// An integer argument with a default value
|
||||||
class DefaultIntArgument<string name, int default> : IntArgument<name> {
|
class DefaultIntArgument<string name, int default> : IntArgument<name> {
|
||||||
int Default = default;
|
int Default = default;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zero or more arguments of a type
|
// This argument is more complex, it includes the enumerator type name,
|
||||||
class VariadicArgument<Argument arg> : Argument<arg.Name> {
|
// a list of strings to accept, and a list of enumerators to map them to.
|
||||||
Argument VariadicArg = arg;
|
class EnumArgument<string name, string type, list<string> values,
|
||||||
|
list<string> enums> : Argument<name> {
|
||||||
|
string Type = type;
|
||||||
|
list<string> Values = values;
|
||||||
|
list<string> Enums = enums;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Attr {
|
class Attr {
|
||||||
|
@ -76,9 +85,8 @@ class Attr {
|
||||||
// The attribute will not be permitted in C++0x attribute-specifiers if
|
// The attribute will not be permitted in C++0x attribute-specifiers if
|
||||||
// this is empty; the empty string can be used as a namespace.
|
// this is empty; the empty string can be used as a namespace.
|
||||||
list<string> Namespaces = [];
|
list<string> Namespaces = [];
|
||||||
// A temporary development bit to tell TableGen not to emit certain
|
// Any additional text that should be included verbatim in the class.
|
||||||
// information about the attribute.
|
code AdditionalMembers = [{}];
|
||||||
bit DoNotEmit = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -87,13 +95,13 @@ class Attr {
|
||||||
|
|
||||||
def Alias : Attr {
|
def Alias : Attr {
|
||||||
let Spellings = ["alias"];
|
let Spellings = ["alias"];
|
||||||
let Args = [StringArgument<"AliasName">];
|
let Args = [StringArgument<"Aliasee">];
|
||||||
}
|
}
|
||||||
|
|
||||||
def Aligned : Attr {
|
def Aligned : Attr {
|
||||||
let Spellings = ["align", "aligned"];
|
let Spellings = ["align", "aligned"];
|
||||||
let Subjects = [NonBitField, NormalVar, Tag];
|
let Subjects = [NonBitField, NormalVar, Tag];
|
||||||
let Args = [UnsignedIntOrTypeArgument<"Alignment">];
|
let Args = [AlignedArgument<"Alignment">];
|
||||||
let Namespaces = ["", "std"];
|
let Namespaces = ["", "std"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,19 +131,17 @@ def BaseCheck : Attr {
|
||||||
let Spellings = ["base_check"];
|
let Spellings = ["base_check"];
|
||||||
let Subjects = [CXXRecord];
|
let Subjects = [CXXRecord];
|
||||||
let Namespaces = ["", "std"];
|
let Namespaces = ["", "std"];
|
||||||
let DoNotEmit = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def Blocks : Attr {
|
def Blocks : Attr {
|
||||||
let Spellings = ["blocks"];
|
let Spellings = ["blocks"];
|
||||||
let Args = [IdentifierArgument<"Type">];
|
let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
|
||||||
}
|
}
|
||||||
|
|
||||||
def CarriesDependency : Attr {
|
def CarriesDependency : Attr {
|
||||||
let Spellings = ["carries_dependency"];
|
let Spellings = ["carries_dependency"];
|
||||||
let Subjects = [ParmVar, Function];
|
let Subjects = [ParmVar, Function];
|
||||||
let Namespaces = ["", "std"];
|
let Namespaces = ["", "std"];
|
||||||
let DoNotEmit = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def CDecl : Attr {
|
def CDecl : Attr {
|
||||||
|
@ -189,7 +195,6 @@ def Final : Attr {
|
||||||
let Spellings = ["final"];
|
let Spellings = ["final"];
|
||||||
let Subjects = [CXXRecord, CXXVirtualMethod];
|
let Subjects = [CXXRecord, CXXVirtualMethod];
|
||||||
let Namespaces = ["", "std"];
|
let Namespaces = ["", "std"];
|
||||||
let DoNotEmit = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def Format : Attr {
|
def Format : Attr {
|
||||||
|
@ -211,7 +216,6 @@ def Hiding : Attr {
|
||||||
let Spellings = ["hiding"];
|
let Spellings = ["hiding"];
|
||||||
let Subjects = [Field, CXXMethod];
|
let Subjects = [Field, CXXMethod];
|
||||||
let Namespaces = ["", "std"];
|
let Namespaces = ["", "std"];
|
||||||
let DoNotEmit = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def IBAction : Attr {
|
def IBAction : Attr {
|
||||||
|
@ -224,7 +228,7 @@ def IBOutlet : Attr {
|
||||||
|
|
||||||
def IBOutletCollection : Attr {
|
def IBOutletCollection : Attr {
|
||||||
let Spellings = ["iboutletcollection"];
|
let Spellings = ["iboutletcollection"];
|
||||||
let Args = [ObjCInterfaceArgument<"Class">];
|
let Args = [TypeArgument<"Interface">];
|
||||||
}
|
}
|
||||||
|
|
||||||
def Malloc : Attr {
|
def Malloc : Attr {
|
||||||
|
@ -233,12 +237,12 @@ def Malloc : Attr {
|
||||||
|
|
||||||
def MaxFieldAlignment : Attr {
|
def MaxFieldAlignment : Attr {
|
||||||
let Spellings = [];
|
let Spellings = [];
|
||||||
let Args = [UnsignedIntArgument<"Alignment">];
|
let Args = [UnsignedArgument<"Alignment">];
|
||||||
}
|
}
|
||||||
|
|
||||||
def MSP430Interrupt : Attr {
|
def MSP430Interrupt : Attr {
|
||||||
let Spellings = [];
|
let Spellings = [];
|
||||||
let Args = [UnsignedIntArgument<"Number">];
|
let Args = [UnsignedArgument<"Number">];
|
||||||
}
|
}
|
||||||
|
|
||||||
def NoDebug : Attr {
|
def NoDebug : Attr {
|
||||||
|
@ -251,7 +255,15 @@ def NoInline : Attr {
|
||||||
|
|
||||||
def NonNull : Attr {
|
def NonNull : Attr {
|
||||||
let Spellings = ["nonnull"];
|
let Spellings = ["nonnull"];
|
||||||
let Args = [VariadicArgument<UnsignedIntArgument<"Args">>];
|
let Args = [VariadicUnsignedArgument<"Args">];
|
||||||
|
let AdditionalMembers =
|
||||||
|
[{bool isNonNull(unsigned idx) const {
|
||||||
|
for (args_iterator i = args_begin(), e = args_end();
|
||||||
|
i != e; ++i)
|
||||||
|
if (*i == idx)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
} }];
|
||||||
}
|
}
|
||||||
|
|
||||||
def NoReturn : Attr {
|
def NoReturn : Attr {
|
||||||
|
@ -290,26 +302,18 @@ def Override : Attr {
|
||||||
let Spellings = ["override"];
|
let Spellings = ["override"];
|
||||||
let Subjects = [CXXVirtualMethod];
|
let Subjects = [CXXVirtualMethod];
|
||||||
let Namespaces = ["", "std"];
|
let Namespaces = ["", "std"];
|
||||||
let DoNotEmit = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def Overloadable : Attr {
|
def Overloadable : Attr {
|
||||||
let Spellings = ["overloadable"];
|
let Spellings = ["overloadable"];
|
||||||
}
|
}
|
||||||
|
|
||||||
def OwnershipReturns : Attr {
|
def Ownership : Attr {
|
||||||
let Spellings = ["ownership_returns"];
|
let Spellings = ["ownership_holds", "ownership_returns", "ownership_takes"];
|
||||||
let Args = [StringArgument<"Module">, IntArgument<"SizeIdx">];
|
let Args = [EnumArgument<"OwnKind", "OwnershipKind",
|
||||||
}
|
["ownership_holds", "ownership_returns", "ownership_takes"],
|
||||||
|
["Holds", "Returns", "Takes"]>,
|
||||||
def OwnershipTakes : Attr {
|
StringArgument<"Module">, VariadicUnsignedArgument<"Args">];
|
||||||
let Spellings = ["ownership_takes"];
|
|
||||||
let Args = [StringArgument<"Module">, IntArgument<"PtrIdx">];
|
|
||||||
}
|
|
||||||
|
|
||||||
def OwnershipHolds : Attr {
|
|
||||||
let Spellings = ["ownership_holds"];
|
|
||||||
let Args = [StringArgument<"Module">, IntArgument<"PtrIdx">];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def Packed : Attr {
|
def Packed : Attr {
|
||||||
|
@ -322,18 +326,18 @@ def Pure : Attr {
|
||||||
|
|
||||||
def Regparm : Attr {
|
def Regparm : Attr {
|
||||||
let Spellings = ["regparm"];
|
let Spellings = ["regparm"];
|
||||||
let Args = [UnsignedIntArgument<"NumParams">];
|
let Args = [UnsignedArgument<"NumParams">];
|
||||||
}
|
}
|
||||||
|
|
||||||
def ReqdWorkGroupSize : Attr {
|
def ReqdWorkGroupSize : Attr {
|
||||||
let Spellings = ["reqd_work_group_size"];
|
let Spellings = ["reqd_work_group_size"];
|
||||||
let Args = [UnsignedIntArgument<"XDim">, UnsignedIntArgument<"YDim">,
|
let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">,
|
||||||
UnsignedIntArgument<"ZDim">];
|
UnsignedArgument<"ZDim">];
|
||||||
}
|
}
|
||||||
|
|
||||||
def InitPriority : Attr {
|
def InitPriority : Attr {
|
||||||
let Spellings = ["init_priority"];
|
let Spellings = ["init_priority"];
|
||||||
let Args = [UnsignedIntArgument<"Priority">];
|
let Args = [UnsignedArgument<"Priority">];
|
||||||
}
|
}
|
||||||
|
|
||||||
def Section : Attr {
|
def Section : Attr {
|
||||||
|
@ -343,8 +347,8 @@ def Section : Attr {
|
||||||
|
|
||||||
def Sentinel : Attr {
|
def Sentinel : Attr {
|
||||||
let Spellings = ["sentinel"];
|
let Spellings = ["sentinel"];
|
||||||
let Args = [DefaultIntArgument<"NulPos", 0>,
|
let Args = [DefaultIntArgument<"Sentinel", 0>,
|
||||||
DefaultIntArgument<"Sentinel", 0>];
|
DefaultIntArgument<"NullPos", 0>];
|
||||||
}
|
}
|
||||||
|
|
||||||
def StdCall : Attr {
|
def StdCall : Attr {
|
||||||
|
@ -373,13 +377,14 @@ def Used : Attr {
|
||||||
|
|
||||||
def Visibility : Attr {
|
def Visibility : Attr {
|
||||||
let Spellings = ["visibility"];
|
let Spellings = ["visibility"];
|
||||||
let Args = [StringArgument<"Visibility">];
|
let Args = [EnumArgument<"Visibility", "VisibilityType",
|
||||||
|
["default", "hidden", "internal", "protected"],
|
||||||
|
["Default", "Hidden", "Hidden", "Protected"]>];
|
||||||
}
|
}
|
||||||
|
|
||||||
def VecReturn : Attr {
|
def VecReturn : Attr {
|
||||||
let Spellings = ["vecreturn"];
|
let Spellings = ["vecreturn"];
|
||||||
let Subjects = [CXXRecord];
|
let Subjects = [CXXRecord];
|
||||||
let DoNotEmit = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def WarnUnusedResult : Attr {
|
def WarnUnusedResult : Attr {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
add_subdirectory(AST)
|
add_subdirectory(AST)
|
||||||
add_subdirectory(Basic)
|
add_subdirectory(Basic)
|
||||||
add_subdirectory(Driver)
|
add_subdirectory(Driver)
|
||||||
|
add_subdirectory(Serialization)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
CLANG_LEVEL := ../..
|
CLANG_LEVEL := ../..
|
||||||
DIRS := AST Basic Driver
|
DIRS := AST Basic Driver Serialization
|
||||||
|
|
||||||
include $(CLANG_LEVEL)/Makefile
|
include $(CLANG_LEVEL)/Makefile
|
||||||
|
|
||||||
|
|
|
@ -4265,7 +4265,8 @@ public:
|
||||||
|
|
||||||
/// PushPragmaVisibility - Push the top element of the visibility stack; used
|
/// PushPragmaVisibility - Push the top element of the visibility stack; used
|
||||||
/// for '#pragma GCC visibility' and visibility attributes on namespaces.
|
/// for '#pragma GCC visibility' and visibility attributes on namespaces.
|
||||||
void PushPragmaVisibility(VisibilityAttr::VisibilityTypes type);
|
void PushPragmaVisibility(VisibilityAttr::VisibilityType type,
|
||||||
|
SourceLocation loc);
|
||||||
|
|
||||||
/// PopPragmaVisibility - Pop the top element of the visibility stack; used
|
/// PopPragmaVisibility - Pop the top element of the visibility stack; used
|
||||||
/// for '#pragma GCC visibility' and visibility attributes on namespaces.
|
/// for '#pragma GCC visibility' and visibility attributes on namespaces.
|
||||||
|
@ -4276,6 +4277,7 @@ public:
|
||||||
|
|
||||||
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
|
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
|
||||||
void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E);
|
void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E);
|
||||||
|
void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, TypeSourceInfo *T);
|
||||||
|
|
||||||
/// CastCategory - Get the correct forwarded implicit cast result category
|
/// CastCategory - Get the correct forwarded implicit cast result category
|
||||||
/// from the inner expression.
|
/// from the inner expression.
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
set(LLVM_TARGET_DEFINITIONS ../Basic/Attr.td)
|
||||||
|
tablegen(AttrPCHRead.inc
|
||||||
|
-gen-clang-attr-pch-read
|
||||||
|
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
|
||||||
|
add_custom_target(ClangAttrPCHRead
|
||||||
|
DEPENDS AttrPCHRead.inc)
|
||||||
|
|
||||||
|
tablegen(AttrPCHWrite.inc
|
||||||
|
-gen-clang-attr-pch-write
|
||||||
|
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
|
||||||
|
add_custom_target(ClangAttrPCHWrite
|
||||||
|
DEPENDS AttrPCHWrite.inc)
|
|
@ -0,0 +1,19 @@
|
||||||
|
CLANG_LEVEL := ../../..
|
||||||
|
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
|
||||||
|
BUILT_SOURCES = AttrPCHRead.inc AttrPCHWrite.inc
|
||||||
|
|
||||||
|
TABLEGEN_INC_FILES_COMMON = 1
|
||||||
|
|
||||||
|
include $(CLANG_LEVEL)/Makefile
|
||||||
|
|
||||||
|
$(ObjDir)/AttrPCHRead.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
|
||||||
|
$(ObjDir)/.dir
|
||||||
|
$(Echo) "Building Clang PCH reader with tblgen"
|
||||||
|
$(Verb) $(TableGen) -gen-clang-attr-pch-read -o $(call SYSPATH, $@) \
|
||||||
|
-I $(PROJ_SRC_DIR)/../../ $<
|
||||||
|
|
||||||
|
$(ObjDir)/AttrPCHWrite.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
|
||||||
|
$(ObjDir)/.dir
|
||||||
|
$(Echo) "Building Clang PCH writer with tblgen"
|
||||||
|
$(Verb) $(TableGen) -gen-clang-attr-pch-write -o $(call SYSPATH, $@) \
|
||||||
|
-I $(PROJ_SRC_DIR)/../../ $<
|
|
@ -908,7 +908,7 @@ public:
|
||||||
CXXTemporary *ReadCXXTemporary(const RecordData &Record, unsigned &Idx);
|
CXXTemporary *ReadCXXTemporary(const RecordData &Record, unsigned &Idx);
|
||||||
|
|
||||||
/// \brief Reads attributes from the current stream position.
|
/// \brief Reads attributes from the current stream position.
|
||||||
Attr *ReadAttributes(llvm::BitstreamCursor &DeclsCursor);
|
void ReadAttributes(llvm::BitstreamCursor &DeclsCursor, AttrVec &Attrs);
|
||||||
|
|
||||||
/// \brief Reads a statement.
|
/// \brief Reads a statement.
|
||||||
Stmt *ReadStmt(llvm::BitstreamCursor &Cursor);
|
Stmt *ReadStmt(llvm::BitstreamCursor &Cursor);
|
||||||
|
|
|
@ -281,7 +281,7 @@ private:
|
||||||
void WriteSelectors(Sema &SemaRef);
|
void WriteSelectors(Sema &SemaRef);
|
||||||
void WriteReferencedSelectorsPool(Sema &SemaRef);
|
void WriteReferencedSelectorsPool(Sema &SemaRef);
|
||||||
void WriteIdentifierTable(Preprocessor &PP);
|
void WriteIdentifierTable(Preprocessor &PP);
|
||||||
void WriteAttributeRecord(const Attr *Attr);
|
void WriteAttributeRecord(const AttrVec &Attrs);
|
||||||
void WriteDeclUpdateBlock();
|
void WriteDeclUpdateBlock();
|
||||||
|
|
||||||
unsigned ParmVarDeclAbbrev;
|
unsigned ParmVarDeclAbbrev;
|
||||||
|
|
|
@ -497,8 +497,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
|
||||||
CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) {
|
CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) {
|
||||||
unsigned Align = Target.getCharWidth();
|
unsigned Align = Target.getCharWidth();
|
||||||
|
|
||||||
if (const AlignedAttr* AA = D->getAttr<AlignedAttr>())
|
Align = std::max(Align, D->getMaxAlignment());
|
||||||
Align = std::max(Align, AA->getMaxAlignment());
|
|
||||||
|
|
||||||
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
|
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
|
||||||
QualType T = VD->getType();
|
QualType T = VD->getType();
|
||||||
|
@ -760,12 +759,9 @@ ASTContext::getTypeInfo(const Type *T) {
|
||||||
|
|
||||||
case Type::Typedef: {
|
case Type::Typedef: {
|
||||||
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
|
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
|
||||||
if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
|
Align = std::max(Typedef->getMaxAlignment(),
|
||||||
Align = std::max(Aligned->getMaxAlignment(),
|
getTypeAlign(Typedef->getUnderlyingType().getTypePtr()));
|
||||||
getTypeAlign(Typedef->getUnderlyingType().getTypePtr()));
|
Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
|
||||||
Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
|
|
||||||
} else
|
|
||||||
return getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,231 +13,10 @@
|
||||||
|
|
||||||
#include "clang/AST/Attr.h"
|
#include "clang/AST/Attr.h"
|
||||||
#include "clang/AST/ASTContext.h"
|
#include "clang/AST/ASTContext.h"
|
||||||
|
#include "clang/AST/Type.h"
|
||||||
|
#include "clang/AST/Expr.h"
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
Attr::~Attr() { }
|
Attr::~Attr() { }
|
||||||
|
|
||||||
AttrWithString::AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s)
|
#include "clang/AST/AttrImpl.inc"
|
||||||
: Attr(AK) {
|
|
||||||
assert(!s.empty());
|
|
||||||
StrLen = s.size();
|
|
||||||
Str = new (C) char[StrLen];
|
|
||||||
memcpy(const_cast<char*>(Str), s.data(), StrLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AttrWithString::ReplaceString(ASTContext &C, llvm::StringRef newS) {
|
|
||||||
if (newS.size() > StrLen) {
|
|
||||||
C.Deallocate(const_cast<char*>(Str));
|
|
||||||
Str = new (C) char[newS.size()];
|
|
||||||
}
|
|
||||||
StrLen = newS.size();
|
|
||||||
memcpy(const_cast<char*>(Str), newS.data(), StrLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FormatAttr::setType(ASTContext &C, llvm::StringRef type) {
|
|
||||||
ReplaceString(C, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
NonNullAttr::NonNullAttr(ASTContext &C, unsigned* arg_nums, unsigned size)
|
|
||||||
: Attr(attr::NonNull), ArgNums(0), Size(0) {
|
|
||||||
if (size == 0)
|
|
||||||
return;
|
|
||||||
assert(arg_nums);
|
|
||||||
ArgNums = new (C) unsigned[size];
|
|
||||||
Size = size;
|
|
||||||
memcpy(ArgNums, arg_nums, sizeof(*ArgNums)*size);
|
|
||||||
}
|
|
||||||
|
|
||||||
OwnershipAttr::OwnershipAttr(attr::Kind AK, ASTContext &C, unsigned* arg_nums,
|
|
||||||
unsigned size, llvm::StringRef module)
|
|
||||||
: AttrWithString(AK, C, module), ArgNums(0), Size(0) {
|
|
||||||
if (size == 0)
|
|
||||||
return;
|
|
||||||
assert(arg_nums);
|
|
||||||
ArgNums = new (C) unsigned[size];
|
|
||||||
Size = size;
|
|
||||||
memcpy(ArgNums, arg_nums, sizeof(*ArgNums) * size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OwnershipAttr::Destroy(ASTContext &C) {
|
|
||||||
if (ArgNums)
|
|
||||||
C.Deallocate(ArgNums);
|
|
||||||
}
|
|
||||||
|
|
||||||
OwnershipTakesAttr::OwnershipTakesAttr(ASTContext &C, unsigned* arg_nums,
|
|
||||||
unsigned size, llvm::StringRef module)
|
|
||||||
: OwnershipAttr(attr::OwnershipTakes, C, arg_nums, size, module) {
|
|
||||||
}
|
|
||||||
|
|
||||||
OwnershipHoldsAttr::OwnershipHoldsAttr(ASTContext &C, unsigned* arg_nums,
|
|
||||||
unsigned size, llvm::StringRef module)
|
|
||||||
: OwnershipAttr(attr::OwnershipHolds, C, arg_nums, size, module) {
|
|
||||||
}
|
|
||||||
|
|
||||||
OwnershipReturnsAttr::OwnershipReturnsAttr(ASTContext &C, unsigned* arg_nums,
|
|
||||||
unsigned size,
|
|
||||||
llvm::StringRef module)
|
|
||||||
: OwnershipAttr(attr::OwnershipReturns, C, arg_nums, size, module) {
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEF_SIMPLE_ATTR_CLONE(ATTR) \
|
|
||||||
Attr *ATTR##Attr::clone(ASTContext &C) const { \
|
|
||||||
return ::new (C) ATTR##Attr; \
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Can we use variadic macro to define DEF_SIMPLE_ATTR_CLONE for
|
|
||||||
// "non-simple" classes?
|
|
||||||
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(AlignMac68k)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(AlwaysInline)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(AnalyzerNoReturn)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(BaseCheck)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(CDecl)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(CFReturnsNotRetained)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(CFReturnsRetained)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(Const)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(DLLExport)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(DLLImport)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(Deprecated)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(FastCall)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(Final)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(Hiding)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(Malloc)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(NSReturnsNotRetained)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(NSReturnsRetained)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(NoDebug)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(NoInline)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(NoInstrumentFunction)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(NoReturn)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(NoThrow)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(ObjCException)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(ObjCNSObject)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(Override)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(Packed)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(Pure)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(StdCall)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(ThisCall)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(TransparentUnion)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(Unavailable)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(Unused)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(Used)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(VecReturn)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(WarnUnusedResult)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(Weak)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(WeakImport)
|
|
||||||
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(WeakRef)
|
|
||||||
DEF_SIMPLE_ATTR_CLONE(X86ForceAlignArgPointer)
|
|
||||||
|
|
||||||
Attr* MaxFieldAlignmentAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) MaxFieldAlignmentAttr(Alignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr* AlignedAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) AlignedAttr(Alignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr* AnnotateAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) AnnotateAttr(C, getAnnotation());
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *AsmLabelAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) AsmLabelAttr(C, getLabel());
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *AliasAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) AliasAttr(C, getAliasee());
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *ConstructorAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) ConstructorAttr(priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *DestructorAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) DestructorAttr(priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *IBOutletAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) IBOutletAttr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *IBOutletCollectionAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) IBOutletCollectionAttr(QT);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *IBActionAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) IBActionAttr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *GNUInlineAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) GNUInlineAttr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *SectionAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) SectionAttr(C, getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *NonNullAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) NonNullAttr(C, ArgNums, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *OwnershipAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) OwnershipAttr(AKind, C, ArgNums, Size, getModule());
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *OwnershipReturnsAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) OwnershipReturnsAttr(C, ArgNums, Size, getModule());
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *OwnershipTakesAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) OwnershipTakesAttr(C, ArgNums, Size, getModule());
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *OwnershipHoldsAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) OwnershipHoldsAttr(C, ArgNums, Size, getModule());
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *FormatAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) FormatAttr(C, getType(), formatIdx, firstArg);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *FormatArgAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) FormatArgAttr(formatIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *SentinelAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) SentinelAttr(sentinel, NullPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *VisibilityAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) VisibilityAttr(VisibilityType, FromPragma);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *OverloadableAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) OverloadableAttr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *BlocksAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) BlocksAttr(BlocksAttrType);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *CleanupAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) CleanupAttr(FD);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *RegparmAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) RegparmAttr(NumParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *ReqdWorkGroupSizeAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) ReqdWorkGroupSizeAttr(X, Y, Z);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *InitPriorityAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) InitPriorityAttr(Priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attr *MSP430InterruptAttr::clone(ASTContext &C) const {
|
|
||||||
return ::new (C) MSP430InterruptAttr(Number);
|
|
||||||
}
|
|
||||||
|
|
|
@ -43,4 +43,4 @@ add_clang_library(clangAST
|
||||||
)
|
)
|
||||||
|
|
||||||
add_dependencies(clangAST ClangARMNeon ClangAttrClasses ClangAttrList
|
add_dependencies(clangAST ClangARMNeon ClangAttrClasses ClangAttrList
|
||||||
ClangDiagnosticAST ClangDeclNodes ClangStmtNodes)
|
ClangAttrImpl ClangDiagnosticAST ClangDeclNodes ClangStmtNodes)
|
||||||
|
|
|
@ -312,35 +312,25 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Decl::initAttrs(Attr *attrs) {
|
void Decl::setAttrs(const AttrVec &attrs) {
|
||||||
assert(!HasAttrs && "Decl already contains attrs.");
|
assert(!HasAttrs && "Decl already contains attrs.");
|
||||||
|
|
||||||
Attr *&AttrBlank = getASTContext().getDeclAttrs(this);
|
AttrVec &AttrBlank = getASTContext().getDeclAttrs(this);
|
||||||
assert(AttrBlank == 0 && "HasAttrs was wrong?");
|
assert(AttrBlank.empty() && "HasAttrs was wrong?");
|
||||||
|
|
||||||
AttrBlank = attrs;
|
AttrBlank = attrs;
|
||||||
HasAttrs = true;
|
HasAttrs = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Decl::addAttr(Attr *NewAttr) {
|
void Decl::dropAttrs() {
|
||||||
Attr *&ExistingAttr = getASTContext().getDeclAttrs(this);
|
|
||||||
|
|
||||||
assert(NewAttr->getNext() == 0 && "Chain of attributes will be truncated!");
|
|
||||||
NewAttr->setNext(ExistingAttr);
|
|
||||||
ExistingAttr = NewAttr;
|
|
||||||
|
|
||||||
HasAttrs = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Decl::invalidateAttrs() {
|
|
||||||
if (!HasAttrs) return;
|
if (!HasAttrs) return;
|
||||||
|
|
||||||
HasAttrs = false;
|
HasAttrs = false;
|
||||||
getASTContext().eraseDeclAttrs(this);
|
getASTContext().eraseDeclAttrs(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Attr *Decl::getAttrsImpl() const {
|
const AttrVec &Decl::getAttrs() const {
|
||||||
assert(HasAttrs && "getAttrs() should verify this!");
|
assert(HasAttrs && "No attrs to get!");
|
||||||
return getASTContext().getDeclAttrs(this);
|
return getASTContext().getDeclAttrs(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1123,8 +1123,8 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
|
||||||
if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
|
if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
|
||||||
MaxFieldAlignment = MFAA->getAlignment();
|
MaxFieldAlignment = MFAA->getAlignment();
|
||||||
|
|
||||||
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
|
if (unsigned MaxAlign = D->getMaxAlignment())
|
||||||
UpdateAlignment(AA->getMaxAlignment());
|
UpdateAlignment(MaxAlign);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1287,8 +1287,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
|
||||||
|
|
||||||
if (FieldPacked || !Context.Target.useBitFieldTypeAlignment())
|
if (FieldPacked || !Context.Target.useBitFieldTypeAlignment())
|
||||||
FieldAlign = 1;
|
FieldAlign = 1;
|
||||||
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
|
FieldAlign = std::max(FieldAlign, D->getMaxAlignment());
|
||||||
FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
|
|
||||||
|
|
||||||
// The maximum field alignment overrides the aligned attribute.
|
// The maximum field alignment overrides the aligned attribute.
|
||||||
if (MaxFieldAlignment)
|
if (MaxFieldAlignment)
|
||||||
|
@ -1357,8 +1356,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
|
||||||
|
|
||||||
if (FieldPacked)
|
if (FieldPacked)
|
||||||
FieldAlign = 8;
|
FieldAlign = 8;
|
||||||
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
|
FieldAlign = std::max(FieldAlign, D->getMaxAlignment());
|
||||||
FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
|
|
||||||
|
|
||||||
// The maximum field alignment overrides the aligned attribute.
|
// The maximum field alignment overrides the aligned attribute.
|
||||||
if (MaxFieldAlignment)
|
if (MaxFieldAlignment)
|
||||||
|
|
|
@ -176,19 +176,23 @@ bool MallocChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
|
||||||
// There can be multiple of these attributes.
|
// There can be multiple of these attributes.
|
||||||
bool rv = false;
|
bool rv = false;
|
||||||
if (FD->hasAttrs()) {
|
if (FD->hasAttrs()) {
|
||||||
for (const Attr *attr = FD->getAttrs(); attr; attr = attr->getNext()) {
|
for (specific_attr_iterator<OwnershipAttr>
|
||||||
switch (attr->getKind()) {
|
i = FD->specific_attr_begin<OwnershipAttr>(),
|
||||||
case attr::OwnershipReturns:
|
e = FD->specific_attr_end<OwnershipAttr>();
|
||||||
MallocMemReturnsAttr(C, CE, cast<OwnershipAttr>(attr));
|
i != e; ++i) {
|
||||||
|
switch ((*i)->getOwnKind()) {
|
||||||
|
case OwnershipAttr::Returns: {
|
||||||
|
MallocMemReturnsAttr(C, CE, *i);
|
||||||
rv = true;
|
rv = true;
|
||||||
break;
|
break;
|
||||||
case attr::OwnershipTakes:
|
}
|
||||||
case attr::OwnershipHolds:
|
case OwnershipAttr::Takes:
|
||||||
FreeMemAttr(C, CE, cast<OwnershipAttr>(attr));
|
case OwnershipAttr::Holds: {
|
||||||
|
FreeMemAttr(C, CE, *i);
|
||||||
rv = true;
|
rv = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
// Ignore non-ownership attributes.
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,10 +208,10 @@ void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
|
||||||
|
|
||||||
void MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
|
void MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
|
||||||
const OwnershipAttr* Att) {
|
const OwnershipAttr* Att) {
|
||||||
if (!Att->isModule("malloc"))
|
if (Att->getModule() != "malloc")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const unsigned *I = Att->begin(), *E = Att->end();
|
OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
|
||||||
if (I != E) {
|
if (I != E) {
|
||||||
const GRState *state =
|
const GRState *state =
|
||||||
MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState());
|
MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState());
|
||||||
|
@ -258,14 +262,15 @@ void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) {
|
||||||
|
|
||||||
void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE,
|
void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE,
|
||||||
const OwnershipAttr* Att) {
|
const OwnershipAttr* Att) {
|
||||||
if (!Att->isModule("malloc"))
|
if (Att->getModule() != "malloc")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (const unsigned *I = Att->begin(), *E = Att->end(); I != E; ++I) {
|
for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
|
||||||
const GRState *state =
|
I != E; ++I) {
|
||||||
FreeMemAux(C, CE, C.getState(), *I, isa<OwnershipHoldsAttr>(Att));
|
const GRState *state = FreeMemAux(C, CE, C.getState(), *I,
|
||||||
if (state)
|
Att->getOwnKind() == OwnershipAttr::Holds);
|
||||||
C.addTransition(state);
|
if (state)
|
||||||
|
C.addTransition(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,11 +150,11 @@ CodeGenModule::getDeclVisibilityMode(const Decl *D) const {
|
||||||
if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) {
|
if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) {
|
||||||
switch (attr->getVisibility()) {
|
switch (attr->getVisibility()) {
|
||||||
default: assert(0 && "Unknown visibility!");
|
default: assert(0 && "Unknown visibility!");
|
||||||
case VisibilityAttr::DefaultVisibility:
|
case VisibilityAttr::Default:
|
||||||
return LangOptions::Default;
|
return LangOptions::Default;
|
||||||
case VisibilityAttr::HiddenVisibility:
|
case VisibilityAttr::Hidden:
|
||||||
return LangOptions::Hidden;
|
return LangOptions::Hidden;
|
||||||
case VisibilityAttr::ProtectedVisibility:
|
case VisibilityAttr::Protected:
|
||||||
return LangOptions::Protected;
|
return LangOptions::Protected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -461,12 +461,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
|
||||||
else if (Features.getStackProtectorMode() == LangOptions::SSPReq)
|
else if (Features.getStackProtectorMode() == LangOptions::SSPReq)
|
||||||
F->addFnAttr(llvm::Attribute::StackProtectReq);
|
F->addFnAttr(llvm::Attribute::StackProtectReq);
|
||||||
|
|
||||||
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) {
|
unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
|
||||||
unsigned width = Context.Target.getCharWidth();
|
if (alignment)
|
||||||
F->setAlignment(AA->getAlignment() / width);
|
F->setAlignment(alignment);
|
||||||
while ((AA = AA->getNext<AlignedAttr>()))
|
|
||||||
F->setAlignment(std::max(F->getAlignment(), AA->getAlignment() / width));
|
|
||||||
}
|
|
||||||
// C++ ABI requires 2-byte alignment for member functions.
|
// C++ ABI requires 2-byte alignment for member functions.
|
||||||
if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D))
|
if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D))
|
||||||
F->setAlignment(2);
|
F->setAlignment(2);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "clang/Sema/Sema.h"
|
#include "clang/Sema/Sema.h"
|
||||||
#include "clang/Sema/Lookup.h"
|
#include "clang/Sema/Lookup.h"
|
||||||
|
#include "clang/AST/Attr.h"
|
||||||
#include "clang/AST/Expr.h"
|
#include "clang/AST/Expr.h"
|
||||||
#include "clang/Basic/TargetInfo.h"
|
#include "clang/Basic/TargetInfo.h"
|
||||||
#include "clang/Lex/Preprocessor.h"
|
#include "clang/Lex/Preprocessor.h"
|
||||||
|
@ -120,9 +121,11 @@ void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
|
||||||
// Otherwise, check to see if we need a max field alignment attribute.
|
// Otherwise, check to see if we need a max field alignment attribute.
|
||||||
if (unsigned Alignment = Stack->getAlignment()) {
|
if (unsigned Alignment = Stack->getAlignment()) {
|
||||||
if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
|
if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
|
||||||
RD->addAttr(::new (Context) AlignMac68kAttr());
|
RD->addAttr(::new (Context) AlignMac68kAttr(SourceLocation(), Context));
|
||||||
else
|
else
|
||||||
RD->addAttr(::new (Context) MaxFieldAlignmentAttr(Alignment * 8));
|
RD->addAttr(::new (Context) MaxFieldAlignmentAttr(SourceLocation(),
|
||||||
|
Context,
|
||||||
|
Alignment * 8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,11 +288,12 @@ void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
VD->addAttr(::new (Context) UnusedAttr());
|
VD->addAttr(::new (Context) UnusedAttr(Tok.getLocation(), Context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::vector<VisibilityAttr::VisibilityTypes> VisStack;
|
typedef std::vector<std::pair<VisibilityAttr::VisibilityType,
|
||||||
|
SourceLocation> > VisStack;
|
||||||
|
|
||||||
void Sema::AddPushedVisibilityAttribute(Decl *D) {
|
void Sema::AddPushedVisibilityAttribute(Decl *D) {
|
||||||
if (!VisContext)
|
if (!VisContext)
|
||||||
|
@ -299,9 +303,10 @@ void Sema::AddPushedVisibilityAttribute(Decl *D) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
VisStack *Stack = static_cast<VisStack*>(VisContext);
|
VisStack *Stack = static_cast<VisStack*>(VisContext);
|
||||||
VisibilityAttr::VisibilityTypes type = Stack->back();
|
VisibilityAttr::VisibilityType type = Stack->back().first;
|
||||||
|
SourceLocation loc = Stack->back().second;
|
||||||
|
|
||||||
D->addAttr(::new (Context) VisibilityAttr(type, true));
|
D->addAttr(::new (Context) VisibilityAttr(loc, Context, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// FreeVisContext - Deallocate and null out VisContext.
|
/// FreeVisContext - Deallocate and null out VisContext.
|
||||||
|
@ -314,33 +319,34 @@ void Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
|
||||||
SourceLocation PragmaLoc) {
|
SourceLocation PragmaLoc) {
|
||||||
if (IsPush) {
|
if (IsPush) {
|
||||||
// Compute visibility to use.
|
// Compute visibility to use.
|
||||||
VisibilityAttr::VisibilityTypes type;
|
VisibilityAttr::VisibilityType type;
|
||||||
if (VisType->isStr("default"))
|
if (VisType->isStr("default"))
|
||||||
type = VisibilityAttr::DefaultVisibility;
|
type = VisibilityAttr::Default;
|
||||||
else if (VisType->isStr("hidden"))
|
else if (VisType->isStr("hidden"))
|
||||||
type = VisibilityAttr::HiddenVisibility;
|
type = VisibilityAttr::Hidden;
|
||||||
else if (VisType->isStr("internal"))
|
else if (VisType->isStr("internal"))
|
||||||
type = VisibilityAttr::HiddenVisibility; // FIXME
|
type = VisibilityAttr::Hidden; // FIXME
|
||||||
else if (VisType->isStr("protected"))
|
else if (VisType->isStr("protected"))
|
||||||
type = VisibilityAttr::ProtectedVisibility;
|
type = VisibilityAttr::Protected;
|
||||||
else {
|
else {
|
||||||
Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) <<
|
Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) <<
|
||||||
VisType->getName();
|
VisType->getName();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PushPragmaVisibility(type);
|
PushPragmaVisibility(type, PragmaLoc);
|
||||||
} else {
|
} else {
|
||||||
PopPragmaVisibility();
|
PopPragmaVisibility();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sema::PushPragmaVisibility(VisibilityAttr::VisibilityTypes type) {
|
void Sema::PushPragmaVisibility(VisibilityAttr::VisibilityType type,
|
||||||
|
SourceLocation loc) {
|
||||||
// Put visibility on stack.
|
// Put visibility on stack.
|
||||||
if (!VisContext)
|
if (!VisContext)
|
||||||
VisContext = new VisStack;
|
VisContext = new VisStack;
|
||||||
|
|
||||||
VisStack *Stack = static_cast<VisStack*>(VisContext);
|
VisStack *Stack = static_cast<VisStack*>(VisContext);
|
||||||
Stack->push_back(type);
|
Stack->push_back(std::make_pair(type, loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sema::PopPragmaVisibility() {
|
void Sema::PopPragmaVisibility() {
|
||||||
|
|
|
@ -347,9 +347,12 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const NonNullAttr *NonNull = FDecl->getAttr<NonNullAttr>(); NonNull;
|
specific_attr_iterator<NonNullAttr>
|
||||||
NonNull = NonNull->getNext<NonNullAttr>())
|
i = FDecl->specific_attr_begin<NonNullAttr>(),
|
||||||
CheckNonNullArguments(NonNull, TheCall);
|
e = FDecl->specific_attr_end<NonNullAttr>();
|
||||||
|
|
||||||
|
for (; i != e; ++i)
|
||||||
|
CheckNonNullArguments(*i, TheCall);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1041,7 +1044,8 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
|
||||||
void
|
void
|
||||||
Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
|
Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
|
||||||
const CallExpr *TheCall) {
|
const CallExpr *TheCall) {
|
||||||
for (NonNullAttr::iterator i = NonNull->begin(), e = NonNull->end();
|
for (NonNullAttr::args_iterator i = NonNull->args_begin(),
|
||||||
|
e = NonNull->args_end();
|
||||||
i != e; ++i) {
|
i != e; ++i) {
|
||||||
const Expr *ArgExpr = TheCall->getArg(*i);
|
const Expr *ArgExpr = TheCall->getArg(*i);
|
||||||
if (ArgExpr->isNullPointerConstant(Context,
|
if (ArgExpr->isNullPointerConstant(Context,
|
||||||
|
|
|
@ -997,19 +997,32 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
|
||||||
/// DeclhasAttr - returns true if decl Declaration already has the target
|
/// DeclhasAttr - returns true if decl Declaration already has the target
|
||||||
/// attribute.
|
/// attribute.
|
||||||
static bool
|
static bool
|
||||||
DeclHasAttr(const Decl *decl, const Attr *target) {
|
DeclHasAttr(const Decl *D, const Attr *A) {
|
||||||
for (const Attr *attr = decl->getAttrs(); attr; attr = attr->getNext())
|
const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A);
|
||||||
if (attr->getKind() == target->getKind())
|
for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i)
|
||||||
|
if ((*i)->getKind() == A->getKind()) {
|
||||||
|
// FIXME: Don't hardcode this check
|
||||||
|
if (OA && isa<OwnershipAttr>(*i))
|
||||||
|
return OA->getOwnKind() == cast<OwnershipAttr>(*i)->getOwnKind();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MergeAttributes - append attributes from the Old decl to the New one.
|
/// MergeDeclAttributes - append attributes from the Old decl to the New one.
|
||||||
static void MergeAttributes(Decl *New, Decl *Old, ASTContext &C) {
|
static void MergeDeclAttributes(Decl *New, Decl *Old, ASTContext &C) {
|
||||||
for (const Attr *attr = Old->getAttrs(); attr; attr = attr->getNext()) {
|
if (!Old->hasAttrs())
|
||||||
if (!DeclHasAttr(New, attr) && attr->isMerged()) {
|
return;
|
||||||
Attr *NewAttr = attr->clone(C);
|
// Ensure that any moving of objects within the allocated map is done before
|
||||||
|
// we process them.
|
||||||
|
if (!New->hasAttrs())
|
||||||
|
New->setAttrs(AttrVec());
|
||||||
|
for (Decl::attr_iterator i = Old->attr_begin(), e = Old->attr_end(); i != e;
|
||||||
|
++i) {
|
||||||
|
// FIXME: Make this more general than just checking for Overloadable.
|
||||||
|
if (!DeclHasAttr(New, *i) && (*i)->getKind() != attr::Overloadable) {
|
||||||
|
Attr *NewAttr = (*i)->clone(C);
|
||||||
NewAttr->setInherited(true);
|
NewAttr->setInherited(true);
|
||||||
New->addAttr(NewAttr);
|
New->addAttr(NewAttr);
|
||||||
}
|
}
|
||||||
|
@ -1402,7 +1415,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
|
||||||
/// \returns false
|
/// \returns false
|
||||||
bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
|
bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
|
||||||
// Merge the attributes
|
// Merge the attributes
|
||||||
MergeAttributes(New, Old, Context);
|
MergeDeclAttributes(New, Old, Context);
|
||||||
|
|
||||||
// Merge the storage class.
|
// Merge the storage class.
|
||||||
if (Old->getStorageClass() != FunctionDecl::Extern &&
|
if (Old->getStorageClass() != FunctionDecl::Extern &&
|
||||||
|
@ -1447,7 +1460,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
||||||
return New->setInvalidDecl();
|
return New->setInvalidDecl();
|
||||||
}
|
}
|
||||||
|
|
||||||
MergeAttributes(New, Old, Context);
|
MergeDeclAttributes(New, Old, Context);
|
||||||
|
|
||||||
// Merge the types
|
// Merge the types
|
||||||
QualType MergedT;
|
QualType MergedT;
|
||||||
|
@ -1611,9 +1624,7 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
|
if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
|
||||||
// If there are attributes in the DeclSpec, apply them to the record.
|
ProcessDeclAttributeList(S, Record, DS.getAttributes());
|
||||||
if (const AttributeList *AL = DS.getAttributes())
|
|
||||||
ProcessDeclAttributeList(S, Record, AL);
|
|
||||||
|
|
||||||
if (!Record->getDeclName() && Record->isDefinition() &&
|
if (!Record->getDeclName() && Record->isDefinition() &&
|
||||||
DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
|
DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
|
||||||
|
@ -2770,7 +2781,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||||
if (Expr *E = (Expr*) D.getAsmLabel()) {
|
if (Expr *E = (Expr*) D.getAsmLabel()) {
|
||||||
// The parser guarantees this is a string.
|
// The parser guarantees this is a string.
|
||||||
StringLiteral *SE = cast<StringLiteral>(E);
|
StringLiteral *SE = cast<StringLiteral>(E);
|
||||||
NewVD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString()));
|
NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0),
|
||||||
|
Context, SE->getString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Diagnose shadowed variables before filtering for scope.
|
// Diagnose shadowed variables before filtering for scope.
|
||||||
|
@ -2810,6 +2822,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||||
NewVD->setInvalidDecl();
|
NewVD->setInvalidDecl();
|
||||||
|
|
||||||
// attributes declared post-definition are currently ignored
|
// attributes declared post-definition are currently ignored
|
||||||
|
// FIXME: This should be handled in attribute merging, not
|
||||||
|
// here.
|
||||||
if (Previous.isSingleResult()) {
|
if (Previous.isSingleResult()) {
|
||||||
VarDecl *Def = dyn_cast<VarDecl>(Previous.getFoundDecl());
|
VarDecl *Def = dyn_cast<VarDecl>(Previous.getFoundDecl());
|
||||||
if (Def && (Def = Def->getDefinition()) &&
|
if (Def && (Def = Def->getDefinition()) &&
|
||||||
|
@ -3447,7 +3461,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||||
if (Expr *E = (Expr*) D.getAsmLabel()) {
|
if (Expr *E = (Expr*) D.getAsmLabel()) {
|
||||||
// The parser guarantees this is a string.
|
// The parser guarantees this is a string.
|
||||||
StringLiteral *SE = cast<StringLiteral>(E);
|
StringLiteral *SE = cast<StringLiteral>(E);
|
||||||
NewFD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString()));
|
NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context,
|
||||||
|
SE->getString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the parameter declarations from the declarator D to the function
|
// Copy the parameter declarations from the declarator D to the function
|
||||||
|
@ -3673,6 +3688,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||||
ProcessDeclAttributes(S, NewFD, D);
|
ProcessDeclAttributes(S, NewFD, D);
|
||||||
|
|
||||||
// attributes declared post-definition are currently ignored
|
// attributes declared post-definition are currently ignored
|
||||||
|
// FIXME: This should happen during attribute merging
|
||||||
if (Redeclaration && Previous.isSingleResult()) {
|
if (Redeclaration && Previous.isSingleResult()) {
|
||||||
const FunctionDecl *Def;
|
const FunctionDecl *Def;
|
||||||
FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl());
|
FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl());
|
||||||
|
@ -3684,7 +3700,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||||
|
|
||||||
AddKnownFunctionAttributes(NewFD);
|
AddKnownFunctionAttributes(NewFD);
|
||||||
|
|
||||||
if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>()) {
|
if (OverloadableAttrRequired && !NewFD->hasAttr<OverloadableAttr>()) {
|
||||||
// If a function name is overloadable in C, then every function
|
// If a function name is overloadable in C, then every function
|
||||||
// with that name must be marked "overloadable".
|
// with that name must be marked "overloadable".
|
||||||
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
|
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
|
||||||
|
@ -3692,7 +3708,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||||
if (!Previous.empty())
|
if (!Previous.empty())
|
||||||
Diag(Previous.getRepresentativeDecl()->getLocation(),
|
Diag(Previous.getRepresentativeDecl()->getLocation(),
|
||||||
diag::note_attribute_overloadable_prev_overload);
|
diag::note_attribute_overloadable_prev_overload);
|
||||||
NewFD->addAttr(::new (Context) OverloadableAttr());
|
NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(), Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NewFD->hasAttr<OverloadableAttr>() &&
|
if (NewFD->hasAttr<OverloadableAttr>() &&
|
||||||
|
@ -4792,10 +4808,10 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
|
||||||
|
|
||||||
// Checking attributes of current function definition
|
// Checking attributes of current function definition
|
||||||
// dllimport attribute.
|
// dllimport attribute.
|
||||||
if (FD->getAttr<DLLImportAttr>() &&
|
DLLImportAttr *DA = FD->getAttr<DLLImportAttr>();
|
||||||
(!FD->getAttr<DLLExportAttr>())) {
|
if (DA && (!FD->getAttr<DLLExportAttr>())) {
|
||||||
// dllimport attribute cannot be applied to definition.
|
// dllimport attribute cannot be directly applied to definition.
|
||||||
if (!(FD->getAttr<DLLImportAttr>())->isInherited()) {
|
if (!DA->isInherited()) {
|
||||||
Diag(FD->getLocation(),
|
Diag(FD->getLocation(),
|
||||||
diag::err_attribute_can_be_applied_only_to_symbol_declaration)
|
diag::err_attribute_can_be_applied_only_to_symbol_declaration)
|
||||||
<< "dllimport";
|
<< "dllimport";
|
||||||
|
@ -5041,7 +5057,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
|
||||||
CurContext = Context.getTranslationUnitDecl();
|
CurContext = Context.getTranslationUnitDecl();
|
||||||
|
|
||||||
FunctionDecl *FD =
|
FunctionDecl *FD =
|
||||||
dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D).getAs<Decl>());
|
dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D).getAs<Decl>());
|
||||||
FD->setImplicit();
|
FD->setImplicit();
|
||||||
|
|
||||||
CurContext = PrevDC;
|
CurContext = PrevDC;
|
||||||
|
@ -5069,13 +5085,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
|
||||||
bool HasVAListArg;
|
bool HasVAListArg;
|
||||||
if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) {
|
if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) {
|
||||||
if (!FD->getAttr<FormatAttr>())
|
if (!FD->getAttr<FormatAttr>())
|
||||||
FD->addAttr(::new (Context) FormatAttr(Context, "printf", FormatIdx+1,
|
FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
|
||||||
|
"printf", FormatIdx+1,
|
||||||
HasVAListArg ? 0 : FormatIdx+2));
|
HasVAListArg ? 0 : FormatIdx+2));
|
||||||
}
|
}
|
||||||
if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx,
|
if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx,
|
||||||
HasVAListArg)) {
|
HasVAListArg)) {
|
||||||
if (!FD->getAttr<FormatAttr>())
|
if (!FD->getAttr<FormatAttr>())
|
||||||
FD->addAttr(::new (Context) FormatAttr(Context, "scanf", FormatIdx+1,
|
FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
|
||||||
|
"scanf", FormatIdx+1,
|
||||||
HasVAListArg ? 0 : FormatIdx+2));
|
HasVAListArg ? 0 : FormatIdx+2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5085,15 +5103,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
|
||||||
if (!getLangOptions().MathErrno &&
|
if (!getLangOptions().MathErrno &&
|
||||||
Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) {
|
Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) {
|
||||||
if (!FD->getAttr<ConstAttr>())
|
if (!FD->getAttr<ConstAttr>())
|
||||||
FD->addAttr(::new (Context) ConstAttr());
|
FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Context.BuiltinInfo.isNoReturn(BuiltinID))
|
if (Context.BuiltinInfo.isNoReturn(BuiltinID))
|
||||||
FD->setType(Context.getNoReturnType(FD->getType()));
|
FD->setType(Context.getNoReturnType(FD->getType()));
|
||||||
if (Context.BuiltinInfo.isNoThrow(BuiltinID))
|
if (Context.BuiltinInfo.isNoThrow(BuiltinID))
|
||||||
FD->addAttr(::new (Context) NoThrowAttr());
|
FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context));
|
||||||
if (Context.BuiltinInfo.isConst(BuiltinID))
|
if (Context.BuiltinInfo.isConst(BuiltinID))
|
||||||
FD->addAttr(::new (Context) ConstAttr());
|
FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentifierInfo *Name = FD->getIdentifier();
|
IdentifierInfo *Name = FD->getIdentifier();
|
||||||
|
@ -5115,13 +5133,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
|
||||||
// FIXME: We known better than our headers.
|
// FIXME: We known better than our headers.
|
||||||
const_cast<FormatAttr *>(Format)->setType(Context, "printf");
|
const_cast<FormatAttr *>(Format)->setType(Context, "printf");
|
||||||
} else
|
} else
|
||||||
FD->addAttr(::new (Context) FormatAttr(Context, "printf", 1,
|
FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
|
||||||
|
"printf", 1,
|
||||||
Name->isStr("NSLogv") ? 0 : 2));
|
Name->isStr("NSLogv") ? 0 : 2));
|
||||||
} else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) {
|
} else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) {
|
||||||
// FIXME: asprintf and vasprintf aren't C99 functions. Should they be
|
// FIXME: asprintf and vasprintf aren't C99 functions. Should they be
|
||||||
// target-specific builtins, perhaps?
|
// target-specific builtins, perhaps?
|
||||||
if (!FD->getAttr<FormatAttr>())
|
if (!FD->getAttr<FormatAttr>())
|
||||||
FD->addAttr(::new (Context) FormatAttr(Context, "printf", 2,
|
FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
|
||||||
|
"printf", 2,
|
||||||
Name->isStr("vasprintf") ? 0 : 3));
|
Name->isStr("vasprintf") ? 0 : 3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7009,7 +7029,7 @@ void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
|
||||||
Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName);
|
Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName);
|
||||||
|
|
||||||
if (PrevDecl) {
|
if (PrevDecl) {
|
||||||
PrevDecl->addAttr(::new (Context) WeakAttr());
|
PrevDecl->addAttr(::new (Context) WeakAttr(PragmaLoc, Context));
|
||||||
} else {
|
} else {
|
||||||
(void)WeakUndeclaredIdentifiers.insert(
|
(void)WeakUndeclaredIdentifiers.insert(
|
||||||
std::pair<IdentifierInfo*,WeakInfo>
|
std::pair<IdentifierInfo*,WeakInfo>
|
||||||
|
|
|
@ -211,7 +211,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TagDecl *TD = dyn_cast<TagDecl>(d))
|
if (TagDecl *TD = dyn_cast<TagDecl>(d))
|
||||||
TD->addAttr(::new (S.Context) PackedAttr);
|
TD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context));
|
||||||
else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
|
else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
|
||||||
// If the alignment is less than or equal to 8 bits, the packed attribute
|
// If the alignment is less than or equal to 8 bits, the packed attribute
|
||||||
// has no effect.
|
// has no effect.
|
||||||
|
@ -220,7 +220,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
|
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
|
||||||
<< Attr.getName() << FD->getType();
|
<< Attr.getName() << FD->getType();
|
||||||
else
|
else
|
||||||
FD->addAttr(::new (S.Context) PackedAttr);
|
FD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context));
|
||||||
} else
|
} else
|
||||||
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
|
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,7 @@ static void HandleIBAction(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
// The IBAction attributes only apply to instance methods.
|
// The IBAction attributes only apply to instance methods.
|
||||||
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
|
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
|
||||||
if (MD->isInstanceMethod()) {
|
if (MD->isInstanceMethod()) {
|
||||||
d->addAttr(::new (S.Context) IBActionAttr());
|
d->addAttr(::new (S.Context) IBActionAttr(Attr.getLoc(), S.Context));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +252,7 @@ static void HandleIBOutlet(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
// The IBOutlet attributes only apply to instance variables of
|
// The IBOutlet attributes only apply to instance variables of
|
||||||
// Objective-C classes.
|
// Objective-C classes.
|
||||||
if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d)) {
|
if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d)) {
|
||||||
d->addAttr(::new (S.Context) IBOutletAttr());
|
d->addAttr(::new (S.Context) IBOutletAttr(Attr.getLoc(), S.Context));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,7 +307,8 @@ static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr,
|
||||||
S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
|
S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
d->addAttr(::new (S.Context) IBOutletCollectionAttr(QT));
|
d->addAttr(::new (S.Context) IBOutletCollectionAttr(Attr.getLoc(), S.Context,
|
||||||
|
QT));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -378,7 +379,8 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
unsigned* start = &NonNullArgs[0];
|
unsigned* start = &NonNullArgs[0];
|
||||||
unsigned size = NonNullArgs.size();
|
unsigned size = NonNullArgs.size();
|
||||||
llvm::array_pod_sort(start, start + size);
|
llvm::array_pod_sort(start, start + size);
|
||||||
d->addAttr(::new (S.Context) NonNullAttr(S.Context, start, size));
|
d->addAttr(::new (S.Context) NonNullAttr(Attr.getLoc(), S.Context, start,
|
||||||
|
size));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
|
static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
|
||||||
|
@ -397,24 +399,24 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Figure out our Kind, and check arguments while we're at it.
|
// Figure out our Kind, and check arguments while we're at it.
|
||||||
attr::Kind K;
|
OwnershipAttr::OwnershipKind K;
|
||||||
switch (AL.getKind()) {
|
switch (AL.getKind()) {
|
||||||
case AttributeList::AT_ownership_takes:
|
case AttributeList::AT_ownership_takes:
|
||||||
K = attr::OwnershipTakes;
|
K = OwnershipAttr::Takes;
|
||||||
if (AL.getNumArgs() < 1) {
|
if (AL.getNumArgs() < 1) {
|
||||||
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
|
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AttributeList::AT_ownership_holds:
|
case AttributeList::AT_ownership_holds:
|
||||||
K = attr::OwnershipHolds;
|
K = OwnershipAttr::Holds;
|
||||||
if (AL.getNumArgs() < 1) {
|
if (AL.getNumArgs() < 1) {
|
||||||
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
|
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AttributeList::AT_ownership_returns:
|
case AttributeList::AT_ownership_returns:
|
||||||
K = attr::OwnershipReturns;
|
K = OwnershipAttr::Returns;
|
||||||
if (AL.getNumArgs() > 1) {
|
if (AL.getNumArgs() > 1) {
|
||||||
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
|
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
|
||||||
<< AL.getNumArgs() + 1;
|
<< AL.getNumArgs() + 1;
|
||||||
|
@ -463,21 +465,21 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
|
||||||
}
|
}
|
||||||
--x;
|
--x;
|
||||||
switch (K) {
|
switch (K) {
|
||||||
case attr::OwnershipTakes:
|
case OwnershipAttr::Takes:
|
||||||
case attr::OwnershipHolds: {
|
case OwnershipAttr::Holds: {
|
||||||
// Is the function argument a pointer type?
|
// Is the function argument a pointer type?
|
||||||
QualType T = getFunctionOrMethodArgType(d, x);
|
QualType T = getFunctionOrMethodArgType(d, x);
|
||||||
if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
|
if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
|
||||||
// FIXME: Should also highlight argument in decl.
|
// FIXME: Should also highlight argument in decl.
|
||||||
S.Diag(AL.getLoc(), diag::err_ownership_type)
|
S.Diag(AL.getLoc(), diag::err_ownership_type)
|
||||||
<< ((K==attr::OwnershipTakes)?"ownership_takes":"ownership_holds")
|
<< ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds")
|
||||||
<< "pointer"
|
<< "pointer"
|
||||||
<< IdxExpr->getSourceRange();
|
<< IdxExpr->getSourceRange();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case attr::OwnershipReturns: {
|
case OwnershipAttr::Returns: {
|
||||||
if (AL.getNumArgs() > 1) {
|
if (AL.getNumArgs() > 1) {
|
||||||
// Is the function argument an integer type?
|
// Is the function argument an integer type?
|
||||||
Expr *IdxExpr = static_cast<Expr *>(AL.getArg(0));
|
Expr *IdxExpr = static_cast<Expr *>(AL.getArg(0));
|
||||||
|
@ -497,18 +499,16 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
|
||||||
} // switch
|
} // switch
|
||||||
|
|
||||||
// Check we don't have a conflict with another ownership attribute.
|
// Check we don't have a conflict with another ownership attribute.
|
||||||
if (K != attr::OwnershipReturns && d->hasAttrs()) {
|
for (specific_attr_iterator<OwnershipAttr>
|
||||||
for (const Attr *attr = d->getAttrs(); attr; attr = attr->getNext()) {
|
i = d->specific_attr_begin<OwnershipAttr>(),
|
||||||
if (const OwnershipAttr* Att = dyn_cast<OwnershipAttr>(attr)) {
|
e = d->specific_attr_end<OwnershipAttr>();
|
||||||
// Two ownership attributes of the same kind can't conflict,
|
i != e; ++i) {
|
||||||
// except returns attributes.
|
if ((*i)->getOwnKind() != K) {
|
||||||
if (Att->getKind() != K) {
|
for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end();
|
||||||
for (const unsigned *I = Att->begin(), *E = Att->end(); I!=E; ++I) {
|
I!=E; ++I) {
|
||||||
if (x == *I) {
|
if (x == *I) {
|
||||||
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
|
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
|
||||||
<< AL.getName()->getName() << "ownership_*";
|
<< AL.getName()->getName() << "ownership_*";
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -519,33 +519,14 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
|
||||||
unsigned* start = OwnershipArgs.data();
|
unsigned* start = OwnershipArgs.data();
|
||||||
unsigned size = OwnershipArgs.size();
|
unsigned size = OwnershipArgs.size();
|
||||||
llvm::array_pod_sort(start, start + size);
|
llvm::array_pod_sort(start, start + size);
|
||||||
switch (K) {
|
|
||||||
case attr::OwnershipTakes: {
|
if (K != OwnershipAttr::Returns && OwnershipArgs.empty()) {
|
||||||
if (OwnershipArgs.empty()) {
|
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
|
||||||
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->addAttr(::new (S.Context) OwnershipTakesAttr(S.Context, start, size,
|
|
||||||
Module));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case attr::OwnershipHolds: {
|
|
||||||
if (OwnershipArgs.empty()) {
|
|
||||||
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->addAttr(::new (S.Context) OwnershipHoldsAttr(S.Context, start, size,
|
|
||||||
Module));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case attr::OwnershipReturns: {
|
|
||||||
d->addAttr(::new (S.Context) OwnershipReturnsAttr(S.Context, start, size,
|
|
||||||
Module));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
llvm_unreachable("Unknown ownership attribute");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d->addAttr(::new (S.Context) OwnershipAttr(AL.getLoc(), S.Context, K, Module,
|
||||||
|
start, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isStaticVarOrStaticFunciton(Decl *D) {
|
static bool isStaticVarOrStaticFunciton(Decl *D) {
|
||||||
|
@ -622,10 +603,10 @@ static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
}
|
}
|
||||||
// GCC will accept anything as the argument of weakref. Should we
|
// GCC will accept anything as the argument of weakref. Should we
|
||||||
// check for an existing decl?
|
// check for an existing decl?
|
||||||
d->addAttr(::new (S.Context) AliasAttr(S.Context, Str->getString()));
|
d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, Str->getString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) WeakRefAttr());
|
d->addAttr(::new (S.Context) WeakRefAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -647,7 +628,7 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
|
||||||
// FIXME: check if target symbol exists in current file
|
// FIXME: check if target symbol exists in current file
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) AliasAttr(S.Context, Str->getString()));
|
d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, Str->getString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
|
static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
|
||||||
|
@ -664,7 +645,7 @@ static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) AlwaysInlineAttr());
|
d->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -677,7 +658,7 @@ static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
|
||||||
QualType RetTy = FD->getResultType();
|
QualType RetTy = FD->getResultType();
|
||||||
if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
|
if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
|
||||||
d->addAttr(::new (S.Context) MallocAttr());
|
d->addAttr(::new (S.Context) MallocAttr(Attr.getLoc(), S.Context));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -711,13 +692,13 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
|
||||||
static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
/* Diagnostics (if any) was emitted by Sema::ProcessFnAttr(). */
|
/* Diagnostics (if any) was emitted by Sema::ProcessFnAttr(). */
|
||||||
assert(Attr.isInvalid() == false);
|
assert(Attr.isInvalid() == false);
|
||||||
d->addAttr(::new (S.Context) NoReturnAttr());
|
d->addAttr(::new (S.Context) NoReturnAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
|
static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
|
||||||
Sema &S) {
|
Sema &S) {
|
||||||
if (HandleCommonNoReturnAttr(d, Attr, S))
|
if (HandleCommonNoReturnAttr(d, Attr, S))
|
||||||
d->addAttr(::new (S.Context) AnalyzerNoReturnAttr());
|
d->addAttr(::new (S.Context) AnalyzerNoReturnAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
// PS3 PPU-specific.
|
// PS3 PPU-specific.
|
||||||
|
@ -756,7 +737,7 @@ static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) VecReturnAttr());
|
d->addAttr(::new (S.Context) VecReturnAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -782,7 +763,7 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) UnusedAttr());
|
d->addAttr(::new (S.Context) UnusedAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -803,7 +784,7 @@ static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) UsedAttr());
|
d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -833,7 +814,7 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) ConstructorAttr(priority));
|
d->addAttr(::new (S.Context) ConstructorAttr(Attr.getLoc(), S.Context, priority));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -863,7 +844,7 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) DestructorAttr(priority));
|
d->addAttr(::new (S.Context) DestructorAttr(Attr.getLoc(), S.Context, priority));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -873,7 +854,7 @@ static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) DeprecatedAttr());
|
d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -883,7 +864,7 @@ static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) UnavailableAttr());
|
d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -904,22 +885,22 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::StringRef TypeStr = Str->getString();
|
llvm::StringRef TypeStr = Str->getString();
|
||||||
VisibilityAttr::VisibilityTypes type;
|
VisibilityAttr::VisibilityType type;
|
||||||
|
|
||||||
if (TypeStr == "default")
|
if (TypeStr == "default")
|
||||||
type = VisibilityAttr::DefaultVisibility;
|
type = VisibilityAttr::Default;
|
||||||
else if (TypeStr == "hidden")
|
else if (TypeStr == "hidden")
|
||||||
type = VisibilityAttr::HiddenVisibility;
|
type = VisibilityAttr::Hidden;
|
||||||
else if (TypeStr == "internal")
|
else if (TypeStr == "internal")
|
||||||
type = VisibilityAttr::HiddenVisibility; // FIXME
|
type = VisibilityAttr::Hidden; // FIXME
|
||||||
else if (TypeStr == "protected")
|
else if (TypeStr == "protected")
|
||||||
type = VisibilityAttr::ProtectedVisibility;
|
type = VisibilityAttr::Protected;
|
||||||
else {
|
else {
|
||||||
S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
|
S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) VisibilityAttr(type, false));
|
d->addAttr(::new (S.Context) VisibilityAttr(Attr.getLoc(), S.Context, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
|
static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
|
||||||
|
@ -935,7 +916,7 @@ static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
D->addAttr(::new (S.Context) ObjCExceptionAttr());
|
D->addAttr(::new (S.Context) ObjCExceptionAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
|
static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -951,7 +932,7 @@ static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
D->addAttr(::new (S.Context) ObjCNSObjectAttr());
|
D->addAttr(::new (S.Context) ObjCNSObjectAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -966,7 +947,7 @@ HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
D->addAttr(::new (S.Context) OverloadableAttr());
|
D->addAttr(::new (S.Context) OverloadableAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -981,7 +962,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlocksAttr::BlocksAttrTypes type;
|
BlocksAttr::BlockType type;
|
||||||
if (Attr.getParameterName()->isStr("byref"))
|
if (Attr.getParameterName()->isStr("byref"))
|
||||||
type = BlocksAttr::ByRef;
|
type = BlocksAttr::ByRef;
|
||||||
else {
|
else {
|
||||||
|
@ -990,7 +971,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) BlocksAttr(type));
|
d->addAttr(::new (S.Context) BlocksAttr(Attr.getLoc(), S.Context, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -1083,7 +1064,7 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
<< Attr.getName() << 6 /*function, method or block */;
|
<< Attr.getName() << 6 /*function, method or block */;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
d->addAttr(::new (S.Context) SentinelAttr(sentinel, nullPos));
|
d->addAttr(::new (S.Context) SentinelAttr(Attr.getLoc(), S.Context, sentinel, nullPos));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) {
|
static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -1111,7 +1092,7 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
D->addAttr(::new (S.Context) WarnUnusedResultAttr());
|
D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -1135,7 +1116,7 @@ static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
D->addAttr(::new (S.Context) WeakAttr());
|
D->addAttr(::new (S.Context) WeakAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -1171,7 +1152,7 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
D->addAttr(::new (S.Context) WeakImportAttr());
|
D->addAttr(::new (S.Context) WeakImportAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
|
static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
|
||||||
|
@ -1194,7 +1175,8 @@ static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
|
||||||
}
|
}
|
||||||
WGSize[i] = (unsigned) ArgNum.getZExtValue();
|
WGSize[i] = (unsigned) ArgNum.getZExtValue();
|
||||||
}
|
}
|
||||||
D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(WGSize[0], WGSize[1],
|
D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(Attr.getLoc(), S.Context,
|
||||||
|
WGSize[0], WGSize[1],
|
||||||
WGSize[2]));
|
WGSize[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1228,7 +1210,7 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
D->addAttr(::new (S.Context) SectionAttr(S.Context, SE->getString()));
|
D->addAttr(::new (S.Context) SectionAttr(Attr.getLoc(), S.Context, SE->getString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1239,7 +1221,7 @@ static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) NoThrowAttr());
|
d->addAttr(::new (S.Context) NoThrowAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -1249,7 +1231,7 @@ static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) ConstAttr());
|
d->addAttr(::new (S.Context) ConstAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -1259,7 +1241,7 @@ static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) PureAttr());
|
d->addAttr(::new (S.Context) PureAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -1317,7 +1299,7 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) CleanupAttr(FD));
|
d->addAttr(::new (S.Context) CleanupAttr(Attr.getLoc(), S.Context, FD));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle __attribute__((format_arg((idx)))) attribute based on
|
/// Handle __attribute__((format_arg((idx)))) attribute based on
|
||||||
|
@ -1380,7 +1362,7 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue()));
|
d->addAttr(::new (S.Context) FormatArgAttr(Attr.getLoc(), S.Context, Idx.getZExtValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FormatAttrKind {
|
enum FormatAttrKind {
|
||||||
|
@ -1462,7 +1444,7 @@ static void HandleInitPriorityAttr(Decl *d, const AttributeList &Attr,
|
||||||
Attr.setInvalid();
|
Attr.setInvalid();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
d->addAttr(::new (S.Context) InitPriorityAttr(prioritynum));
|
d->addAttr(::new (S.Context) InitPriorityAttr(Attr.getLoc(), S.Context, prioritynum));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle __attribute__((format(type,idx,firstarg))) attributes based on
|
/// Handle __attribute__((format(type,idx,firstarg))) attributes based on
|
||||||
|
@ -1606,7 +1588,8 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) FormatAttr(S.Context, Format, Idx.getZExtValue(),
|
d->addAttr(::new (S.Context) FormatAttr(Attr.getLoc(), S.Context, Format,
|
||||||
|
Idx.getZExtValue(),
|
||||||
FirstArg.getZExtValue()));
|
FirstArg.getZExtValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1675,7 +1658,7 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RD->addAttr(::new (S.Context) TransparentUnionAttr());
|
RD->addAttr(::new (S.Context) TransparentUnionAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -1693,7 +1676,7 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate";
|
S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
d->addAttr(::new (S.Context) AnnotateAttr(S.Context, SE->getString()));
|
d->addAttr(::new (S.Context) AnnotateAttr(Attr.getLoc(), S.Context, SE->getString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -1708,9 +1691,7 @@ static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
// weaker alignment, rather than being silently ignored.
|
// weaker alignment, rather than being silently ignored.
|
||||||
|
|
||||||
if (Attr.getNumArgs() == 0) {
|
if (Attr.getNumArgs() == 0) {
|
||||||
// FIXME: This should be the target specific maximum alignment.
|
D->addAttr(::new (S.Context) AlignedAttr(Attr.getLoc(), S.Context, true, 0));
|
||||||
// (For now we just use 128 bits which is the maximum on X86).
|
|
||||||
D->addAttr(::new (S.Context) AlignedAttr(128));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1720,10 +1701,11 @@ static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) {
|
void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) {
|
||||||
if (E->isTypeDependent() || E->isValueDependent()) {
|
if (E->isTypeDependent() || E->isValueDependent()) {
|
||||||
// Save dependent expressions in the AST to be instantiated.
|
// Save dependent expressions in the AST to be instantiated.
|
||||||
D->addAttr(::new (Context) AlignedAttr(E));
|
D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Cache the number on the Attr object?
|
||||||
llvm::APSInt Alignment(32);
|
llvm::APSInt Alignment(32);
|
||||||
if (!E->isIntegerConstantExpr(Alignment, Context)) {
|
if (!E->isIntegerConstantExpr(Alignment, Context)) {
|
||||||
Diag(AttrLoc, diag::err_attribute_argument_not_int)
|
Diag(AttrLoc, diag::err_attribute_argument_not_int)
|
||||||
|
@ -1736,7 +1718,14 @@ void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
D->addAttr(::new (Context) AlignedAttr(Alignment.getZExtValue() * 8));
|
D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, TypeSourceInfo *TS) {
|
||||||
|
// FIXME: Cache the number on the Attr object if non-dependent?
|
||||||
|
// FIXME: Perform checking of type validity
|
||||||
|
D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, false, TS));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HandleModeAttr - This attribute modifies the width of a decl with primitive
|
/// HandleModeAttr - This attribute modifies the width of a decl with primitive
|
||||||
|
@ -1923,7 +1912,7 @@ static void HandleNoDebugAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) NoDebugAttr());
|
d->addAttr(::new (S.Context) NoDebugAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -1939,7 +1928,7 @@ static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) NoInlineAttr());
|
d->addAttr(::new (S.Context) NoInlineAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr,
|
static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr,
|
||||||
|
@ -1956,7 +1945,7 @@ static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) NoInstrumentFunctionAttr());
|
d->addAttr(::new (S.Context) NoInstrumentFunctionAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -1978,7 +1967,7 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) GNUInlineAttr());
|
d->addAttr(::new (S.Context) GNUInlineAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -1988,15 +1977,15 @@ static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
|
||||||
switch (Attr.getKind()) {
|
switch (Attr.getKind()) {
|
||||||
case AttributeList::AT_fastcall:
|
case AttributeList::AT_fastcall:
|
||||||
d->addAttr(::new (S.Context) FastCallAttr());
|
d->addAttr(::new (S.Context) FastCallAttr(Attr.getLoc(), S.Context));
|
||||||
return;
|
return;
|
||||||
case AttributeList::AT_stdcall:
|
case AttributeList::AT_stdcall:
|
||||||
d->addAttr(::new (S.Context) StdCallAttr());
|
d->addAttr(::new (S.Context) StdCallAttr(Attr.getLoc(), S.Context));
|
||||||
return;
|
return;
|
||||||
case AttributeList::AT_thiscall:
|
case AttributeList::AT_thiscall:
|
||||||
d->addAttr(::new (S.Context) ThisCallAttr());
|
d->addAttr(::new (S.Context) ThisCallAttr(Attr.getLoc(), S.Context));
|
||||||
case AttributeList::AT_cdecl:
|
case AttributeList::AT_cdecl:
|
||||||
d->addAttr(::new (S.Context) CDeclAttr());
|
d->addAttr(::new (S.Context) CDeclAttr(Attr.getLoc(), S.Context));
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
llvm_unreachable("unexpected attribute kind");
|
llvm_unreachable("unexpected attribute kind");
|
||||||
|
@ -2038,7 +2027,8 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue()));
|
d->addAttr(::new (S.Context) RegparmAttr(Attr.getLoc(), S.Context,
|
||||||
|
NumParams.getZExtValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -2064,7 +2054,7 @@ static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) FinalAttr());
|
d->addAttr(::new (S.Context) FinalAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -2090,7 +2080,7 @@ static void HandleBaseCheckAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) BaseCheckAttr());
|
d->addAttr(::new (S.Context) BaseCheckAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -2115,7 +2105,7 @@ static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) HidingAttr());
|
d->addAttr(::new (S.Context) HidingAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -2140,7 +2130,7 @@ static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) OverrideAttr());
|
d->addAttr(::new (S.Context) OverrideAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -2176,16 +2166,16 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr,
|
||||||
assert(0 && "invalid ownership attribute");
|
assert(0 && "invalid ownership attribute");
|
||||||
return;
|
return;
|
||||||
case AttributeList::AT_cf_returns_not_retained:
|
case AttributeList::AT_cf_returns_not_retained:
|
||||||
d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr());
|
d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(Attr.getLoc(), S.Context));
|
||||||
return;
|
return;
|
||||||
case AttributeList::AT_ns_returns_not_retained:
|
case AttributeList::AT_ns_returns_not_retained:
|
||||||
d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr());
|
d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(Attr.getLoc(), S.Context));
|
||||||
return;
|
return;
|
||||||
case AttributeList::AT_cf_returns_retained:
|
case AttributeList::AT_cf_returns_retained:
|
||||||
d->addAttr(::new (S.Context) CFReturnsRetainedAttr());
|
d->addAttr(::new (S.Context) CFReturnsRetainedAttr(Attr.getLoc(), S.Context));
|
||||||
return;
|
return;
|
||||||
case AttributeList::AT_ns_returns_retained:
|
case AttributeList::AT_ns_returns_retained:
|
||||||
d->addAttr(::new (S.Context) NSReturnsRetainedAttr());
|
d->addAttr(::new (S.Context) NSReturnsRetainedAttr(Attr.getLoc(), S.Context));
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2369,8 +2359,9 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
|
||||||
if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
|
if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
|
||||||
IdentifierInfo *NDId = ND->getIdentifier();
|
IdentifierInfo *NDId = ND->getIdentifier();
|
||||||
NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias());
|
NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias());
|
||||||
NewD->addAttr(::new (Context) AliasAttr(Context, NDId->getName()));
|
NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context,
|
||||||
NewD->addAttr(::new (Context) WeakAttr());
|
NDId->getName()));
|
||||||
|
NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
|
||||||
WeakTopLevelDecl.push_back(NewD);
|
WeakTopLevelDecl.push_back(NewD);
|
||||||
// FIXME: "hideous" code from Sema::LazilyCreateBuiltin
|
// FIXME: "hideous" code from Sema::LazilyCreateBuiltin
|
||||||
// to insert Decl at TU scope, sorry.
|
// to insert Decl at TU scope, sorry.
|
||||||
|
@ -2379,7 +2370,7 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
|
||||||
PushOnScopeChains(NewD, S);
|
PushOnScopeChains(NewD, S);
|
||||||
CurContext = SavedContext;
|
CurContext = SavedContext;
|
||||||
} else { // just add weak to existing
|
} else { // just add weak to existing
|
||||||
ND->addAttr(::new (Context) WeakAttr());
|
ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3292,7 +3292,7 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
|
||||||
ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
|
ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
|
||||||
|
|
||||||
if (const VisibilityAttr *attr = Namespc->getAttr<VisibilityAttr>())
|
if (const VisibilityAttr *attr = Namespc->getAttr<VisibilityAttr>())
|
||||||
PushPragmaVisibility(attr->getVisibility());
|
PushPragmaVisibility(attr->getVisibility(), attr->getLocation());
|
||||||
|
|
||||||
if (II) {
|
if (II) {
|
||||||
// C++ [namespace.def]p2:
|
// C++ [namespace.def]p2:
|
||||||
|
|
|
@ -1454,13 +1454,14 @@ CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
bool containsInvalidMethodImplAttribute(const AttributeList *A) {
|
bool containsInvalidMethodImplAttribute(const AttrVec &A) {
|
||||||
// The 'ibaction' attribute is allowed on method definitions because of
|
// The 'ibaction' attribute is allowed on method definitions because of
|
||||||
// how the IBAction macro is used on both method declarations and definitions.
|
// how the IBAction macro is used on both method declarations and definitions.
|
||||||
// If the method definitions contains any other attributes, return true.
|
// If the method definitions contains any other attributes, return true.
|
||||||
while (A && A->getKind() == AttributeList::AT_IBAction)
|
for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i)
|
||||||
A = A->getNext();
|
if ((*i)->getKind() != attr::IBAction)
|
||||||
return A != NULL;
|
return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
|
Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
|
||||||
|
@ -1590,7 +1591,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
|
||||||
}
|
}
|
||||||
InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel,
|
InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel,
|
||||||
MethodType == tok::minus);
|
MethodType == tok::minus);
|
||||||
if (containsInvalidMethodImplAttribute(AttrList))
|
if (ObjCMethod->hasAttrs() &&
|
||||||
|
containsInvalidMethodImplAttribute(ObjCMethod->getAttrs()))
|
||||||
Diag(EndLoc, diag::warn_attribute_method_def);
|
Diag(EndLoc, diag::warn_attribute_method_def);
|
||||||
} else if (ObjCCategoryImplDecl *CatImpDecl =
|
} else if (ObjCCategoryImplDecl *CatImpDecl =
|
||||||
dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {
|
dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {
|
||||||
|
@ -1601,7 +1603,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
|
||||||
PrevMethod = CatImpDecl->getClassMethod(Sel);
|
PrevMethod = CatImpDecl->getClassMethod(Sel);
|
||||||
CatImpDecl->addClassMethod(ObjCMethod);
|
CatImpDecl->addClassMethod(ObjCMethod);
|
||||||
}
|
}
|
||||||
if (containsInvalidMethodImplAttribute(AttrList))
|
if (ObjCMethod->hasAttrs() &&
|
||||||
|
containsInvalidMethodImplAttribute(ObjCMethod->getAttrs()))
|
||||||
Diag(EndLoc, diag::warn_attribute_method_def);
|
Diag(EndLoc, diag::warn_attribute_method_def);
|
||||||
}
|
}
|
||||||
if (PrevMethod) {
|
if (PrevMethod) {
|
||||||
|
@ -1613,8 +1616,10 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
|
||||||
|
|
||||||
// If the interface declared this method, and it was deprecated there,
|
// If the interface declared this method, and it was deprecated there,
|
||||||
// mark it deprecated here.
|
// mark it deprecated here.
|
||||||
if (InterfaceMD && InterfaceMD->hasAttr<DeprecatedAttr>())
|
if (InterfaceMD)
|
||||||
ObjCMethod->addAttr(::new (Context) DeprecatedAttr());
|
if (Attr *DA = InterfaceMD->getAttr<DeprecatedAttr>())
|
||||||
|
ObjCMethod->addAttr(::new (Context) DeprecatedAttr(DA->getLocation(),
|
||||||
|
Context));
|
||||||
|
|
||||||
return DeclPtrTy::make(ObjCMethod);
|
return DeclPtrTy::make(ObjCMethod);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1259,7 +1259,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
|
||||||
// FIXME: Do we need to check for default arguments here?
|
// FIXME: Do we need to check for default arguments here?
|
||||||
if (Func->getNumParams() == 1 && InitialParamType == Argument) {
|
if (Func->getNumParams() == 1 && InitialParamType == Argument) {
|
||||||
if(AddMallocAttr && !Func->hasAttr<MallocAttr>())
|
if(AddMallocAttr && !Func->hasAttr<MallocAttr>())
|
||||||
Func->addAttr(::new (Context) MallocAttr());
|
Func->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1287,7 +1287,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
|
||||||
Alloc->setImplicit();
|
Alloc->setImplicit();
|
||||||
|
|
||||||
if (AddMallocAttr)
|
if (AddMallocAttr)
|
||||||
Alloc->addAttr(::new (Context) MallocAttr());
|
Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
|
||||||
|
|
||||||
ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
|
ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
|
||||||
0, Argument, /*TInfo=*/0,
|
0, Argument, /*TInfo=*/0,
|
||||||
|
|
|
@ -4031,7 +4031,7 @@ Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
|
||||||
/// \brief Strips various properties off an implicit instantiation
|
/// \brief Strips various properties off an implicit instantiation
|
||||||
/// that has just been explicitly specialized.
|
/// that has just been explicitly specialized.
|
||||||
static void StripImplicitInstantiation(NamedDecl *D) {
|
static void StripImplicitInstantiation(NamedDecl *D) {
|
||||||
D->invalidateAttrs();
|
D->dropAttrs();
|
||||||
|
|
||||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||||
FD->setInlineSpecified(false);
|
FD->setInlineSpecified(false);
|
||||||
|
|
|
@ -140,21 +140,30 @@ bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
|
||||||
// FIXME: Is this still too simple?
|
// FIXME: Is this still too simple?
|
||||||
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
|
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||||
Decl *Tmpl, Decl *New) {
|
Decl *Tmpl, Decl *New) {
|
||||||
for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr;
|
for (AttrVec::const_iterator i = Tmpl->attr_begin(), e = Tmpl->attr_end();
|
||||||
TmplAttr = TmplAttr->getNext()) {
|
i != e; ++i) {
|
||||||
|
const Attr *TmplAttr = *i;
|
||||||
// FIXME: This should be generalized to more than just the AlignedAttr.
|
// FIXME: This should be generalized to more than just the AlignedAttr.
|
||||||
if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) {
|
if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) {
|
||||||
if (Aligned->isDependent()) {
|
if (Aligned->isAlignmentDependent()) {
|
||||||
// The alignment expression is not potentially evaluated.
|
// The alignment expression is not potentially evaluated.
|
||||||
EnterExpressionEvaluationContext Unevaluated(*this,
|
EnterExpressionEvaluationContext Unevaluated(*this,
|
||||||
Action::Unevaluated);
|
Action::Unevaluated);
|
||||||
|
|
||||||
OwningExprResult Result = SubstExpr(Aligned->getAlignmentExpr(),
|
if (Aligned->isAlignmentExpr()) {
|
||||||
TemplateArgs);
|
OwningExprResult Result = SubstExpr(Aligned->getAlignmentExpr(),
|
||||||
if (!Result.isInvalid())
|
TemplateArgs);
|
||||||
// FIXME: Is this the correct source location?
|
if (!Result.isInvalid())
|
||||||
AddAlignedAttr(Aligned->getAlignmentExpr()->getExprLoc(),
|
AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>());
|
||||||
New, Result.takeAs<Expr>());
|
}
|
||||||
|
else {
|
||||||
|
TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(),
|
||||||
|
TemplateArgs,
|
||||||
|
Aligned->getLocation(),
|
||||||
|
DeclarationName());
|
||||||
|
if (Result)
|
||||||
|
AddAlignedAttr(Aligned->getLocation(), New, Result);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,8 +51,8 @@ static void HandleMSP430InterruptAttr(Decl *d,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->addAttr(::new (S.Context) MSP430InterruptAttr(Num));
|
d->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num));
|
||||||
d->addAttr(::new (S.Context) UsedAttr());
|
d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -97,7 +97,7 @@ static void HandleX86ForceAlignArgPointerAttr(Decl *D,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr());
|
D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -109,7 +109,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
|
|
||||||
// Attribute can be applied only to functions or variables.
|
// Attribute can be applied only to functions or variables.
|
||||||
if (isa<VarDecl>(D)) {
|
if (isa<VarDecl>(D)) {
|
||||||
D->addAttr(::new (S.Context) DLLImportAttr());
|
D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
D->addAttr(::new (S.Context) DLLImportAttr());
|
D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
|
@ -158,7 +158,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
|
|
||||||
// Attribute can be applied only to functions or variables.
|
// Attribute can be applied only to functions or variables.
|
||||||
if (isa<VarDecl>(D)) {
|
if (isa<VarDecl>(D)) {
|
||||||
D->addAttr(::new (S.Context) DLLExportAttr());
|
D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +177,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
D->addAttr(::new (S.Context) DLLExportAttr());
|
D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -13,6 +13,8 @@ add_clang_library(clangSerialization
|
||||||
add_dependencies(clangSerialization
|
add_dependencies(clangSerialization
|
||||||
ClangAttrClasses
|
ClangAttrClasses
|
||||||
ClangAttrList
|
ClangAttrList
|
||||||
|
ClangAttrPCHRead
|
||||||
|
ClangAttrPCHWrite
|
||||||
ClangDiagnosticFrontend
|
ClangDiagnosticFrontend
|
||||||
ClangDiagnosticLex
|
ClangDiagnosticLex
|
||||||
ClangDiagnosticSema
|
ClangDiagnosticSema
|
||||||
|
|
|
@ -148,8 +148,11 @@ void PCHDeclReader::VisitDecl(Decl *D) {
|
||||||
cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
|
cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
|
||||||
D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||||
D->setInvalidDecl(Record[Idx++]);
|
D->setInvalidDecl(Record[Idx++]);
|
||||||
if (Record[Idx++])
|
if (Record[Idx++]) {
|
||||||
D->initAttrs(Reader.ReadAttributes(Cursor));
|
AttrVec Attrs;
|
||||||
|
Reader.ReadAttributes(Cursor, Attrs);
|
||||||
|
D->setAttrs(Attrs);
|
||||||
|
}
|
||||||
D->setImplicit(Record[Idx++]);
|
D->setImplicit(Record[Idx++]);
|
||||||
D->setUsed(Record[Idx++]);
|
D->setUsed(Record[Idx++]);
|
||||||
D->setAccess((AccessSpecifier)Record[Idx++]);
|
D->setAccess((AccessSpecifier)Record[Idx++]);
|
||||||
|
@ -1091,7 +1094,8 @@ void PCHDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// \brief Reads attributes from the current stream position.
|
/// \brief Reads attributes from the current stream position.
|
||||||
Attr *PCHReader::ReadAttributes(llvm::BitstreamCursor &DeclsCursor) {
|
void PCHReader::ReadAttributes(llvm::BitstreamCursor &DeclsCursor,
|
||||||
|
AttrVec &Attrs) {
|
||||||
unsigned Code = DeclsCursor.ReadCode();
|
unsigned Code = DeclsCursor.ReadCode();
|
||||||
assert(Code == llvm::bitc::UNABBREV_RECORD &&
|
assert(Code == llvm::bitc::UNABBREV_RECORD &&
|
||||||
"Expected unabbreviated record"); (void)Code;
|
"Expected unabbreviated record"); (void)Code;
|
||||||
|
@ -1102,174 +1106,18 @@ Attr *PCHReader::ReadAttributes(llvm::BitstreamCursor &DeclsCursor) {
|
||||||
assert(RecCode == pch::DECL_ATTR && "Expected attribute record");
|
assert(RecCode == pch::DECL_ATTR && "Expected attribute record");
|
||||||
(void)RecCode;
|
(void)RecCode;
|
||||||
|
|
||||||
#define SIMPLE_ATTR(Name) \
|
|
||||||
case attr::Name: \
|
|
||||||
New = ::new (*Context) Name##Attr(); \
|
|
||||||
break
|
|
||||||
|
|
||||||
#define STRING_ATTR(Name) \
|
|
||||||
case attr::Name: \
|
|
||||||
New = ::new (*Context) Name##Attr(*Context, ReadString(Record, Idx)); \
|
|
||||||
break
|
|
||||||
|
|
||||||
#define UNSIGNED_ATTR(Name) \
|
|
||||||
case attr::Name: \
|
|
||||||
New = ::new (*Context) Name##Attr(Record[Idx++]); \
|
|
||||||
break
|
|
||||||
|
|
||||||
Attr *Attrs = 0;
|
|
||||||
while (Idx < Record.size()) {
|
while (Idx < Record.size()) {
|
||||||
Attr *New = 0;
|
Attr *New = 0;
|
||||||
attr::Kind Kind = (attr::Kind)Record[Idx++];
|
attr::Kind Kind = (attr::Kind)Record[Idx++];
|
||||||
bool IsInherited = Record[Idx++];
|
SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[Idx++]);
|
||||||
|
bool isInherited = Record[Idx++];
|
||||||
|
|
||||||
switch (Kind) {
|
#include "clang/Serialization/AttrPCHRead.inc"
|
||||||
default:
|
|
||||||
assert(0 && "Unknown attribute!");
|
|
||||||
break;
|
|
||||||
STRING_ATTR(Alias);
|
|
||||||
SIMPLE_ATTR(AlignMac68k);
|
|
||||||
UNSIGNED_ATTR(Aligned);
|
|
||||||
SIMPLE_ATTR(AlwaysInline);
|
|
||||||
SIMPLE_ATTR(AnalyzerNoReturn);
|
|
||||||
STRING_ATTR(Annotate);
|
|
||||||
STRING_ATTR(AsmLabel);
|
|
||||||
SIMPLE_ATTR(BaseCheck);
|
|
||||||
|
|
||||||
case attr::Blocks:
|
|
||||||
New = ::new (*Context) BlocksAttr(
|
|
||||||
(BlocksAttr::BlocksAttrTypes)Record[Idx++]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
SIMPLE_ATTR(CDecl);
|
|
||||||
|
|
||||||
case attr::Cleanup:
|
|
||||||
New = ::new (*Context) CleanupAttr(
|
|
||||||
cast<FunctionDecl>(GetDecl(Record[Idx++])));
|
|
||||||
break;
|
|
||||||
|
|
||||||
SIMPLE_ATTR(Const);
|
|
||||||
UNSIGNED_ATTR(Constructor);
|
|
||||||
SIMPLE_ATTR(DLLExport);
|
|
||||||
SIMPLE_ATTR(DLLImport);
|
|
||||||
SIMPLE_ATTR(Deprecated);
|
|
||||||
UNSIGNED_ATTR(Destructor);
|
|
||||||
SIMPLE_ATTR(FastCall);
|
|
||||||
SIMPLE_ATTR(Final);
|
|
||||||
|
|
||||||
case attr::Format: {
|
|
||||||
std::string Type = ReadString(Record, Idx);
|
|
||||||
unsigned FormatIdx = Record[Idx++];
|
|
||||||
unsigned FirstArg = Record[Idx++];
|
|
||||||
New = ::new (*Context) FormatAttr(*Context, Type, FormatIdx, FirstArg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case attr::FormatArg: {
|
|
||||||
unsigned FormatIdx = Record[Idx++];
|
|
||||||
New = ::new (*Context) FormatArgAttr(FormatIdx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case attr::Sentinel: {
|
|
||||||
int sentinel = Record[Idx++];
|
|
||||||
int nullPos = Record[Idx++];
|
|
||||||
New = ::new (*Context) SentinelAttr(sentinel, nullPos);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
SIMPLE_ATTR(GNUInline);
|
|
||||||
SIMPLE_ATTR(Hiding);
|
|
||||||
|
|
||||||
case attr::IBAction:
|
|
||||||
New = ::new (*Context) IBActionAttr();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::IBOutlet:
|
|
||||||
New = ::new (*Context) IBOutletAttr();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::IBOutletCollection: {
|
|
||||||
QualType QT = GetType(Record[Idx++]);
|
|
||||||
New = ::new (*Context) IBOutletCollectionAttr(QT);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
SIMPLE_ATTR(Malloc);
|
|
||||||
SIMPLE_ATTR(NoDebug);
|
|
||||||
SIMPLE_ATTR(NoInline);
|
|
||||||
SIMPLE_ATTR(NoReturn);
|
|
||||||
SIMPLE_ATTR(NoThrow);
|
|
||||||
|
|
||||||
case attr::NonNull: {
|
|
||||||
unsigned Size = Record[Idx++];
|
|
||||||
llvm::SmallVector<unsigned, 16> ArgNums;
|
|
||||||
ArgNums.insert(ArgNums.end(), &Record[Idx], &Record[Idx] + Size);
|
|
||||||
Idx += Size;
|
|
||||||
New = ::new (*Context) NonNullAttr(*Context, ArgNums.data(), Size);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case attr::ReqdWorkGroupSize: {
|
|
||||||
unsigned X = Record[Idx++];
|
|
||||||
unsigned Y = Record[Idx++];
|
|
||||||
unsigned Z = Record[Idx++];
|
|
||||||
New = ::new (*Context) ReqdWorkGroupSizeAttr(X, Y, Z);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
SIMPLE_ATTR(ObjCException);
|
|
||||||
SIMPLE_ATTR(ObjCNSObject);
|
|
||||||
SIMPLE_ATTR(CFReturnsNotRetained);
|
|
||||||
SIMPLE_ATTR(CFReturnsRetained);
|
|
||||||
SIMPLE_ATTR(NSReturnsNotRetained);
|
|
||||||
SIMPLE_ATTR(NSReturnsRetained);
|
|
||||||
SIMPLE_ATTR(Overloadable);
|
|
||||||
SIMPLE_ATTR(Override);
|
|
||||||
SIMPLE_ATTR(Packed);
|
|
||||||
UNSIGNED_ATTR(MaxFieldAlignment);
|
|
||||||
SIMPLE_ATTR(Pure);
|
|
||||||
UNSIGNED_ATTR(Regparm);
|
|
||||||
STRING_ATTR(Section);
|
|
||||||
SIMPLE_ATTR(StdCall);
|
|
||||||
SIMPLE_ATTR(ThisCall);
|
|
||||||
SIMPLE_ATTR(TransparentUnion);
|
|
||||||
SIMPLE_ATTR(Unavailable);
|
|
||||||
SIMPLE_ATTR(Unused);
|
|
||||||
SIMPLE_ATTR(Used);
|
|
||||||
|
|
||||||
case attr::Visibility:
|
|
||||||
New = ::new (*Context) VisibilityAttr(
|
|
||||||
(VisibilityAttr::VisibilityTypes)Record[Idx++],
|
|
||||||
(bool)Record[Idx++]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
SIMPLE_ATTR(WarnUnusedResult);
|
|
||||||
SIMPLE_ATTR(Weak);
|
|
||||||
SIMPLE_ATTR(WeakRef);
|
|
||||||
SIMPLE_ATTR(WeakImport);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(New && "Unable to decode attribute?");
|
assert(New && "Unable to decode attribute?");
|
||||||
New->setInherited(IsInherited);
|
New->setInherited(isInherited);
|
||||||
New->setNext(Attrs);
|
Attrs.push_back(New);
|
||||||
Attrs = New;
|
|
||||||
}
|
}
|
||||||
#undef UNSIGNED_ATTR
|
|
||||||
#undef STRING_ATTR
|
|
||||||
#undef SIMPLE_ATTR
|
|
||||||
|
|
||||||
// The list of attributes was built backwards. Reverse the list
|
|
||||||
// before returning it.
|
|
||||||
Attr *PrevAttr = 0, *NextAttr = 0;
|
|
||||||
while (Attrs) {
|
|
||||||
NextAttr = Attrs->getNext();
|
|
||||||
Attrs->setNext(PrevAttr);
|
|
||||||
PrevAttr = Attrs;
|
|
||||||
Attrs = NextAttr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PrevAttr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -1949,172 +1949,16 @@ void PCHWriter::WriteIdentifierTable(Preprocessor &PP) {
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// \brief Write a record containing the given attributes.
|
/// \brief Write a record containing the given attributes.
|
||||||
void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
|
void PCHWriter::WriteAttributeRecord(const AttrVec &Attrs) {
|
||||||
RecordData Record;
|
RecordData Record;
|
||||||
for (; Attr; Attr = Attr->getNext()) {
|
for (AttrVec::const_iterator i = Attrs.begin(), e = Attrs.end(); i != e; ++i){
|
||||||
Record.push_back(Attr->getKind()); // FIXME: stable encoding, target attrs
|
const Attr * A = *i;
|
||||||
Record.push_back(Attr->isInherited());
|
Record.push_back(A->getKind()); // FIXME: stable encoding, target attrs
|
||||||
switch (Attr->getKind()) {
|
AddSourceLocation(A->getLocation(), Record);
|
||||||
default:
|
Record.push_back(A->isInherited());
|
||||||
assert(0 && "Does not support PCH writing for this attribute yet!");
|
|
||||||
break;
|
|
||||||
case attr::Alias:
|
|
||||||
AddString(cast<AliasAttr>(Attr)->getAliasee(), Record);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::AlignMac68k:
|
#include "clang/Serialization/AttrPCHWrite.inc"
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::Aligned:
|
|
||||||
Record.push_back(cast<AlignedAttr>(Attr)->getAlignment());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::AlwaysInline:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::AnalyzerNoReturn:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::Annotate:
|
|
||||||
AddString(cast<AnnotateAttr>(Attr)->getAnnotation(), Record);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::AsmLabel:
|
|
||||||
AddString(cast<AsmLabelAttr>(Attr)->getLabel(), Record);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::BaseCheck:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::Blocks:
|
|
||||||
Record.push_back(cast<BlocksAttr>(Attr)->getType()); // FIXME: stable
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::CDecl:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::Cleanup:
|
|
||||||
AddDeclRef(cast<CleanupAttr>(Attr)->getFunctionDecl(), Record);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::Const:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::Constructor:
|
|
||||||
Record.push_back(cast<ConstructorAttr>(Attr)->getPriority());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::DLLExport:
|
|
||||||
case attr::DLLImport:
|
|
||||||
case attr::Deprecated:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::Destructor:
|
|
||||||
Record.push_back(cast<DestructorAttr>(Attr)->getPriority());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::FastCall:
|
|
||||||
case attr::Final:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::Format: {
|
|
||||||
const FormatAttr *Format = cast<FormatAttr>(Attr);
|
|
||||||
AddString(Format->getType(), Record);
|
|
||||||
Record.push_back(Format->getFormatIdx());
|
|
||||||
Record.push_back(Format->getFirstArg());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case attr::FormatArg: {
|
|
||||||
const FormatArgAttr *Format = cast<FormatArgAttr>(Attr);
|
|
||||||
Record.push_back(Format->getFormatIdx());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case attr::Sentinel : {
|
|
||||||
const SentinelAttr *Sentinel = cast<SentinelAttr>(Attr);
|
|
||||||
Record.push_back(Sentinel->getSentinel());
|
|
||||||
Record.push_back(Sentinel->getNullPos());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case attr::GNUInline:
|
|
||||||
case attr::Hiding:
|
|
||||||
case attr::IBAction:
|
|
||||||
case attr::IBOutlet:
|
|
||||||
case attr::Malloc:
|
|
||||||
case attr::NoDebug:
|
|
||||||
case attr::NoInline:
|
|
||||||
case attr::NoReturn:
|
|
||||||
case attr::NoThrow:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::IBOutletCollection: {
|
|
||||||
const IBOutletCollectionAttr *ICA = cast<IBOutletCollectionAttr>(Attr);
|
|
||||||
AddTypeRef(ICA->getType(), Record);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case attr::NonNull: {
|
|
||||||
const NonNullAttr *NonNull = cast<NonNullAttr>(Attr);
|
|
||||||
Record.push_back(NonNull->size());
|
|
||||||
Record.insert(Record.end(), NonNull->begin(), NonNull->end());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case attr::CFReturnsNotRetained:
|
|
||||||
case attr::CFReturnsRetained:
|
|
||||||
case attr::NSReturnsNotRetained:
|
|
||||||
case attr::NSReturnsRetained:
|
|
||||||
case attr::ObjCException:
|
|
||||||
case attr::ObjCNSObject:
|
|
||||||
case attr::Overloadable:
|
|
||||||
case attr::Override:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::MaxFieldAlignment:
|
|
||||||
Record.push_back(cast<MaxFieldAlignmentAttr>(Attr)->getAlignment());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::Packed:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::Pure:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::Regparm:
|
|
||||||
Record.push_back(cast<RegparmAttr>(Attr)->getNumParams());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::ReqdWorkGroupSize:
|
|
||||||
Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getXDim());
|
|
||||||
Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getYDim());
|
|
||||||
Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getZDim());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::Section:
|
|
||||||
AddString(cast<SectionAttr>(Attr)->getName(), Record);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::StdCall:
|
|
||||||
case attr::TransparentUnion:
|
|
||||||
case attr::Unavailable:
|
|
||||||
case attr::Unused:
|
|
||||||
case attr::Used:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::Visibility:
|
|
||||||
// FIXME: stable encoding
|
|
||||||
Record.push_back(cast<VisibilityAttr>(Attr)->getVisibility());
|
|
||||||
Record.push_back(cast<VisibilityAttr>(Attr)->isFromPragma());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case attr::WarnUnusedResult:
|
|
||||||
case attr::Weak:
|
|
||||||
case attr::WeakRef:
|
|
||||||
case attr::WeakImport:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream.EmitRecord(pch::DECL_ATTR, Record);
|
Stream.EmitRecord(pch::DECL_ATTR, Record);
|
||||||
|
|
|
@ -1144,8 +1144,9 @@ bool CursorVisitor::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
|
||||||
|
|
||||||
|
|
||||||
bool CursorVisitor::VisitAttributes(Decl *D) {
|
bool CursorVisitor::VisitAttributes(Decl *D) {
|
||||||
for (const Attr *A = D->getAttrs(); A; A = A->getNext())
|
for (AttrVec::const_iterator i = D->attr_begin(), e = D->attr_end();
|
||||||
if (Visit(MakeCXCursor(A, D, TU)))
|
i != e; ++i)
|
||||||
|
if (Visit(MakeCXCursor(*i, D, TU)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче