forked from OSchip/llvm-project
Unifies the name-lookup mechanisms used in various parts of the AST
and separates lexical name lookup from qualified name lookup. In particular: * Make DeclContext the central data structure for storing and looking up declarations within existing declarations, e.g., members of structs/unions/classes, enumerators in C++0x enums, members of C++ namespaces, and (later) members of Objective-C interfaces/implementations. DeclContext uses a lazily-constructed data structure optimized for fast lookup (array for small contexts, hash table for larger contexts). * Implement C++ qualified name lookup in terms of lookup into DeclContext. * Implement C++ unqualified name lookup in terms of qualified+unqualified name lookup (since unqualified lookup is not purely lexical in C++!) * Limit the use of the chains of declarations stored in IdentifierInfo to those names declared lexically. * Eliminate CXXFieldDecl, collapsing its behavior into FieldDecl. (FieldDecl is now a ScopedDecl). * Make RecordDecl into a DeclContext and eliminates its Members/NumMembers fields (since one can just iterate through the DeclContext to get the fields). llvm-svn: 60878
This commit is contained in:
parent
32bfb5de34
commit
91f84216f7
|
@ -185,13 +185,14 @@ namespace {
|
|||
|
||||
/// Act on @defs() element found when parsing a structure. ClassName is the
|
||||
/// name of the referenced class.
|
||||
virtual void ActOnDefs(Scope *S, SourceLocation DeclStart,
|
||||
virtual void ActOnDefs(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
|
||||
IdentifierInfo *ClassName,
|
||||
llvm::SmallVectorImpl<DeclTy*> &Decls) {
|
||||
llvm::cout << __FUNCTION__ << "\n";
|
||||
}
|
||||
|
||||
virtual DeclTy *ActOnField(Scope *S, SourceLocation DeclStart,
|
||||
virtual DeclTy *ActOnField(Scope *S, DeclTy *TagD,
|
||||
SourceLocation DeclStart,
|
||||
Declarator &D, ExprTy *BitfieldWidth) {
|
||||
llvm::cout << __FUNCTION__ << "\n";
|
||||
return 0;
|
||||
|
|
|
@ -2169,14 +2169,18 @@ QualType RewriteObjC::getSuperStructType() {
|
|||
FieldTypes[0] = Context->getObjCIdType();
|
||||
// struct objc_class *super;
|
||||
FieldTypes[1] = Context->getObjCClassType();
|
||||
|
||||
// Create fields
|
||||
FieldDecl *FieldDecls[2];
|
||||
for (unsigned i = 0; i < 2; ++i) {
|
||||
SuperStructDecl->addDecl(*Context,
|
||||
FieldDecl::Create(*Context, SuperStructDecl,
|
||||
SourceLocation(), 0,
|
||||
FieldTypes[i], /*BitWidth=*/0,
|
||||
/*Mutable=*/false, 0),
|
||||
true);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < 2; ++i)
|
||||
FieldDecls[i] = FieldDecl::Create(*Context, SourceLocation(), 0,
|
||||
FieldTypes[i]);
|
||||
|
||||
SuperStructDecl->defineBody(*Context, FieldDecls, 4);
|
||||
SuperStructDecl->completeDefinition(*Context);
|
||||
}
|
||||
return Context->getTagDeclType(SuperStructDecl);
|
||||
}
|
||||
|
@ -2196,14 +2200,20 @@ QualType RewriteObjC::getConstantStringStructType() {
|
|||
FieldTypes[2] = Context->getPointerType(Context->CharTy);
|
||||
// long length;
|
||||
FieldTypes[3] = Context->LongTy;
|
||||
|
||||
// Create fields
|
||||
FieldDecl *FieldDecls[4];
|
||||
|
||||
for (unsigned i = 0; i < 4; ++i)
|
||||
FieldDecls[i] = FieldDecl::Create(*Context, SourceLocation(), 0,
|
||||
FieldTypes[i]);
|
||||
|
||||
ConstantStringDecl->defineBody(*Context, FieldDecls, 4);
|
||||
for (unsigned i = 0; i < 4; ++i) {
|
||||
ConstantStringDecl->addDecl(*Context,
|
||||
FieldDecl::Create(*Context,
|
||||
ConstantStringDecl,
|
||||
SourceLocation(), 0,
|
||||
FieldTypes[i],
|
||||
/*BitWidth=*/0,
|
||||
/*Mutable=*/true, 0),
|
||||
true);
|
||||
}
|
||||
|
||||
ConstantStringDecl->completeDefinition(*Context);
|
||||
}
|
||||
return Context->getTagDeclType(ConstantStringDecl);
|
||||
}
|
||||
|
@ -3788,8 +3798,9 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp) {
|
|||
ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), BlkCast);
|
||||
//PE->dump();
|
||||
|
||||
FieldDecl *FD = FieldDecl::Create(*Context, SourceLocation(),
|
||||
&Context->Idents.get("FuncPtr"), Context->VoidPtrTy);
|
||||
FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
|
||||
&Context->Idents.get("FuncPtr"), Context->VoidPtrTy,
|
||||
/*BitWidth=*/0, /*Mutable=*/true, 0);
|
||||
MemberExpr *ME = new MemberExpr(PE, true, FD, SourceLocation(), FD->getType());
|
||||
|
||||
CastExpr *FunkCast = new CStyleCastExpr(PtrToFuncCastType, ME, PtrToFuncCastType, SourceLocation(), SourceLocation());
|
||||
|
|
|
@ -513,10 +513,12 @@ private:
|
|||
void InitBuiltinTypes();
|
||||
void InitBuiltinType(QualType &R, BuiltinType::Kind K);
|
||||
|
||||
/// setRecordDefinition - Used by RecordDecl::defineBody to inform ASTContext
|
||||
/// about which RecordDecl serves as the definition of a particular
|
||||
/// struct/union/class. This will eventually be used by enums as well.
|
||||
/// setTagDefinition - Used by RecordDecl::completeDefinition and
|
||||
/// EnumDecl::completeDefinition to inform
|
||||
/// about which RecordDecl/EnumDecl serves as the definition of a particular
|
||||
/// struct/union/class/enum.
|
||||
void setTagDefinition(TagDecl* R);
|
||||
friend class EnumDecl;
|
||||
friend class RecordDecl;
|
||||
|
||||
// Return the ObjC type encoding for a given type.
|
||||
|
|
|
@ -115,12 +115,6 @@ class ScopedDecl : public NamedDecl {
|
|||
/// such as "int X, Y, *Z;" this indicates Decl for the next declarator.
|
||||
ScopedDecl *NextDeclarator;
|
||||
|
||||
/// When this decl is in scope while parsing, the Next field contains a
|
||||
/// pointer to the shadowed decl of the same name. When the scope is popped,
|
||||
/// Decls are relinked onto a containing decl object.
|
||||
///
|
||||
ScopedDecl *Next;
|
||||
|
||||
/// DeclCtx - Holds either a DeclContext* or a MultipleDC*.
|
||||
/// For declarations that don't contain C++ scope specifiers, it contains
|
||||
/// the DeclContext where the ScopedDecl was declared.
|
||||
|
@ -150,7 +144,7 @@ class ScopedDecl : public NamedDecl {
|
|||
protected:
|
||||
ScopedDecl(Kind DK, DeclContext *DC, SourceLocation L,
|
||||
DeclarationName N, ScopedDecl *PrevDecl)
|
||||
: NamedDecl(DK, L, N), NextDeclarator(PrevDecl), Next(0),
|
||||
: NamedDecl(DK, L, N), NextDeclarator(PrevDecl),
|
||||
DeclCtx(reinterpret_cast<uintptr_t>(DC)) {}
|
||||
|
||||
virtual ~ScopedDecl();
|
||||
|
@ -188,9 +182,6 @@ public:
|
|||
|
||||
void setLexicalDeclContext(DeclContext *DC);
|
||||
|
||||
ScopedDecl *getNext() const { return Next; }
|
||||
void setNext(ScopedDecl *N) { Next = N; }
|
||||
|
||||
/// getNextDeclarator - If this decl was part of a multi-declarator
|
||||
/// declaration, such as "int X, Y, *Z;" this returns the decl for the next
|
||||
/// declarator. Otherwise it returns null.
|
||||
|
@ -680,22 +671,31 @@ protected:
|
|||
|
||||
/// FieldDecl - An instance of this class is created by Sema::ActOnField to
|
||||
/// represent a member of a struct/union/class.
|
||||
class FieldDecl : public NamedDecl {
|
||||
class FieldDecl : public ScopedDecl {
|
||||
bool Mutable : 1;
|
||||
QualType DeclType;
|
||||
Expr *BitWidth;
|
||||
protected:
|
||||
FieldDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, QualType T,
|
||||
Expr *BW = NULL)
|
||||
: NamedDecl(DK, L, Id), DeclType(T), BitWidth(BW) {}
|
||||
FieldDecl(SourceLocation L, IdentifierInfo *Id, QualType T, Expr *BW)
|
||||
: NamedDecl(Field, L, Id), DeclType(T), BitWidth(BW) {}
|
||||
FieldDecl(Kind DK, DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T, Expr *BW, bool Mutable,
|
||||
ScopedDecl *PrevDecl)
|
||||
: ScopedDecl(DK, DC, L, Id, PrevDecl), Mutable(Mutable), DeclType(T),
|
||||
BitWidth(BW)
|
||||
{ }
|
||||
|
||||
public:
|
||||
static FieldDecl *Create(ASTContext &C, SourceLocation L, IdentifierInfo *Id,
|
||||
QualType T, Expr *BW = NULL);
|
||||
static FieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T, Expr *BW,
|
||||
bool Mutable, ScopedDecl *PrevDecl);
|
||||
|
||||
QualType getType() const { return DeclType; }
|
||||
|
||||
|
||||
/// isMutable - Determines whether this field is mutable (C++ only).
|
||||
bool isMutable() const { return Mutable; }
|
||||
|
||||
/// isBitfield - Determines whether this field is a bitfield.
|
||||
bool isBitField() const { return BitWidth != NULL; }
|
||||
|
||||
Expr *getBitWidth() const { return BitWidth; }
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
|
@ -888,9 +888,6 @@ protected:
|
|||
/// EnumDecl - Represents an enum. As an extension, we allow forward-declared
|
||||
/// enums.
|
||||
class EnumDecl : public TagDecl, public DeclContext {
|
||||
// EnumDecl's DeclChain points to a linked list of EnumConstantDecl's which
|
||||
// are linked together through their getNextDeclarator pointers.
|
||||
|
||||
/// IntegerType - This represent the integer type that the enum corresponds
|
||||
/// to for code generation purposes. Note that the enumerator constants may
|
||||
/// have a different type than this does.
|
||||
|
@ -908,30 +905,46 @@ public:
|
|||
|
||||
virtual void Destroy(ASTContext& C);
|
||||
|
||||
/// defineElements - When created, EnumDecl correspond to a forward declared
|
||||
/// enum. This method is used to mark the decl as being defined, with the
|
||||
/// specified list of enums.
|
||||
void defineElements(EnumConstantDecl *ListHead, QualType NewType) {
|
||||
assert(!isDefinition() && "Cannot redefine enums!");
|
||||
setDeclChain(ListHead);
|
||||
setDefinition(true);
|
||||
|
||||
IntegerType = NewType;
|
||||
}
|
||||
/// completeDefinition - When created, the EnumDecl corresponds to a
|
||||
/// forward-declared enum. This method is used to mark the
|
||||
/// declaration as being defined; it's enumerators have already been
|
||||
/// added (via DeclContext::addDecl). NewType is the new underlying
|
||||
/// type of the enumeration type.
|
||||
void completeDefinition(ASTContext &C, QualType NewType);
|
||||
|
||||
// enumerator_iterator - Iterates through the enumerators of this
|
||||
// enumeration.
|
||||
struct enumerator_iterator : public DeclContext::decl_iterator {
|
||||
typedef EnumConstantDecl* value_type;
|
||||
typedef EnumConstantDecl* reference;
|
||||
typedef EnumConstantDecl* pointer;
|
||||
|
||||
enumerator_iterator() : DeclContext::decl_iterator() { }
|
||||
|
||||
explicit enumerator_iterator(DeclContext::decl_iterator Pos)
|
||||
: DeclContext::decl_iterator(Pos) { }
|
||||
|
||||
reference operator*() const {
|
||||
return cast<EnumConstantDecl>(DeclContext::decl_iterator::operator*());
|
||||
}
|
||||
|
||||
pointer operator->() const {
|
||||
return cast<EnumConstantDecl>(DeclContext::decl_iterator::operator*());
|
||||
}
|
||||
};
|
||||
|
||||
enumerator_iterator enumerator_begin() const {
|
||||
return enumerator_iterator(this->decls_begin());
|
||||
}
|
||||
|
||||
enumerator_iterator enumerator_end() const {
|
||||
return enumerator_iterator(this->decls_end());
|
||||
}
|
||||
|
||||
/// getIntegerType - Return the integer type this enum decl corresponds to.
|
||||
/// This returns a null qualtype for an enum forward definition.
|
||||
QualType getIntegerType() const { return IntegerType; }
|
||||
|
||||
/// getEnumConstantList - Return the first EnumConstantDecl in the enum.
|
||||
///
|
||||
EnumConstantDecl *getEnumConstantList() {
|
||||
return cast_or_null<EnumConstantDecl>(getDeclChain());
|
||||
}
|
||||
const EnumConstantDecl *getEnumConstantList() const {
|
||||
return cast_or_null<const EnumConstantDecl>(getDeclChain());
|
||||
}
|
||||
|
||||
|
||||
static bool classof(const Decl *D) { return D->getKind() == Enum; }
|
||||
static bool classof(const EnumDecl *D) { return true; }
|
||||
static DeclContext *castToDeclContext(const EnumDecl *D) {
|
||||
|
@ -957,16 +970,12 @@ protected:
|
|||
/// union Y { int A, B; }; // Has body with members A and B (FieldDecls).
|
||||
/// This decl will be marked invalid if *any* members are invalid.
|
||||
///
|
||||
class RecordDecl : public TagDecl {
|
||||
class RecordDecl : public TagDecl, public DeclContext {
|
||||
/// HasFlexibleArrayMember - This is true if this struct ends with a flexible
|
||||
/// array member (e.g. int X[]) or if this union contains a struct that does.
|
||||
/// If so, this cannot be contained in arrays or other structs as a member.
|
||||
bool HasFlexibleArrayMember : 1;
|
||||
|
||||
/// Members/NumMembers - This is a new[]'d array of pointers to Decls.
|
||||
FieldDecl **Members; // Null if not defined.
|
||||
int NumMembers; // -1 if not defined.
|
||||
|
||||
protected:
|
||||
RecordDecl(Kind DK, TagKind TK, DeclContext *DC,
|
||||
SourceLocation L, IdentifierInfo *Id);
|
||||
|
@ -993,42 +1002,74 @@ public:
|
|||
return cast_or_null<RecordDecl>(TagDecl::getDefinition(C));
|
||||
}
|
||||
|
||||
/// getNumMembers - Return the number of members, or -1 if this is a forward
|
||||
/// definition.
|
||||
int getNumMembers() const { return NumMembers; }
|
||||
const FieldDecl *getMember(unsigned i) const { return Members[i]; }
|
||||
FieldDecl *getMember(unsigned i) { return Members[i]; }
|
||||
|
||||
// Iterator access to field members.
|
||||
typedef FieldDecl **field_iterator;
|
||||
typedef FieldDecl * const *field_const_iterator;
|
||||
class field_iterator {
|
||||
/// Current - Current position within the sequence of declarations
|
||||
/// in this record.
|
||||
DeclContext::decl_iterator Current;
|
||||
|
||||
field_iterator field_begin() {
|
||||
assert(isDefinition() && "Not a definition!");
|
||||
return Members;
|
||||
/// End - Last position in the sequence of declarations in this
|
||||
/// record.
|
||||
DeclContext::decl_iterator End;
|
||||
|
||||
/// SkipToNextField - Advances the current position up to the next
|
||||
/// FieldDecl.
|
||||
void SkipToNextField() {
|
||||
while (Current != End && !isa<FieldDecl>(*Current))
|
||||
++Current;
|
||||
}
|
||||
|
||||
public:
|
||||
typedef FieldDecl* value_type;
|
||||
typedef FieldDecl* reference;
|
||||
typedef FieldDecl* pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
field_iterator() : Current(), End() { }
|
||||
|
||||
field_iterator(DeclContext::decl_iterator C, DeclContext::decl_iterator E)
|
||||
: Current(C), End(E) {
|
||||
SkipToNextField();
|
||||
}
|
||||
|
||||
reference operator*() const { return cast<FieldDecl>(*Current); }
|
||||
|
||||
pointer operator->() const { return cast<FieldDecl>(*Current); }
|
||||
|
||||
field_iterator& operator++() {
|
||||
++Current;
|
||||
SkipToNextField();
|
||||
return *this;
|
||||
}
|
||||
|
||||
field_iterator operator++(int) {
|
||||
field_iterator tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(const field_iterator& x, const field_iterator& y) {
|
||||
return x.Current == y.Current;
|
||||
}
|
||||
|
||||
friend bool operator!=(const field_iterator& x, const field_iterator& y) {
|
||||
return x.Current != y.Current;
|
||||
}
|
||||
};
|
||||
|
||||
typedef field_iterator field_const_iterator;
|
||||
|
||||
field_iterator field_begin() const {
|
||||
return field_iterator(decls_begin(), decls_end());
|
||||
}
|
||||
field_iterator field_end() {
|
||||
assert(isDefinition() && "Not a definition!");
|
||||
return Members + getNumMembers();
|
||||
field_iterator field_end() const {
|
||||
return field_iterator(decls_end(), decls_end());
|
||||
}
|
||||
|
||||
field_const_iterator field_begin() const {
|
||||
assert(isDefinition() && "Not a definition!");
|
||||
return Members;
|
||||
}
|
||||
field_const_iterator field_end() const {
|
||||
assert(isDefinition() && "Not a definition!");
|
||||
return Members + getNumMembers();
|
||||
}
|
||||
|
||||
/// defineBody - When created, RecordDecl's correspond to a forward declared
|
||||
/// record. This method is used to mark the decl as being defined, with the
|
||||
/// specified contents.
|
||||
void defineBody(ASTContext& C, FieldDecl **Members, unsigned numMembers);
|
||||
|
||||
/// getMember - If the member doesn't exist, or there are no members, this
|
||||
/// function will return 0;
|
||||
FieldDecl *getMember(IdentifierInfo *name);
|
||||
/// completeDefinition - Notes that the definition of this type is
|
||||
/// now complete.
|
||||
void completeDefinition(ASTContext& C);
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= RecordFirst && D->getKind() <= RecordLast;
|
||||
|
|
|
@ -17,11 +17,14 @@
|
|||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
class DeclContext;
|
||||
class TranslationUnitDecl;
|
||||
class NamespaceDecl;
|
||||
class NamedDecl;
|
||||
class ScopedDecl;
|
||||
class FunctionDecl;
|
||||
class CXXRecordDecl;
|
||||
|
@ -29,6 +32,7 @@ class EnumDecl;
|
|||
class ObjCMethodDecl;
|
||||
class ObjCInterfaceDecl;
|
||||
class BlockDecl;
|
||||
class DeclarationName;
|
||||
|
||||
/// Decl - This represents one declaration (or definition), e.g. a variable,
|
||||
/// typedef, function, struct, etc.
|
||||
|
@ -44,10 +48,6 @@ public:
|
|||
// Decl
|
||||
TranslationUnit, // [DeclContext]
|
||||
// NamedDecl
|
||||
Field,
|
||||
CXXField,
|
||||
ObjCIvar,
|
||||
ObjCAtDefsField,
|
||||
OverloadedFunction,
|
||||
ObjCCategory,
|
||||
ObjCCategoryImpl,
|
||||
|
@ -56,13 +56,16 @@ public:
|
|||
ObjCProtocol,
|
||||
ObjCProperty,
|
||||
// ScopedDecl
|
||||
Field,
|
||||
ObjCIvar,
|
||||
ObjCAtDefsField,
|
||||
Namespace, // [DeclContext]
|
||||
// TypeDecl
|
||||
Typedef,
|
||||
// TagDecl
|
||||
Enum, // [DeclContext]
|
||||
Record,
|
||||
CXXRecord, // [DeclContext]
|
||||
Record, // [DeclContext]
|
||||
CXXRecord,
|
||||
TemplateTypeParm,
|
||||
// ValueDecl
|
||||
EnumConstant,
|
||||
|
@ -87,9 +90,9 @@ public:
|
|||
|
||||
// For each non-leaf class, we now define a mapping to the first/last member
|
||||
// of the class, to allow efficient classof.
|
||||
NamedFirst = Field , NamedLast = NonTypeTemplateParm,
|
||||
NamedFirst = OverloadedFunction , NamedLast = NonTypeTemplateParm,
|
||||
FieldFirst = Field , FieldLast = ObjCAtDefsField,
|
||||
ScopedFirst = Namespace , ScopedLast = NonTypeTemplateParm,
|
||||
ScopedFirst = Field , ScopedLast = NonTypeTemplateParm,
|
||||
TypeFirst = Typedef , TypeLast = TemplateTypeParm,
|
||||
TagFirst = Enum , TagLast = CXXRecord,
|
||||
RecordFirst = Record , RecordLast = CXXRecord,
|
||||
|
@ -183,10 +186,10 @@ public:
|
|||
case ParmVar:
|
||||
case EnumConstant:
|
||||
case NonTypeTemplateParm:
|
||||
case Field:
|
||||
case ObjCInterface:
|
||||
case ObjCCompatibleAlias:
|
||||
case OverloadedFunction:
|
||||
case CXXField:
|
||||
case CXXMethod:
|
||||
case CXXConversion:
|
||||
case CXXClassVar:
|
||||
|
@ -247,7 +250,7 @@ protected:
|
|||
/// TranslationUnitDecl
|
||||
/// NamespaceDecl
|
||||
/// FunctionDecl
|
||||
/// CXXRecordDecl
|
||||
/// RecordDecl/CXXRecordDecl
|
||||
/// EnumDecl
|
||||
/// ObjCMethodDecl
|
||||
/// ObjCInterfaceDecl
|
||||
|
@ -257,9 +260,26 @@ class DeclContext {
|
|||
/// DeclKind - This indicates which class this is.
|
||||
Decl::Kind DeclKind : 8;
|
||||
|
||||
/// DeclChain - Linked list of declarations that are defined inside this
|
||||
/// declaration context.
|
||||
ScopedDecl *DeclChain;
|
||||
/// LookupPtrKind - Describes what kind of pointer LookupPtr
|
||||
/// actually is.
|
||||
enum LookupPtrKind {
|
||||
/// LookupIsMap - Indicates that LookupPtr is actually a
|
||||
/// DenseMap<DeclarationName, TwoNamedDecls> pointer.
|
||||
LookupIsMap = 7
|
||||
};
|
||||
|
||||
/// LookupPtr - Pointer to a data structure used to lookup
|
||||
/// declarations within this context. If the context contains fewer
|
||||
/// than seven declarations, the number of declarations is provided
|
||||
/// in the 3 lowest-order bits and the upper bits are treated as a
|
||||
/// pointer to an array of NamedDecl pointers. If the context
|
||||
/// contains seven or more declarations, the upper bits are treated
|
||||
/// as a pointer to a DenseMap<DeclarationName, TwoNamedDecls>.
|
||||
llvm::PointerIntPair<void*, 3> LookupPtr;
|
||||
|
||||
/// Decls - Contains all of the declarations that are defined inside
|
||||
/// this declaration context.
|
||||
std::vector<ScopedDecl*> Decls;
|
||||
|
||||
// Used in the CastTo template to get the DeclKind
|
||||
// from a Decl or a DeclContext. DeclContext doesn't have a getKind() method
|
||||
|
@ -281,6 +301,8 @@ class DeclContext {
|
|||
return static_cast<NamespaceDecl*>(const_cast<From*>(D));
|
||||
case Decl::Enum:
|
||||
return static_cast<EnumDecl*>(const_cast<From*>(D));
|
||||
case Decl::Record:
|
||||
return static_cast<RecordDecl*>(const_cast<From*>(D));
|
||||
case Decl::CXXRecord:
|
||||
return static_cast<CXXRecordDecl*>(const_cast<From*>(D));
|
||||
case Decl::ObjCMethod:
|
||||
|
@ -296,10 +318,19 @@ class DeclContext {
|
|||
}
|
||||
}
|
||||
|
||||
/// isLookupMap - Determine if the lookup structure is a
|
||||
/// DenseMap. Othewise, it is an array.
|
||||
bool isLookupMap() const { return LookupPtr.getInt() == LookupIsMap; }
|
||||
|
||||
protected:
|
||||
DeclContext(Decl::Kind K) : DeclKind(K), DeclChain(0) {}
|
||||
DeclContext(Decl::Kind K) : DeclKind(K), LookupPtr() {
|
||||
}
|
||||
|
||||
void DestroyDecls(ASTContext &C);
|
||||
|
||||
public:
|
||||
~DeclContext();
|
||||
|
||||
/// getParent - Returns the containing DeclContext if this is a ScopedDecl,
|
||||
/// else returns NULL.
|
||||
const DeclContext *getParent() const;
|
||||
|
@ -309,12 +340,12 @@ public:
|
|||
}
|
||||
|
||||
/// getLexicalParent - Returns the containing lexical DeclContext. May be
|
||||
/// different from getParent, e.g.:
|
||||
///
|
||||
/// namespace A {
|
||||
/// struct S;
|
||||
/// }
|
||||
/// struct A::S {}; // getParent() == namespace 'A'
|
||||
/// different from getParent, e.g.:
|
||||
///
|
||||
/// namespace A {
|
||||
/// struct S;
|
||||
/// }
|
||||
/// struct A::S {}; // getParent() == namespace 'A'
|
||||
/// // getLexicalParent() == translation unit
|
||||
///
|
||||
const DeclContext *getLexicalParent() const;
|
||||
|
@ -326,11 +357,12 @@ public:
|
|||
bool isFunctionOrMethod() const {
|
||||
switch (DeclKind) {
|
||||
case Decl::Block:
|
||||
case Decl::Function:
|
||||
case Decl::CXXMethod:
|
||||
case Decl::ObjCMethod:
|
||||
return true;
|
||||
|
||||
default:
|
||||
if (DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -343,6 +375,10 @@ public:
|
|||
return DeclKind == Decl::CXXRecord;
|
||||
}
|
||||
|
||||
bool isNamespace() const {
|
||||
return DeclKind == Decl::Namespace;
|
||||
}
|
||||
|
||||
bool Encloses(DeclContext *DC) const {
|
||||
for (; DC; DC = DC->getParent())
|
||||
if (DC == this)
|
||||
|
@ -350,15 +386,105 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
const ScopedDecl *getDeclChain() const { return DeclChain; }
|
||||
ScopedDecl *getDeclChain() { return DeclChain; }
|
||||
void setDeclChain(ScopedDecl *D) { DeclChain = D; }
|
||||
/// getPrimaryContext - There may be many different
|
||||
/// declarations of the same entity (including forward declarations
|
||||
/// of classes, multiple definitions of namespaces, etc.), each with
|
||||
/// a different set of declarations. This routine returns the
|
||||
/// "primary" DeclContext structure, which will contain the
|
||||
/// information needed to perform name lookup into this context.
|
||||
DeclContext *getPrimaryContext(ASTContext &Context);
|
||||
|
||||
/// getNextContext - If this is a DeclContext that may have other
|
||||
/// DeclContexts that are semantically connected but syntactically
|
||||
/// different, such as C++ namespaces, this routine retrieves the
|
||||
/// next DeclContext in the link. Iteration through the chain of
|
||||
/// DeclContexts should begin at the primary DeclContext and
|
||||
/// continue until this function returns NULL. For example, given:
|
||||
/// @code
|
||||
/// namespace N {
|
||||
/// int x;
|
||||
/// }
|
||||
/// namespace N {
|
||||
/// int y;
|
||||
/// }
|
||||
/// @endcode
|
||||
/// The first occurrence of namespace N will be the primary
|
||||
/// DeclContext. Its getNextContext will return the second
|
||||
/// occurrence of namespace N.
|
||||
DeclContext *getNextContext();
|
||||
|
||||
/// decl_iterator - Iterates through the declarations stored
|
||||
/// within this context.
|
||||
typedef std::vector<ScopedDecl*>::const_iterator decl_iterator;
|
||||
|
||||
/// reverse_decl_iterator - Iterates through the declarations stored
|
||||
/// within this context in reverse order.
|
||||
typedef std::vector<ScopedDecl*>::const_reverse_iterator
|
||||
reverse_decl_iterator;
|
||||
|
||||
/// decls_begin/decls_end - Iterate over the declarations stored in
|
||||
/// this context.
|
||||
decl_iterator decls_begin() const { return Decls.begin(); }
|
||||
decl_iterator decls_end() const { return Decls.end(); }
|
||||
|
||||
/// decls_rbegin/decls_rend - Iterate over the declarations stored
|
||||
/// in this context in reverse order.
|
||||
reverse_decl_iterator decls_rbegin() const { return Decls.rbegin(); }
|
||||
reverse_decl_iterator decls_rend() const { return Decls.rend(); }
|
||||
|
||||
/// addDecl - Add the declaration D to this scope. Note that
|
||||
/// declarations are added at the beginning of the declaration
|
||||
/// chain, so reverseDeclChain() should be called after all
|
||||
/// declarations have been added. If AllowLookup, also adds this
|
||||
/// declaration into data structure for name lookup.
|
||||
void addDecl(ASTContext &Context, ScopedDecl *D, bool AllowLookup = true);
|
||||
|
||||
/// reverseDeclChain - Reverse the chain of declarations stored in
|
||||
/// this scope. Typically called once after all declarations have
|
||||
/// been added and the scope is closed.
|
||||
void reverseDeclChain();
|
||||
|
||||
/// lookup_iterator - An iterator that provides access to the results
|
||||
/// of looking up a name within this context.
|
||||
typedef NamedDecl **lookup_iterator;
|
||||
|
||||
/// lookup_const_iterator - An iterator that provides non-mutable
|
||||
/// access to the results of lookup up a name within this context.
|
||||
typedef NamedDecl * const * lookup_const_iterator;
|
||||
|
||||
typedef std::pair<lookup_iterator, lookup_iterator> lookup_result;
|
||||
typedef std::pair<lookup_const_iterator, lookup_const_iterator>
|
||||
lookup_const_result;
|
||||
|
||||
/// lookup - Find the declarations (if any) with the given Name in
|
||||
/// this context. Returns a range of iterators that contains all of
|
||||
/// the declarations with this name (which may be 0, 1, or 2
|
||||
/// declarations). If two declarations are returned, the declaration
|
||||
/// in the "ordinary" identifier namespace will precede the
|
||||
/// declaration in the "tag" identifier namespace (e.g., values
|
||||
/// before types). Note that this routine will not look into parent
|
||||
/// contexts.
|
||||
lookup_result lookup(ASTContext &Context, DeclarationName Name);
|
||||
lookup_const_result lookup(ASTContext &Context, DeclarationName Name) const;
|
||||
|
||||
/// insert - Insert the declaration D into this context. Up to two
|
||||
/// declarations with the same name can be inserted into a single
|
||||
/// declaration context, one in the "tag" namespace (e.g., for
|
||||
/// classes and enums) and one in the "ordinary" namespaces (e.g.,
|
||||
/// for variables, functions, and other values). Note that, if there
|
||||
/// is already a declaration with the same name and identifier
|
||||
/// namespace, D will replace it. It is up to the caller to ensure
|
||||
/// that this replacement is semantically correct, e.g., that
|
||||
/// declarations are only replaced by later declarations of the same
|
||||
/// entity and not a declaration of some other kind of entity.
|
||||
void insert(ASTContext &Context, NamedDecl *D);
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
switch (D->getKind()) {
|
||||
case Decl::TranslationUnit:
|
||||
case Decl::Namespace:
|
||||
case Decl::Enum:
|
||||
case Decl::Record:
|
||||
case Decl::CXXRecord:
|
||||
case Decl::ObjCMethod:
|
||||
case Decl::ObjCInterface:
|
||||
|
@ -375,6 +501,7 @@ public:
|
|||
static bool classof(const TranslationUnitDecl *D) { return true; }
|
||||
static bool classof(const NamespaceDecl *D) { return true; }
|
||||
static bool classof(const FunctionDecl *D) { return true; }
|
||||
static bool classof(const RecordDecl *D) { return true; }
|
||||
static bool classof(const CXXRecordDecl *D) { return true; }
|
||||
static bool classof(const EnumDecl *D) { return true; }
|
||||
static bool classof(const ObjCMethodDecl *D) { return true; }
|
||||
|
@ -382,6 +509,8 @@ public:
|
|||
static bool classof(const BlockDecl *D) { return true; }
|
||||
|
||||
private:
|
||||
void insertImpl(NamedDecl *D);
|
||||
|
||||
void EmitOutRec(llvm::Serializer& S) const;
|
||||
void ReadOutRec(llvm::Deserializer& D, ASTContext& C);
|
||||
|
||||
|
@ -430,6 +559,20 @@ struct cast_convert_val< ::clang::DeclContext, FromTy*, FromTy*> {
|
|||
}
|
||||
};
|
||||
|
||||
template<class FromTy>
|
||||
struct cast_convert_val< const ::clang::DeclContext, FromTy, FromTy> {
|
||||
static const ::clang::DeclContext &doit(const FromTy &Val) {
|
||||
return *FromTy::castToDeclContext(&Val);
|
||||
}
|
||||
};
|
||||
|
||||
template<class FromTy>
|
||||
struct cast_convert_val< const ::clang::DeclContext, FromTy*, FromTy*> {
|
||||
static const ::clang::DeclContext *doit(const FromTy *Val) {
|
||||
return FromTy::castToDeclContext(Val);
|
||||
}
|
||||
};
|
||||
|
||||
/// Implement cast_convert_val for DeclContext -> Decl conversions.
|
||||
template<class ToTy>
|
||||
struct cast_convert_val<ToTy,
|
||||
|
|
|
@ -116,8 +116,6 @@ public:
|
|||
/// addOverload - Add an overloaded function FD to this set of
|
||||
/// overloaded functions.
|
||||
void addOverload(FunctionDecl *FD) {
|
||||
assert((!getNumFunctions() || (FD->getDeclContext() == getDeclContext())) &&
|
||||
"Overloaded functions must all be in the same context");
|
||||
assert((FD->getDeclName() == getDeclName() ||
|
||||
isa<CXXConversionDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&
|
||||
"Overloaded functions must have the same name");
|
||||
|
@ -173,29 +171,6 @@ protected:
|
|||
friend class CXXRecordDecl;
|
||||
};
|
||||
|
||||
/// CXXFieldDecl - Represents an instance field of a C++ struct/union/class.
|
||||
class CXXFieldDecl : public FieldDecl {
|
||||
CXXRecordDecl *Parent;
|
||||
bool Mutable;
|
||||
|
||||
CXXFieldDecl(CXXRecordDecl *RD, SourceLocation L, IdentifierInfo *Id,
|
||||
QualType T, bool Mut, Expr *BW = NULL)
|
||||
: FieldDecl(CXXField, L, Id, T, BW), Parent(RD), Mutable(Mut) {}
|
||||
public:
|
||||
static CXXFieldDecl *Create(ASTContext &C, CXXRecordDecl *RD,SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T, bool Mut,
|
||||
Expr *BW = NULL);
|
||||
|
||||
void setAccess(AccessSpecifier AS) { Access = AS; }
|
||||
AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
|
||||
CXXRecordDecl *getParent() const { return Parent; }
|
||||
bool isMutable() const { return Mutable; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return D->getKind() == CXXField; }
|
||||
static bool classof(const CXXFieldDecl *D) { return true; }
|
||||
};
|
||||
|
||||
/// CXXBaseSpecifier - A base class of a C++ class.
|
||||
///
|
||||
/// Each CXXBaseSpecifier represents a single, direct base class (or
|
||||
|
@ -277,11 +252,9 @@ public:
|
|||
};
|
||||
|
||||
/// CXXRecordDecl - Represents a C++ struct/union/class.
|
||||
/// CXXRecordDecl differs from RecordDecl in several ways. First, it
|
||||
/// is a DeclContext, because it can contain other
|
||||
/// declarations. Second, it provides additional C++ fields, including
|
||||
/// storage for base classes and constructors.
|
||||
class CXXRecordDecl : public RecordDecl, public DeclContext {
|
||||
/// FIXME: This class will disappear once we've properly taught RecordDecl
|
||||
/// to deal with C++-specific things.
|
||||
class CXXRecordDecl : public RecordDecl {
|
||||
/// UserDeclaredConstructor - True when this class has a
|
||||
/// user-declared constructor.
|
||||
bool UserDeclaredConstructor : 1;
|
||||
|
@ -348,19 +321,6 @@ public:
|
|||
base_class_iterator bases_end() { return Bases + NumBases; }
|
||||
base_class_const_iterator bases_end() const { return Bases + NumBases; }
|
||||
|
||||
const CXXFieldDecl *getMember(unsigned i) const {
|
||||
return cast<const CXXFieldDecl>(RecordDecl::getMember(i));
|
||||
}
|
||||
CXXFieldDecl *getMember(unsigned i) {
|
||||
return cast<CXXFieldDecl>(RecordDecl::getMember(i));
|
||||
}
|
||||
|
||||
/// getMember - If the member doesn't exist, or there are no members, this
|
||||
/// function will return 0;
|
||||
CXXFieldDecl *getMember(IdentifierInfo *name) {
|
||||
return cast_or_null<CXXFieldDecl>(RecordDecl::getMember(name));
|
||||
}
|
||||
|
||||
/// getConstructors - Retrieve the overload set containing all of
|
||||
/// the constructors of this class.
|
||||
OverloadedFunctionDecl *getConstructors() { return &Constructors; }
|
||||
|
@ -537,7 +497,7 @@ protected:
|
|||
class CXXBaseOrMemberInitializer {
|
||||
/// BaseOrMember - This points to the entity being initialized,
|
||||
/// which is either a base class (a Type) or a non-static data
|
||||
/// member (a CXXFieldDecl). When the low bit is 1, it's a base
|
||||
/// member. When the low bit is 1, it's a base
|
||||
/// class; when the low bit is 0, it's a member.
|
||||
uintptr_t BaseOrMember;
|
||||
|
||||
|
@ -552,7 +512,7 @@ public:
|
|||
|
||||
/// CXXBaseOrMemberInitializer - Creates a new member initializer.
|
||||
explicit
|
||||
CXXBaseOrMemberInitializer(CXXFieldDecl *Member, Expr **Args, unsigned NumArgs);
|
||||
CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs);
|
||||
|
||||
/// ~CXXBaseOrMemberInitializer - Destroy the base or member initializer.
|
||||
~CXXBaseOrMemberInitializer();
|
||||
|
@ -598,9 +558,9 @@ public:
|
|||
/// getMember - If this is a member initializer, returns the
|
||||
/// declaration of the non-static data member being
|
||||
/// initialized. Otherwise, returns NULL.
|
||||
CXXFieldDecl *getMember() {
|
||||
FieldDecl *getMember() {
|
||||
if (isMemberInitializer())
|
||||
return reinterpret_cast<CXXFieldDecl *>(BaseOrMember);
|
||||
return reinterpret_cast<FieldDecl *>(BaseOrMember);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
@ -917,14 +877,14 @@ public:
|
|||
if (ScopedDecl *SD = dyn_cast<ScopedDecl>(MD)) {
|
||||
return cast<CXXRecordDecl>(SD->getDeclContext());
|
||||
}
|
||||
return cast<CXXFieldDecl>(MD)->getParent();
|
||||
return cast<CXXRecordDecl>(cast<FieldDecl>(MD)->getDeclContext());
|
||||
}
|
||||
|
||||
static bool isMember(Decl *D) {
|
||||
if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
|
||||
return isa<CXXRecordDecl>(SD->getDeclContext());
|
||||
}
|
||||
return isa<CXXFieldDecl>(D);
|
||||
return isa<FieldDecl>(D);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -506,7 +506,8 @@ public:
|
|||
private:
|
||||
ObjCIvarDecl(SourceLocation L, IdentifierInfo *Id, QualType T,
|
||||
AccessControl ac, Expr *BW)
|
||||
: FieldDecl(ObjCIvar, L, Id, T, BW), DeclAccess(ac) {}
|
||||
: FieldDecl(ObjCIvar, 0, L, Id, T, BW, /*Mutable=*/false, 0),
|
||||
DeclAccess(ac) {}
|
||||
|
||||
public:
|
||||
static ObjCIvarDecl *Create(ASTContext &C, SourceLocation L,
|
||||
|
@ -534,12 +535,13 @@ private:
|
|||
/// @defs(...).
|
||||
class ObjCAtDefsFieldDecl : public FieldDecl {
|
||||
private:
|
||||
ObjCAtDefsFieldDecl(SourceLocation L, IdentifierInfo *Id,
|
||||
ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
|
||||
QualType T, Expr *BW)
|
||||
: FieldDecl(ObjCAtDefsField, L, Id, T, BW) {}
|
||||
: FieldDecl(ObjCAtDefsField, DC, L, Id, T, BW, /*Mutable=*/false, 0) {}
|
||||
|
||||
public:
|
||||
static ObjCAtDefsFieldDecl *Create(ASTContext &C, SourceLocation L,
|
||||
static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T,
|
||||
Expr *BW);
|
||||
|
||||
|
|
|
@ -198,6 +198,10 @@ public:
|
|||
/// name as an opaque integer.
|
||||
uintptr_t getAsOpaqueInteger() const { return Ptr; }
|
||||
|
||||
/// getAsOpaquePtr - Get the representation of this declaration name as
|
||||
/// an opaque pointer.
|
||||
void *getAsOpaquePtr() const { return reinterpret_cast<void*>(Ptr); }
|
||||
|
||||
static DeclarationName getFromOpaqueInteger(uintptr_t P) {
|
||||
DeclarationName N;
|
||||
N.Ptr = P;
|
||||
|
|
|
@ -265,10 +265,10 @@ public:
|
|||
|
||||
/// Act on @defs() element found when parsing a structure. ClassName is the
|
||||
/// name of the referenced class.
|
||||
virtual void ActOnDefs(Scope *S, SourceLocation DeclStart,
|
||||
virtual void ActOnDefs(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
|
||||
IdentifierInfo *ClassName,
|
||||
llvm::SmallVectorImpl<DeclTy*> &Decls) {}
|
||||
virtual DeclTy *ActOnField(Scope *S, SourceLocation DeclStart,
|
||||
virtual DeclTy *ActOnField(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
|
||||
Declarator &D, ExprTy *BitfieldWidth) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -112,6 +112,12 @@ private:
|
|||
typedef llvm::SmallPtrSet<Action::DeclTy*, 32> DeclSetTy;
|
||||
DeclSetTy DeclsInScope;
|
||||
|
||||
/// Entity - The entity with which this scope is associated. For
|
||||
/// example, the entity of a class scope is the class itself, the
|
||||
/// entity of a function scope is a function, etc. This field is
|
||||
/// maintained by the Action implementation.
|
||||
void *Entity;
|
||||
|
||||
public:
|
||||
Scope(Scope *Parent, unsigned ScopeFlags) {
|
||||
Init(Parent, ScopeFlags);
|
||||
|
@ -178,12 +184,19 @@ public:
|
|||
DeclsInScope.insert(D);
|
||||
}
|
||||
|
||||
void RemoveDecl(Action::DeclTy *D) {
|
||||
DeclsInScope.erase(D);
|
||||
}
|
||||
|
||||
/// isDeclScope - Return true if this is the scope that the specified decl is
|
||||
/// declared in.
|
||||
bool isDeclScope(Action::DeclTy *D) {
|
||||
return DeclsInScope.count(D) != 0;
|
||||
}
|
||||
|
||||
void* getEntity() const { return Entity; }
|
||||
void setEntity(void *E) { Entity = E; }
|
||||
|
||||
/// isCXXClassScope - Return true if this scope is a C++ class scope.
|
||||
bool isCXXClassScope() const {
|
||||
return (getFlags() & Scope::CXXClassScope);
|
||||
|
@ -242,6 +255,7 @@ public:
|
|||
if (Flags & BlockScope) BlockParent = this;
|
||||
if (Flags & TemplateParamScope) TemplateParamParent = this;
|
||||
DeclsInScope.clear();
|
||||
Entity = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -539,7 +539,7 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
|
|||
ASTRecordLayout *NewEntry = new ASTRecordLayout();
|
||||
Entry = NewEntry;
|
||||
|
||||
NewEntry->InitializeLayout(D->getNumMembers());
|
||||
NewEntry->InitializeLayout(std::distance(D->field_begin(), D->field_end()));
|
||||
bool IsUnion = D->isUnion();
|
||||
|
||||
unsigned StructPacking = 0;
|
||||
|
@ -552,10 +552,11 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
|
|||
|
||||
// Layout each field, for now, just sequentially, respecting alignment. In
|
||||
// the future, this will need to be tweakable by targets.
|
||||
for (unsigned i = 0, e = D->getNumMembers(); i != e; ++i) {
|
||||
const FieldDecl *FD = D->getMember(i);
|
||||
NewEntry->LayoutField(FD, i, IsUnion, StructPacking, *this);
|
||||
}
|
||||
unsigned FieldIdx = 0;
|
||||
for (RecordDecl::field_iterator Field = D->field_begin(),
|
||||
FieldEnd = D->field_end();
|
||||
Field != FieldEnd; (void)++Field, ++FieldIdx)
|
||||
NewEntry->LayoutField(*Field, FieldIdx, IsUnion, StructPacking, *this);
|
||||
|
||||
// Finally, round the size of the total struct up to the alignment of the
|
||||
// struct itself.
|
||||
|
@ -996,12 +997,16 @@ QualType ASTContext::getTypeDeclType(TypeDecl *Decl, TypeDecl* PrevDecl) {
|
|||
return QualType(Decl->TypeForDecl, 0);
|
||||
}
|
||||
|
||||
/// setTagDefinition - Used by RecordDecl::defineBody to inform ASTContext
|
||||
/// about which RecordDecl serves as the definition of a particular
|
||||
/// struct/union/class. This will eventually be used by enums as well.
|
||||
/// setTagDefinition - Used by RecordDecl::completeDefinition and
|
||||
/// EnumDecl::completeDefinition to inform about which
|
||||
/// RecordDecl/EnumDecl serves as the definition of a particular
|
||||
/// struct/union/class/enum.
|
||||
void ASTContext::setTagDefinition(TagDecl* D) {
|
||||
assert (D->isDefinition());
|
||||
cast<TagType>(D->TypeForDecl)->decl = D;
|
||||
if (!D->TypeForDecl)
|
||||
getTypeDeclType(D);
|
||||
else
|
||||
cast<TagType>(D->TypeForDecl)->decl = D;
|
||||
}
|
||||
|
||||
/// getTypedefType - Return the unique reference to the type for the
|
||||
|
@ -1460,14 +1465,17 @@ QualType ASTContext::getCFConstantStringType() {
|
|||
FieldTypes[2] = getPointerType(CharTy.getQualifiedType(QualType::Const));
|
||||
// long length;
|
||||
FieldTypes[3] = LongTy;
|
||||
|
||||
// Create fields
|
||||
FieldDecl *FieldDecls[4];
|
||||
|
||||
for (unsigned i = 0; i < 4; ++i)
|
||||
FieldDecls[i] = FieldDecl::Create(*this, SourceLocation(), 0,
|
||||
FieldTypes[i]);
|
||||
|
||||
CFConstantStringTypeDecl->defineBody(*this, FieldDecls, 4);
|
||||
for (unsigned i = 0; i < 4; ++i) {
|
||||
FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTypeDecl,
|
||||
SourceLocation(), 0,
|
||||
FieldTypes[i], /*BitWidth=*/0,
|
||||
/*Mutable=*/false, /*PrevDecl=*/0);
|
||||
CFConstantStringTypeDecl->addDecl(*this, Field, true);
|
||||
}
|
||||
|
||||
CFConstantStringTypeDecl->completeDefinition(*this);
|
||||
}
|
||||
|
||||
return getTagDeclType(CFConstantStringTypeDecl);
|
||||
|
@ -1476,6 +1484,10 @@ QualType ASTContext::getCFConstantStringType() {
|
|||
QualType ASTContext::getObjCFastEnumerationStateType()
|
||||
{
|
||||
if (!ObjCFastEnumerationStateTypeDecl) {
|
||||
ObjCFastEnumerationStateTypeDecl =
|
||||
RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get("__objcFastEnumerationState"));
|
||||
|
||||
QualType FieldTypes[] = {
|
||||
UnsignedLongTy,
|
||||
getPointerType(ObjCIdType),
|
||||
|
@ -1484,16 +1496,16 @@ QualType ASTContext::getObjCFastEnumerationStateType()
|
|||
llvm::APInt(32, 5), ArrayType::Normal, 0)
|
||||
};
|
||||
|
||||
FieldDecl *FieldDecls[4];
|
||||
for (size_t i = 0; i < 4; ++i)
|
||||
FieldDecls[i] = FieldDecl::Create(*this, SourceLocation(), 0,
|
||||
FieldTypes[i]);
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
FieldDecl *Field = FieldDecl::Create(*this,
|
||||
ObjCFastEnumerationStateTypeDecl,
|
||||
SourceLocation(), 0,
|
||||
FieldTypes[i], /*BitWidth=*/0,
|
||||
/*Mutable=*/false, /*PrevDecl=*/0);
|
||||
ObjCFastEnumerationStateTypeDecl->addDecl(*this, Field, true);
|
||||
}
|
||||
|
||||
ObjCFastEnumerationStateTypeDecl =
|
||||
RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get("__objcFastEnumerationState"));
|
||||
|
||||
ObjCFastEnumerationStateTypeDecl->defineBody(*this, FieldDecls, 4);
|
||||
ObjCFastEnumerationStateTypeDecl->completeDefinition(*this);
|
||||
}
|
||||
|
||||
return getTagDeclType(ObjCFastEnumerationStateTypeDecl);
|
||||
|
@ -1745,16 +1757,17 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
|||
}
|
||||
if (ExpandStructures) {
|
||||
S += '=';
|
||||
for (int i = 0; i < RDecl->getNumMembers(); i++) {
|
||||
FieldDecl *FD = RDecl->getMember(i);
|
||||
for (RecordDecl::field_iterator Field = RDecl->field_begin(),
|
||||
FieldEnd = RDecl->field_end();
|
||||
Field != FieldEnd; ++Field) {
|
||||
if (NameFields) {
|
||||
S += '"';
|
||||
S += FD->getNameAsString();
|
||||
S += Field->getNameAsString();
|
||||
S += '"';
|
||||
}
|
||||
|
||||
// Special case bit-fields.
|
||||
if (const Expr *E = FD->getBitWidth()) {
|
||||
if (const Expr *E = Field->getBitWidth()) {
|
||||
// FIXME: Fix constness.
|
||||
ASTContext *Ctx = const_cast<ASTContext*>(this);
|
||||
unsigned N = E->getIntegerConstantExprValue(*Ctx).getZExtValue();
|
||||
|
@ -1763,7 +1776,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
|||
S += 'b';
|
||||
S += llvm::utostr(N);
|
||||
} else {
|
||||
getObjCEncodingForTypeImpl(FD->getType(), S, false, true, NameFields);
|
||||
getObjCEncodingForTypeImpl(Field->getType(), S, false, true,
|
||||
NameFields);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,10 +81,11 @@ BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
|
|||
return new (Mem) BlockDecl(DC, L);
|
||||
}
|
||||
|
||||
FieldDecl *FieldDecl::Create(ASTContext &C, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T, Expr *BW) {
|
||||
FieldDecl *FieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T, Expr *BW,
|
||||
bool Mutable, ScopedDecl *PrevDecl) {
|
||||
void *Mem = C.getAllocator().Allocate<FieldDecl>();
|
||||
return new (Mem) FieldDecl(L, Id, T, BW);
|
||||
return new (Mem) FieldDecl(Decl::Field, DC, L, Id, T, BW, Mutable, PrevDecl);
|
||||
}
|
||||
|
||||
|
||||
|
@ -118,10 +119,21 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
|||
}
|
||||
|
||||
void EnumDecl::Destroy(ASTContext& C) {
|
||||
if (getEnumConstantList()) getEnumConstantList()->Destroy(C);
|
||||
DeclContext::DestroyDecls(C);
|
||||
Decl::Destroy(C);
|
||||
}
|
||||
|
||||
void EnumDecl::completeDefinition(ASTContext &C, QualType NewType) {
|
||||
assert(!isDefinition() && "Cannot redefine enums!");
|
||||
setDefinition(true);
|
||||
|
||||
IntegerType = NewType;
|
||||
|
||||
// Let ASTContext know that this is the defining EnumDecl for this
|
||||
// type.
|
||||
C.setTagDefinition(this);
|
||||
}
|
||||
|
||||
FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C,
|
||||
SourceLocation L,
|
||||
StringLiteral *Str) {
|
||||
|
@ -248,12 +260,10 @@ TagDecl* TagDecl::getDefinition(ASTContext& C) const {
|
|||
|
||||
RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id)
|
||||
: TagDecl(DK, TK, DC, L, Id, 0) {
|
||||
: TagDecl(DK, TK, DC, L, Id, 0), DeclContext(DK) {
|
||||
|
||||
HasFlexibleArrayMember = false;
|
||||
assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
|
||||
Members = 0;
|
||||
NumMembers = -1;
|
||||
}
|
||||
|
||||
RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
|
||||
|
@ -267,46 +277,25 @@ RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
|
|||
}
|
||||
|
||||
RecordDecl::~RecordDecl() {
|
||||
delete[] Members;
|
||||
}
|
||||
|
||||
void RecordDecl::Destroy(ASTContext& C) {
|
||||
if (isDefinition())
|
||||
for (field_iterator I=field_begin(), E=field_end(); I!=E; ++I)
|
||||
(*I)->Destroy(C);
|
||||
|
||||
DeclContext::DestroyDecls(C);
|
||||
TagDecl::Destroy(C);
|
||||
}
|
||||
|
||||
/// defineBody - When created, RecordDecl's correspond to a forward declared
|
||||
/// record. This method is used to mark the decl as being defined, with the
|
||||
/// specified contents.
|
||||
void RecordDecl::defineBody(ASTContext& C, FieldDecl **members,
|
||||
unsigned numMembers) {
|
||||
/// completeDefinition - Notes that the definition of this type is now
|
||||
/// complete.
|
||||
void RecordDecl::completeDefinition(ASTContext& C) {
|
||||
assert(!isDefinition() && "Cannot redefine record!");
|
||||
|
||||
setDefinition(true);
|
||||
NumMembers = numMembers;
|
||||
if (numMembers) {
|
||||
Members = new FieldDecl*[numMembers];
|
||||
memcpy(Members, members, numMembers*sizeof(Decl*));
|
||||
}
|
||||
|
||||
// Let ASTContext know that this is the defining RecordDecl this type.
|
||||
// Let ASTContext know that this is the defining RecordDecl for this
|
||||
// type.
|
||||
C.setTagDefinition(this);
|
||||
}
|
||||
|
||||
|
||||
FieldDecl *RecordDecl::getMember(IdentifierInfo *II) {
|
||||
if (Members == 0 || NumMembers < 0)
|
||||
return 0;
|
||||
|
||||
// Linear search. When C++ classes come along, will likely need to revisit.
|
||||
for (int i = 0; i != NumMembers; ++i)
|
||||
if (Members[i]->getIdentifier() == II)
|
||||
return Members[i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// BlockDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
using namespace clang;
|
||||
|
||||
|
@ -34,7 +35,6 @@ static unsigned nNamespaces = 0;
|
|||
static unsigned nOverFuncs = 0;
|
||||
static unsigned nTypedef = 0;
|
||||
static unsigned nFieldDecls = 0;
|
||||
static unsigned nCXXFieldDecls = 0;
|
||||
static unsigned nInterfaceDecls = 0;
|
||||
static unsigned nClassDecls = 0;
|
||||
static unsigned nMethodDecls = 0;
|
||||
|
@ -95,7 +95,7 @@ bool Decl::CollectingStats(bool Enable) {
|
|||
void Decl::PrintStats() {
|
||||
fprintf(stderr, "*** Decl Stats:\n");
|
||||
fprintf(stderr, " %d decls total.\n",
|
||||
int(nFuncs+nVars+nParmVars+nFieldDecls+nSUC+nCXXFieldDecls+nCXXSUC+
|
||||
int(nFuncs+nVars+nParmVars+nFieldDecls+nSUC+nCXXSUC+
|
||||
nEnumDecls+nEnumConst+nTypedef+nInterfaceDecls+nClassDecls+
|
||||
nMethodDecls+nProtocolDecls+nCategoryDecls+nIvarDecls+
|
||||
nAtDefsFieldDecls+nNamespaces+nOverFuncs));
|
||||
|
@ -122,9 +122,6 @@ void Decl::PrintStats() {
|
|||
fprintf(stderr, " %d struct/union/class decls, %d each (%d bytes)\n",
|
||||
nSUC, (int)sizeof(RecordDecl),
|
||||
int(nSUC*sizeof(RecordDecl)));
|
||||
fprintf(stderr, " %d C++ field decls, %d each (%d bytes)\n",
|
||||
nCXXFieldDecls, (int)sizeof(CXXFieldDecl),
|
||||
int(nCXXFieldDecls*sizeof(CXXFieldDecl)));
|
||||
fprintf(stderr, " %d C++ struct/union/class decls, %d each (%d bytes)\n",
|
||||
nCXXSUC, (int)sizeof(CXXRecordDecl),
|
||||
int(nCXXSUC*sizeof(CXXRecordDecl)));
|
||||
|
@ -183,7 +180,7 @@ void Decl::PrintStats() {
|
|||
int(nFuncs*sizeof(FunctionDecl)+
|
||||
nVars*sizeof(VarDecl)+nParmVars*sizeof(ParmVarDecl)+
|
||||
nFieldDecls*sizeof(FieldDecl)+nSUC*sizeof(RecordDecl)+
|
||||
nCXXFieldDecls*sizeof(CXXFieldDecl)+nCXXSUC*sizeof(CXXRecordDecl)+
|
||||
nCXXSUC*sizeof(CXXRecordDecl)+
|
||||
nEnumDecls*sizeof(EnumDecl)+nEnumConst*sizeof(EnumConstantDecl)+
|
||||
nTypedef*sizeof(TypedefDecl)+
|
||||
nInterfaceDecls*sizeof(ObjCInterfaceDecl)+
|
||||
|
@ -236,7 +233,6 @@ void Decl::addDeclKind(Kind k) {
|
|||
case ImplicitParam:
|
||||
case TranslationUnit: break;
|
||||
|
||||
case CXXField: nCXXFieldDecls++; break;
|
||||
case CXXRecord: nCXXSUC++; break;
|
||||
// FIXME: Statistics for C++ decls.
|
||||
case TemplateTypeParm:
|
||||
|
@ -372,3 +368,269 @@ const DeclContext *DeclContext::getLexicalParent() const {
|
|||
return SD->getLexicalDeclContext();
|
||||
return getParent();
|
||||
}
|
||||
|
||||
/// TwoNamedDecls - Stores up to two NamedDecls. The first
|
||||
/// declaration, if any, is in the ordinary identifier namespace, and
|
||||
/// corresponds to values (functions, variables, etc.). The second
|
||||
/// declaration, if any, is in the tag identifier namespace, and
|
||||
/// corresponds to tag types (classes, enums).
|
||||
struct TwoNamedDecls {
|
||||
NamedDecl* Decls[2];
|
||||
};
|
||||
|
||||
// FIXME: We really want to use a DenseSet here to eliminate the
|
||||
// redundant storage of the declaration names, but (1) it doesn't give
|
||||
// us the ability to search based on DeclarationName, (2) we really
|
||||
// need something more like a DenseMultiSet, and (3) it's
|
||||
// implemented in terms of DenseMap anyway.
|
||||
typedef llvm::DenseMap<DeclarationName, TwoNamedDecls> StoredDeclsMap;
|
||||
|
||||
DeclContext::~DeclContext() {
|
||||
unsigned Size = LookupPtr.getInt();
|
||||
if (Size == LookupIsMap) {
|
||||
StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
|
||||
delete Map;
|
||||
} else {
|
||||
NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer());
|
||||
delete [] Array;
|
||||
}
|
||||
}
|
||||
|
||||
void DeclContext::DestroyDecls(ASTContext &C) {
|
||||
for (decl_iterator D = Decls.begin(); D != Decls.end(); ++D) {
|
||||
if ((*D)->getLexicalDeclContext() == this)
|
||||
(*D)->Destroy(C);
|
||||
}
|
||||
}
|
||||
|
||||
DeclContext *DeclContext::getPrimaryContext(ASTContext &Context) {
|
||||
switch (DeclKind) {
|
||||
case Decl::Block:
|
||||
case Decl::TranslationUnit:
|
||||
// There is only one DeclContext for these entities.
|
||||
return this;
|
||||
|
||||
case Decl::Namespace:
|
||||
// The original namespace is our primary context.
|
||||
return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();
|
||||
|
||||
case Decl::Enum:
|
||||
// The declaration associated with the enumeration type is our
|
||||
// primary context.
|
||||
return Context.getTypeDeclType(static_cast<EnumDecl*>(this))
|
||||
->getAsEnumType()->getDecl();
|
||||
|
||||
case Decl::Record:
|
||||
case Decl::CXXRecord: {
|
||||
// The declaration associated with the type is be our primary
|
||||
// context.
|
||||
#if 0
|
||||
// FIXME: This is what we expect to do. However, it doesn't work
|
||||
// because ASTContext::setTagDefinition changes the result of
|
||||
// Context.getTypeDeclType, meaning that our "primary" declaration
|
||||
// of a RecordDecl/CXXRecordDecl will change, and we won't be able
|
||||
// to find any values inserted into the earlier "primary"
|
||||
// declaration. We need better tracking of redeclarations and
|
||||
// definitions.
|
||||
QualType Type = Context.getTypeDeclType(static_cast<RecordDecl*>(this));
|
||||
return Type->getAsRecordType()->getDecl();
|
||||
#else
|
||||
// FIXME: This hack will work for now, because the declaration we
|
||||
// create when we're defining the record is the one we'll use as
|
||||
// the definition later.
|
||||
return this;
|
||||
#endif
|
||||
}
|
||||
|
||||
case Decl::ObjCMethod:
|
||||
return this;
|
||||
|
||||
case Decl::ObjCInterface:
|
||||
// FIXME: Can Objective-C interfaces be forward-declared?
|
||||
return this;
|
||||
|
||||
default:
|
||||
assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
|
||||
"Unknown DeclContext kind");
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
DeclContext *DeclContext::getNextContext() {
|
||||
switch (DeclKind) {
|
||||
case Decl::Block:
|
||||
case Decl::TranslationUnit:
|
||||
case Decl::Enum:
|
||||
case Decl::Record:
|
||||
case Decl::CXXRecord:
|
||||
case Decl::ObjCMethod:
|
||||
case Decl::ObjCInterface:
|
||||
// There is only one DeclContext for these entities.
|
||||
return 0;
|
||||
|
||||
case Decl::Namespace:
|
||||
// Return the next namespace
|
||||
return static_cast<NamespaceDecl*>(this)->getNextNamespace();
|
||||
|
||||
default:
|
||||
assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
|
||||
"Unknown DeclContext kind");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DeclContext::addDecl(ASTContext &Context, ScopedDecl *D, bool AllowLookup) {
|
||||
Decls.push_back(D);
|
||||
if (AllowLookup)
|
||||
D->getDeclContext()->insert(Context, D);
|
||||
}
|
||||
|
||||
DeclContext::lookup_result
|
||||
DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
|
||||
DeclContext *PrimaryContext = getPrimaryContext(Context);
|
||||
if (PrimaryContext != this)
|
||||
return PrimaryContext->lookup(Context, Name);
|
||||
|
||||
/// If there is no lookup data structure, build one now by talking
|
||||
/// all of the linked DeclContexts (in declaration order!) and
|
||||
/// inserting their values.
|
||||
if (LookupPtr.getPointer() == 0) {
|
||||
for (DeclContext *DCtx = this; DCtx; DCtx = DCtx->getNextContext())
|
||||
for (decl_iterator D = DCtx->decls_begin(); D != DCtx->decls_end(); ++D)
|
||||
insertImpl(*D);
|
||||
}
|
||||
|
||||
lookup_result Result(0, 0);
|
||||
if (isLookupMap()) {
|
||||
StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
|
||||
StoredDeclsMap::iterator Pos = Map->find(Name);
|
||||
if (Pos != Map->end()) {
|
||||
Result.first = Pos->second.Decls[0]? &Pos->second.Decls[0]
|
||||
: &Pos->second.Decls[1];
|
||||
Result.second = Pos->second.Decls[1]? &Pos->second.Decls[2]
|
||||
: &Pos->second.Decls[1];
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
// We have a small array. Look into it.
|
||||
unsigned Size = LookupPtr.getInt();
|
||||
NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer());
|
||||
for (unsigned Idx = 0; Idx < Size; ++Idx)
|
||||
if (Array[Idx]->getDeclName() == Name) {
|
||||
Result.first = &Array[Idx];
|
||||
Result.second = Result.first + 1;
|
||||
if (Idx + 1 < Size && Array[Idx + 1]->getDeclName() == Name)
|
||||
++Result.second;
|
||||
break;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
DeclContext::lookup_const_result
|
||||
DeclContext::lookup(ASTContext &Context, DeclarationName Name) const {
|
||||
return const_cast<DeclContext*>(this)->lookup(Context, Name);
|
||||
}
|
||||
|
||||
void DeclContext::insert(ASTContext &Context, NamedDecl *D) {
|
||||
DeclContext *PrimaryContext = getPrimaryContext(Context);
|
||||
if (PrimaryContext != this) {
|
||||
PrimaryContext->insert(Context, D);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we already have a lookup data structure, perform the insertion
|
||||
// into it. Otherwise, be lazy and don't build that structure until
|
||||
// someone asks for it.
|
||||
if (LookupPtr.getPointer())
|
||||
insertImpl(D);
|
||||
}
|
||||
|
||||
void DeclContext::insertImpl(NamedDecl *D) {
|
||||
if (!isLookupMap()) {
|
||||
unsigned Size = LookupPtr.getInt();
|
||||
|
||||
// The lookup data is stored as an array. Search through the array
|
||||
// to find the insertion location.
|
||||
NamedDecl **Array;
|
||||
if (Size == 0) {
|
||||
Array = new NamedDecl*[LookupIsMap - 1];
|
||||
LookupPtr.setPointer(Array);
|
||||
} else {
|
||||
Array = static_cast<NamedDecl **>(LookupPtr.getPointer());
|
||||
}
|
||||
|
||||
// We always keep declarations of the same name next to each other
|
||||
// in the array, so that it is easy to return multiple results
|
||||
// from lookup(). There will be zero, one, or two declarations of
|
||||
// the same name.
|
||||
unsigned Match;
|
||||
for (Match = 0; Match < Size; ++Match) {
|
||||
if (Array[Match]->getDeclName() == D->getDeclName())
|
||||
break;
|
||||
}
|
||||
|
||||
if (Match < Size) {
|
||||
// We found another declaration with the same name. If it's also
|
||||
// in the same identifier namespace, update the declaration in
|
||||
// place.
|
||||
Decl::IdentifierNamespace NS = D->getIdentifierNamespace();
|
||||
if (Array[Match]->getIdentifierNamespace() == NS) {
|
||||
Array[Match] = D;
|
||||
return;
|
||||
}
|
||||
if (Match + 1 < Size && Array[Match + 1]->getIdentifierNamespace() == NS) {
|
||||
Array[Match + 1] = D;
|
||||
return;
|
||||
}
|
||||
|
||||
// If there is an existing declaration in the namespace of
|
||||
// ordinary identifiers, then it must precede the tag
|
||||
// declaration for C++ name lookup to operate properly. Therefore,
|
||||
// if our match is an ordinary name and the new name is in the
|
||||
// tag namespace, we'll insert the new declaration after it.
|
||||
if (Match < Size && (NS == Decl::IDNS_Tag) &&
|
||||
(Array[Match]->getIdentifierNamespace() & Decl::IDNS_Ordinary))
|
||||
++Match;
|
||||
}
|
||||
|
||||
if (Size < LookupIsMap - 1) {
|
||||
// The new declaration will fit in the array. Insert the new
|
||||
// declaration at the position Match in the array.
|
||||
for (unsigned Idx = Size; Idx > Match; --Idx)
|
||||
Array[Idx] = Array[Idx-1];
|
||||
|
||||
Array[Match] = D;
|
||||
LookupPtr.setInt(Size + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// We've reached capacity in this array. Create a map and copy in
|
||||
// all of the declarations that were stored in the array.
|
||||
StoredDeclsMap *Map = new StoredDeclsMap(16);
|
||||
LookupPtr.setPointer(Map);
|
||||
LookupPtr.setInt(LookupIsMap);
|
||||
for (unsigned Idx = 0; Idx < LookupIsMap - 1; ++Idx)
|
||||
insertImpl(Array[Idx]);
|
||||
delete [] Array;
|
||||
|
||||
// Fall through to perform insertion into the map.
|
||||
}
|
||||
|
||||
// Insert this declaration into the map.
|
||||
StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
|
||||
StoredDeclsMap::iterator Pos = Map->find(D->getDeclName());
|
||||
unsigned IndexOfD = D->getIdentifierNamespace() & Decl::IDNS_Ordinary? 0 : 1;
|
||||
|
||||
if (Pos == Map->end()) {
|
||||
// Put this declaration into the appropriate slot.
|
||||
TwoNamedDecls Val;
|
||||
Val.Decls[0] = 0;
|
||||
Val.Decls[1] = 0;
|
||||
Val.Decls[IndexOfD] = D;
|
||||
Pos = Map->insert(std::make_pair(D->getDeclName(),Val)).first;
|
||||
} else {
|
||||
Pos->second.Decls[IndexOfD] = D;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,16 +36,9 @@ NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
|
|||
return new (Mem) NonTypeTemplateParmDecl(DC, L, Id, T, TypeSpecStartLoc);
|
||||
}
|
||||
|
||||
CXXFieldDecl *CXXFieldDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
SourceLocation L, IdentifierInfo *Id,
|
||||
QualType T, bool Mut, Expr *BW) {
|
||||
void *Mem = C.getAllocator().Allocate<CXXFieldDecl>();
|
||||
return new (Mem) CXXFieldDecl(RD, L, Id, T, Mut, BW);
|
||||
}
|
||||
|
||||
CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC,
|
||||
SourceLocation L, IdentifierInfo *Id)
|
||||
: RecordDecl(CXXRecord, TK, DC, L, Id), DeclContext(CXXRecord),
|
||||
: RecordDecl(CXXRecord, TK, DC, L, Id),
|
||||
UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
|
||||
Aggregate(true), Polymorphic(false), Bases(0), NumBases(0),
|
||||
Constructors(DC, DeclarationName()),
|
||||
|
@ -74,11 +67,6 @@ void CXXRecordDecl::Destroy(ASTContext &C) {
|
|||
if (isDefinition())
|
||||
Destructor->Destroy(C);
|
||||
|
||||
for (OverloadedFunctionDecl::function_iterator func
|
||||
= Conversions.function_begin();
|
||||
func != Conversions.function_end(); ++func)
|
||||
(*func)->Destroy(C);
|
||||
|
||||
RecordDecl::Destroy(C);
|
||||
}
|
||||
|
||||
|
@ -176,7 +164,7 @@ CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
|
|||
}
|
||||
|
||||
CXXBaseOrMemberInitializer::
|
||||
CXXBaseOrMemberInitializer(CXXFieldDecl *Member, Expr **Args, unsigned NumArgs)
|
||||
CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs)
|
||||
: Args(0), NumArgs(0) {
|
||||
BaseOrMember = reinterpret_cast<uintptr_t>(Member);
|
||||
assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
|
||||
|
|
|
@ -95,10 +95,10 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, SourceLocation L,
|
|||
|
||||
|
||||
ObjCAtDefsFieldDecl
|
||||
*ObjCAtDefsFieldDecl::Create(ASTContext &C, SourceLocation L,
|
||||
*ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T, Expr *BW) {
|
||||
void *Mem = C.getAllocator().Allocate<ObjCAtDefsFieldDecl>();
|
||||
return new (Mem) ObjCAtDefsFieldDecl(L, Id, T, BW);
|
||||
return new (Mem) ObjCAtDefsFieldDecl(DC, L, Id, T, BW);
|
||||
}
|
||||
|
||||
void ObjCAtDefsFieldDecl::Destroy(ASTContext& C) {
|
||||
|
|
|
@ -120,11 +120,29 @@ void Decl::ReadInRec(Deserializer& D, ASTContext& C) {
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void DeclContext::EmitOutRec(Serializer& S) const {
|
||||
S.EmitPtr(DeclChain);
|
||||
S.EmitInt(Decls.size());
|
||||
for (decl_iterator D = decls_begin(); D != decls_end(); ++D) {
|
||||
bool Owned = ((*D)->getLexicalDeclContext() == this &&
|
||||
DeclKind != Decl::TranslationUnit &&
|
||||
!isFunctionOrMethod());
|
||||
S.EmitBool(Owned);
|
||||
if (Owned)
|
||||
S.EmitOwnedPtr(*D);
|
||||
else
|
||||
S.EmitPtr(*D);
|
||||
}
|
||||
}
|
||||
|
||||
void DeclContext::ReadOutRec(Deserializer& D, ASTContext& C) {
|
||||
D.ReadPtr(DeclChain);
|
||||
unsigned NumDecls = D.ReadInt();
|
||||
Decls.resize(NumDecls);
|
||||
for (unsigned Idx = 0; Idx < NumDecls; ++Idx) {
|
||||
bool Owned = D.ReadBool();
|
||||
if (Owned)
|
||||
Decls[Idx] = cast_or_null<ScopedDecl>(D.ReadOwnedPtr<Decl>(C));
|
||||
else
|
||||
D.ReadPtr<ScopedDecl>(Decls[Idx]);
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -205,14 +223,12 @@ void NamedDecl::ReadInRec(Deserializer& D, ASTContext& C) {
|
|||
|
||||
void ScopedDecl::EmitInRec(Serializer& S) const {
|
||||
NamedDecl::EmitInRec(S);
|
||||
S.EmitPtr(getNext()); // From ScopedDecl.
|
||||
S.EmitPtr(cast_or_null<Decl>(getDeclContext())); // From ScopedDecl.
|
||||
S.EmitPtr(cast_or_null<Decl>(getLexicalDeclContext())); // From ScopedDecl.
|
||||
}
|
||||
|
||||
void ScopedDecl::ReadInRec(Deserializer& D, ASTContext& C) {
|
||||
NamedDecl::ReadInRec(D, C);
|
||||
D.ReadPtr(Next); // From ScopedDecl.
|
||||
|
||||
assert(DeclCtx == 0);
|
||||
|
||||
|
@ -394,8 +410,8 @@ ParmVarDecl* ParmVarDecl::CreateImpl(Deserializer& D, ASTContext& C) {
|
|||
void EnumDecl::EmitImpl(Serializer& S) const {
|
||||
ScopedDecl::EmitInRec(S);
|
||||
S.EmitBool(isDefinition());
|
||||
S.Emit(IntegerType);
|
||||
S.BatchEmitOwnedPtrs(getEnumConstantList(),getNextDeclarator());
|
||||
S.Emit(IntegerType);
|
||||
S.EmitOwnedPtr(getNextDeclarator());
|
||||
}
|
||||
|
||||
EnumDecl* EnumDecl::CreateImpl(Deserializer& D, ASTContext& C) {
|
||||
|
@ -406,12 +422,7 @@ EnumDecl* EnumDecl::CreateImpl(Deserializer& D, ASTContext& C) {
|
|||
decl->setDefinition(D.ReadBool());
|
||||
decl->IntegerType = QualType::ReadVal(D);
|
||||
|
||||
Decl* next_declarator;
|
||||
Decl* Elist;
|
||||
|
||||
D.BatchReadOwnedPtrs(Elist, next_declarator, C);
|
||||
|
||||
decl->setDeclChain(cast_or_null<EnumConstantDecl>(Elist));
|
||||
Decl* next_declarator = D.ReadOwnedPtr<Decl>(C);
|
||||
decl->setNextDeclarator(cast_or_null<ScopedDecl>(next_declarator));
|
||||
|
||||
return decl;
|
||||
|
@ -451,14 +462,17 @@ EnumConstantDecl* EnumConstantDecl::CreateImpl(Deserializer& D, ASTContext& C) {
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void FieldDecl::EmitImpl(Serializer& S) const {
|
||||
S.EmitBool(Mutable);
|
||||
S.Emit(getType());
|
||||
NamedDecl::EmitInRec(S);
|
||||
ScopedDecl::EmitInRec(S);
|
||||
S.EmitOwnedPtr(BitWidth);
|
||||
}
|
||||
|
||||
FieldDecl* FieldDecl::CreateImpl(Deserializer& D, ASTContext& C) {
|
||||
void *Mem = C.getAllocator().Allocate<FieldDecl>();
|
||||
FieldDecl* decl = new (Mem) FieldDecl(SourceLocation(), NULL, QualType(), 0);
|
||||
FieldDecl* decl = new (Mem) FieldDecl(Field, 0, SourceLocation(), NULL,
|
||||
QualType(), 0, false, 0);
|
||||
decl->Mutable = D.ReadBool();
|
||||
decl->DeclType.ReadBackpatch(D);
|
||||
decl->ReadInRec(D, C);
|
||||
decl->BitWidth = D.ReadOwnedPtr<Expr>(C);
|
||||
|
@ -579,13 +593,7 @@ void RecordDecl::EmitImpl(Serializer& S) const {
|
|||
ScopedDecl::EmitInRec(S);
|
||||
S.EmitBool(isDefinition());
|
||||
S.EmitBool(hasFlexibleArrayMember());
|
||||
S.EmitSInt(getNumMembers());
|
||||
if (getNumMembers() > 0) {
|
||||
assert (Members);
|
||||
S.BatchEmitOwnedPtrs((unsigned) getNumMembers(), (Decl**) &Members[0]);
|
||||
}
|
||||
else
|
||||
ScopedDecl::EmitOutRec(S);
|
||||
ScopedDecl::EmitOutRec(S);
|
||||
}
|
||||
|
||||
RecordDecl* RecordDecl::CreateImpl(Deserializer& D, ASTContext& C) {
|
||||
|
@ -597,17 +605,8 @@ RecordDecl* RecordDecl::CreateImpl(Deserializer& D, ASTContext& C) {
|
|||
decl->ScopedDecl::ReadInRec(D, C);
|
||||
decl->setDefinition(D.ReadBool());
|
||||
decl->setHasFlexibleArrayMember(D.ReadBool());
|
||||
decl->NumMembers = D.ReadSInt();
|
||||
|
||||
if (decl->getNumMembers() > 0) {
|
||||
decl->Members = new FieldDecl*[(unsigned) decl->getNumMembers()];
|
||||
|
||||
D.BatchReadOwnedPtrs((unsigned) decl->getNumMembers(),
|
||||
(Decl**) &decl->Members[0], C);
|
||||
}
|
||||
else
|
||||
decl->ScopedDecl::ReadOutRec(D, C);
|
||||
|
||||
decl->ScopedDecl::ReadOutRec(D, C);
|
||||
|
||||
return decl;
|
||||
}
|
||||
|
||||
|
|
|
@ -311,3 +311,9 @@ DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
|
|||
return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
|
||||
}
|
||||
|
||||
unsigned
|
||||
llvm::DenseMapInfo<clang::DeclarationName>::
|
||||
getHashValue(clang::DeclarationName N) {
|
||||
return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
|
||||
}
|
||||
|
||||
|
|
|
@ -353,7 +353,7 @@ static bool DeclCanBeLvalue(const NamedDecl *Decl, ASTContext &Ctx) {
|
|||
= dyn_cast<NonTypeTemplateParmDecl>(Decl))
|
||||
return NTTParm->getType()->isReferenceType();
|
||||
|
||||
return isa<VarDecl>(Decl) || isa<CXXFieldDecl>(Decl) ||
|
||||
return isa<VarDecl>(Decl) || isa<FieldDecl>(Decl) ||
|
||||
// C++ 3.10p2: An lvalue refers to an object or function.
|
||||
(Ctx.getLangOptions().CPlusPlus &&
|
||||
(isa<FunctionDecl>(Decl) || isa<OverloadedFunctionDecl>(Decl)));
|
||||
|
@ -1222,10 +1222,15 @@ static int64_t evaluateOffsetOf(ASTContext& C, const Expr *E)
|
|||
const ASTRecordLayout &RL = C.getASTRecordLayout(RD);
|
||||
FieldDecl *FD = ME->getMemberDecl();
|
||||
|
||||
// FIXME: This is linear time.
|
||||
unsigned i = 0, e = 0;
|
||||
for (i = 0, e = RD->getNumMembers(); i != e; i++) {
|
||||
if (RD->getMember(i) == FD)
|
||||
// FIXME: This is linear time. And the fact that we're indexing
|
||||
// into the layout by position in the record means that we're
|
||||
// either stuck numbering the fields in the AST or we have to keep
|
||||
// the linear search (yuck and yuck).
|
||||
unsigned i = 0;
|
||||
for (RecordDecl::field_iterator Field = RD->field_begin(),
|
||||
FieldEnd = RD->field_end();
|
||||
Field != FieldEnd; (void)++Field, ++i) {
|
||||
if (*Field == FD)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -156,9 +156,11 @@ APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
|
|||
FieldDecl *FD = E->getMemberDecl();
|
||||
|
||||
// FIXME: This is linear time.
|
||||
unsigned i = 0, e = 0;
|
||||
for (i = 0, e = RD->getNumMembers(); i != e; i++) {
|
||||
if (RD->getMember(i) == FD)
|
||||
unsigned i = 0;
|
||||
for (RecordDecl::field_iterator Field = RD->field_begin(),
|
||||
FieldEnd = RD->field_end();
|
||||
Field != FieldEnd; (void)++Field, ++i) {
|
||||
if (*Field == FD)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -433,8 +433,13 @@ SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {
|
|||
|
||||
llvm::ImmutableList<SVal> StructVal = getBasicVals().getEmptySValList();
|
||||
|
||||
for (int i = RD->getNumMembers() - 1; i >= 0; --i) {
|
||||
FieldRegion* FR = MRMgr.getFieldRegion(RD->getMember(i), R);
|
||||
for (DeclContext::reverse_decl_iterator Mem = RD->decls_rbegin();
|
||||
Mem != RD->decls_rend(); ++Mem) {
|
||||
FieldDecl *FD = dyn_cast<FieldDecl>(*Mem);
|
||||
if (!FD)
|
||||
continue;
|
||||
|
||||
FieldRegion* FR = MRMgr.getFieldRegion(FD, R);
|
||||
RegionBindingsTy B(static_cast<const RegionBindingsTy::TreeTy*>(store));
|
||||
RegionBindingsTy::data_type* data = B.lookup(FR);
|
||||
|
||||
|
|
|
@ -289,10 +289,11 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,
|
|||
llvm::SmallVector<llvm::DIDescriptor, 32> Enumerators;
|
||||
|
||||
// Create DIEnumerator elements for each enumerator.
|
||||
for (EnumConstantDecl *Elt = Decl->getEnumConstantList(); Elt;
|
||||
Elt = dyn_cast_or_null<EnumConstantDecl>(Elt->getNextDeclarator())) {
|
||||
Enumerators.push_back(DebugFactory.CreateEnumerator(Elt->getNameAsString(),
|
||||
Elt->getInitVal().getZExtValue()));
|
||||
for (EnumDecl::enumerator_iterator Enum = Decl->enumerator_begin(),
|
||||
EnumEnd = Decl->enumerator_end();
|
||||
Enum != EnumEnd; ++Enum) {
|
||||
Enumerators.push_back(DebugFactory.CreateEnumerator(Enum->getNameAsString(),
|
||||
Enum->getInitVal().getZExtValue()));
|
||||
}
|
||||
|
||||
// Return a CompositeType for the enum itself.
|
||||
|
|
|
@ -434,20 +434,24 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
|
|||
// the optimizer, especially with bitfields.
|
||||
unsigned NumInitElements = E->getNumInits();
|
||||
RecordDecl *SD = E->getType()->getAsRecordType()->getDecl();
|
||||
unsigned NumMembers = SD->getNumMembers() - SD->hasFlexibleArrayMember();
|
||||
unsigned CurInitVal = 0;
|
||||
bool isUnion = E->getType()->isUnionType();
|
||||
|
||||
// Here we iterate over the fields; this makes it simpler to both
|
||||
// default-initialize fields and skip over unnamed fields.
|
||||
for (unsigned CurFieldNo = 0; CurFieldNo != NumMembers; ++CurFieldNo) {
|
||||
FieldDecl *CurField = SD->getMember(CurFieldNo);
|
||||
if (CurField->getIdentifier() == 0) {
|
||||
for (RecordDecl::field_iterator Field = SD->field_begin(),
|
||||
FieldEnd = SD->field_end();
|
||||
Field != FieldEnd; ++Field) {
|
||||
// We're done once we hit the flexible array member
|
||||
if (Field->getType()->isIncompleteArrayType())
|
||||
break;
|
||||
|
||||
if (Field->getIdentifier() == 0) {
|
||||
// Initializers can't initialize unnamed fields, e.g. "int : 20;"
|
||||
continue;
|
||||
}
|
||||
// FIXME: volatility
|
||||
LValue FieldLoc = CGF.EmitLValueForField(DestPtr, CurField, isUnion,0);
|
||||
LValue FieldLoc = CGF.EmitLValueForField(DestPtr, *Field, isUnion,0);
|
||||
if (CurInitVal < NumInitElements) {
|
||||
// Store the initializer into the field
|
||||
// This will probably have to get a bit smarter when we support
|
||||
|
@ -455,7 +459,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
|
|||
EmitInitializationToLValue(E->getInit(CurInitVal++), FieldLoc);
|
||||
} else {
|
||||
// We're out of initalizers; default-initialize to null
|
||||
EmitNullInitializationToLValue(FieldLoc, CurField->getType());
|
||||
EmitNullInitializationToLValue(FieldLoc, Field->getType());
|
||||
}
|
||||
|
||||
// Unions only initialize one field.
|
||||
|
|
|
@ -187,16 +187,17 @@ public:
|
|||
unsigned EltNo = 0; // Element no in ILE
|
||||
int FieldNo = 0; // Field no in RecordDecl
|
||||
bool RewriteType = false;
|
||||
while (EltNo < ILE->getNumInits() && FieldNo < RD->getNumMembers()) {
|
||||
FieldDecl* curField = RD->getMember(FieldNo);
|
||||
for (RecordDecl::field_iterator Field = RD->field_begin(),
|
||||
FieldEnd = RD->field_end();
|
||||
EltNo < ILE->getNumInits() && Field != FieldEnd; ++Field) {
|
||||
FieldNo++;
|
||||
if (!curField->getIdentifier())
|
||||
if (!Field->getIdentifier())
|
||||
continue;
|
||||
|
||||
if (curField->isBitField()) {
|
||||
InsertBitfieldIntoStruct(Elts, curField, ILE->getInit(EltNo));
|
||||
if (Field->isBitField()) {
|
||||
InsertBitfieldIntoStruct(Elts, *Field, ILE->getInit(EltNo));
|
||||
} else {
|
||||
unsigned FieldNo = CGM.getTypes().getLLVMFieldNo(curField);
|
||||
unsigned FieldNo = CGM.getTypes().getLLVMFieldNo(*Field);
|
||||
llvm::Constant *C = CGM.EmitConstantExpr(ILE->getInit(EltNo), CGF);
|
||||
RewriteType |= (C->getType() != Elts[FieldNo]->getType());
|
||||
Elts[FieldNo] = C;
|
||||
|
@ -223,8 +224,10 @@ public:
|
|||
// Find the field decl we're initializing, if any
|
||||
int FieldNo = 0; // Field no in RecordDecl
|
||||
FieldDecl* curField = 0;
|
||||
while (FieldNo < RD->getNumMembers()) {
|
||||
curField = RD->getMember(FieldNo);
|
||||
for (RecordDecl::field_iterator Field = RD->field_begin(),
|
||||
FieldEnd = RD->field_end();
|
||||
Field != FieldEnd; ++Field) {
|
||||
curField = *Field;
|
||||
FieldNo++;
|
||||
if (curField->getIdentifier())
|
||||
break;
|
||||
|
|
|
@ -2373,12 +2373,15 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
|
|||
RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
|
||||
SourceLocation(),
|
||||
&Ctx.Idents.get("_objc_super"));
|
||||
FieldDecl *FieldDecls[2];
|
||||
FieldDecls[0] = FieldDecl::Create(Ctx, SourceLocation(), 0,
|
||||
Ctx.getObjCIdType());
|
||||
FieldDecls[1] = FieldDecl::Create(Ctx, SourceLocation(), 0,
|
||||
Ctx.getObjCClassType());
|
||||
RD->defineBody(Ctx, FieldDecls, 2);
|
||||
RD->addDecl(Ctx,
|
||||
FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
|
||||
Ctx.getObjCIdType(), 0, false, 0),
|
||||
true);
|
||||
RD->addDecl(Ctx,
|
||||
FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
|
||||
Ctx.getObjCClassType(), 0, false, 0),
|
||||
true);
|
||||
RD->completeDefinition(Ctx);
|
||||
|
||||
SuperCTy = Ctx.getTagDeclType(RD);
|
||||
SuperPtrCTy = Ctx.getPointerType(SuperCTy);
|
||||
|
|
|
@ -775,21 +775,20 @@ llvm::Function *CodeGenModule::getMemSetFn() {
|
|||
|
||||
static void appendFieldAndPadding(CodeGenModule &CGM,
|
||||
std::vector<llvm::Constant*>& Fields,
|
||||
int FieldNo, llvm::Constant* Field,
|
||||
FieldDecl *FieldD, FieldDecl *NextFieldD,
|
||||
llvm::Constant* Field,
|
||||
RecordDecl* RD, const llvm::StructType *STy)
|
||||
{
|
||||
// Append the field.
|
||||
Fields.push_back(Field);
|
||||
|
||||
int StructFieldNo =
|
||||
CGM.getTypes().getLLVMFieldNo(RD->getMember(FieldNo));
|
||||
int StructFieldNo = CGM.getTypes().getLLVMFieldNo(FieldD);
|
||||
|
||||
int NextStructFieldNo;
|
||||
if (FieldNo + 1 == RD->getNumMembers()) {
|
||||
if (!NextFieldD) {
|
||||
NextStructFieldNo = STy->getNumElements();
|
||||
} else {
|
||||
NextStructFieldNo =
|
||||
CGM.getTypes().getLLVMFieldNo(RD->getMember(FieldNo + 1));
|
||||
NextStructFieldNo = CGM.getTypes().getLLVMFieldNo(NextFieldD);
|
||||
}
|
||||
|
||||
// Append padding
|
||||
|
@ -841,29 +840,38 @@ GetAddrOfConstantCFString(const std::string &str) {
|
|||
cast<llvm::StructType>(getTypes().ConvertType(CFTy));
|
||||
|
||||
std::vector<llvm::Constant*> Fields;
|
||||
|
||||
|
||||
RecordDecl::field_iterator Field = CFRD->field_begin();
|
||||
|
||||
// Class pointer.
|
||||
appendFieldAndPadding(*this, Fields, 0, CFConstantStringClassRef, CFRD, STy);
|
||||
FieldDecl *CurField = *Field++;
|
||||
FieldDecl *NextField = *Field++;
|
||||
appendFieldAndPadding(*this, Fields, CurField, NextField,
|
||||
CFConstantStringClassRef, CFRD, STy);
|
||||
|
||||
// Flags.
|
||||
CurField = NextField;
|
||||
NextField = *Field++;
|
||||
const llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy);
|
||||
appendFieldAndPadding(*this, Fields, 1, llvm::ConstantInt::get(Ty, 0x07C8),
|
||||
CFRD, STy);
|
||||
appendFieldAndPadding(*this, Fields, CurField, NextField,
|
||||
llvm::ConstantInt::get(Ty, 0x07C8), CFRD, STy);
|
||||
|
||||
// String pointer.
|
||||
CurField = NextField;
|
||||
NextField = *Field++;
|
||||
llvm::Constant *C = llvm::ConstantArray::get(str);
|
||||
C = new llvm::GlobalVariable(C->getType(), true,
|
||||
llvm::GlobalValue::InternalLinkage,
|
||||
C, ".str", &getModule());
|
||||
appendFieldAndPadding(*this, Fields, 2,
|
||||
appendFieldAndPadding(*this, Fields, CurField, NextField,
|
||||
llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2),
|
||||
CFRD, STy);
|
||||
|
||||
// String length.
|
||||
CurField = NextField;
|
||||
NextField = 0;
|
||||
Ty = getTypes().ConvertType(getContext().LongTy);
|
||||
appendFieldAndPadding(*this, Fields, 3, llvm::ConstantInt::get(Ty, str.length()),
|
||||
CFRD, STy);
|
||||
appendFieldAndPadding(*this, Fields, CurField, NextField,
|
||||
llvm::ConstantInt::get(Ty, str.length()), CFRD, STy);
|
||||
|
||||
// The struct.
|
||||
C = llvm::ConstantStruct::get(STy, Fields);
|
||||
|
|
|
@ -392,7 +392,7 @@ const llvm::Type *CodeGenTypes::ConvertTagDeclType(const TagDecl *TD) {
|
|||
} else if (TD->isUnion()) {
|
||||
// Just use the largest element of the union, breaking ties with the
|
||||
// highest aligned member.
|
||||
if (RD->getNumMembers() != 0) {
|
||||
if (RD->field_begin() != RD->field_end()) {
|
||||
RecordOrganizer RO(*this, *RD);
|
||||
|
||||
RO.layoutUnionFields(Context.getASTRecordLayout(RD));
|
||||
|
@ -478,16 +478,17 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {
|
|||
uint64_t llvmSize = 0;
|
||||
// FIXME: Make this a SmallVector
|
||||
std::vector<const llvm::Type*> LLVMFields;
|
||||
int NumMembers = RD.getNumMembers();
|
||||
|
||||
for (int curField = 0; curField < NumMembers; curField++) {
|
||||
const FieldDecl *FD = RD.getMember(curField);
|
||||
unsigned curField = 0;
|
||||
for (RecordDecl::field_iterator Field = RD.field_begin(),
|
||||
FieldEnd = RD.field_end();
|
||||
Field != FieldEnd; ++Field) {
|
||||
uint64_t offset = RL.getFieldOffset(curField);
|
||||
const llvm::Type *Ty = CGT.ConvertTypeRecursive(FD->getType());
|
||||
const llvm::Type *Ty = CGT.ConvertTypeRecursive(Field->getType());
|
||||
uint64_t size = CGT.getTargetData().getABITypeSizeInBits(Ty);
|
||||
|
||||
if (FD->isBitField()) {
|
||||
Expr *BitWidth = FD->getBitWidth();
|
||||
if (Field->isBitField()) {
|
||||
Expr *BitWidth = Field->getBitWidth();
|
||||
llvm::APSInt FieldSize(32);
|
||||
bool isBitField =
|
||||
BitWidth->isIntegerConstantExpr(FieldSize, CGT.getContext());
|
||||
|
@ -498,8 +499,8 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {
|
|||
// Bitfield field info is different from other field info;
|
||||
// it actually ignores the underlying LLVM struct because
|
||||
// there isn't any convenient mapping.
|
||||
CGT.addFieldInfo(FD, offset / size);
|
||||
CGT.addBitFieldInfo(FD, offset % size, BitFieldSize);
|
||||
CGT.addFieldInfo(*Field, offset / size);
|
||||
CGT.addBitFieldInfo(*Field, offset % size, BitFieldSize);
|
||||
} else {
|
||||
// Put the element into the struct. This would be simpler
|
||||
// if we didn't bother, but it seems a bit too strange to
|
||||
|
@ -510,9 +511,10 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {
|
|||
}
|
||||
|
||||
llvmSize += size;
|
||||
CGT.addFieldInfo(FD, LLVMFields.size());
|
||||
CGT.addFieldInfo(*Field, LLVMFields.size());
|
||||
LLVMFields.push_back(Ty);
|
||||
}
|
||||
++curField;
|
||||
}
|
||||
|
||||
while (llvmSize < RL.getSize()) {
|
||||
|
@ -528,21 +530,24 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {
|
|||
/// corresponding llvm struct type. This should be invoked only after
|
||||
/// all fields are added.
|
||||
void RecordOrganizer::layoutUnionFields(const ASTRecordLayout &RL) {
|
||||
for (int curField = 0; curField < RD.getNumMembers(); curField++) {
|
||||
const FieldDecl *FD = RD.getMember(curField);
|
||||
unsigned curField = 0;
|
||||
for (RecordDecl::field_iterator Field = RD.field_begin(),
|
||||
FieldEnd = RD.field_end();
|
||||
Field != FieldEnd; ++Field) {
|
||||
// The offset should usually be zero, but bitfields could be strange
|
||||
uint64_t offset = RL.getFieldOffset(curField);
|
||||
|
||||
if (FD->isBitField()) {
|
||||
Expr *BitWidth = FD->getBitWidth();
|
||||
if (Field->isBitField()) {
|
||||
Expr *BitWidth = Field->getBitWidth();
|
||||
uint64_t BitFieldSize =
|
||||
BitWidth->getIntegerConstantExprValue(CGT.getContext()).getZExtValue();
|
||||
|
||||
CGT.addFieldInfo(FD, 0);
|
||||
CGT.addBitFieldInfo(FD, offset, BitFieldSize);
|
||||
CGT.addFieldInfo(*Field, 0);
|
||||
CGT.addBitFieldInfo(*Field, offset, BitFieldSize);
|
||||
} else {
|
||||
CGT.addFieldInfo(FD, 0);
|
||||
CGT.addFieldInfo(*Field, 0);
|
||||
}
|
||||
++curField;
|
||||
}
|
||||
|
||||
// This looks stupid, but it is correct in the sense that
|
||||
|
|
|
@ -914,7 +914,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
|
|||
for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
|
||||
FieldDeclarator &FD = FieldDeclarators[i];
|
||||
// Install the declarator into the current TagDecl.
|
||||
DeclTy *Field = Actions.ActOnField(CurScope,
|
||||
DeclTy *Field = Actions.ActOnField(CurScope, TagDecl,
|
||||
DS.getSourceRange().getBegin(),
|
||||
FD.D, FD.BitfieldSize);
|
||||
FieldDecls.push_back(Field);
|
||||
|
@ -934,8 +934,8 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
|
|||
continue;
|
||||
}
|
||||
llvm::SmallVector<DeclTy*, 16> Fields;
|
||||
Actions.ActOnDefs(CurScope, Tok.getLocation(), Tok.getIdentifierInfo(),
|
||||
Fields);
|
||||
Actions.ActOnDefs(CurScope, TagDecl, Tok.getLocation(),
|
||||
Tok.getIdentifierInfo(), Fields);
|
||||
FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end());
|
||||
ConsumeToken();
|
||||
ExpectAndConsume(tok::r_paren, diag::err_expected_rparen);
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace clang {
|
||||
class CXXFieldDecl;
|
||||
class FieldDecl;
|
||||
|
||||
/// CXXFieldCollector - Used to keep track of CXXFieldDecls during parsing of
|
||||
/// C++ classes.
|
||||
class CXXFieldCollector {
|
||||
/// Fields - Contains all CXXFieldDecls collected during parsing of a C++
|
||||
/// Fields - Contains all FieldDecls collected during parsing of a C++
|
||||
/// class. When a nested class is entered, its fields are appended to the
|
||||
/// fields of its parent class, when it is exited its fields are removed.
|
||||
llvm::SmallVector<CXXFieldDecl*, 32> Fields;
|
||||
llvm::SmallVector<FieldDecl*, 32> Fields;
|
||||
|
||||
/// FieldCount - Each entry represents the number of fields collected during
|
||||
/// the parsing of a C++ class. When a nested class is entered, a new field
|
||||
|
@ -52,7 +52,7 @@ public:
|
|||
void StartClass() { FieldCount.push_back(0); }
|
||||
|
||||
/// Add - Called by Sema::ActOnCXXMemberDeclarator.
|
||||
void Add(CXXFieldDecl *D) {
|
||||
void Add(FieldDecl *D) {
|
||||
Fields.push_back(D);
|
||||
++FieldCount.back();
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ public:
|
|||
|
||||
/// getCurFields - Pointer to array of fields added to the currently parsed
|
||||
/// class.
|
||||
CXXFieldDecl **getCurFields() { return &*(Fields.end() - getCurNumFields()); }
|
||||
FieldDecl **getCurFields() { return &*(Fields.end() - getCurNumFields()); }
|
||||
|
||||
/// FinishClass - Called by Sema::ActOnFinishCXXClassDef.
|
||||
void FinishClass() {
|
||||
|
|
|
@ -51,9 +51,6 @@ public:
|
|||
DeclContext *IdentifierResolver::LookupContext::getContext(Decl *D) {
|
||||
DeclContext *Ctx;
|
||||
|
||||
if (CXXFieldDecl *FD = dyn_cast<CXXFieldDecl>(D))
|
||||
return FD->getParent();
|
||||
|
||||
if (EnumConstantDecl *EnumD = dyn_cast<EnumConstantDecl>(D)) {
|
||||
Ctx = EnumD->getDeclContext()->getParent();
|
||||
} else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D))
|
||||
|
@ -149,7 +146,7 @@ IdentifierResolver::~IdentifierResolver() {
|
|||
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
|
||||
/// true if 'D' belongs to the given declaration context.
|
||||
bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
|
||||
Scope *S) const {
|
||||
ASTContext &Context, Scope *S) const {
|
||||
if (Ctx->isFunctionOrMethod()) {
|
||||
if (S->isDeclScope(D))
|
||||
return true;
|
||||
|
@ -169,7 +166,7 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
|
|||
return false;
|
||||
}
|
||||
|
||||
return LookupContext(D) == LookupContext(Ctx);
|
||||
return LookupContext(D) == LookupContext(Ctx->getPrimaryContext(Context));
|
||||
}
|
||||
|
||||
/// AddDecl - Link the decl to its shadowed decl chain.
|
||||
|
|
|
@ -208,7 +208,8 @@ public:
|
|||
/// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
|
||||
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
|
||||
/// true if 'D' belongs to the given declaration context.
|
||||
bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0) const;
|
||||
bool isDeclInScope(Decl *D, DeclContext *Ctx, ASTContext &Context,
|
||||
Scope *S = 0) const;
|
||||
|
||||
/// AddDecl - Link the decl to its shadowed decl chain.
|
||||
void AddDecl(NamedDecl *D);
|
||||
|
|
|
@ -68,7 +68,7 @@ static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name) {
|
|||
|
||||
void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
|
||||
TUScope = S;
|
||||
PushDeclContext(Context.getTranslationUnitDecl());
|
||||
PushDeclContext(S, Context.getTranslationUnitDecl());
|
||||
if (!PP.getLangOptions().ObjC1) return;
|
||||
|
||||
// Synthesize "typedef struct objc_selector *SEL;"
|
||||
|
|
|
@ -300,10 +300,10 @@ public:
|
|||
IdentifierInfo *Name, SourceLocation NameLoc,
|
||||
AttributeList *Attr);
|
||||
|
||||
virtual void ActOnDefs(Scope *S, SourceLocation DeclStart,
|
||||
virtual void ActOnDefs(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
|
||||
IdentifierInfo *ClassName,
|
||||
llvm::SmallVectorImpl<DeclTy*> &Decls);
|
||||
virtual DeclTy *ActOnField(Scope *S, SourceLocation DeclStart,
|
||||
virtual DeclTy *ActOnField(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
|
||||
Declarator &D, ExprTy *BitfieldWidth);
|
||||
|
||||
virtual DeclTy *ActOnIvar(Scope *S, SourceLocation DeclStart,
|
||||
|
@ -326,7 +326,7 @@ public:
|
|||
DeclContext *getContainingDC(DeclContext *DC);
|
||||
|
||||
/// Set the current declaration context until it gets popped.
|
||||
void PushDeclContext(DeclContext *DC);
|
||||
void PushDeclContext(Scope *S, DeclContext *DC);
|
||||
void PopDeclContext();
|
||||
|
||||
/// getCurFunctionDecl - If inside of a function body, this returns a pointer
|
||||
|
@ -351,7 +351,7 @@ public:
|
|||
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
|
||||
/// true if 'D' belongs to the given declaration context.
|
||||
bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0) {
|
||||
return IdResolver.isDeclInScope(D, Ctx, S);
|
||||
return IdResolver.isDeclInScope(D, Ctx, Context, S);
|
||||
}
|
||||
|
||||
/// Subroutines of ActOnDeclarator().
|
||||
|
@ -478,7 +478,8 @@ public:
|
|||
/// More parsing and symbol table subroutines...
|
||||
Decl *LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
|
||||
const DeclContext *LookupCtx = 0,
|
||||
bool enableLazyBuiltinCreation = true);
|
||||
bool enableLazyBuiltinCreation = true,
|
||||
bool LookInParent = true);
|
||||
ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id);
|
||||
ScopedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
|
||||
Scope *S);
|
||||
|
|
|
@ -20,7 +20,25 @@ using namespace clang;
|
|||
|
||||
namespace {
|
||||
Decl *LookupNestedName(DeclContext *LookupCtx, bool LookInParentCtx,
|
||||
DeclarationName Name, bool &IdIsUndeclared) {
|
||||
DeclarationName Name, bool &IdIsUndeclared,
|
||||
ASTContext &Context) {
|
||||
if (LookupCtx && !LookInParentCtx) {
|
||||
IdIsUndeclared = true;
|
||||
for (DeclContext::lookup_const_result I = LookupCtx->lookup(Context, Name);
|
||||
I.first != I.second; ++I.first) {
|
||||
IdIsUndeclared = false;
|
||||
if (((*I.first)->getIdentifierNamespace() & Decl::IDNS_Tag) &&
|
||||
!isa<EnumDecl>(*I.first))
|
||||
return *I.first;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FIXME: Decouple this from the IdentifierResolver so that we can
|
||||
// deal with lookups into the semantic parent contexts that aren't
|
||||
// lexical parent contexts.
|
||||
|
||||
IdentifierResolver::iterator
|
||||
I = IdentifierResolver::begin(Name, LookupCtx, LookInParentCtx),
|
||||
E = IdentifierResolver::end();
|
||||
|
@ -73,10 +91,11 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
|
|||
bool IdIsUndeclared;
|
||||
|
||||
if (DC)
|
||||
SD = LookupNestedName(DC, false/*LookInParentCtx*/, &II, IdIsUndeclared);
|
||||
SD = LookupNestedName(DC, false/*LookInParentCtx*/, &II, IdIsUndeclared,
|
||||
Context);
|
||||
else
|
||||
SD = LookupNestedName(CurContext, true/*LookInParent*/, &II,
|
||||
IdIsUndeclared);
|
||||
IdIsUndeclared, Context);
|
||||
|
||||
if (SD) {
|
||||
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
|
||||
|
|
|
@ -74,14 +74,16 @@ DeclContext *Sema::getContainingDC(DeclContext *DC) {
|
|||
return DC->getLexicalParent();
|
||||
}
|
||||
|
||||
void Sema::PushDeclContext(DeclContext *DC) {
|
||||
void Sema::PushDeclContext(Scope *S, DeclContext *DC) {
|
||||
assert(getContainingDC(DC) == CurContext &&
|
||||
"The next DeclContext should be lexically contained in the current one.");
|
||||
CurContext = DC;
|
||||
S->setEntity(DC);
|
||||
}
|
||||
|
||||
void Sema::PopDeclContext() {
|
||||
assert(CurContext && "DeclContext imbalance!");
|
||||
|
||||
CurContext = getContainingDC(CurContext);
|
||||
}
|
||||
|
||||
|
@ -97,53 +99,90 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
|
|||
// in this case the class name or enumeration name is hidden.
|
||||
if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
|
||||
// We are pushing the name of a tag (enum or class).
|
||||
IdentifierResolver::iterator
|
||||
I = IdResolver.begin(TD->getIdentifier(),
|
||||
TD->getDeclContext(), false/*LookInParentCtx*/);
|
||||
if (I != IdResolver.end() && isDeclInScope(*I, TD->getDeclContext(), S)) {
|
||||
// There is already a declaration with the same name in the same
|
||||
// scope. It must be found before we find the new declaration,
|
||||
// so swap the order on the shadowed declaration chain.
|
||||
if (CurContext == TD->getDeclContext()) {
|
||||
// We're pushing the tag into the current context, which might
|
||||
// require some reshuffling in the identifier resolver.
|
||||
IdentifierResolver::iterator
|
||||
I = IdResolver.begin(TD->getIdentifier(), CurContext,
|
||||
false/*LookInParentCtx*/);
|
||||
if (I != IdResolver.end()) {
|
||||
// There is already a declaration with the same name in the same
|
||||
// scope. It must be found before we find the new declaration,
|
||||
// so swap the order on the shadowed declaration chain.
|
||||
IdResolver.AddShadowedDecl(TD, *I);
|
||||
|
||||
IdResolver.AddShadowedDecl(TD, *I);
|
||||
return;
|
||||
// Add this declaration to the current context.
|
||||
CurContext->addDecl(Context, TD);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) {
|
||||
FunctionDecl *FD = cast<FunctionDecl>(D);
|
||||
// We are pushing the name of a function, which might be an
|
||||
// overloaded name.
|
||||
IdentifierResolver::iterator
|
||||
I = IdResolver.begin(FD->getDeclName(),
|
||||
FD->getDeclContext(), false/*LookInParentCtx*/);
|
||||
if (I != IdResolver.end() &&
|
||||
IdResolver.isDeclInScope(*I, FD->getDeclContext(), S) &&
|
||||
(isa<OverloadedFunctionDecl>(*I) || isa<FunctionDecl>(*I))) {
|
||||
// There is already a declaration with the same name in the same
|
||||
// scope. It must be a function or an overloaded function.
|
||||
OverloadedFunctionDecl* Ovl = dyn_cast<OverloadedFunctionDecl>(*I);
|
||||
FunctionDecl *FD = cast<FunctionDecl>(D);
|
||||
Decl *Prev = LookupDecl(FD->getDeclName(), Decl::IDNS_Ordinary, S,
|
||||
FD->getDeclContext(), false, false);
|
||||
if (Prev && (isa<OverloadedFunctionDecl>(Prev) || isa<FunctionDecl>(Prev))) {
|
||||
// There is already a declaration with the same name in
|
||||
// the same scope. It must be a function or an overloaded
|
||||
// function.
|
||||
OverloadedFunctionDecl* Ovl = dyn_cast<OverloadedFunctionDecl>(Prev);
|
||||
if (!Ovl) {
|
||||
// We haven't yet overloaded this function. Take the existing
|
||||
// FunctionDecl and put it into an OverloadedFunctionDecl.
|
||||
Ovl = OverloadedFunctionDecl::Create(Context,
|
||||
FD->getDeclContext(),
|
||||
FD->getDeclName());
|
||||
Ovl->addOverload(dyn_cast<FunctionDecl>(*I));
|
||||
Ovl->addOverload(dyn_cast<FunctionDecl>(Prev));
|
||||
|
||||
// Remove the name binding to the existing FunctionDecl...
|
||||
IdResolver.RemoveDecl(*I);
|
||||
|
||||
// ... and put the OverloadedFunctionDecl in its place.
|
||||
// If there is an name binding for the existing FunctionDecl,
|
||||
// remove it.
|
||||
for (IdentifierResolver::iterator I
|
||||
= IdResolver.begin(FD->getDeclName(), FD->getDeclContext(),
|
||||
false/*LookInParentCtx*/);
|
||||
I != IdResolver.end(); ++I) {
|
||||
if (*I == Prev) {
|
||||
IdResolver.RemoveDecl(*I);
|
||||
S->RemoveDecl(*I);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the name binding for the OverloadedFunctionDecl.
|
||||
IdResolver.AddDecl(Ovl);
|
||||
|
||||
// Update the context with the newly-created overloaded
|
||||
// function set.
|
||||
FD->getDeclContext()->insert(Context, Ovl);
|
||||
|
||||
S->AddDecl(Ovl);
|
||||
}
|
||||
|
||||
// We added this function declaration to the scope earlier, but
|
||||
// we don't want it there because it is part of the overloaded
|
||||
// function declaration.
|
||||
S->RemoveDecl(FD);
|
||||
|
||||
// We have an OverloadedFunctionDecl. Add the new FunctionDecl
|
||||
// to its list of overloads.
|
||||
Ovl->addOverload(FD);
|
||||
|
||||
return;
|
||||
// Add this new function declaration to the declaration context.
|
||||
CurContext->addDecl(Context, FD, false);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D))
|
||||
CurContext->addDecl(Context, SD);
|
||||
else {
|
||||
// Other kinds of declarations don't currently have a context
|
||||
// where they need to be inserted.
|
||||
}
|
||||
|
||||
|
||||
IdResolver.AddDecl(D);
|
||||
}
|
||||
|
||||
|
@ -157,25 +196,13 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
|
|||
Decl *TmpD = static_cast<Decl*>(*I);
|
||||
assert(TmpD && "This decl didn't get pushed??");
|
||||
|
||||
if (isa<CXXFieldDecl>(TmpD)) continue;
|
||||
assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?");
|
||||
NamedDecl *D = cast<NamedDecl>(TmpD);
|
||||
|
||||
assert(isa<ScopedDecl>(TmpD) && "Decl isn't ScopedDecl?");
|
||||
ScopedDecl *D = cast<ScopedDecl>(TmpD);
|
||||
|
||||
IdentifierInfo *II = D->getIdentifier();
|
||||
if (!II) continue;
|
||||
|
||||
// We only want to remove the decls from the identifier decl chains for
|
||||
// local scopes, when inside a function/method.
|
||||
// However, we *always* remove template parameters, since they are
|
||||
// purely lexically scoped (and can never be found by qualified
|
||||
// name lookup).
|
||||
if (S->getFnParent() != 0 || isa<TemplateTypeParmDecl>(D))
|
||||
IdResolver.RemoveDecl(D);
|
||||
if (!D->getDeclName()) continue;
|
||||
|
||||
// Chain this decl to the containing DeclContext.
|
||||
D->setNext(CurContext->getDeclChain());
|
||||
CurContext->setDeclChain(D);
|
||||
// Remove this name from our lexical scope.
|
||||
IdResolver.RemoveDecl(D);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,21 +220,76 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) {
|
|||
/// namespace.
|
||||
Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
|
||||
const DeclContext *LookupCtx,
|
||||
bool enableLazyBuiltinCreation) {
|
||||
bool enableLazyBuiltinCreation,
|
||||
bool LookInParent) {
|
||||
if (!Name) return 0;
|
||||
unsigned NS = NSI;
|
||||
if (getLangOptions().CPlusPlus && (NS & Decl::IDNS_Ordinary))
|
||||
NS |= Decl::IDNS_Tag;
|
||||
|
||||
IdentifierResolver::iterator
|
||||
I = LookupCtx ? IdResolver.begin(Name, LookupCtx, false/*LookInParentCtx*/)
|
||||
: IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/);
|
||||
// Scan up the scope chain looking for a decl that matches this identifier
|
||||
// that is in the appropriate namespace. This search should not take long, as
|
||||
// shadowing of names is uncommon, and deep shadowing is extremely uncommon.
|
||||
for (; I != IdResolver.end(); ++I)
|
||||
if ((*I)->getIdentifierNamespace() & NS)
|
||||
return *I;
|
||||
if (LookupCtx) {
|
||||
assert(getLangOptions().CPlusPlus && "No qualified name lookup in C");
|
||||
|
||||
// Perform qualified name lookup into the LookupCtx.
|
||||
// FIXME: Will need to look into base classes and such.
|
||||
for (DeclContext::lookup_const_result I = LookupCtx->lookup(Context, Name);
|
||||
I.first != I.second; ++I.first)
|
||||
if ((*I.first)->getIdentifierNamespace() & NS)
|
||||
return *I.first;
|
||||
} else if (getLangOptions().CPlusPlus &&
|
||||
(NS & (Decl::IDNS_Ordinary | Decl::IDNS_Tag))) {
|
||||
// Name lookup for ordinary names and tag names in C++ requires
|
||||
// looking into scopes that aren't strictly lexical, and
|
||||
// therefore we walk through the context as well as walking
|
||||
// through the scopes.
|
||||
IdentifierResolver::iterator
|
||||
I = IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/),
|
||||
IEnd = IdResolver.end();
|
||||
for (; S; S = S->getParent()) {
|
||||
// Check whether the IdResolver has anything in this scope.
|
||||
// FIXME: The isDeclScope check could be expensive. Can we do better?
|
||||
for (; I != IEnd && S->isDeclScope(*I); ++I)
|
||||
if ((*I)->getIdentifierNamespace() & NS)
|
||||
return *I;
|
||||
|
||||
// If there is an entity associated with this scope, it's a
|
||||
// DeclContext. We might need to perform qualified lookup into
|
||||
// it.
|
||||
DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
|
||||
while (Ctx && Ctx->isFunctionOrMethod())
|
||||
Ctx = Ctx->getParent();
|
||||
while (Ctx && (Ctx->isNamespace() || Ctx->isCXXRecord())) {
|
||||
// Look for declarations of this name in this scope.
|
||||
for (DeclContext::lookup_const_result I = Ctx->lookup(Context, Name);
|
||||
I.first != I.second; ++I.first) {
|
||||
// FIXME: Cache this result in the IdResolver
|
||||
if ((*I.first)->getIdentifierNamespace() & NS)
|
||||
return *I.first;
|
||||
}
|
||||
|
||||
Ctx = Ctx->getParent();
|
||||
}
|
||||
|
||||
if (!LookInParent)
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
// Unqualified name lookup for names in our lexical scope. This
|
||||
// name lookup suffices when all of the potential names are known
|
||||
// to have been pushed onto the IdResolver, as happens in C
|
||||
// (always) and in C++ for names in the "label" namespace.
|
||||
assert(!LookupCtx && "Can't perform qualified name lookup here");
|
||||
IdentifierResolver::iterator I
|
||||
= IdResolver.begin(Name, CurContext, LookInParent);
|
||||
|
||||
// Scan up the scope chain looking for a decl that matches this
|
||||
// identifier that is in the appropriate namespace. This search
|
||||
// should not take long, as shadowing of names is uncommon, and
|
||||
// deep shadowing is extremely uncommon.
|
||||
for (; I != IdResolver.end(); ++I)
|
||||
if ((*I)->getIdentifierNamespace() & NS)
|
||||
return *I;
|
||||
}
|
||||
|
||||
// If we didn't find a use of this identifier, and if the identifier
|
||||
// corresponds to a compiler builtin, create the decl object for the builtin
|
||||
|
@ -826,7 +908,8 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
|
|||
|
||||
// The scope passed in may not be a decl scope. Zip up the scope tree until
|
||||
// we find one that is.
|
||||
while ((S->getFlags() & Scope::DeclScope) == 0)
|
||||
while ((S->getFlags() & Scope::DeclScope) == 0 ||
|
||||
(S->getFlags() & Scope::TemplateParamScope) != 0)
|
||||
S = S->getParent();
|
||||
|
||||
DeclContext *DC;
|
||||
|
@ -854,6 +937,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
|
|||
// No previous declaration in the qualifying scope.
|
||||
Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)
|
||||
<< Name << D.getCXXScopeSpec().getRange();
|
||||
InvalidDecl = true;
|
||||
} else if (!CurContext->Encloses(DC)) {
|
||||
// The qualifying scope doesn't enclose the original declaration.
|
||||
// Emit diagnostic based on current scope.
|
||||
|
@ -865,6 +949,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
|
|||
Diag(L, diag::err_invalid_declarator_scope)
|
||||
<< Name << cast<NamedDecl>(DC)->getDeclName() << R;
|
||||
}
|
||||
InvalidDecl = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1127,23 +1212,42 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
|
|||
|
||||
if (OldDecl == PrevDecl) {
|
||||
// Remove the name binding for the previous
|
||||
// declaration. We'll add the binding back later, but then
|
||||
// it will refer to the new declaration (which will
|
||||
// contain more information).
|
||||
IdResolver.RemoveDecl(cast<NamedDecl>(PrevDecl));
|
||||
// declaration.
|
||||
if (S->isDeclScope(PrevDecl)) {
|
||||
IdResolver.RemoveDecl(cast<NamedDecl>(PrevDecl));
|
||||
S->RemoveDecl(PrevDecl);
|
||||
}
|
||||
|
||||
// Introduce the new binding for this declaration.
|
||||
IdResolver.AddDecl(NewFD);
|
||||
if (getLangOptions().CPlusPlus && NewFD->getParent())
|
||||
NewFD->getParent()->insert(Context, NewFD);
|
||||
|
||||
// Add the redeclaration to the current scope, since we'll
|
||||
// be skipping PushOnScopeChains.
|
||||
S->AddDecl(NewFD);
|
||||
} else {
|
||||
// We need to update the OverloadedFunctionDecl with the
|
||||
// latest declaration of this function, so that name
|
||||
// lookup will always refer to the latest declaration of
|
||||
// this function.
|
||||
*MatchedDecl = NewFD;
|
||||
}
|
||||
|
||||
// Add the redeclaration to the current scope, since we'll
|
||||
// be skipping PushOnScopeChains.
|
||||
S->AddDecl(NewFD);
|
||||
if (getLangOptions().CPlusPlus) {
|
||||
// Add this declaration to the current context.
|
||||
CurContext->addDecl(Context, NewFD, false);
|
||||
|
||||
return NewFD;
|
||||
// Check default arguments now that we have merged decls.
|
||||
CheckCXXDefaultArguments(NewFD);
|
||||
}
|
||||
|
||||
// Set the lexical context. If the declarator has a C++
|
||||
// scope specifier, the lexical context will be different
|
||||
// from the semantic context.
|
||||
NewFD->setLexicalDeclContext(CurContext);
|
||||
|
||||
return NewFD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2071,7 +2175,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
|
|||
parmDeclType = Context.getArrayDecayedType(parmDeclType);
|
||||
} else if (parmDeclType->isFunctionType())
|
||||
parmDeclType = Context.getPointerType(parmDeclType);
|
||||
|
||||
|
||||
ParmVarDecl *New = ParmVarDecl::Create(Context, CurContext,
|
||||
D.getIdentifierLoc(), II,
|
||||
parmDeclType, StorageClass,
|
||||
|
@ -2079,9 +2183,11 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
|
|||
|
||||
if (D.getInvalidType())
|
||||
New->setInvalidDecl();
|
||||
|
||||
|
||||
// Add the parameter declaration into this scope.
|
||||
S->AddDecl(New);
|
||||
if (II)
|
||||
PushOnScopeChains(New, S);
|
||||
IdResolver.AddDecl(New);
|
||||
|
||||
ProcessDeclAttributes(New, D);
|
||||
return New;
|
||||
|
@ -2133,7 +2239,7 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) {
|
|||
Diag(Definition->getLocation(), diag::note_previous_definition);
|
||||
}
|
||||
|
||||
PushDeclContext(FD);
|
||||
PushDeclContext(FnBodyScope, FD);
|
||||
|
||||
// Check the validity of our function parameters
|
||||
CheckParmsForFunctionDef(FD);
|
||||
|
@ -2573,17 +2679,19 @@ Sema::DeclTy *Sema::ActOnTagStruct(Scope *S, TagDecl::TagKind Kind, TagKind TK,
|
|||
|
||||
/// Collect the instance variables declared in an Objective-C object. Used in
|
||||
/// the creation of structures from objects using the @defs directive.
|
||||
static void CollectIvars(ObjCInterfaceDecl *Class, ASTContext& Ctx,
|
||||
static void CollectIvars(ObjCInterfaceDecl *Class, RecordDecl *Record,
|
||||
ASTContext& Ctx,
|
||||
llvm::SmallVectorImpl<Sema::DeclTy*> &ivars) {
|
||||
if (Class->getSuperClass())
|
||||
CollectIvars(Class->getSuperClass(), Ctx, ivars);
|
||||
CollectIvars(Class->getSuperClass(), Record, Ctx, ivars);
|
||||
|
||||
// For each ivar, create a fresh ObjCAtDefsFieldDecl.
|
||||
for (ObjCInterfaceDecl::ivar_iterator
|
||||
I=Class->ivar_begin(), E=Class->ivar_end(); I!=E; ++I) {
|
||||
|
||||
ObjCIvarDecl* ID = *I;
|
||||
ivars.push_back(ObjCAtDefsFieldDecl::Create(Ctx, ID->getLocation(),
|
||||
ivars.push_back(ObjCAtDefsFieldDecl::Create(Ctx, Record,
|
||||
ID->getLocation(),
|
||||
ID->getIdentifier(),
|
||||
ID->getType(),
|
||||
ID->getBitWidth()));
|
||||
|
@ -2592,7 +2700,7 @@ static void CollectIvars(ObjCInterfaceDecl *Class, ASTContext& Ctx,
|
|||
|
||||
/// Called whenever @defs(ClassName) is encountered in the source. Inserts the
|
||||
/// instance variables of ClassName into Decls.
|
||||
void Sema::ActOnDefs(Scope *S, SourceLocation DeclStart,
|
||||
void Sema::ActOnDefs(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
|
||||
IdentifierInfo *ClassName,
|
||||
llvm::SmallVectorImpl<DeclTy*> &Decls) {
|
||||
// Check that ClassName is a valid class
|
||||
|
@ -2602,7 +2710,17 @@ void Sema::ActOnDefs(Scope *S, SourceLocation DeclStart,
|
|||
return;
|
||||
}
|
||||
// Collect the instance variables
|
||||
CollectIvars(Class, Context, Decls);
|
||||
CollectIvars(Class, dyn_cast<RecordDecl>((Decl*)TagD), Context, Decls);
|
||||
|
||||
// Introduce all of these fields into the appropriate scope.
|
||||
for (llvm::SmallVectorImpl<DeclTy*>::iterator D = Decls.begin();
|
||||
D != Decls.end(); ++D) {
|
||||
FieldDecl *FD = cast<FieldDecl>((Decl*)*D);
|
||||
if (getLangOptions().CPlusPlus)
|
||||
PushOnScopeChains(cast<FieldDecl>(FD), S);
|
||||
else if (RecordDecl *Record = dyn_cast<RecordDecl>((Decl*)TagD))
|
||||
Record->addDecl(Context, FD);
|
||||
}
|
||||
}
|
||||
|
||||
/// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array
|
||||
|
@ -2657,12 +2775,13 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
|
|||
|
||||
/// ActOnField - Each field of a struct/union/class is passed into this in order
|
||||
/// to create a FieldDecl object for it.
|
||||
Sema::DeclTy *Sema::ActOnField(Scope *S,
|
||||
Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD,
|
||||
SourceLocation DeclStart,
|
||||
Declarator &D, ExprTy *BitfieldWidth) {
|
||||
IdentifierInfo *II = D.getIdentifier();
|
||||
Expr *BitWidth = (Expr*)BitfieldWidth;
|
||||
SourceLocation Loc = DeclStart;
|
||||
RecordDecl *Record = (RecordDecl *)TagD;
|
||||
if (II) Loc = D.getIdentifierLoc();
|
||||
|
||||
// FIXME: Unnamed fields can be handled in various different ways, for
|
||||
|
@ -2699,22 +2818,24 @@ Sema::DeclTy *Sema::ActOnField(Scope *S,
|
|||
// FIXME: Chain fielddecls together.
|
||||
FieldDecl *NewFD;
|
||||
|
||||
if (getLangOptions().CPlusPlus) {
|
||||
// FIXME: Replace CXXFieldDecls with FieldDecls for simple structs.
|
||||
NewFD = CXXFieldDecl::Create(Context, cast<CXXRecordDecl>(CurContext),
|
||||
Loc, II, T,
|
||||
D.getDeclSpec().getStorageClassSpec() ==
|
||||
DeclSpec::SCS_mutable, BitWidth);
|
||||
if (II)
|
||||
PushOnScopeChains(NewFD, S);
|
||||
}
|
||||
else
|
||||
NewFD = FieldDecl::Create(Context, Loc, II, T, BitWidth);
|
||||
|
||||
// FIXME: We don't want CurContext for C, do we? No, we'll need some
|
||||
// other way to determine the current RecordDecl.
|
||||
NewFD = FieldDecl::Create(Context, Record,
|
||||
Loc, II, T, BitWidth,
|
||||
D.getDeclSpec().getStorageClassSpec() ==
|
||||
DeclSpec::SCS_mutable,
|
||||
/*PrevDecl=*/0);
|
||||
|
||||
ProcessDeclAttributes(NewFD, D);
|
||||
|
||||
if (D.getInvalidType() || InvalidDecl)
|
||||
NewFD->setInvalidDecl();
|
||||
|
||||
if (II && getLangOptions().CPlusPlus)
|
||||
PushOnScopeChains(NewFD, S);
|
||||
else
|
||||
Record->addDecl(Context, NewFD);
|
||||
|
||||
return NewFD;
|
||||
}
|
||||
|
||||
|
@ -2921,7 +3042,7 @@ void Sema::ActOnFields(Scope* S,
|
|||
|
||||
// Okay, we successfully defined 'Record'.
|
||||
if (Record) {
|
||||
Record->defineBody(Context, &RecFields[0], RecFields.size());
|
||||
Record->completeDefinition(Context);
|
||||
// If this is a C++ record, HandleTagDeclDefinition will be invoked in
|
||||
// Sema::ActOnFinishCXXClassDef.
|
||||
if (!isa<CXXRecordDecl>(Record))
|
||||
|
@ -3189,7 +3310,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
|
|||
ECD->setType(NewTy);
|
||||
}
|
||||
|
||||
Enum->defineElements(EltList, BestType);
|
||||
Enum->completeDefinition(Context, BestType);
|
||||
Consumer.HandleTagDeclDefinition(Enum);
|
||||
}
|
||||
|
||||
|
|
|
@ -904,8 +904,10 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
|
|||
|
||||
// FIXME: This isn't supposed to be restricted to pointers, but otherwise
|
||||
// we might silently generate incorrect code; see following code
|
||||
for (int i = 0; i < RD->getNumMembers(); i++) {
|
||||
if (!RD->getMember(i)->getType()->isPointerType()) {
|
||||
for (RecordDecl::field_iterator Field = RD->field_begin(),
|
||||
FieldEnd = RD->field_end();
|
||||
Field != FieldEnd; ++Field) {
|
||||
if (!Field->getType()->isPointerType()) {
|
||||
S.Diag(Attr.getLoc(), diag::warn_transparent_union_nonpointer);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -382,7 +382,7 @@ void Sema::ActOnBaseSpecifiers(DeclTy *ClassDecl, BaseTy **Bases,
|
|||
/// definition, when on C++.
|
||||
void Sema::ActOnStartCXXClassDef(Scope *S, DeclTy *D, SourceLocation LBrace) {
|
||||
CXXRecordDecl *Dcl = cast<CXXRecordDecl>(static_cast<Decl *>(D));
|
||||
PushDeclContext(Dcl);
|
||||
PushDeclContext(S, Dcl);
|
||||
FieldCollector->StartClass();
|
||||
|
||||
if (Dcl->getIdentifier()) {
|
||||
|
@ -486,7 +486,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
|
|||
bool InvalidDecl = false;
|
||||
|
||||
if (isInstField)
|
||||
Member = static_cast<Decl*>(ActOnField(S, Loc, D, BitWidth));
|
||||
Member = static_cast<Decl*>(ActOnField(S, cast<CXXRecordDecl>(CurContext),
|
||||
Loc, D, BitWidth));
|
||||
else
|
||||
Member = static_cast<Decl*>(ActOnDeclarator(S, D, LastInGroup));
|
||||
|
||||
|
@ -593,7 +594,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
|
|||
Member->setInvalidDecl();
|
||||
|
||||
if (isInstField) {
|
||||
FieldCollector->Add(cast<CXXFieldDecl>(Member));
|
||||
FieldCollector->Add(cast<FieldDecl>(Member));
|
||||
return LastInGroup;
|
||||
}
|
||||
return Member;
|
||||
|
@ -632,7 +633,10 @@ Sema::ActOnMemInitializer(DeclTy *ConstructorD,
|
|||
// mem-initializer-id for the hidden base class may be specified
|
||||
// using a qualified name. ]
|
||||
// Look for a member, first.
|
||||
CXXFieldDecl *Member = ClassDecl->getMember(MemberOrBase);
|
||||
FieldDecl *Member = 0;
|
||||
DeclContext::lookup_result Result = ClassDecl->lookup(Context, MemberOrBase);
|
||||
if (Result.first != Result.second)
|
||||
Member = dyn_cast<FieldDecl>(*Result.first);
|
||||
|
||||
// FIXME: Handle members of an anonymous union.
|
||||
|
||||
|
@ -1251,43 +1255,42 @@ Sema::DeclTy *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
|
|||
// in that declarative region, it is treated as an original-namespace-name.
|
||||
|
||||
Decl *PrevDecl =
|
||||
LookupDecl(II, Decl::IDNS_Tag | Decl::IDNS_Ordinary, DeclRegionScope, 0,
|
||||
/*enableLazyBuiltinCreation=*/false);
|
||||
LookupDecl(II, Decl::IDNS_Tag | Decl::IDNS_Ordinary, DeclRegionScope, 0,
|
||||
/*enableLazyBuiltinCreation=*/false,
|
||||
/*LookupInParent=*/false);
|
||||
|
||||
if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) {
|
||||
// This is an extended namespace definition.
|
||||
// Attach this namespace decl to the chain of extended namespace
|
||||
// definitions.
|
||||
OrigNS->setNextNamespace(Namespc);
|
||||
Namespc->setOriginalNamespace(OrigNS->getOriginalNamespace());
|
||||
|
||||
if (PrevDecl && isDeclInScope(PrevDecl, CurContext, DeclRegionScope)) {
|
||||
if (NamespaceDecl *OrigNS = dyn_cast<NamespaceDecl>(PrevDecl)) {
|
||||
// This is an extended namespace definition.
|
||||
// Attach this namespace decl to the chain of extended namespace
|
||||
// definitions.
|
||||
NamespaceDecl *NextNS = OrigNS;
|
||||
while (NextNS->getNextNamespace())
|
||||
NextNS = NextNS->getNextNamespace();
|
||||
|
||||
NextNS->setNextNamespace(Namespc);
|
||||
Namespc->setOriginalNamespace(OrigNS);
|
||||
|
||||
// We won't add this decl to the current scope. We want the namespace
|
||||
// name to return the original namespace decl during a name lookup.
|
||||
} else {
|
||||
// This is an invalid name redefinition.
|
||||
Diag(Namespc->getLocation(), diag::err_redefinition_different_kind)
|
||||
<< Namespc->getDeclName();
|
||||
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
||||
Namespc->setInvalidDecl();
|
||||
// Continue on to push Namespc as current DeclContext and return it.
|
||||
// Remove the previous declaration from the scope.
|
||||
if (DeclRegionScope->isDeclScope(OrigNS)) {
|
||||
IdResolver.RemoveDecl(OrigNS);
|
||||
DeclRegionScope->RemoveDecl(OrigNS);
|
||||
}
|
||||
} else {
|
||||
// This namespace name is declared for the first time.
|
||||
PushOnScopeChains(Namespc, DeclRegionScope);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else if (PrevDecl) {
|
||||
// This is an invalid name redefinition.
|
||||
Diag(Namespc->getLocation(), diag::err_redefinition_different_kind)
|
||||
<< Namespc->getDeclName();
|
||||
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
||||
Namespc->setInvalidDecl();
|
||||
// Continue on to push Namespc as current DeclContext and return it.
|
||||
}
|
||||
|
||||
PushOnScopeChains(Namespc, DeclRegionScope);
|
||||
} else {
|
||||
// FIXME: Handle anonymous namespaces
|
||||
}
|
||||
|
||||
// Although we could have an invalid decl (i.e. the namespace name is a
|
||||
// redefinition), push it as current DeclContext and try to continue parsing.
|
||||
PushDeclContext(Namespc->getOriginalNamespace());
|
||||
// FIXME: We should be able to push Namespc here, so that the
|
||||
// each DeclContext for the namespace has the declarations
|
||||
// that showed up in that particular namespace definition.
|
||||
PushDeclContext(NamespcScope, Namespc);
|
||||
return Namespc;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ void Sema::ObjCActOnStartOfMethodDef(Scope *FnBodyScope, DeclTy *D) {
|
|||
AddFactoryMethodToGlobalPool(MDecl);
|
||||
|
||||
// Allow all of Sema to see that we are entering a method definition.
|
||||
PushDeclContext(MDecl);
|
||||
PushDeclContext(FnBodyScope, MDecl);
|
||||
|
||||
// Create Decl objects for each parameter, entrring them in the scope for
|
||||
// binding to their use.
|
||||
|
|
|
@ -453,13 +453,13 @@ Sema::ExprResult Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
|
|||
}
|
||||
}
|
||||
|
||||
if (CXXFieldDecl *FD = dyn_cast<CXXFieldDecl>(D)) {
|
||||
if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
|
||||
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
|
||||
if (MD->isStatic())
|
||||
// "invalid use of member 'x' in static member function"
|
||||
return Diag(Loc, diag::err_invalid_member_use_in_static_method)
|
||||
<< FD->getDeclName();
|
||||
if (cast<CXXRecordDecl>(MD->getParent()) != FD->getParent())
|
||||
if (MD->getParent() != FD->getDeclContext())
|
||||
// "invalid use of nonstatic data member 'x'"
|
||||
return Diag(Loc, diag::err_invalid_non_static_member_use)
|
||||
<< FD->getDeclName();
|
||||
|
@ -1231,20 +1231,28 @@ ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
|
|||
return Diag(OpLoc, diag::err_typecheck_incomplete_tag)
|
||||
<< RDecl->getDeclName() << BaseExpr->getSourceRange();
|
||||
// The record definition is complete, now make sure the member is valid.
|
||||
FieldDecl *MemberDecl = RDecl->getMember(&Member);
|
||||
if (!MemberDecl)
|
||||
// FIXME: Qualified name lookup for C++ is a bit more complicated
|
||||
// than this.
|
||||
DeclContext::lookup_result Lookup = RDecl->lookup(Context, &Member);
|
||||
if (Lookup.first == Lookup.second) {
|
||||
return Diag(MemberLoc, diag::err_typecheck_no_member)
|
||||
<< &Member << BaseExpr->getSourceRange();
|
||||
}
|
||||
|
||||
FieldDecl *MemberDecl = dyn_cast<FieldDecl>(*Lookup.first);
|
||||
if (!MemberDecl) {
|
||||
unsigned DiagID = PP.getDiagnostics().getCustomDiagID(Diagnostic::Error,
|
||||
"Clang only supports references to members");
|
||||
return Diag(MemberLoc, DiagID);
|
||||
}
|
||||
|
||||
// Figure out the type of the member; see C99 6.5.2.3p3
|
||||
// FIXME: Handle address space modifiers
|
||||
QualType MemberType = MemberDecl->getType();
|
||||
unsigned combinedQualifiers =
|
||||
MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers();
|
||||
if (CXXFieldDecl *CXXMember = dyn_cast<CXXFieldDecl>(MemberDecl)) {
|
||||
if (CXXMember->isMutable())
|
||||
combinedQualifiers &= ~QualType::Const;
|
||||
}
|
||||
if (MemberDecl->isMutable())
|
||||
combinedQualifiers &= ~QualType::Const;
|
||||
MemberType = MemberType.getQualifiedType(combinedQualifiers);
|
||||
|
||||
return new MemberExpr(BaseExpr, OpKind == tok::arrow, MemberDecl,
|
||||
|
@ -3484,7 +3492,11 @@ Sema::ExprResult Sema::ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
|
|||
|
||||
// Get the decl corresponding to this.
|
||||
RecordDecl *RD = RC->getDecl();
|
||||
FieldDecl *MemberDecl = RD->getMember(OC.U.IdentInfo);
|
||||
FieldDecl *MemberDecl = 0;
|
||||
DeclContext::lookup_result Lookup = RD->lookup(Context, OC.U.IdentInfo);
|
||||
if (Lookup.first != Lookup.second)
|
||||
MemberDecl = dyn_cast<FieldDecl>(*Lookup.first);
|
||||
|
||||
if (!MemberDecl)
|
||||
return Diag(BuiltinLoc, diag::err_typecheck_no_member)
|
||||
<< OC.U.IdentInfo << SourceRange(OC.LocStart, OC.LocEnd);
|
||||
|
@ -3552,7 +3564,7 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) {
|
|||
BSI->TheScope = BlockScope;
|
||||
|
||||
BSI->TheDecl = BlockDecl::Create(Context, CurContext, CaretLoc);
|
||||
PushDeclContext(BSI->TheDecl);
|
||||
PushDeclContext(BlockScope, BSI->TheDecl);
|
||||
}
|
||||
|
||||
void Sema::ActOnBlockArguments(Declarator &ParamInfo) {
|
||||
|
|
|
@ -412,9 +412,8 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, DeclarationName Name,
|
|||
DeclContext *Ctx, bool AllowMissing,
|
||||
FunctionDecl *&Operator)
|
||||
{
|
||||
IdentifierResolver::iterator I =
|
||||
IdResolver.begin(Name, Ctx, /*LookInParentCtx=*/false);
|
||||
if (I == IdResolver.end()) {
|
||||
DeclContext::lookup_result Lookup = Ctx->lookup(Context, Name);
|
||||
if (Lookup.first == Lookup.second) {
|
||||
if (AllowMissing)
|
||||
return false;
|
||||
// FIXME: Bad location information.
|
||||
|
@ -423,7 +422,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, DeclarationName Name,
|
|||
}
|
||||
|
||||
OverloadCandidateSet Candidates;
|
||||
NamedDecl *Decl = *I;
|
||||
NamedDecl *Decl = *Lookup.first;
|
||||
// Even member operator new/delete are implicitly treated as static, so don't
|
||||
// use AddMemberCandidate.
|
||||
if (FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(Decl))
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include <algorithm> // for std::count_if
|
||||
#include <functional> // for std::mem_fun
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
@ -39,10 +41,9 @@ int InitListChecker::numArrayElements(QualType DeclType) {
|
|||
|
||||
int InitListChecker::numStructUnionElements(QualType DeclType) {
|
||||
RecordDecl *structDecl = DeclType->getAsRecordType()->getDecl();
|
||||
int InitializableMembers = 0;
|
||||
for (int i = 0; i < structDecl->getNumMembers(); i++)
|
||||
if (structDecl->getMember(i)->getIdentifier())
|
||||
++InitializableMembers;
|
||||
int InitializableMembers
|
||||
= std::count_if(structDecl->field_begin(), structDecl->field_end(),
|
||||
std::mem_fun(&FieldDecl::getDeclName));
|
||||
if (structDecl->isUnion())
|
||||
return std::min(InitializableMembers, 1);
|
||||
return InitializableMembers - structDecl->hasFlexibleArrayMember();
|
||||
|
@ -286,21 +287,28 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
|
|||
// If structDecl is a forward declaration, this loop won't do anything;
|
||||
// That's okay, because an error should get printed out elsewhere. It
|
||||
// might be worthwhile to skip over the rest of the initializer, though.
|
||||
int numMembers = DeclType->getAsRecordType()->getDecl()->getNumMembers() -
|
||||
structDecl->hasFlexibleArrayMember();
|
||||
for (int i = 0; i < numMembers; i++) {
|
||||
RecordDecl *RD = DeclType->getAsRecordType()->getDecl();
|
||||
for (RecordDecl::field_iterator Field = RD->field_begin(),
|
||||
FieldEnd = RD->field_end();
|
||||
Field != FieldEnd; ++Field) {
|
||||
// If we've hit the flexible array member at the end, we're done.
|
||||
if (Field->getType()->isIncompleteArrayType())
|
||||
break;
|
||||
|
||||
// Don't attempt to go past the end of the init list
|
||||
if (Index >= IList->getNumInits())
|
||||
break;
|
||||
FieldDecl * curField = structDecl->getMember(i);
|
||||
if (!curField->getIdentifier()) {
|
||||
|
||||
if (!Field->getIdentifier()) {
|
||||
// Don't initialize unnamed fields, e.g. "int : 20;"
|
||||
continue;
|
||||
}
|
||||
CheckSubElementType(IList, curField->getType(), Index);
|
||||
|
||||
CheckSubElementType(IList, Field->getType(), Index);
|
||||
if (DeclType->isUnionType())
|
||||
break;
|
||||
}
|
||||
|
||||
// FIXME: Implement flexible array initialization GCC extension (it's a
|
||||
// really messy extension to implement, unfortunately...the necessary
|
||||
// information isn't actually even here!)
|
||||
|
|
|
@ -1955,10 +1955,9 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
|
|||
// (13.3.1.1.1); otherwise, the set of member candidates is
|
||||
// empty.
|
||||
if (const RecordType *T1Rec = T1->getAsRecordType()) {
|
||||
IdentifierResolver::iterator I
|
||||
= IdResolver.begin(OpName, cast<CXXRecordType>(T1Rec)->getDecl(),
|
||||
/*LookInParentCtx=*/false);
|
||||
NamedDecl *MemberOps = (I == IdResolver.end())? 0 : *I;
|
||||
DeclContext::lookup_const_result Lookup
|
||||
= cast<CXXRecordType>(T1Rec)->getDecl()->lookup(Context, OpName);
|
||||
NamedDecl *MemberOps = (Lookup.first == Lookup.second)? 0 : *Lookup.first;
|
||||
if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(MemberOps))
|
||||
AddMethodCandidate(Method, Args[0], Args+1, NumArgs - 1, CandidateSet,
|
||||
/*SuppressUserConversions=*/false);
|
||||
|
@ -3118,11 +3117,10 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
|
|||
// ordinary lookup of the name operator() in the context of
|
||||
// (E).operator().
|
||||
OverloadCandidateSet CandidateSet;
|
||||
IdentifierResolver::iterator I
|
||||
= IdResolver.begin(Context.DeclarationNames.getCXXOperatorName(OO_Call),
|
||||
cast<CXXRecordType>(Record)->getDecl(),
|
||||
/*LookInParentCtx=*/false);
|
||||
NamedDecl *MemberOps = (I == IdResolver.end())? 0 : *I;
|
||||
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
|
||||
DeclContext::lookup_const_result Lookup
|
||||
= cast<CXXRecordType>(Record)->getDecl()->lookup(Context, OpName);
|
||||
NamedDecl *MemberOps = (Lookup.first == Lookup.second)? 0 : *Lookup.first;
|
||||
if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(MemberOps))
|
||||
AddMethodCandidate(Method, Object, Args, NumArgs, CandidateSet,
|
||||
/*SuppressUserConversions=*/false);
|
||||
|
@ -3315,10 +3313,9 @@ Sema::BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
|
|||
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
|
||||
OverloadCandidateSet CandidateSet;
|
||||
const RecordType *BaseRecord = Base->getType()->getAsRecordType();
|
||||
IdentifierResolver::iterator I
|
||||
= IdResolver.begin(OpName, cast<CXXRecordType>(BaseRecord)->getDecl(),
|
||||
/*LookInParentCtx=*/false);
|
||||
NamedDecl *MemberOps = (I == IdResolver.end())? 0 : *I;
|
||||
DeclContext::lookup_const_result Lookup
|
||||
= cast<CXXRecordType>(BaseRecord)->getDecl()->lookup(Context, OpName);
|
||||
NamedDecl *MemberOps = (Lookup.first == Lookup.second)? 0 : *Lookup.first;
|
||||
if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(MemberOps))
|
||||
AddMethodCandidate(Method, Base, 0, 0, CandidateSet,
|
||||
/*SuppressUserConversions=*/false);
|
||||
|
|
|
@ -9,7 +9,6 @@ int A; // expected-error {{redefinition of 'A' as different kind of symbol}}
|
|||
class A; // expected-error {{redefinition of 'A' as different kind of symbol}}
|
||||
|
||||
class B {}; // expected-note {{previous definition is here}}
|
||||
namespace B {} // expected-error {{redefinition of 'B' as different kind of symbol}}
|
||||
|
||||
void C(); // expected-note {{previous definition is here}}
|
||||
namespace C {} // expected-error {{redefinition of 'C' as different kind of symbol}}
|
||||
|
@ -55,3 +54,5 @@ namespace S1 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace B {} // expected-error {{redefinition of 'B' as different kind of symbol}}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
|
||||
namespace Ns {
|
||||
int f(); // expected-note{{previous declaration is here}}
|
||||
}
|
||||
namespace Ns {
|
||||
double f(); // expected-error{{functions that differ only in their return type cannot be overloaded}}
|
||||
}
|
||||
|
||||
namespace Ns2 {
|
||||
float f();
|
||||
}
|
||||
|
||||
namespace Ns2 {
|
||||
float f(int); // expected-note{{previous declaration is here}}
|
||||
}
|
||||
|
||||
namespace Ns2 {
|
||||
double f(int); // expected-error{{functions that differ only in their return type cannot be overloaded}}
|
||||
}
|
||||
|
||||
namespace N {
|
||||
int& f1();
|
||||
}
|
||||
|
||||
namespace N {
|
||||
struct f1 {
|
||||
static int member;
|
||||
};
|
||||
|
||||
void test_f1() {
|
||||
int &i1 = f1();
|
||||
}
|
||||
}
|
||||
|
||||
namespace N {
|
||||
float& f1(int);
|
||||
|
||||
struct f2 {
|
||||
static int member;
|
||||
};
|
||||
void f2();
|
||||
}
|
||||
|
||||
int i1 = N::f1::member;
|
||||
typedef struct N::f1 type1;
|
||||
int i2 = N::f2::member;
|
||||
typedef struct N::f2 type2;
|
||||
|
||||
void test_f1(int i) {
|
||||
int &v1 = N::f1();
|
||||
float &v2 = N::f1(i);
|
||||
}
|
Loading…
Reference in New Issue