diff options
Diffstat (limited to 'include/clang/AST')
27 files changed, 1887 insertions, 425 deletions
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h index 9d4bff893f02f..5effa9057a4e1 100644 --- a/include/clang/AST/APValue.h +++ b/include/clang/AST/APValue.h @@ -122,13 +122,17 @@ public: return const_cast<APValue*>(this)->getFloat(); } - APValue &getVectorElt(unsigned i) const { + APValue &getVectorElt(unsigned i) { assert(isVector() && "Invalid accessor"); return ((Vec*)(char*)Data)->Elts[i]; } + const APValue &getVectorElt(unsigned i) const { + assert(isVector() && "Invalid accessor"); + return ((const Vec*)(const char*)Data)->Elts[i]; + } unsigned getVectorLength() const { assert(isVector() && "Invalid accessor"); - return ((Vec*)(void *)Data)->NumElts; + return ((const Vec*)(const void *)Data)->NumElts; } APSInt &getComplexIntReal() { diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index c41857ec02001..f8a8f179ae58a 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -25,6 +25,7 @@ #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/AST/CanonicalType.h" +#include "clang/AST/UsuallyTinyPtrVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/OwningPtr.h" @@ -34,6 +35,7 @@ namespace llvm { struct fltSemantics; + class raw_ostream; } namespace clang { @@ -70,28 +72,6 @@ namespace clang { namespace Builtin { class Context; } -/// \brief A vector of C++ member functions that is optimized for -/// storing a single method. -class CXXMethodVector { - /// \brief Storage for the vector. - /// - /// When the low bit is zero, this is a const CXXMethodDecl *. When the - /// low bit is one, this is a std::vector<const CXXMethodDecl *> *. - mutable uintptr_t Storage; - - typedef std::vector<const CXXMethodDecl *> vector_type; - -public: - CXXMethodVector() : Storage(0) { } - - typedef const CXXMethodDecl **iterator; - iterator begin() const; - iterator end() const; - - void push_back(const CXXMethodDecl *Method); - void Destroy(); -}; - /// ASTContext - This class holds long-lived AST nodes (such as types and /// decls) that can be referred to throughout the semantic analysis of a file. class ASTContext { @@ -164,6 +144,8 @@ class ASTContext { QualType ObjCConstantStringType; RecordDecl *CFConstantStringTypeDecl; + RecordDecl *NSConstantStringTypeDecl; + RecordDecl *ObjCFastEnumerationStateTypeDecl; /// \brief The type for the C FILE type. @@ -250,6 +232,7 @@ class ASTContext { /// Since most C++ member functions aren't virtual and therefore /// don't override anything, we store the overridden functions in /// this map on the side rather than within the CXXMethodDecl structure. + typedef UsuallyTinyPtrVector<const CXXMethodDecl> CXXMethodVector; llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods; TranslationUnitDecl *TUDecl; @@ -617,11 +600,13 @@ public: QualType getTemplateSpecializationType(TemplateName T, const TemplateArgument *Args, unsigned NumArgs, - QualType Canon = QualType()); + QualType Canon = QualType(), + bool IsCurrentInstantiation = false); QualType getTemplateSpecializationType(TemplateName T, const TemplateArgumentListInfo &Args, - QualType Canon = QualType()); + QualType Canon = QualType(), + bool IsCurrentInstantiation = false); TypeSourceInfo * getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc, @@ -688,6 +673,19 @@ public: // constant CFStrings. QualType getCFConstantStringType(); + // getNSConstantStringType - Return the C structure type used to represent + // constant NSStrings. + QualType getNSConstantStringType(); + /// Get the structure type used to representation NSStrings, or NULL + /// if it hasn't yet been built. + QualType getRawNSConstantStringType() { + if (NSConstantStringTypeDecl) + return getTagDeclType(NSConstantStringTypeDecl); + return QualType(); + } + void setNSConstantStringType(QualType T); + + /// Get the structure type used to representation CFStrings, or NULL /// if it hasn't yet been built. QualType getRawCFConstantStringType() { @@ -937,6 +935,8 @@ public: /// layout of the specified Objective-C interface. const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D); + void DumpRecordLayout(const RecordDecl *RD, llvm::raw_ostream &OS); + /// getASTObjCImplementationLayout - Get or compute information about /// the layout of the specified Objective-C implementation. This may /// differ from the interface if synthesized ivars are present. diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h new file mode 100644 index 0000000000000..217dfade525f9 --- /dev/null +++ b/include/clang/AST/ASTVector.h @@ -0,0 +1,397 @@ +//===- ASTVector.h - Vector that uses ASTContext for allocation --*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides ASTVector, a vector ADT whose contents are +// allocated using the allocator associated with an ASTContext.. +// +//===----------------------------------------------------------------------===// + +// FIXME: Most of this is copy-and-paste from BumpVector.h and SmallVector.h. +// We can refactor this core logic into something common. + +#ifndef LLVM_CLANG_AST_VECTOR +#define LLVM_CLANG_AST_VECTOR + +#include "llvm/Support/type_traits.h" +#include "llvm/Support/Allocator.h" +#include "llvm/ADT/PointerIntPair.h" +#include <algorithm> +#include <memory> +#include <cstring> + +#ifdef _MSC_VER +namespace std { +#if _MSC_VER <= 1310 + // Work around flawed VC++ implementation of std::uninitialized_copy. Define + // additional overloads so that elements with pointer types are recognized as + // scalars and not objects, causing bizarre type conversion errors. + template<class T1, class T2> + inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) { + _Scalar_ptr_iterator_tag _Cat; + return _Cat; + } + + template<class T1, class T2> + inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) { + _Scalar_ptr_iterator_tag _Cat; + return _Cat; + } +#else + // FIXME: It is not clear if the problem is fixed in VS 2005. What is clear + // is that the above hack won't work if it wasn't fixed. +#endif +} +#endif + +namespace clang { + +template<typename T> +class ASTVector { + T *Begin, *End, *Capacity; + + void setEnd(T *P) { this->End = P; } + +public: + // Default ctor - Initialize to empty. + explicit ASTVector(ASTContext &C, unsigned N = 0) + : Begin(NULL), End(NULL), Capacity(NULL) { + reserve(C, N); + } + + ~ASTVector() { + if (llvm::is_class<T>::value) { + // Destroy the constructed elements in the vector. + destroy_range(Begin, End); + } + } + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T* iterator; + typedef const T* const_iterator; + + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + + // forward iterator creation methods. + iterator begin() { return Begin; } + const_iterator begin() const { return Begin; } + iterator end() { return End; } + const_iterator end() const { return End; } + + // reverse iterator creation methods. + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin());} + + bool empty() const { return Begin == End; } + size_type size() const { return End-Begin; } + + reference operator[](unsigned idx) { + assert(Begin + idx < End); + return Begin[idx]; + } + const_reference operator[](unsigned idx) const { + assert(Begin + idx < End); + return Begin[idx]; + } + + reference front() { + return begin()[0]; + } + const_reference front() const { + return begin()[0]; + } + + reference back() { + return end()[-1]; + } + const_reference back() const { + return end()[-1]; + } + + void pop_back() { + --End; + End->~T(); + } + + T pop_back_val() { + T Result = back(); + pop_back(); + return Result; + } + + void clear() { + if (llvm::is_class<T>::value) { + destroy_range(Begin, End); + } + End = Begin; + } + + /// data - Return a pointer to the vector's buffer, even if empty(). + pointer data() { + return pointer(Begin); + } + + /// data - Return a pointer to the vector's buffer, even if empty(). + const_pointer data() const { + return const_pointer(Begin); + } + + void push_back(const_reference Elt, ASTContext &C) { + if (End < Capacity) { + Retry: + new (End) T(Elt); + ++End; + return; + } + grow(C); + goto Retry; + } + + void reserve(ASTContext &C, unsigned N) { + if (unsigned(Capacity-Begin) < N) + grow(C, N); + } + + /// capacity - Return the total number of elements in the currently allocated + /// buffer. + size_t capacity() const { return Capacity - Begin; } + + /// append - Add the specified range to the end of the SmallVector. + /// + template<typename in_iter> + void append(ASTContext &C, in_iter in_start, in_iter in_end) { + size_type NumInputs = std::distance(in_start, in_end); + + if (NumInputs == 0) + return; + + // Grow allocated space if needed. + if (NumInputs > size_type(this->capacity_ptr()-this->end())) + this->grow(C, this->size()+NumInputs); + + // Copy the new elements over. + // TODO: NEED To compile time dispatch on whether in_iter is a random access + // iterator to use the fast uninitialized_copy. + std::uninitialized_copy(in_start, in_end, this->end()); + this->setEnd(this->end() + NumInputs); + } + + /// append - Add the specified range to the end of the SmallVector. + /// + void append(ASTContext &C, size_type NumInputs, const T &Elt) { + // Grow allocated space if needed. + if (NumInputs > size_type(this->capacity_ptr()-this->end())) + this->grow(C, this->size()+NumInputs); + + // Copy the new elements over. + std::uninitialized_fill_n(this->end(), NumInputs, Elt); + this->setEnd(this->end() + NumInputs); + } + + /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template<typename It1, typename It2> + static void uninitialized_copy(It1 I, It1 E, It2 Dest) { + std::uninitialized_copy(I, E, Dest); + } + + iterator insert(ASTContext &C, iterator I, const T &Elt) { + if (I == this->end()) { // Important special case for empty vector. + push_back(Elt); + return this->end()-1; + } + + if (this->EndX < this->CapacityX) { + Retry: + new (this->end()) T(this->back()); + this->setEnd(this->end()+1); + // Push everything else over. + std::copy_backward(I, this->end()-1, this->end()); + *I = Elt; + return I; + } + size_t EltNo = I-this->begin(); + this->grow(C); + I = this->begin()+EltNo; + goto Retry; + } + + iterator insert(ASTContext &C, iterator I, size_type NumToInsert, + const T &Elt) { + if (I == this->end()) { // Important special case for empty vector. + append(C, NumToInsert, Elt); + return this->end()-1; + } + + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + + // Ensure there is enough space. + reserve(C, static_cast<unsigned>(this->size() + NumToInsert)); + + // Uninvalidate the iterator. + I = this->begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(this->end()-I) >= NumToInsert) { + T *OldEnd = this->end(); + append(C, this->end()-NumToInsert, this->end()); + + // Copy the existing elements that get replaced. + std::copy_backward(I, OldEnd-NumToInsert, OldEnd); + + std::fill_n(I, NumToInsert, Elt); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Copy over the elements that we're about to overwrite. + T *OldEnd = this->end(); + this->setEnd(this->end() + NumToInsert); + size_t NumOverwritten = OldEnd-I; + this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); + + // Replace the overwritten part. + std::fill_n(I, NumOverwritten, Elt); + + // Insert the non-overwritten middle part. + std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); + return I; + } + + template<typename ItTy> + iterator insert(ASTContext &C, iterator I, ItTy From, ItTy To) { + if (I == this->end()) { // Important special case for empty vector. + append(C, From, To); + return this->end()-1; + } + + size_t NumToInsert = std::distance(From, To); + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + + // Ensure there is enough space. + reserve(C, static_cast<unsigned>(this->size() + NumToInsert)); + + // Uninvalidate the iterator. + I = this->begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(this->end()-I) >= NumToInsert) { + T *OldEnd = this->end(); + append(C, this->end()-NumToInsert, this->end()); + + // Copy the existing elements that get replaced. + std::copy_backward(I, OldEnd-NumToInsert, OldEnd); + + std::copy(From, To, I); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Copy over the elements that we're about to overwrite. + T *OldEnd = this->end(); + this->setEnd(this->end() + NumToInsert); + size_t NumOverwritten = OldEnd-I; + this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); + + // Replace the overwritten part. + for (; NumOverwritten > 0; --NumOverwritten) { + *I = *From; + ++I; ++From; + } + + // Insert the non-overwritten middle part. + this->uninitialized_copy(From, To, OldEnd); + return I; + } + + void resize(ASTContext &C, unsigned N, const T &NV) { + if (N < this->size()) { + this->destroy_range(this->begin()+N, this->end()); + this->setEnd(this->begin()+N); + } else if (N > this->size()) { + if (this->capacity() < N) + this->grow(C, N); + construct_range(this->end(), this->begin()+N, NV); + this->setEnd(this->begin()+N); + } + } + +private: + /// grow - double the size of the allocated memory, guaranteeing space for at + /// least one more element or MinSize if specified. + void grow(ASTContext &C, size_type MinSize = 1); + + void construct_range(T *S, T *E, const T &Elt) { + for (; S != E; ++S) + new (S) T(Elt); + } + + void destroy_range(T *S, T *E) { + while (S != E) { + --E; + E->~T(); + } + } + +protected: + iterator capacity_ptr() { return (iterator)this->Capacity; } +}; + +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template <typename T> +void ASTVector<T>::grow(ASTContext &C, size_t MinSize) { + size_t CurCapacity = Capacity-Begin; + size_t CurSize = size(); + size_t NewCapacity = 2*CurCapacity; + if (NewCapacity < MinSize) + NewCapacity = MinSize; + + // Allocate the memory from the ASTContext. + T *NewElts = new (C) T[NewCapacity]; + + // Copy the elements over. + if (llvm::is_class<T>::value) { + std::uninitialized_copy(Begin, End, NewElts); + // Destroy the original elements. + destroy_range(Begin, End); + } + else { + // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove). + memcpy(NewElts, Begin, CurSize * sizeof(T)); + } + + C.Deallocate(Begin); + Begin = NewElts; + End = NewElts+CurSize; + Capacity = Begin+NewCapacity; +} + +} // end: clang namespace +#endif diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index b2a87f617063c..93dcad7512214 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -263,6 +263,7 @@ public: LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 2cdb98351394e..834c9a0c563fd 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -31,7 +31,9 @@ class StringLiteral; class TemplateArgumentList; class MemberSpecializationInfo; class FunctionTemplateSpecializationInfo; +class DependentFunctionTemplateSpecializationInfo; class TypeLoc; +class UnresolvedSetImpl; /// \brief A container of type source information. /// @@ -196,6 +198,10 @@ public: return DC->isRecord(); } + /// \brief Given that this declaration is a C++ class member, + /// determine whether it's an instance member of its class. + bool isCXXInstanceMember() const; + /// \brief Determine what kind of linkage this entity has. Linkage getLinkage() const; @@ -211,6 +217,12 @@ public: static bool classofKind(Kind K) { return K >= NamedFirst && K <= NamedLast; } }; +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const NamedDecl *ND) { + ND->getDeclName().printName(OS); + return OS; +} + /// NamespaceDecl - Represent a C++ namespace. class NamespaceDecl : public NamedDecl, public DeclContext { SourceLocation LBracLoc, RBracLoc; @@ -478,6 +490,7 @@ protected: private: // FIXME: This can be packed into the bitfields in Decl. unsigned SClass : 3; + unsigned SClassAsWritten : 3; bool ThreadSpecified : 1; bool HasCXXDirectInit : 1; @@ -485,14 +498,20 @@ private: /// condition, e.g., if (int x = foo()) { ... }. bool DeclaredInCondition : 1; + /// \brief Whether this variable is the exception variable in a C++ catch + /// or an Objective-C @catch statement. + bool ExceptionVar : 1; + friend class StmtIteratorBase; protected: VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, StorageClass SC) + QualType T, TypeSourceInfo *TInfo, StorageClass SC, + StorageClass SCAsWritten) : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(), ThreadSpecified(false), HasCXXDirectInit(false), - DeclaredInCondition(false) { + DeclaredInCondition(false), ExceptionVar(false) { SClass = SC; + SClassAsWritten = SCAsWritten; } typedef Redeclarable<VarDecl> redeclarable_base; @@ -509,7 +528,8 @@ public: static VarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, StorageClass S); + QualType T, TypeSourceInfo *TInfo, StorageClass S, + StorageClass SCAsWritten); virtual void Destroy(ASTContext& C); virtual ~VarDecl(); @@ -517,7 +537,11 @@ public: virtual SourceRange getSourceRange() const; StorageClass getStorageClass() const { return (StorageClass)SClass; } + StorageClass getStorageClassAsWritten() const { + return (StorageClass) SClassAsWritten; + } void setStorageClass(StorageClass SC) { SClass = SC; } + void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; } void setThreadSpecified(bool T) { ThreadSpecified = T; } bool isThreadSpecified() const { @@ -536,6 +560,12 @@ public: return getStorageClass() <= Register; } + /// isStaticLocal - Returns true if a variable with function scope is a + /// static local variable. + bool isStaticLocal() const { + return getStorageClass() == Static && !isFileVarDecl(); + } + /// hasExternStorage - Returns true if a variable has extern or /// __private_extern__ storage. bool hasExternalStorage() const { @@ -815,6 +845,13 @@ public: DeclaredInCondition = InCondition; } + /// \brief Determine whether this variable is the exception variable in a + /// C++ catch statememt or an Objective-C @catch statement. + bool isExceptionVariable() const { + return ExceptionVar; + } + void setExceptionVariable(bool EV) { ExceptionVar = EV; } + /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member /// from which it was instantiated. @@ -844,7 +881,7 @@ class ImplicitParamDecl : public VarDecl { protected: ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType Tw) - : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, VarDecl::None) {} + : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, VarDecl::None, VarDecl::None) {} public: static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, @@ -866,9 +903,9 @@ class ParmVarDecl : public VarDecl { protected: ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, Expr *DefArg) - : VarDecl(DK, DC, L, Id, T, TInfo, S), - objcDeclQualifier(OBJC_TQ_None), HasInheritedDefaultArg(false) { + StorageClass S, StorageClass SCAsWritten, Expr *DefArg) + : VarDecl(DK, DC, L, Id, T, TInfo, S, SCAsWritten), + objcDeclQualifier(OBJC_TQ_None), HasInheritedDefaultArg(false) { setDefaultArg(DefArg); } @@ -876,7 +913,8 @@ public: static ParmVarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, Expr *DefArg); + StorageClass S, StorageClass SCAsWritten, + Expr *DefArg); ObjCDeclQualifier getObjCDeclQualifier() const { return ObjCDeclQualifier(objcDeclQualifier); @@ -1002,6 +1040,7 @@ private: // FIXME: This can be packed into the bitfields in Decl. // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum unsigned SClass : 2; + unsigned SClassAsWritten : 2; bool IsInline : 1; bool IsVirtualAsWritten : 1; bool IsPure : 1; @@ -1033,19 +1072,20 @@ private: /// FunctionTemplateSpecializationInfo, which contains information about /// the template being specialized and the template arguments involved in /// that specialization. - llvm::PointerUnion3<FunctionTemplateDecl *, + llvm::PointerUnion4<FunctionTemplateDecl *, MemberSpecializationInfo *, - FunctionTemplateSpecializationInfo *> + FunctionTemplateSpecializationInfo *, + DependentFunctionTemplateSpecializationInfo *> TemplateOrSpecialization; protected: FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - StorageClass S, bool isInline) + StorageClass S, StorageClass SCAsWritten, bool isInline) : DeclaratorDecl(DK, DC, L, N, T, TInfo), DeclContext(DK), ParamInfo(0), Body(), - SClass(S), IsInline(isInline), + SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInline), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), IsCopyAssignment(false), @@ -1070,7 +1110,9 @@ public: static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - StorageClass S = None, bool isInline = false, + StorageClass S = None, + StorageClass SCAsWritten = None, + bool isInline = false, bool hasWrittenPrototype = true); virtual void getNameForDiagnostic(std::string &S, @@ -1107,6 +1149,9 @@ public: void setBody(Stmt *B); void setLazyBody(uint64_t Offset) { Body = Offset; } + /// Whether this function is variadic. + bool isVariadic() const; + /// Whether this function is marked as virtual explicitly. bool isVirtualAsWritten() const { return IsVirtualAsWritten; } void setVirtualAsWritten(bool V) { IsVirtualAsWritten = V; } @@ -1225,6 +1270,11 @@ public: StorageClass getStorageClass() const { return StorageClass(SClass); } void setStorageClass(StorageClass SC) { SClass = SC; } + StorageClass getStorageClassAsWritten() const { + return StorageClass(SClassAsWritten); + } + void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; } + /// \brief Determine whether the "inline" keyword was specified for this /// function. bool isInlineSpecified() const { return IsInline; } @@ -1361,6 +1411,18 @@ public: void *InsertPos, TemplateSpecializationKind TSK = TSK_ImplicitInstantiation); + /// \brief Specifies that this function declaration is actually a + /// dependent function template specialization. + void setDependentTemplateSpecialization(ASTContext &Context, + const UnresolvedSetImpl &Templates, + const TemplateArgumentListInfo &TemplateArgs); + + DependentFunctionTemplateSpecializationInfo * + getDependentSpecializationInfo() const { + return TemplateOrSpecialization. + dyn_cast<DependentFunctionTemplateSpecializationInfo*>(); + } + /// \brief Determine what kind of template instantiation this function /// represents. TemplateSpecializationKind getTemplateSpecializationKind() const; @@ -1961,7 +2023,7 @@ public: /// class BlockDecl : public Decl, public DeclContext { // FIXME: This can be packed into the bitfields in Decl. - bool isVariadic : 1; + bool IsVariadic : 1; /// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal /// parameters of this function. This is null if a prototype or if there are /// no formals. @@ -1973,7 +2035,7 @@ class BlockDecl : public Decl, public DeclContext { protected: BlockDecl(DeclContext *DC, SourceLocation CaretLoc) : Decl(Block, DC, CaretLoc), DeclContext(Block), - isVariadic(false), ParamInfo(0), NumParams(0), Body(0) {} + IsVariadic(false), ParamInfo(0), NumParams(0), Body(0) {} virtual ~BlockDecl(); virtual void Destroy(ASTContext& C); @@ -1983,8 +2045,8 @@ public: SourceLocation getCaretLocation() const { return getLocation(); } - bool IsVariadic() const { return isVariadic; } - void setIsVariadic(bool value) { isVariadic = value; } + bool isVariadic() const { return IsVariadic; } + void setIsVariadic(bool value) { IsVariadic = value; } CompoundStmt *getCompoundBody() const { return (CompoundStmt*) Body; } Stmt *getBody() const { return (Stmt*) Body; } diff --git a/include/clang/AST/DeclAccessPair.h b/include/clang/AST/DeclAccessPair.h new file mode 100644 index 0000000000000..7ecd8f8bcd783 --- /dev/null +++ b/include/clang/AST/DeclAccessPair.h @@ -0,0 +1,72 @@ +//===--- DeclAccessPair.h - A decl bundled with its path access -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DeclAccessPair class, which provides an +// efficient representation of a pair of a NamedDecl* and an +// AccessSpecifier. Generally the access specifier gives the +// natural access of a declaration when named in a class, as +// defined in C++ [class.access.base]p1. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLACCESSPAIR_H +#define LLVM_CLANG_AST_DECLACCESSPAIR_H + +#include "clang/Basic/Specifiers.h" + +namespace clang { + +class NamedDecl; + +/// A POD class for pairing a NamedDecl* with an access specifier. +/// Can be put into unions. +class DeclAccessPair { + NamedDecl *Ptr; // we'd use llvm::PointerUnion, but it isn't trivial + + enum { Mask = 0x3 }; + +public: + static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS) { + DeclAccessPair p; + p.set(D, AS); + return p; + } + + NamedDecl *getDecl() const { + return (NamedDecl*) (~Mask & (uintptr_t) Ptr); + } + AccessSpecifier getAccess() const { + return AccessSpecifier(Mask & (uintptr_t) Ptr); + } + + void setDecl(NamedDecl *D) { + set(D, getAccess()); + } + void setAccess(AccessSpecifier AS) { + set(getDecl(), AS); + } + void set(NamedDecl *D, AccessSpecifier AS) { + Ptr = reinterpret_cast<NamedDecl*>(uintptr_t(AS) | + reinterpret_cast<uintptr_t>(D)); + } + + operator NamedDecl*() const { return getDecl(); } + NamedDecl *operator->() const { return getDecl(); } +}; +} + +// Take a moment to tell SmallVector that DeclAccessPair is POD. +namespace llvm { +template<typename> struct isPodLike; +template<> struct isPodLike<clang::DeclAccessPair> { + static const bool value = true; +}; +} + +#endif diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index d5913e236c2c4..a9b948eee546f 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -76,26 +76,68 @@ public: #include "clang/AST/DeclNodes.def" }; - /// IdentifierNamespace - According to C99 6.2.3, there are four - /// namespaces, labels, tags, members and ordinary - /// identifiers. These are meant as bitmasks, so that searches in - /// C++ can look into the "tag" namespace during ordinary lookup. We - /// use additional namespaces for Objective-C entities. We also put - /// C++ friend declarations (of previously-undeclared entities) in - /// shadow namespaces, and 'using' declarations (as opposed to their - /// implicit shadow declarations) can be found in their own - /// namespace. + /// IdentifierNamespace - The different namespaces in which + /// declarations may appear. According to C99 6.2.3, there are + /// four namespaces, labels, tags, members and ordinary + /// identifiers. C++ describes lookup completely differently: + /// certain lookups merely "ignore" certain kinds of declarations, + /// usually based on whether the declaration is of a type, etc. + /// + /// These are meant as bitmasks, so that searches in + /// C++ can look into the "tag" namespace during ordinary lookup. + /// + /// Decl currently provides 16 bits of IDNS bits. enum IdentifierNamespace { - IDNS_Label = 0x1, - IDNS_Tag = 0x2, - IDNS_Member = 0x4, - IDNS_Ordinary = 0x8, - IDNS_ObjCProtocol = 0x10, - IDNS_ObjCImplementation = 0x20, - IDNS_ObjCCategoryName = 0x40, - IDNS_OrdinaryFriend = 0x80, - IDNS_TagFriend = 0x100, - IDNS_Using = 0x200 + /// Labels, declared with 'x:' and referenced with 'goto x'. + IDNS_Label = 0x0001, + + /// Tags, declared with 'struct foo;' and referenced with + /// 'struct foo'. All tags are also types. This is what + /// elaborated-type-specifiers look for in C. + IDNS_Tag = 0x0002, + + /// Types, declared with 'struct foo', typedefs, etc. + /// This is what elaborated-type-specifiers look for in C++, + /// but note that it's ill-formed to find a non-tag. + IDNS_Type = 0x0004, + + /// Members, declared with object declarations within tag + /// definitions. In C, these can only be found by "qualified" + /// lookup in member expressions. In C++, they're found by + /// normal lookup. + IDNS_Member = 0x0008, + + /// Namespaces, declared with 'namespace foo {}'. + /// Lookup for nested-name-specifiers find these. + IDNS_Namespace = 0x0010, + + /// Ordinary names. In C, everything that's not a label, tag, + /// or member ends up here. + IDNS_Ordinary = 0x0020, + + /// Objective C @protocol. + IDNS_ObjCProtocol = 0x0040, + + /// This declaration is a friend function. A friend function + /// declaration is always in this namespace but may also be in + /// IDNS_Ordinary if it was previously declared. + IDNS_OrdinaryFriend = 0x0080, + + /// This declaration is a friend class. A friend class + /// declaration is always in this namespace but may also be in + /// IDNS_Tag|IDNS_Type if it was previously declared. + IDNS_TagFriend = 0x0100, + + /// This declaration is a using declaration. A using declaration + /// *introduces* a number of other declarations into the current + /// scope, and those declarations use the IDNS of their targets, + /// but the actual using declarations go in this namespace. + IDNS_Using = 0x0200, + + /// This declaration is a C++ operator declared in a non-class + /// context. All such operators are also in IDNS_Ordinary. + /// C++ lexical operator lookup looks for these. + IDNS_NonMemberOperator = 0x0400 }; /// ObjCDeclQualifier - Qualifier used on types in method declarations @@ -313,6 +355,13 @@ public: } static unsigned getIdentifierNamespaceForKind(Kind DK); + bool hasTagIdentifierNamespace() const { + return isTagIdentifierNamespace(getIdentifierNamespace()); + } + static bool isTagIdentifierNamespace(unsigned NS) { + // TagDecls have Tag and Type set and may also have TagFriend. + return (NS & ~IDNS_TagFriend) == (IDNS_Tag | IDNS_Type); + } /// getLexicalDeclContext - The declaration context where this Decl was /// lexically declared (LexicalDC). May be different from @@ -455,14 +504,14 @@ public: assert((OldNS & (IDNS_Tag | IDNS_Ordinary | IDNS_TagFriend | IDNS_OrdinaryFriend)) && "namespace includes neither ordinary nor tag"); - assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | + assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | IDNS_Type | IDNS_TagFriend | IDNS_OrdinaryFriend)) && "namespace includes other than ordinary or tag"); IdentifierNamespace = 0; if (OldNS & (IDNS_Tag | IDNS_TagFriend)) { IdentifierNamespace |= IDNS_TagFriend; - if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag; + if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag | IDNS_Type; } if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) { @@ -489,6 +538,14 @@ public: FOK_Declared : FOK_Undeclared); } + /// Specifies that this declaration is a C++ overloaded non-member. + void setNonMemberOperator() { + assert(getKind() == Function || getKind() == FunctionTemplate); + assert((IdentifierNamespace & IDNS_Ordinary) && + "visible non-member operators should be in ordinary namespace"); + IdentifierNamespace |= IDNS_NonMemberOperator; + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *) { return true; } static bool classofKind(Kind K) { return true; } diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 23769af46b367..aa649c811115a 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -471,6 +471,11 @@ public: friend_iterator friend_end() const; void pushFriendDecl(FriendDecl *FD); + /// Determines whether this record has any friends. + bool hasFriends() const { + return data().FirstFriend != 0; + } + /// hasConstCopyConstructor - Determines whether this class has a /// copy constructor that accepts a const-qualified argument. bool hasConstCopyConstructor(ASTContext &Context) const; @@ -931,15 +936,16 @@ class CXXMethodDecl : public FunctionDecl { protected: CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - bool isStatic, bool isInline) + bool isStatic, StorageClass SCAsWritten, bool isInline) : FunctionDecl(DK, RD, L, N, T, TInfo, (isStatic ? Static : None), - isInline) {} + SCAsWritten, isInline) {} public: static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, bool isStatic = false, + StorageClass SCAsWritten = FunctionDecl::None, bool isInline = false); bool isStatic() const { return getStorageClass() == Static; } @@ -960,6 +966,10 @@ public: /// delete or delete[] operator with a particular signature. bool isUsualDeallocationFunction() const; + /// \brief Determine whether this is a copy-assignment operator, regardless + /// of whether it was declared implicitly or explicitly. + bool isCopyAssignmentOperator() const; + const CXXMethodDecl *getCanonicalDecl() const { return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl()); } @@ -1052,6 +1062,10 @@ class CXXBaseOrMemberInitializer { /// and AnonUnionMember holds field decl for au_i1. FieldDecl *AnonUnionMember; + /// IsVirtual - If the initializer is a base initializer, this keeps track + /// of whether the base is virtual or not. + bool IsVirtual; + /// LParenLoc - Location of the left paren of the ctor-initializer. SourceLocation LParenLoc; @@ -1062,7 +1076,7 @@ public: /// CXXBaseOrMemberInitializer - Creates a new base-class initializer. explicit CXXBaseOrMemberInitializer(ASTContext &Context, - TypeSourceInfo *TInfo, + TypeSourceInfo *TInfo, bool IsVirtual, SourceLocation L, Expr *Init, SourceLocation R); @@ -1095,7 +1109,14 @@ public: /// Otherwise, returns NULL. const Type *getBaseClass() const; Type *getBaseClass(); - + + /// Returns whether the base is virtual or not. + bool isBaseVirtual() const { + assert(isBaseInitializer() && "Must call this on base initializer!"); + + return IsVirtual; + } + /// \brief Returns the declarator information for a base class initializer. TypeSourceInfo *getBaseClassInfo() const { return BaseOrMember.dyn_cast<TypeSourceInfo *>(); @@ -1171,7 +1192,8 @@ class CXXConstructorDecl : public CXXMethodDecl { DeclarationName N, QualType T, TypeSourceInfo *TInfo, bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false, isInline), + : CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false, + FunctionDecl::None, isInline), IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false), BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) { setImplicit(isImplicitlyDeclared); @@ -1199,7 +1221,7 @@ public: /// defined. If false, then this constructor was defined by the /// user. This operation can only be invoked if the constructor has /// already been defined. - bool isImplicitlyDefined(ASTContext &C) const { + bool isImplicitlyDefined() const { assert(isThisDeclarationADefinition() && "Can only get the implicit-definition flag once the " "constructor has been defined"); @@ -1314,7 +1336,8 @@ class CXXDestructorDecl : public CXXMethodDecl { CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*TInfo=*/0, false, isInline), + : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*TInfo=*/0, false, + FunctionDecl::None, isInline), ImplicitlyDefined(false), OperatorDelete(0) { setImplicit(isImplicitlyDeclared); } @@ -1370,7 +1393,8 @@ class CXXConversionDecl : public CXXMethodDecl { CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicitSpecified) - : CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false, isInline), + : CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false, + FunctionDecl::None, isInline), IsExplicitSpecified(isExplicitSpecified) { } public: diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index 16cb491344bc8..2a4b12ac2eafe 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -230,7 +230,7 @@ public: // Tag declarations always go at the end of the list so that an // iterator which points at the first tag will start a span of // decls that only contains tags. - if (D->getIdentifierNamespace() == Decl::IDNS_Tag) + if (D->hasTagIdentifierNamespace()) Vec.push_back(reinterpret_cast<uintptr_t>(D)); // Resolved using declarations go at the front of the list so that @@ -251,7 +251,7 @@ public: // tag declarations. But we can be clever about tag declarations // because there can only ever be one in a scope. } else if (reinterpret_cast<NamedDecl *>(Vec.back()) - ->getIdentifierNamespace() == Decl::IDNS_Tag) { + ->hasTagIdentifierNamespace()) { uintptr_t TagD = Vec.back(); Vec.back() = reinterpret_cast<uintptr_t>(D); Vec.push_back(TagD); diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 99ef738980cc8..a20625da56b7d 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -48,10 +48,6 @@ private: // Location of the 'friend' specifier. SourceLocation FriendLoc; - // FIXME: Hack to keep track of whether this was a friend function - // template specialization. - bool WasSpecialization; - friend class CXXRecordDecl::friend_iterator; friend class CXXRecordDecl; @@ -60,8 +56,7 @@ private: : Decl(Decl::Friend, DC, L), Friend(Friend), NextFriend(0), - FriendLoc(FriendL), - WasSpecialization(false) { + FriendLoc(FriendL) { } public: @@ -88,9 +83,6 @@ public: return FriendLoc; } - bool wasSpecialization() const { return WasSpecialization; } - void setSpecialization(bool WS) { WasSpecialization = WS; } - // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FriendDecl *D) { return true; } diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def index 082299c41f503..5b03ff8d91193 100644 --- a/include/clang/AST/DeclNodes.def +++ b/include/clang/AST/DeclNodes.def @@ -105,14 +105,14 @@ ABSTRACT_DECL(Named, Decl) DECL(ImplicitParam, VarDecl) DECL(ParmVar, VarDecl) DECL(NonTypeTemplateParm, VarDecl) - DECL(Template, NamedDecl) + ABSTRACT_DECL(Template, NamedDecl) DECL(FunctionTemplate, TemplateDecl) DECL(ClassTemplate, TemplateDecl) DECL(TemplateTemplateParm, TemplateDecl) DECL(Using, NamedDecl) DECL(UsingShadow, NamedDecl) DECL(ObjCMethod, NamedDecl) - DECL(ObjCContainer, NamedDecl) + ABSTRACT_DECL(ObjCContainer, NamedDecl) DECL(ObjCCategory, ObjCContainerDecl) DECL(ObjCProtocol, ObjCContainerDecl) DECL(ObjCInterface, ObjCContainerDecl) @@ -143,7 +143,7 @@ LAST_DECL_CONTEXT(Block) // Declaration ranges DECL_RANGE(Named, Namespace, ObjCCompatibleAlias) -DECL_RANGE(ObjCContainer, ObjCContainer, ObjCImplementation) +DECL_RANGE(ObjCContainer, ObjCCategory, ObjCImplementation) DECL_RANGE(Field, Field, ObjCAtDefsField) DECL_RANGE(Type, Typedef, TemplateTypeParm) DECL_RANGE(Tag, Enum, ClassTemplatePartialSpecialization) @@ -151,7 +151,7 @@ DECL_RANGE(Record, Record, ClassTemplatePartialSpecialization) DECL_RANGE(Value, EnumConstant, NonTypeTemplateParm) DECL_RANGE(Declarator, Function, NonTypeTemplateParm) DECL_RANGE(Function, Function, CXXConversion) -DECL_RANGE(Template, Template, TemplateTemplateParm) +DECL_RANGE(Template, FunctionTemplate, TemplateTemplateParm) DECL_RANGE(ObjCImpl, ObjCCategoryImpl, ObjCImplementation) LAST_DECL_RANGE(Var, Var, NonTypeTemplateParm) diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 9b2b6096e81d9..e34ec9ffcdf01 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -29,6 +29,7 @@ class ObjCProtocolDecl; class ObjCCategoryDecl; class ObjCPropertyDecl; class ObjCPropertyImplDecl; +class CXXBaseOrMemberInitializer; class ObjCListBase { void operator=(const ObjCListBase &); // DO NOT IMPLEMENT @@ -136,6 +137,9 @@ private: /// in, inout, etc. unsigned objcDeclQualifier : 6; + // Number of args separated by ':' in a method declaration. + unsigned NumSelectorArgs; + // Result type of this method. QualType MethodDeclType; @@ -167,13 +171,15 @@ private: bool isInstance = true, bool isVariadic = false, bool isSynthesized = false, - ImplementationControl impControl = None) + ImplementationControl impControl = None, + unsigned numSelectorArgs = 0) : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), DeclContext(ObjCMethod), IsInstance(isInstance), IsVariadic(isVariadic), IsSynthesized(isSynthesized), DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), - MethodDeclType(T), ResultTInfo(ResultTInfo), + NumSelectorArgs(numSelectorArgs), MethodDeclType(T), + ResultTInfo(ResultTInfo), EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {} virtual ~ObjCMethodDecl() {} @@ -197,7 +203,8 @@ public: bool isInstance = true, bool isVariadic = false, bool isSynthesized = false, - ImplementationControl impControl = None); + ImplementationControl impControl = None, + unsigned numSelectorArgs = 0); virtual ObjCMethodDecl *getCanonicalDecl(); const ObjCMethodDecl *getCanonicalDecl() const { @@ -209,6 +216,11 @@ public: } void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; } + unsigned getNumSelectorArgs() const { return NumSelectorArgs; } + void setNumSelectorArgs(unsigned numSelectorArgs) { + NumSelectorArgs = numSelectorArgs; + } + // Location information, modeled after the Stmt API. SourceLocation getLocStart() const { return getLocation(); } SourceLocation getLocEnd() const { return EndLoc; } @@ -235,9 +247,16 @@ public: typedef ObjCList<ParmVarDecl>::iterator param_iterator; param_iterator param_begin() const { return ParamInfo.begin(); } param_iterator param_end() const { return ParamInfo.end(); } + // This method returns and of the parameters which are part of the selector + // name mangling requirements. + param_iterator sel_param_end() const { + return ParamInfo.begin() + NumSelectorArgs; + } - void setMethodParams(ASTContext &C, ParmVarDecl *const *List, unsigned Num) { + void setMethodParams(ASTContext &C, ParmVarDecl *const *List, unsigned Num, + unsigned numSelectorArgs) { ParamInfo.set(List, Num, C); + NumSelectorArgs = numSelectorArgs; } // Iterator access to parameter types. @@ -1114,6 +1133,9 @@ public: static bool classofKind(Kind K) { return K == ObjCCategoryImpl;} }; +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const ObjCCategoryImplDecl *CID); + /// ObjCImplementationDecl - Represents a class definition - this is where /// method definitions are specified. For example: /// @@ -1131,18 +1153,54 @@ public: class ObjCImplementationDecl : public ObjCImplDecl { /// Implementation Class's super class. ObjCInterfaceDecl *SuperClass; - + /// Support for ivar initialization. + /// IvarInitializers - The arguments used to initialize the ivars + CXXBaseOrMemberInitializer **IvarInitializers; + unsigned NumIvarInitializers; + ObjCImplementationDecl(DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl) : ObjCImplDecl(ObjCImplementation, DC, L, classInterface), - SuperClass(superDecl){} + SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0) {} public: static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl); - + + /// init_iterator - Iterates through the ivar initializer list. + typedef CXXBaseOrMemberInitializer **init_iterator; + + /// init_const_iterator - Iterates through the ivar initializer list. + typedef CXXBaseOrMemberInitializer * const * init_const_iterator; + + /// init_begin() - Retrieve an iterator to the first initializer. + init_iterator init_begin() { return IvarInitializers; } + /// begin() - Retrieve an iterator to the first initializer. + init_const_iterator init_begin() const { return IvarInitializers; } + + /// init_end() - Retrieve an iterator past the last initializer. + init_iterator init_end() { + return IvarInitializers + NumIvarInitializers; + } + /// end() - Retrieve an iterator past the last initializer. + init_const_iterator init_end() const { + return IvarInitializers + NumIvarInitializers; + } + /// getNumArgs - Number of ivars which must be initialized. + unsigned getNumIvarInitializers() const { + return NumIvarInitializers; + } + + void setNumIvarInitializers(unsigned numNumIvarInitializers) { + NumIvarInitializers = numNumIvarInitializers; + } + + void setIvarInitializers(ASTContext &C, + CXXBaseOrMemberInitializer ** initializers, + unsigned numInitializers); + /// getIdentifier - Get the identifier that names the class /// interface associated with this implementation. IdentifierInfo *getIdentifier() const { @@ -1199,6 +1257,9 @@ public: static bool classofKind(Kind K) { return K == ObjCImplementation; } }; +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const ObjCImplementationDecl *ID); + /// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is /// declared as @compatibility_alias alias class. class ObjCCompatibleAliasDecl : public NamedDecl { diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 8d1a4caccb232..1ec38bacb51f2 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -376,6 +376,81 @@ public: PointOfInstantiation = POI; } }; + +/// \brief Provides information about a dependent function-template +/// specialization declaration. Since explicit function template +/// specialization and instantiation declarations can only appear in +/// namespace scope, and you can only specialize a member of a +/// fully-specialized class, the only way to get one of these is in +/// a friend declaration like the following: +/// +/// template <class T> void foo(T); +/// template <class T> class A { +/// friend void foo<>(T); +/// }; +class DependentFunctionTemplateSpecializationInfo { + union { + // Force sizeof to be a multiple of sizeof(void*) so that the + // trailing data is aligned. + void *Aligner; + + struct { + /// The number of potential template candidates. + unsigned NumTemplates; + + /// The number of template arguments. + unsigned NumArgs; + } d; + }; + + /// The locations of the left and right angle brackets. + SourceRange AngleLocs; + + FunctionTemplateDecl * const *getTemplates() const { + return reinterpret_cast<FunctionTemplateDecl*const*>(this+1); + } + + const TemplateArgumentLoc *getTemplateArgs() const { + return reinterpret_cast<const TemplateArgumentLoc*>( + &getTemplates()[getNumTemplates()]); + } + +public: + DependentFunctionTemplateSpecializationInfo( + const UnresolvedSetImpl &Templates, + const TemplateArgumentListInfo &TemplateArgs); + + /// \brief Returns the number of function templates that this might + /// be a specialization of. + unsigned getNumTemplates() const { + return d.NumTemplates; + } + + /// \brief Returns the i'th template candidate. + FunctionTemplateDecl *getTemplate(unsigned I) const { + assert(I < getNumTemplates() && "template index out of range"); + return getTemplates()[I]; + } + + /// \brief Returns the number of explicit template arguments that were given. + unsigned getNumTemplateArgs() const { + return d.NumArgs; + } + + /// \brief Returns the nth template argument. + const TemplateArgumentLoc &getTemplateArg(unsigned I) const { + assert(I < getNumTemplateArgs() && "template arg index out of range"); + return getTemplateArgs()[I]; + } + + SourceLocation getLAngleLoc() const { + return AngleLocs.getBegin(); + } + + SourceLocation getRAngleLoc() const { + return AngleLocs.getEnd(); + } +}; /// Declaration of a template function. class FunctionTemplateDecl : public TemplateDecl { @@ -652,7 +727,8 @@ class NonTypeTemplateParmDecl NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo) - : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, VarDecl::None), + : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, VarDecl::None, + VarDecl::None), TemplateParmPosition(D, P), DefaultArgument(0) { } @@ -935,6 +1011,11 @@ class ClassTemplatePartialSpecializationDecl TemplateArgumentLoc *ArgsAsWritten; unsigned NumArgsAsWritten; + /// \brief Sequence number indicating when this class template partial + /// specialization was added to the set of partial specializations for + /// its owning class template. + unsigned SequenceNumber; + /// \brief The class template partial specialization from which this /// class template partial specialization was instantiated. /// @@ -950,13 +1031,15 @@ class ClassTemplatePartialSpecializationDecl TemplateArgumentListBuilder &Builder, TemplateArgumentLoc *ArgInfos, unsigned NumArgInfos, - ClassTemplatePartialSpecializationDecl *PrevDecl) + ClassTemplatePartialSpecializationDecl *PrevDecl, + unsigned SequenceNumber) : ClassTemplateSpecializationDecl(Context, ClassTemplatePartialSpecialization, DC, L, SpecializedTemplate, Builder, PrevDecl), TemplateParams(Params), ArgsAsWritten(ArgInfos), - NumArgsAsWritten(NumArgInfos), InstantiatedFromMember(0, false) { } + NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber), + InstantiatedFromMember(0, false) { } public: static ClassTemplatePartialSpecializationDecl * @@ -966,7 +1049,8 @@ public: TemplateArgumentListBuilder &Builder, const TemplateArgumentListInfo &ArgInfos, QualType CanonInjectedType, - ClassTemplatePartialSpecializationDecl *PrevDecl); + ClassTemplatePartialSpecializationDecl *PrevDecl, + unsigned SequenceNumber); /// Get the list of template parameters TemplateParameterList *getTemplateParameters() const { @@ -983,6 +1067,10 @@ public: return NumArgsAsWritten; } + /// \brief Get the sequence number for this class template partial + /// specialization. + unsigned getSequenceNumber() const { return SequenceNumber; } + /// \brief Retrieve the member class template partial specialization from /// which this particular class template partial specialization was /// instantiated. @@ -1046,6 +1134,15 @@ public: "Only member templates can be member template specializations"); return First->InstantiatedFromMember.setInt(true); } + + /// Retrieves the injected specialization type for this partial + /// specialization. This is not the same as the type-decl-type for + /// this partial specialization, which is an InjectedClassNameType. + QualType getInjectedSpecializationType() const { + assert(getTypeForDecl() && "partial specialization has no type set!"); + return cast<InjectedClassNameType>(getTypeForDecl()) + ->getInjectedSpecializationType(); + } // FIXME: Add Profile support! @@ -1141,6 +1238,10 @@ public: return CommonPtr->PartialSpecializations; } + /// \brief Retrieve the partial specializations as an ordered list. + void getPartialSpecializations( + llvm::SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS); + /// \brief Find a class template partial specialization with the given /// type T. /// diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 6225069c602fe..94017865d4c6d 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -198,9 +198,12 @@ public: /// callee in a call expression with dependent arguments. bool isDependentName() const; - /// getName - Retrieve the human-readable string for this name. + /// getNameAsString - Retrieve the human-readable string for this name. std::string getAsString() const; + /// printName - Print the human-readable name to a stream. + void printName(llvm::raw_ostream &OS) const; + /// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in /// this declaration name, or NULL if this declaration name isn't a /// simple identifier. @@ -331,13 +334,15 @@ public: /// getCXXConstructorName - Returns the name of a C++ constructor /// for the given Type. DeclarationName getCXXConstructorName(CanQualType Ty) { - return getCXXSpecialName(DeclarationName::CXXConstructorName, Ty); + return getCXXSpecialName(DeclarationName::CXXConstructorName, + Ty.getUnqualifiedType()); } /// getCXXDestructorName - Returns the name of a C++ destructor /// for the given Type. DeclarationName getCXXDestructorName(CanQualType Ty) { - return getCXXSpecialName(DeclarationName::CXXDestructorName, Ty); + return getCXXSpecialName(DeclarationName::CXXDestructorName, + Ty.getUnqualifiedType()); } /// getCXXConversionFunctionName - Returns the name of a C++ diff --git a/include/clang/AST/DependentDiagnostic.h b/include/clang/AST/DependentDiagnostic.h index 1954a282e8020..2bbe5020cb3a5 100644 --- a/include/clang/AST/DependentDiagnostic.h +++ b/include/clang/AST/DependentDiagnostic.h @@ -22,6 +22,7 @@ #include "clang/Basic/SourceLocation.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclContextInternals.h" +#include "clang/AST/Type.h" namespace clang { @@ -42,6 +43,7 @@ public: AccessSpecifier AS, NamedDecl *TargetDecl, CXXRecordDecl *NamingClass, + QualType BaseObjectType, const PartialDiagnostic &PDiag) { DependentDiagnostic *DD = Create(Context, Parent, PDiag); DD->AccessData.Loc = Loc.getRawEncoding(); @@ -49,6 +51,7 @@ public: DD->AccessData.Access = AS; DD->AccessData.TargetDecl = TargetDecl; DD->AccessData.NamingClass = NamingClass; + DD->AccessData.BaseObjectType = BaseObjectType.getAsOpaquePtr(); return DD; } @@ -81,6 +84,11 @@ public: return AccessData.NamingClass; } + QualType getAccessBaseObjectType() const { + assert(getKind() == Access); + return QualType::getFromOpaquePtr(AccessData.BaseObjectType); + } + const PartialDiagnostic &getDiagnostic() const { return Diag; } @@ -107,6 +115,7 @@ private: unsigned IsMember : 1; NamedDecl *TargetDecl; CXXRecordDecl *NamingClass; + void *BaseObjectType; } AccessData; }; }; diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index a687ee5f01c8b..2946e464a7cfe 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -17,6 +17,9 @@ #include "clang/AST/APValue.h" #include "clang/AST/Stmt.h" #include "clang/AST/Type.h" +#include "clang/AST/DeclAccessPair.h" +#include "clang/AST/ASTVector.h" +#include "clang/AST/UsuallyTinyPtrVector.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallVector.h" @@ -32,11 +35,15 @@ namespace clang { class NamedDecl; class ValueDecl; class BlockDecl; + class CXXBaseSpecifier; class CXXOperatorCallExpr; class CXXMemberCallExpr; class TemplateArgumentLoc; class TemplateArgumentListInfo; +/// \brief A simple array of base specifiers. +typedef UsuallyTinyPtrVector<const CXXBaseSpecifier> CXXBaseSpecifierArray; + /// Expr - This represents one expression. Note that Expr's are subclasses of /// Stmt. This allows an expression to be transparently used any place a Stmt /// is required. @@ -197,6 +204,12 @@ public: /// \brief Returns whether this expression refers to a vector element. bool refersToVectorElement() const; + /// isKnownToHaveBooleanValue - Return true if this is an integer expression + /// that is known to return 0 or 1. This happens for _Bool/bool expressions + /// but also int expressions which are produced by things like comparisons in + /// C. + bool isKnownToHaveBooleanValue() const; + /// isIntegerConstantExpr - Return true if this expression is a valid integer /// constant expression, and, if so, return its value in Result. If not a /// valid i-c-e, return false and fill in Loc (if specified) with the location @@ -210,7 +223,7 @@ public: } /// isConstantInitializer - Returns true if this expression is a constant /// initializer, which can be emitted at compile-time. - bool isConstantInitializer(ASTContext &Ctx) const; + bool isConstantInitializer(ASTContext &Ctx) const; /// EvalResult is a struct with detailed info about an evaluated expression. struct EvalResult { @@ -302,7 +315,7 @@ public: /// its subexpression. If that subexpression is also a ParenExpr, /// then this method recursively returns its subexpression, and so forth. /// Otherwise, the method returns the current Expr. - Expr* IgnoreParens(); + Expr *IgnoreParens(); /// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr /// or CastExprs, returning their operand. @@ -331,7 +344,7 @@ public: /// temporary object. const Expr *getTemporaryObject() const; - const Expr* IgnoreParens() const { + const Expr *IgnoreParens() const { return const_cast<Expr*>(this)->IgnoreParens(); } const Expr *IgnoreParenCasts() const { @@ -901,7 +914,7 @@ public: /// /// __builtin_offsetof(type, a.b[10]) is represented as a unary operator whose /// subexpression is a compound literal with the various MemberExpr and -/// ArraySubscriptExpr's applied to it. +/// ArraySubscriptExpr's applied to it. (This is only used in C) /// class UnaryOperator : public Expr { public: @@ -990,6 +1003,205 @@ public: virtual child_iterator child_end(); }; +/// OffsetOfExpr - [C99 7.17] - This represents an expression of the form +/// offsetof(record-type, member-designator). For example, given: +/// @code +/// struct S { +/// float f; +/// double d; +/// }; +/// struct T { +/// int i; +/// struct S s[10]; +/// }; +/// @endcode +/// we can represent and evaluate the expression @c offsetof(struct T, s[2].d). + +class OffsetOfExpr : public Expr { +public: + // __builtin_offsetof(type, identifier(.identifier|[expr])*) + class OffsetOfNode { + public: + /// \brief The kind of offsetof node we have. + enum Kind { + /// \brief An index into an array. + Array = 0x00, + /// \brief A field. + Field = 0x01, + /// \brief A field in a dependent type, known only by its name. + Identifier = 0x02, + /// \brief An implicit indirection through a C++ base class, when the + /// field found is in a base class. + Base = 0x03 + }; + + private: + enum { MaskBits = 2, Mask = 0x03 }; + + /// \brief The source range that covers this part of the designator. + SourceRange Range; + + /// \brief The data describing the designator, which comes in three + /// different forms, depending on the lower two bits. + /// - An unsigned index into the array of Expr*'s stored after this node + /// in memory, for [constant-expression] designators. + /// - A FieldDecl*, for references to a known field. + /// - An IdentifierInfo*, for references to a field with a given name + /// when the class type is dependent. + /// - A CXXBaseSpecifier*, for references that look at a field in a + /// base class. + uintptr_t Data; + + public: + /// \brief Create an offsetof node that refers to an array element. + OffsetOfNode(SourceLocation LBracketLoc, unsigned Index, + SourceLocation RBracketLoc) + : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) { } + + /// \brief Create an offsetof node that refers to a field. + OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, + SourceLocation NameLoc) + : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc), + Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) { } + + /// \brief Create an offsetof node that refers to an identifier. + OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name, + SourceLocation NameLoc) + : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc), + Data(reinterpret_cast<uintptr_t>(Name) | Identifier) { } + + /// \brief Create an offsetof node that refers into a C++ base class. + explicit OffsetOfNode(const CXXBaseSpecifier *Base) + : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {} + + /// \brief Determine what kind of offsetof node this is. + Kind getKind() const { + return static_cast<Kind>(Data & Mask); + } + + /// \brief For an array element node, returns the index into the array + /// of expressions. + unsigned getArrayExprIndex() const { + assert(getKind() == Array); + return Data >> 2; + } + + /// \brief For a field offsetof node, returns the field. + FieldDecl *getField() const { + assert(getKind() == Field); + return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask); + } + + /// \brief For a field or identifier offsetof node, returns the name of + /// the field. + IdentifierInfo *getFieldName() const; + + /// \brief For a base class node, returns the base specifier. + CXXBaseSpecifier *getBase() const { + assert(getKind() == Base); + return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask); + } + + /// \brief Retrieve the source range that covers this offsetof node. + /// + /// For an array element node, the source range contains the locations of + /// the square brackets. For a field or identifier node, the source range + /// contains the location of the period (if there is one) and the + /// identifier. + SourceRange getRange() const { return Range; } + }; + +private: + + SourceLocation OperatorLoc, RParenLoc; + // Base type; + TypeSourceInfo *TSInfo; + // Number of sub-components (i.e. instances of OffsetOfNode). + unsigned NumComps; + // Number of sub-expressions (i.e. array subscript expressions). + unsigned NumExprs; + + OffsetOfExpr(ASTContext &C, QualType type, + SourceLocation OperatorLoc, TypeSourceInfo *tsi, + OffsetOfNode* compsPtr, unsigned numComps, + Expr** exprsPtr, unsigned numExprs, + SourceLocation RParenLoc); + + explicit OffsetOfExpr(unsigned numComps, unsigned numExprs) + : Expr(OffsetOfExprClass, EmptyShell()), + TSInfo(0), NumComps(numComps), NumExprs(numExprs) {} + +public: + + static OffsetOfExpr *Create(ASTContext &C, QualType type, + SourceLocation OperatorLoc, TypeSourceInfo *tsi, + OffsetOfNode* compsPtr, unsigned numComps, + Expr** exprsPtr, unsigned numExprs, + SourceLocation RParenLoc); + + static OffsetOfExpr *CreateEmpty(ASTContext &C, + unsigned NumComps, unsigned NumExprs); + + /// getOperatorLoc - Return the location of the operator. + SourceLocation getOperatorLoc() const { return OperatorLoc; } + void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } + + /// \brief Return the location of the right parentheses. + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation R) { RParenLoc = R; } + + TypeSourceInfo *getTypeSourceInfo() const { + return TSInfo; + } + void setTypeSourceInfo(TypeSourceInfo *tsi) { + TSInfo = tsi; + } + + const OffsetOfNode &getComponent(unsigned Idx) { + assert(Idx < NumComps && "Subscript out of range"); + return reinterpret_cast<OffsetOfNode *> (this + 1)[Idx]; + } + + void setComponent(unsigned Idx, OffsetOfNode ON) { + assert(Idx < NumComps && "Subscript out of range"); + reinterpret_cast<OffsetOfNode *> (this + 1)[Idx] = ON; + } + + unsigned getNumComponents() const { + return NumComps; + } + + Expr* getIndexExpr(unsigned Idx) { + assert(Idx < NumExprs && "Subscript out of range"); + return reinterpret_cast<Expr **>( + reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx]; + } + + void setIndexExpr(unsigned Idx, Expr* E) { + assert(Idx < NumComps && "Subscript out of range"); + reinterpret_cast<Expr **>( + reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx] = E; + } + + unsigned getNumExpressions() const { + return NumExprs; + } + + virtual SourceRange getSourceRange() const { + return SourceRange(OperatorLoc, RParenLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OffsetOfExprClass; + } + + static bool classof(const OffsetOfExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + /// SizeOfAlignOfExpr - [C99 6.5.3.4] - This is for sizeof/alignof, both of /// types and expressions. class SizeOfAlignOfExpr : public Expr { @@ -1274,7 +1486,7 @@ public: class MemberExpr : public Expr { /// Extra data stored in some member expressions. struct MemberNameQualifier : public NameQualifier { - NamedDecl *FoundDecl; + DeclAccessPair FoundDecl; }; /// Base - the expression for the base pointer or structure references. In @@ -1349,7 +1561,7 @@ public: static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, NestedNameSpecifier *qual, SourceRange qualrange, - ValueDecl *memberdecl, NamedDecl *founddecl, + ValueDecl *memberdecl, DeclAccessPair founddecl, SourceLocation l, const TemplateArgumentListInfo *targs, QualType ty); @@ -1365,9 +1577,10 @@ public: void setMemberDecl(ValueDecl *D) { MemberDecl = D; } /// \brief Retrieves the declaration found by lookup. - NamedDecl *getFoundDecl() const { + DeclAccessPair getFoundDecl() const { if (!HasQualifierOrFoundDecl) - return getMemberDecl(); + return DeclAccessPair::make(getMemberDecl(), + getMemberDecl()->getAccess()); return getMemberQualifier()->FoundDecl; } @@ -1636,8 +1849,53 @@ public: private: CastKind Kind; Stmt *Op; + + /// BasePath - For derived-to-base and base-to-derived casts, the base array + /// contains the inheritance path. + CXXBaseSpecifierArray BasePath; + + void CheckBasePath() const { +#ifndef NDEBUG + switch (getCastKind()) { + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + case CK_DerivedToBaseMemberPointer: + case CK_BaseToDerived: + case CK_BaseToDerivedMemberPointer: + assert(!BasePath.empty() && "Cast kind should have a base path!"); + break; + + // These should not have an inheritance path. + case CK_Unknown: + case CK_BitCast: + case CK_NoOp: + case CK_Dynamic: + case CK_ToUnion: + case CK_ArrayToPointerDecay: + case CK_FunctionToPointerDecay: + case CK_NullToMemberPointer: + case CK_UserDefinedConversion: + case CK_ConstructorConversion: + case CK_IntegralToPointer: + case CK_PointerToIntegral: + case CK_ToVoid: + case CK_VectorSplat: + case CK_IntegralCast: + case CK_IntegralToFloating: + case CK_FloatingToIntegral: + case CK_FloatingCast: + case CK_MemberPointerToBoolean: + case CK_AnyPointerToObjCPointerCast: + case CK_AnyPointerToBlockPointerCast: + assert(BasePath.empty() && "Cast kind should not have a base path!"); + break; + } +#endif + } + protected: - CastExpr(StmtClass SC, QualType ty, const CastKind kind, Expr *op) : + CastExpr(StmtClass SC, QualType ty, const CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath) : Expr(SC, ty, // Cast expressions are type-dependent if the type is // dependent (C++ [temp.dep.expr]p3). @@ -1645,12 +1903,16 @@ protected: // Cast expressions are value-dependent if the type is // dependent or if the subexpression is value-dependent. ty->isDependentType() || (op && op->isValueDependent())), - Kind(kind), Op(op) {} + Kind(kind), Op(op), BasePath(BasePath) { + CheckBasePath(); + } /// \brief Construct an empty cast. CastExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) { } + virtual void DoDestroy(ASTContext &C); + public: CastKind getCastKind() const { return Kind; } void setCastKind(CastKind K) { Kind = K; } @@ -1667,10 +1929,12 @@ public: const Expr *getSubExprAsWritten() const { return const_cast<CastExpr *>(this)->getSubExprAsWritten(); } - + + const CXXBaseSpecifierArray& getBasePath() const { return BasePath; } + static bool classof(const Stmt *T) { StmtClass SC = T->getStmtClass(); - if (SC >= CXXNamedCastExprClass && SC <= CXXFunctionalCastExprClass) + if (SC >= CXXStaticCastExprClass && SC <= CXXFunctionalCastExprClass) return true; if (SC >= ImplicitCastExprClass && SC <= CStyleCastExprClass) @@ -1706,14 +1970,15 @@ class ImplicitCastExpr : public CastExpr { bool LvalueCast; public: - ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, bool Lvalue) : - CastExpr(ImplicitCastExprClass, ty, kind, op), LvalueCast(Lvalue) { } + ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath, bool Lvalue) + : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePath), + LvalueCast(Lvalue) { } /// \brief Construct an empty implicit cast. explicit ImplicitCastExpr(EmptyShell Shell) : CastExpr(ImplicitCastExprClass, Shell) { } - virtual SourceRange getSourceRange() const { return getSubExpr()->getSourceRange(); } @@ -1753,8 +2018,9 @@ class ExplicitCastExpr : public CastExpr { protected: ExplicitCastExpr(StmtClass SC, QualType exprTy, CastKind kind, - Expr *op, TypeSourceInfo *writtenTy) - : CastExpr(SC, exprTy, kind, op), TInfo(writtenTy) {} + Expr *op, CXXBaseSpecifierArray BasePath, + TypeSourceInfo *writtenTy) + : CastExpr(SC, exprTy, kind, op, BasePath), TInfo(writtenTy) {} /// \brief Construct an empty explicit cast. ExplicitCastExpr(StmtClass SC, EmptyShell Shell) @@ -1774,7 +2040,7 @@ public: StmtClass SC = T->getStmtClass(); if (SC >= CStyleCastExprClass && SC <= CStyleCastExprClass) return true; - if (SC >= CXXNamedCastExprClass && SC <= CXXFunctionalCastExprClass) + if (SC >= CXXStaticCastExprClass && SC <= CXXFunctionalCastExprClass) return true; return false; @@ -1790,10 +2056,10 @@ class CStyleCastExpr : public ExplicitCastExpr { SourceLocation RPLoc; // the location of the right paren public: CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op, - TypeSourceInfo *writtenTy, - SourceLocation l, SourceLocation r) : - ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, writtenTy), - LPLoc(l), RPLoc(r) {} + CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + SourceLocation l, SourceLocation r) + : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, BasePath, + writtenTy), LPLoc(l), RPLoc(r) {} /// \brief Construct an empty C-style explicit cast. explicit CStyleCastExpr(EmptyShell Shell) @@ -2362,7 +2628,7 @@ public: virtual child_iterator child_end(); }; -/// VAArgExpr, used for the builtin function __builtin_va_start. +/// VAArgExpr, used for the builtin function __builtin_va_arg. class VAArgExpr : public Expr { Stmt *Val; SourceLocation BuiltinLoc, RParenLoc; @@ -2373,7 +2639,7 @@ public: BuiltinLoc(BLoc), RParenLoc(RPLoc) { } - /// \brief Create an empty __builtin_va_start expression. + /// \brief Create an empty __builtin_va_arg expression. explicit VAArgExpr(EmptyShell Empty) : Expr(VAArgExprClass, Empty) { } const Expr *getSubExpr() const { return cast<Expr>(Val); } @@ -2438,7 +2704,8 @@ public: /// serves as its syntactic form. class InitListExpr : public Expr { // FIXME: Eliminate this vector in favor of ASTContext allocation - std::vector<Stmt *> InitExprs; + typedef ASTVector<Stmt *> InitExprsTy; + InitExprsTy InitExprs; SourceLocation LBraceLoc, RBraceLoc; /// Contains the initializer list that describes the syntactic form @@ -2454,11 +2721,13 @@ class InitListExpr : public Expr { bool HadArrayRangeDesignator; public: - InitListExpr(SourceLocation lbraceloc, Expr **initexprs, unsigned numinits, + InitListExpr(ASTContext &C, SourceLocation lbraceloc, + Expr **initexprs, unsigned numinits, SourceLocation rbraceloc); /// \brief Build an empty initializer list. - explicit InitListExpr(EmptyShell Empty) : Expr(InitListExprClass, Empty) { } + explicit InitListExpr(ASTContext &C, EmptyShell Empty) + : Expr(InitListExprClass, Empty), InitExprs(C) { } unsigned getNumInits() const { return InitExprs.size(); } @@ -2478,7 +2747,7 @@ public: } /// \brief Reserve space for some number of initializers. - void reserveInits(unsigned NumInits); + void reserveInits(ASTContext &C, unsigned NumInits); /// @brief Specify the number of initializers /// @@ -2495,7 +2764,7 @@ public: /// When @p Init is out of range for this initializer list, the /// initializer list will be extended with NULL expressions to /// accomodate the new entry. - Expr *updateInit(unsigned Init, Expr *expr); + Expr *updateInit(ASTContext &C, unsigned Init, Expr *expr); /// \brief If this initializes a union, specifies which field in the /// union to initialize. @@ -2541,8 +2810,8 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); - typedef std::vector<Stmt *>::iterator iterator; - typedef std::vector<Stmt *>::reverse_iterator reverse_iterator; + typedef InitExprsTy::iterator iterator; + typedef InitExprsTy::reverse_iterator reverse_iterator; iterator begin() { return InitExprs.begin(); } iterator end() { return InitExprs.end(); } diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 6e2e832e3542d..f9ca78ad292d7 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -118,8 +118,9 @@ private: protected: CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op, - TypeSourceInfo *writtenTy, SourceLocation l) - : ExplicitCastExpr(SC, ty, kind, op, writtenTy), Loc(l) {} + CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + SourceLocation l) + : ExplicitCastExpr(SC, ty, kind, op, BasePath, writtenTy), Loc(l) {} explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell) : ExplicitCastExpr(SC, Shell) { } @@ -137,7 +138,6 @@ public: } static bool classof(const Stmt *T) { switch (T->getStmtClass()) { - case CXXNamedCastExprClass: case CXXStaticCastExprClass: case CXXDynamicCastExprClass: case CXXReinterpretCastExprClass: @@ -156,9 +156,10 @@ public: /// @c static_cast<int>(1.0). class CXXStaticCastExpr : public CXXNamedCastExpr { public: - CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op, - TypeSourceInfo *writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, writtenTy, l) {} + CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + SourceLocation l) + : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, BasePath, writtenTy, l) {} explicit CXXStaticCastExpr(EmptyShell Empty) : CXXNamedCastExpr(CXXStaticCastExprClass, Empty) { } @@ -177,9 +178,11 @@ public: /// @c dynamic_cast<Derived*>(BasePtr). class CXXDynamicCastExpr : public CXXNamedCastExpr { public: - CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op, - TypeSourceInfo *writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, writtenTy, l) {} + CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + SourceLocation l) + : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, BasePath, + writtenTy, l) {} explicit CXXDynamicCastExpr(EmptyShell Empty) : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty) { } @@ -199,8 +202,9 @@ public: class CXXReinterpretCastExpr : public CXXNamedCastExpr { public: CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, + : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, BasePath, writtenTy, l) {} explicit CXXReinterpretCastExpr(EmptyShell Empty) @@ -221,7 +225,8 @@ class CXXConstCastExpr : public CXXNamedCastExpr { public: CXXConstCastExpr(QualType ty, Expr *op, TypeSourceInfo *writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op, writtenTy, l) {} + : CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op, + CXXBaseSpecifierArray(), writtenTy, l) {} explicit CXXConstCastExpr(EmptyShell Empty) : CXXNamedCastExpr(CXXConstCastExprClass, Empty) { } @@ -293,37 +298,41 @@ public: /// This represents code like @c typeid(int) or @c typeid(*objPtr) class CXXTypeidExpr : public Expr { private: - bool isTypeOp : 1; - union { - void *Ty; - Stmt *Ex; - } Operand; + llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand; SourceRange Range; public: - CXXTypeidExpr(bool isTypeOp, void *op, QualType Ty, const SourceRange r) : - Expr(CXXTypeidExprClass, Ty, + CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R) + : Expr(CXXTypeidExprClass, Ty, + // typeid is never type-dependent (C++ [temp.dep.expr]p4) + false, + // typeid is value-dependent if the type or expression are dependent + Operand->getType()->isDependentType()), + Operand(Operand), Range(R) { } + + CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R) + : Expr(CXXTypeidExprClass, Ty, // typeid is never type-dependent (C++ [temp.dep.expr]p4) false, // typeid is value-dependent if the type or expression are dependent - (isTypeOp ? QualType::getFromOpaquePtr(op)->isDependentType() - : static_cast<Expr*>(op)->isValueDependent())), - isTypeOp(isTypeOp), Range(r) { - if (isTypeOp) - Operand.Ty = op; - else - // op was an Expr*, so cast it back to that to be safe - Operand.Ex = static_cast<Expr*>(op); - } + Operand->isTypeDependent() || Operand->isValueDependent()), + Operand(Operand), Range(R) { } + + bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } + + /// \brief Retrieves the type operand of this typeid() expression after + /// various required adjustments (removing reference types, cv-qualifiers). + QualType getTypeOperand() const; - bool isTypeOperand() const { return isTypeOp; } - QualType getTypeOperand() const { + /// \brief Retrieve source information for the type operand. + TypeSourceInfo *getTypeOperandSourceInfo() const { assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); - return QualType::getFromOpaquePtr(Operand.Ty); + return Operand.get<TypeSourceInfo *>(); } + Expr* getExprOperand() const { assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); - return static_cast<Expr*>(Operand.Ex); + return static_cast<Expr*>(Operand.get<Stmt *>()); } virtual SourceRange getSourceRange() const { @@ -621,12 +630,20 @@ public: /// CXXConstructExpr - Represents a call to a C++ constructor. class CXXConstructExpr : public Expr { +public: + enum ConstructionKind { + CK_Complete, + CK_NonVirtualBase, + CK_VirtualBase + }; + +private: CXXConstructorDecl *Constructor; SourceLocation Loc; bool Elidable : 1; bool ZeroInitialization : 1; - bool BaseInitialization : 1; + unsigned ConstructKind : 2; Stmt **Args; unsigned NumArgs; @@ -636,7 +653,7 @@ protected: CXXConstructorDecl *d, bool elidable, Expr **args, unsigned numargs, bool ZeroInitialization = false, - bool BaseInitialization = false); + ConstructionKind ConstructKind = CK_Complete); ~CXXConstructExpr() { } virtual void DoDestroy(ASTContext &C); @@ -651,7 +668,7 @@ public: CXXConstructorDecl *D, bool Elidable, Expr **Args, unsigned NumArgs, bool ZeroInitialization = false, - bool BaseInitialization = false); + ConstructionKind ConstructKind = CK_Complete); CXXConstructorDecl* getConstructor() const { return Constructor; } @@ -673,8 +690,12 @@ public: /// \brief Determines whether this constructor is actually constructing /// a base class (rather than a complete object). - bool isBaseInitialization() const { return BaseInitialization; } - void setBaseInitialization(bool BI) { BaseInitialization = BI; } + ConstructionKind getConstructionKind() const { + return (ConstructionKind)ConstructKind; + } + void setConstructionKind(ConstructionKind CK) { + ConstructKind = CK; + } typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; @@ -725,9 +746,10 @@ class CXXFunctionalCastExpr : public ExplicitCastExpr { public: CXXFunctionalCastExpr(QualType ty, TypeSourceInfo *writtenTy, SourceLocation tyBeginLoc, CastKind kind, - Expr *castExpr, SourceLocation rParenLoc) + Expr *castExpr, CXXBaseSpecifierArray BasePath, + SourceLocation rParenLoc) : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr, - writtenTy), + BasePath, writtenTy), TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} explicit CXXFunctionalCastExpr(EmptyShell Shell) @@ -774,7 +796,8 @@ public: CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons, QualType writtenTy, SourceLocation tyBeginLoc, Expr **Args,unsigned NumArgs, - SourceLocation rParenLoc); + SourceLocation rParenLoc, + bool ZeroInitialization = false); ~CXXTemporaryObjectExpr() { } @@ -1290,6 +1313,9 @@ public: Results.append(Begin, End); } + /// Gets the naming class of this lookup, if any. + CXXRecordDecl *getNamingClass() const; + typedef UnresolvedSetImpl::iterator decls_iterator; decls_iterator decls_begin() const { return Results.begin(); } decls_iterator decls_end() const { return Results.end(); } diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 6f43973a3e1dc..8a09f4e9a6a92 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -59,13 +59,14 @@ public: /// and behavior as StringLiteral except that the string initializer is obtained /// from ASTContext with the encoding type as an argument. class ObjCEncodeExpr : public Expr { - QualType EncType; + TypeSourceInfo *EncodedType; SourceLocation AtLoc, RParenLoc; public: - ObjCEncodeExpr(QualType T, QualType ET, + ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType, SourceLocation at, SourceLocation rp) - : Expr(ObjCEncodeExprClass, T, ET->isDependentType(), - ET->isDependentType()), EncType(ET), AtLoc(at), RParenLoc(rp) {} + : Expr(ObjCEncodeExprClass, T, EncodedType->getType()->isDependentType(), + EncodedType->getType()->isDependentType()), + EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {} explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){} @@ -75,9 +76,12 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - QualType getEncodedType() const { return EncType; } - void setEncodedType(QualType T) { EncType = T; } + QualType getEncodedType() const { return EncodedType->getType(); } + TypeSourceInfo *getEncodedTypeSourceInfo() const { return EncodedType; } + void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) { + EncodedType = EncType; + } virtual SourceRange getSourceRange() const { return SourceRange(AtLoc, RParenLoc); @@ -177,11 +181,12 @@ class ObjCIvarRefExpr : public Expr { public: ObjCIvarRefExpr(ObjCIvarDecl *d, - QualType t, SourceLocation l, Expr *base=0, + QualType t, SourceLocation l, Expr *base, bool arrow = false, bool freeIvar = false) : - Expr(ObjCIvarRefExprClass, t, false, false), D(d), - Loc(l), Base(base), IsArrow(arrow), - IsFreeIvar(freeIvar) {} + Expr(ObjCIvarRefExprClass, t, /*TypeDependent=*/false, + base->isValueDependent()), D(d), + Loc(l), Base(base), IsArrow(arrow), + IsFreeIvar(freeIvar) {} explicit ObjCIvarRefExpr(EmptyShell Empty) : Expr(ObjCIvarRefExprClass, Empty) {} @@ -228,8 +233,9 @@ private: public: ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, SourceLocation l, Expr *base) - : Expr(ObjCPropertyRefExprClass, t, false, false), AsProperty(PD), - IdLoc(l), Base(base) { + : Expr(ObjCPropertyRefExprClass, t, /*TypeDependent=*/false, + base->isValueDependent()), + AsProperty(PD), IdLoc(l), Base(base) { } explicit ObjCPropertyRefExpr(EmptyShell Empty) @@ -293,7 +299,8 @@ public: QualType t, ObjCMethodDecl *setter, SourceLocation l, Expr *base) - : Expr(ObjCImplicitSetterGetterRefExprClass, t, false, false), + : Expr(ObjCImplicitSetterGetterRefExprClass, t, /*TypeDependent=*/false, + base->isValueDependent()), Setter(setter), Getter(getter), MemberLoc(l), Base(base), InterfaceDecl(0), ClassLoc(SourceLocation()) { } @@ -339,152 +346,376 @@ public: virtual child_iterator child_end(); }; +/// \brief An expression that sends a message to the given Objective-C +/// object or class. +/// +/// The following contains two message send expressions: +/// +/// \code +/// [[NSString alloc] initWithString:@"Hello"] +/// \endcode +/// +/// The innermost message send invokes the "alloc" class method on the +/// NSString class, while the outermost message send invokes the +/// "initWithString" instance method on the object returned from +/// NSString's "alloc". In all, an Objective-C message send can take +/// on four different (although related) forms: +/// +/// 1. Send to an object instance. +/// 2. Send to a class. +/// 3. Send to the superclass instance of the current class. +/// 4. Send to the superclass of the current class. +/// +/// All four kinds of message sends are modeled by the ObjCMessageExpr +/// class, and can be distinguished via \c getReceiverKind(). Example: +/// class ObjCMessageExpr : public Expr { - // SubExprs - The receiver and arguments of the message expression. - Stmt **SubExprs; + /// \brief The number of arguments in the message send, not + /// including the receiver. + unsigned NumArgs : 16; + + /// \brief The kind of message send this is, which is one of the + /// ReceiverKind values. + /// + /// We pad this out to a byte to avoid excessive masking and shifting. + unsigned Kind : 8; + + /// \brief Whether we have an actual method prototype in \c + /// SelectorOrMethod. + /// + /// When non-zero, we have a method declaration; otherwise, we just + /// have a selector. + unsigned HasMethod : 8; + + /// \brief When the message expression is a send to 'super', this is + /// the location of the 'super' keyword. + SourceLocation SuperLoc; + + /// \brief Stores either the selector that this message is sending + /// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer + /// referring to the method that we type-checked against. + uintptr_t SelectorOrMethod; + + /// \brief The source locations of the open and close square + /// brackets ('[' and ']', respectively). + SourceLocation LBracLoc, RBracLoc; + + ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs) + : Expr(ObjCMessageExprClass, Empty), NumArgs(NumArgs), Kind(0), + HasMethod(0), SelectorOrMethod(0) { } + + ObjCMessageExpr(QualType T, + SourceLocation LBracLoc, + SourceLocation SuperLoc, + bool IsInstanceSuper, + QualType SuperType, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + ObjCMessageExpr(QualType T, + SourceLocation LBracLoc, + TypeSourceInfo *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + ObjCMessageExpr(QualType T, + SourceLocation LBracLoc, + Expr *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Retrieve the pointer value of the message receiver. + void *getReceiverPointer() const { + return *const_cast<void **>( + reinterpret_cast<const void * const*>(this + 1)); + } - // NumArgs - The number of arguments (not including the receiver) to the - // message expression. - unsigned NumArgs; + /// \brief Set the pointer value of the message receiver. + void setReceiverPointer(void *Value) { + *reinterpret_cast<void **>(this + 1) = Value; + } - /// \brief The location of the class name in a class message. - SourceLocation ClassNameLoc; +public: + /// \brief The kind of receiver this message is sending to. + enum ReceiverKind { + /// \brief The receiver is a class. + Class = 0, + /// \brief The receiver is an object instance. + Instance, + /// \brief The receiver is a superclass. + SuperClass, + /// \brief The receiver is the instance of the superclass object. + SuperInstance + }; - // A unigue name for this message. - Selector SelName; + /// \brief Create a message send to super. + /// + /// \param Context The ASTContext in which this expression will be created. + /// + /// \param T The result type of this message. + /// + /// \param LBrac The location of the open square bracket '['. + /// + /// \param SuperLoc The location of the "super" keyword. + /// + /// \param IsInstanceSuper Whether this is an instance "super" + /// message (otherwise, it's a class "super" message). + /// + /// \param Sel The selector used to determine which method gets called. + /// + /// \param Method The Objective-C method against which this message + /// send was type-checked. May be NULL. + /// + /// \param Args The message send arguments. + /// + /// \param NumArgs The number of arguments. + /// + /// \param RBracLoc The location of the closing square bracket ']'. + static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + SourceLocation LBracLoc, + SourceLocation SuperLoc, + bool IsInstanceSuper, + QualType SuperType, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Create a class message send. + /// + /// \param Context The ASTContext in which this expression will be created. + /// + /// \param T The result type of this message. + /// + /// \param LBrac The location of the open square bracket '['. + /// + /// \param Receiver The type of the receiver, including + /// source-location information. + /// + /// \param Sel The selector used to determine which method gets called. + /// + /// \param Method The Objective-C method against which this message + /// send was type-checked. May be NULL. + /// + /// \param Args The message send arguments. + /// + /// \param NumArgs The number of arguments. + /// + /// \param RBracLoc The location of the closing square bracket ']'. + static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + SourceLocation LBracLoc, + TypeSourceInfo *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Create an instance message send. + /// + /// \param Context The ASTContext in which this expression will be created. + /// + /// \param T The result type of this message. + /// + /// \param LBrac The location of the open square bracket '['. + /// + /// \param Receiver The expression used to produce the object that + /// will receive this message. + /// + /// \param Sel The selector used to determine which method gets called. + /// + /// \param Method The Objective-C method against which this message + /// send was type-checked. May be NULL. + /// + /// \param Args The message send arguments. + /// + /// \param NumArgs The number of arguments. + /// + /// \param RBracLoc The location of the closing square bracket ']'. + static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + SourceLocation LBracLoc, + Expr *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Create an empty Objective-C message expression, to be + /// filled in by subsequent calls. + /// + /// \param Context The context in which the message send will be created. + /// + /// \param NumArgs The number of message arguments, not including + /// the receiver. + static ObjCMessageExpr *CreateEmpty(ASTContext &Context, unsigned NumArgs); + + /// \brief Determine the kind of receiver that this message is being + /// sent to. + ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; } + + /// \brief Determine whether this is an instance message to either a + /// computed object or to super. + bool isInstanceMessage() const { + return getReceiverKind() == Instance || getReceiverKind() == SuperInstance; + } - // A method prototype for this message (optional). - // FIXME: Since method decls contain the selector, and most messages have a - // prototype, consider devising a scheme for unifying SelName/MethodProto. - ObjCMethodDecl *MethodProto; + /// \brief Determine whether this is an class message to either a + /// specified class or to super. + bool isClassMessage() const { + return getReceiverKind() == Class || getReceiverKind() == SuperClass; + } - SourceLocation LBracloc, RBracloc; + /// \brief Returns the receiver of an instance message. + /// + /// \brief Returns the object expression for an instance message, or + /// NULL for a message that is not an instance message. + Expr *getInstanceReceiver() { + if (getReceiverKind() == Instance) + return static_cast<Expr *>(getReceiverPointer()); - // Constants for indexing into SubExprs. - enum { RECEIVER=0, ARGS_START=1 }; + return 0; + } + const Expr *getInstanceReceiver() const { + return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver(); + } - // Bit-swizzling flags. - enum { IsInstMeth=0, IsClsMethDeclUnknown, IsClsMethDeclKnown, Flags=0x3 }; - unsigned getFlag() const { return (uintptr_t) SubExprs[RECEIVER] & Flags; } + /// \brief Turn this message send into an instance message that + /// computes the receiver object with the given expression. + void setInstanceReceiver(Expr *rec) { + Kind = Instance; + setReceiverPointer(rec); + } + + /// \brief Returns the type of a class message send, or NULL if the + /// message is not a class message. + QualType getClassReceiver() const { + if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo()) + return TSInfo->getType(); + + return QualType(); + } -public: - /// This constructor is used to represent class messages where the - /// ObjCInterfaceDecl* of the receiver is not known. - ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName, - SourceLocation clsNameLoc, Selector selInfo, - QualType retType, ObjCMethodDecl *methDecl, - SourceLocation LBrac, SourceLocation RBrac, - Expr **ArgExprs, unsigned NumArgs); - - /// This constructor is used to represent class messages where the - /// ObjCInterfaceDecl* of the receiver is known. - // FIXME: clsName should be typed to ObjCInterfaceType - ObjCMessageExpr(ASTContext &C, ObjCInterfaceDecl *cls, - SourceLocation clsNameLoc, Selector selInfo, - QualType retType, ObjCMethodDecl *methDecl, - SourceLocation LBrac, SourceLocation RBrac, - Expr **ArgExprs, unsigned NumArgs); - - // constructor for instance messages. - ObjCMessageExpr(ASTContext &C, Expr *receiver, Selector selInfo, - QualType retType, ObjCMethodDecl *methDecl, - SourceLocation LBrac, SourceLocation RBrac, - Expr **ArgExprs, unsigned NumArgs); - - explicit ObjCMessageExpr(EmptyShell Empty) - : Expr(ObjCMessageExprClass, Empty), SubExprs(0), NumArgs(0) {} - - virtual void DoDestroy(ASTContext &C); - - /// getReceiver - Returns the receiver of the message expression. - /// This can be NULL if the message is for class methods. For - /// class methods, use getClassName. - /// FIXME: need to handle/detect 'super' usage within a class method. - Expr *getReceiver() { - uintptr_t x = (uintptr_t) SubExprs[RECEIVER]; - return (x & Flags) == IsInstMeth ? (Expr*) x : 0; - } - const Expr *getReceiver() const { - return const_cast<ObjCMessageExpr*>(this)->getReceiver(); - } - // FIXME: need setters for different receiver types. - void setReceiver(Expr *rec) { SubExprs[RECEIVER] = rec; } - Selector getSelector() const { return SelName; } - void setSelector(Selector S) { SelName = S; } + /// \brief Returns a type-source information of a class message + /// send, or NULL if the message is not a class message. + TypeSourceInfo *getClassReceiverTypeInfo() const { + if (getReceiverKind() == Class) + return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer()); + return 0; + } + + void setClassReceiver(TypeSourceInfo *TSInfo) { + Kind = Class; + setReceiverPointer(TSInfo); + } - const ObjCMethodDecl *getMethodDecl() const { return MethodProto; } - ObjCMethodDecl *getMethodDecl() { return MethodProto; } - void setMethodDecl(ObjCMethodDecl *MD) { MethodProto = MD; } + /// \brief Retrieve the location of the 'super' keyword for a class + /// or instance message to 'super', otherwise an invalid source location. + SourceLocation getSuperLoc() const { + if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass) + return SuperLoc; - /// \brief Describes the class receiver of a message send. - struct ClassInfo { - /// \brief The interface declaration for the class that is - /// receiving the message. May be NULL. - ObjCInterfaceDecl *Decl; + return SourceLocation(); + } - /// \brief The name of the class that is receiving the - /// message. This will never be NULL. - IdentifierInfo *Name; + /// \brief Retrieve the Objective-C interface to which this message + /// is being directed, if known. + /// + /// This routine cross-cuts all of the different kinds of message + /// sends to determine what the underlying (statically known) type + /// of the receiver will be; use \c getReceiverKind() to determine + /// whether the message is a class or an instance method, whether it + /// is a send to super or not, etc. + /// + /// \returns The Objective-C interface if known, otherwise NULL. + ObjCInterfaceDecl *getReceiverInterface() const; + + /// \brief Retrieve the type referred to by 'super'. + /// + /// The returned type will either be an ObjCInterfaceType (for an + /// class message to super) or an ObjCObjectPointerType that refers + /// to a class (for an instance message to super); + QualType getSuperType() const { + if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass) + return QualType::getFromOpaquePtr(getReceiverPointer()); + + return QualType(); + } - /// \brief The source location of the class name. - SourceLocation Loc; + void setSuper(SourceLocation Loc, QualType T, bool IsInstanceSuper) { + Kind = IsInstanceSuper? SuperInstance : SuperClass; + SuperLoc = Loc; + setReceiverPointer(T.getAsOpaquePtr()); + } - ClassInfo() : Decl(0), Name(0), Loc() { } + Selector getSelector() const; - ClassInfo(ObjCInterfaceDecl *Decl, IdentifierInfo *Name, SourceLocation Loc) - : Decl(Decl), Name(Name), Loc(Loc) { } - }; + void setSelector(Selector S) { + HasMethod = false; + SelectorOrMethod = reinterpret_cast<uintptr_t>(S.getAsOpaquePtr()); + } - /// getClassInfo - For class methods, this returns both the ObjCInterfaceDecl* - /// and IdentifierInfo* of the invoked class. Both can be NULL if this - /// is an instance message, and the ObjCInterfaceDecl* can be NULL if none - /// was available when this ObjCMessageExpr object was constructed. - ClassInfo getClassInfo() const; - void setClassInfo(const ClassInfo &C); + const ObjCMethodDecl *getMethodDecl() const { + if (HasMethod) + return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod); - /// getClassName - For class methods, this returns the invoked class, - /// and returns NULL otherwise. For instance methods, use getReceiver. - IdentifierInfo *getClassName() const { - return getClassInfo().Name; + return 0; } - /// getNumArgs - Return the number of actual arguments to this call. + ObjCMethodDecl *getMethodDecl() { + if (HasMethod) + return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod); + + return 0; + } + + void setMethodDecl(ObjCMethodDecl *MD) { + HasMethod = true; + SelectorOrMethod = reinterpret_cast<uintptr_t>(MD); + } + + /// \brief Return the number of actual arguments in this message, + /// not counting the receiver. unsigned getNumArgs() const { return NumArgs; } - void setNumArgs(unsigned nArgs) { - NumArgs = nArgs; - // FIXME: should always allocate SubExprs via the ASTContext's - // allocator. - if (!SubExprs) - SubExprs = new Stmt* [NumArgs + 1]; + + /// \brief Retrieve the arguments to this message, not including the + /// receiver. + Stmt **getArgs() { + return reinterpret_cast<Stmt **>(this + 1) + 1; + } + const Stmt * const *getArgs() const { + return reinterpret_cast<const Stmt * const *>(this + 1) + 1; } /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) { assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(SubExprs[Arg+ARGS_START]); + return cast<Expr>(getArgs()[Arg]); } const Expr *getArg(unsigned Arg) const { assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(SubExprs[Arg+ARGS_START]); + return cast<Expr>(getArgs()[Arg]); } /// setArg - Set the specified argument. void setArg(unsigned Arg, Expr *ArgExpr) { assert(Arg < NumArgs && "Arg access out of range!"); - SubExprs[Arg+ARGS_START] = ArgExpr; + getArgs()[Arg] = ArgExpr; } - SourceLocation getLeftLoc() const { return LBracloc; } - SourceLocation getRightLoc() const { return RBracloc; } + SourceLocation getLeftLoc() const { return LBracLoc; } + SourceLocation getRightLoc() const { return RBracLoc; } - void setLeftLoc(SourceLocation L) { LBracloc = L; } - void setRightLoc(SourceLocation L) { RBracloc = L; } + void setLeftLoc(SourceLocation L) { LBracLoc = L; } + void setRightLoc(SourceLocation L) { RBracLoc = L; } void setSourceRange(SourceRange R) { - LBracloc = R.getBegin(); - RBracloc = R.getEnd(); + LBracLoc = R.getBegin(); + RBracLoc = R.getEnd(); } virtual SourceRange getSourceRange() const { - return SourceRange(LBracloc, RBracloc); + return SourceRange(LBracLoc, RBracLoc); } static bool classof(const Stmt *T) { @@ -499,14 +730,17 @@ public: typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; - arg_iterator arg_begin() { return &SubExprs[ARGS_START]; } - arg_iterator arg_end() { return &SubExprs[ARGS_START] + NumArgs; } - const_arg_iterator arg_begin() const { return &SubExprs[ARGS_START]; } - const_arg_iterator arg_end() const { return &SubExprs[ARGS_START] + NumArgs; } + arg_iterator arg_begin() { return getArgs(); } + arg_iterator arg_end() { return getArgs() + NumArgs; } + const_arg_iterator arg_begin() const { return getArgs(); } + const_arg_iterator arg_end() const { return getArgs() + NumArgs; } }; /// ObjCSuperExpr - Represents the "super" expression in Objective-C, /// which refers to the object on which the current method is executing. +/// +/// FIXME: This class is intended for removal, once its remaining +/// clients have been altered to represent "super" internally. class ObjCSuperExpr : public Expr { SourceLocation Loc; public: @@ -542,7 +776,8 @@ class ObjCIsaExpr : public Expr { bool IsArrow; public: ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty) - : Expr(ObjCIsaExprClass, ty, false, false), + : Expr(ObjCIsaExprClass, ty, /*TypeDependent=*/false, + base->isValueDependent()), Base(base), IsaMemberLoc(l), IsArrow(isarrow) {} /// \brief Build an empty expression. diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index b8d80bc8978df..79e44511d32d3 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -66,6 +66,13 @@ public: /// building a new declaration. virtual Decl *GetDecl(uint32_t ID) = 0; + /// \brief Resolve a selector ID into a selector. + virtual Selector GetSelector(uint32_t ID) = 0; + + /// \brief Returns the number of selectors known to the external AST + /// source. + virtual uint32_t GetNumKnownSelectors() = 0; + /// \brief Resolve the offset of a statement in the decl stream into a /// statement. /// diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 466848976cb39..0b68a40073637 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -70,13 +70,13 @@ namespace clang { }; class ConstExprIterator { - Stmt* const * I; + const Stmt * const *I; public: - ConstExprIterator(Stmt* const* i) : I(i) {} + ConstExprIterator(const Stmt * const *i) : I(i) {} ConstExprIterator() : I(0) {} ConstExprIterator& operator++() { ++I; return *this; } - ConstExprIterator operator+(size_t i) { return I+i; } - ConstExprIterator operator-(size_t i) { return I-i; } + ConstExprIterator operator+(size_t i) const { return I+i; } + ConstExprIterator operator-(size_t i) const { return I-i; } const Expr * operator[](size_t idx) const; signed operator-(const ConstExprIterator& R) const { return I - R.I; } const Expr * operator*() const; diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index ec6149e55f11c..3a23e49148d52 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -78,6 +78,7 @@ EXPR(StringLiteral , Expr) EXPR(CharacterLiteral , Expr) EXPR(ParenExpr , Expr) EXPR(UnaryOperator , Expr) +EXPR(OffsetOfExpr , Expr) EXPR(SizeOfAlignOfExpr , Expr) EXPR(ArraySubscriptExpr , Expr) EXPR(CallExpr , Expr) @@ -107,7 +108,7 @@ EXPR(GNUNullExpr , Expr) // C++ Expressions. EXPR(CXXOperatorCallExpr , CallExpr) EXPR(CXXMemberCallExpr , CallExpr) -EXPR(CXXNamedCastExpr , ExplicitCastExpr) +ABSTRACT_EXPR(CXXNamedCastExpr , ExplicitCastExpr) EXPR(CXXStaticCastExpr , CXXNamedCastExpr) EXPR(CXXDynamicCastExpr , CXXNamedCastExpr) EXPR(CXXReinterpretCastExpr , CXXNamedCastExpr) diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h index 3fd8f1672deb2..269aa4c6dab2d 100644 --- a/include/clang/AST/StmtObjC.h +++ b/include/clang/AST/StmtObjC.h @@ -71,38 +71,31 @@ public: /// ObjCAtCatchStmt - This represents objective-c's @catch statement. class ObjCAtCatchStmt : public Stmt { private: - enum { BODY, NEXT_CATCH, END_EXPR }; - ParmVarDecl *ExceptionDecl; - Stmt *SubExprs[END_EXPR]; + VarDecl *ExceptionDecl; + Stmt *Body; SourceLocation AtCatchLoc, RParenLoc; public: ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc, - ParmVarDecl *catchVarDecl, - Stmt *atCatchStmt, Stmt *atCatchList); + VarDecl *catchVarDecl, + Stmt *atCatchStmt) + : Stmt(ObjCAtCatchStmtClass), ExceptionDecl(catchVarDecl), + Body(atCatchStmt), AtCatchLoc(atCatchLoc), RParenLoc(rparenloc) { } explicit ObjCAtCatchStmt(EmptyShell Empty) : Stmt(ObjCAtCatchStmtClass, Empty) { } - const Stmt *getCatchBody() const { return SubExprs[BODY]; } - Stmt *getCatchBody() { return SubExprs[BODY]; } - void setCatchBody(Stmt *S) { SubExprs[BODY] = S; } + const Stmt *getCatchBody() const { return Body; } + Stmt *getCatchBody() { return Body; } + void setCatchBody(Stmt *S) { Body = S; } - const ObjCAtCatchStmt *getNextCatchStmt() const { - return static_cast<const ObjCAtCatchStmt*>(SubExprs[NEXT_CATCH]); - } - ObjCAtCatchStmt *getNextCatchStmt() { - return static_cast<ObjCAtCatchStmt*>(SubExprs[NEXT_CATCH]); - } - void setNextCatchStmt(Stmt *S) { SubExprs[NEXT_CATCH] = S; } - - const ParmVarDecl *getCatchParamDecl() const { + const VarDecl *getCatchParamDecl() const { return ExceptionDecl; } - ParmVarDecl *getCatchParamDecl() { + VarDecl *getCatchParamDecl() { return ExceptionDecl; } - void setCatchParamDecl(ParmVarDecl *D) { ExceptionDecl = D; } + void setCatchParamDecl(VarDecl *D) { ExceptionDecl = D; } SourceLocation getAtCatchLoc() const { return AtCatchLoc; } void setAtCatchLoc(SourceLocation Loc) { AtCatchLoc = Loc; } @@ -110,7 +103,7 @@ public: void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } virtual SourceRange getSourceRange() const { - return SourceRange(AtCatchLoc, SubExprs[BODY]->getLocEnd()); + return SourceRange(AtCatchLoc, Body->getLocEnd()); } bool hasEllipsis() const { return getCatchParamDecl() == 0; } @@ -160,50 +153,94 @@ public: /// @try ... @catch ... @finally statement. class ObjCAtTryStmt : public Stmt { private: - enum { TRY, CATCH, FINALLY, END_EXPR }; - Stmt* SubStmts[END_EXPR]; - + // The location of the SourceLocation AtTryLoc; -public: + + // The number of catch blocks in this statement. + unsigned NumCatchStmts : 16; + + // Whether this statement has a @finally statement. + bool HasFinally : 1; + + /// \brief Retrieve the statements that are stored after this @try statement. + /// + /// The order of the statements in memory follows the order in the source, + /// with the @try body first, followed by the @catch statements (if any) and, + /// finally, the @finally (if it exists). + Stmt **getStmts() { return reinterpret_cast<Stmt **> (this + 1); } + const Stmt* const *getStmts() const { + return reinterpret_cast<const Stmt * const*> (this + 1); + } + ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt, - Stmt *atCatchStmt, - Stmt *atFinallyStmt) - : Stmt(ObjCAtTryStmtClass) { - SubStmts[TRY] = atTryStmt; - SubStmts[CATCH] = atCatchStmt; - SubStmts[FINALLY] = atFinallyStmt; - AtTryLoc = atTryLoc; - } - explicit ObjCAtTryStmt(EmptyShell Empty) : - Stmt(ObjCAtTryStmtClass, Empty) { } + Stmt **CatchStmts, unsigned NumCatchStmts, + Stmt *atFinallyStmt); + + explicit ObjCAtTryStmt(EmptyShell Empty, unsigned NumCatchStmts, + bool HasFinally) + : Stmt(ObjCAtTryStmtClass, Empty), NumCatchStmts(NumCatchStmts), + HasFinally(HasFinally) { } +public: + static ObjCAtTryStmt *Create(ASTContext &Context, SourceLocation atTryLoc, + Stmt *atTryStmt, + Stmt **CatchStmts, unsigned NumCatchStmts, + Stmt *atFinallyStmt); + static ObjCAtTryStmt *CreateEmpty(ASTContext &Context, + unsigned NumCatchStmts, + bool HasFinally); + + /// \brief Retrieve the location of the @ in the @try. SourceLocation getAtTryLoc() const { return AtTryLoc; } void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; } - const Stmt *getTryBody() const { return SubStmts[TRY]; } - Stmt *getTryBody() { return SubStmts[TRY]; } - void setTryBody(Stmt *S) { SubStmts[TRY] = S; } - - const ObjCAtCatchStmt *getCatchStmts() const { - return dyn_cast_or_null<ObjCAtCatchStmt>(SubStmts[CATCH]); + /// \brief Retrieve the @try body. + const Stmt *getTryBody() const { return getStmts()[0]; } + Stmt *getTryBody() { return getStmts()[0]; } + void setTryBody(Stmt *S) { getStmts()[0] = S; } + + /// \brief Retrieve the number of @catch statements in this try-catch-finally + /// block. + unsigned getNumCatchStmts() const { return NumCatchStmts; } + + /// \brief Retrieve a @catch statement. + const ObjCAtCatchStmt *getCatchStmt(unsigned I) const { + assert(I < NumCatchStmts && "Out-of-bounds @catch index"); + return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]); } - ObjCAtCatchStmt *getCatchStmts() { - return dyn_cast_or_null<ObjCAtCatchStmt>(SubStmts[CATCH]); + + /// \brief Retrieve a @catch statement. + ObjCAtCatchStmt *getCatchStmt(unsigned I) { + assert(I < NumCatchStmts && "Out-of-bounds @catch index"); + return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]); } - void setCatchStmts(Stmt *S) { SubStmts[CATCH] = S; } - + + /// \brief Set a particular catch statement. + void setCatchStmt(unsigned I, ObjCAtCatchStmt *S) { + assert(I < NumCatchStmts && "Out-of-bounds @catch index"); + getStmts()[I + 1] = S; + } + + /// Retrieve the @finally statement, if any. const ObjCAtFinallyStmt *getFinallyStmt() const { - return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]); + if (!HasFinally) + return 0; + + return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); } ObjCAtFinallyStmt *getFinallyStmt() { - return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]); + if (!HasFinally) + return 0; + + return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); } - void setFinallyStmt(Stmt *S) { SubStmts[FINALLY] = S; } - - virtual SourceRange getSourceRange() const { - return SourceRange(AtTryLoc, SubStmts[TRY]->getLocEnd()); + void setFinallyStmt(Stmt *S) { + assert(HasFinally && "@try does not have a @finally slot!"); + getStmts()[1 + NumCatchStmts] = S; } + virtual SourceRange getSourceRange() const; + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtTryStmtClass; } diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index aafe963811920..f3de9fa011bc2 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -25,6 +25,7 @@ namespace llvm { namespace clang { class DependentTemplateName; +class DiagnosticBuilder; class IdentifierInfo; class NestedNameSpecifier; struct PrintingPolicy; @@ -173,6 +174,11 @@ public: } }; +/// Insertion operator for diagnostics. This allows sending TemplateName's +/// into a diagnostic with <<. +const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + TemplateName N); + /// \brief Represents a template name that was expressed as a /// qualified name. /// diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 72793651c4be9..030c74c64089a 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -871,6 +871,7 @@ public: bool isRecordType() const; bool isClassType() const; bool isStructureType() const; + bool isStructureOrClassType() const; bool isUnionType() const; bool isComplexIntegerType() const; // GCC _Complex integer type. bool isVectorType() const; // GCC vector type. @@ -922,6 +923,11 @@ public: const ObjCInterfaceType *getAsObjCQualifiedInterfaceType() const; const CXXRecordDecl *getCXXRecordDeclForPointerType() const; + /// \brief Retrieves the CXXRecordDecl that this type refers to, either + /// because the type is a RecordType or because it is the injected-class-name + /// type of a class template or class template partial specialization. + CXXRecordDecl *getAsCXXRecordDecl() const; + // Member-template getAs<specific type>'. This scheme will eventually // replace the specific getAsXXXX methods above. // @@ -2433,8 +2439,11 @@ public: class TemplateSpecializationType : public Type, public llvm::FoldingSetNode { - // FIXME: Currently needed for profiling expressions; can we avoid this? - ASTContext &Context; + // The ASTContext is currently needed in order to profile expressions. + // FIXME: avoid this. + // + // The bool is whether this is a current instantiation. + llvm::PointerIntPair<ASTContext*, 1, bool> ContextAndCurrentInstantiation; /// \brief The name of the template being specialized. TemplateName Template; @@ -2445,6 +2454,7 @@ class TemplateSpecializationType TemplateSpecializationType(ASTContext &Context, TemplateName T, + bool IsCurrentInstantiation, const TemplateArgument *Args, unsigned NumArgs, QualType Canon); @@ -2476,6 +2486,12 @@ public: static std::string PrintTemplateArgumentList(const TemplateArgumentListInfo &, const PrintingPolicy &Policy); + /// True if this template specialization type matches a current + /// instantiation in the context in which it is found. + bool isCurrentInstantiation() const { + return ContextAndCurrentInstantiation.getInt(); + } + typedef const TemplateArgument * iterator; iterator begin() const { return getArgs(); } @@ -2496,15 +2512,20 @@ public: /// \precondition @c isArgType(Arg) const TemplateArgument &getArg(unsigned Idx) const; - bool isSugared() const { return !isDependentType(); } + bool isSugared() const { + return !isDependentType() || isCurrentInstantiation(); + } QualType desugar() const { return getCanonicalTypeInternal(); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Template, getArgs(), NumArgs, Context); + Profile(ID, Template, isCurrentInstantiation(), getArgs(), NumArgs, + *ContextAndCurrentInstantiation.getPointer()); } static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T, - const TemplateArgument *Args, unsigned NumArgs, + bool IsCurrentInstantiation, + const TemplateArgument *Args, + unsigned NumArgs, ASTContext &Context); static bool classof(const Type *T) { @@ -2513,40 +2534,57 @@ public: static bool classof(const TemplateSpecializationType *T) { return true; } }; -/// \brief The injected class name of a C++ class template. Used to -/// record that a type was spelled with a bare identifier rather than -/// as a template-id; the equivalent for non-templated classes is just -/// RecordType. +/// \brief The injected class name of a C++ class template or class +/// template partial specialization. Used to record that a type was +/// spelled with a bare identifier rather than as a template-id; the +/// equivalent for non-templated classes is just RecordType. /// -/// For consistency, template instantiation turns these into RecordTypes. +/// Injected class name types are always dependent. Template +/// instantiation turns these into RecordTypes. /// -/// The desugared form is always a unqualified TemplateSpecializationType. -/// The canonical form is always either a TemplateSpecializationType -/// (when dependent) or a RecordType (otherwise). +/// Injected class name types are always canonical. This works +/// because it is impossible to compare an injected class name type +/// with the corresponding non-injected template type, for the same +/// reason that it is impossible to directly compare template +/// parameters from different dependent contexts: injected class name +/// types can only occur within the scope of a particular templated +/// declaration, and within that scope every template specialization +/// will canonicalize to the injected class name (when appropriate +/// according to the rules of the language). class InjectedClassNameType : public Type { CXXRecordDecl *Decl; - QualType UnderlyingType; + /// The template specialization which this type represents. + /// For example, in + /// template <class T> class A { ... }; + /// this is A<T>, whereas in + /// template <class X, class Y> class A<B<X,Y> > { ... }; + /// this is A<B<X,Y> >. + /// + /// It is always unqualified, always a template specialization type, + /// and always dependent. + QualType InjectedType; friend class ASTContext; // ASTContext creates these. - InjectedClassNameType(CXXRecordDecl *D, QualType TST, QualType Canon) - : Type(InjectedClassName, Canon, Canon->isDependentType()), - Decl(D), UnderlyingType(TST) { + friend class TagDecl; // TagDecl mutilates the Decl + InjectedClassNameType(CXXRecordDecl *D, QualType TST) + : Type(InjectedClassName, QualType(), true), + Decl(D), InjectedType(TST) { assert(isa<TemplateSpecializationType>(TST)); assert(!TST.hasQualifiers()); - assert(TST->getCanonicalTypeInternal() == Canon); + assert(TST->isDependentType()); } public: - QualType getUnderlyingType() const { return UnderlyingType; } - const TemplateSpecializationType *getUnderlyingTST() const { - return cast<TemplateSpecializationType>(UnderlyingType.getTypePtr()); + QualType getInjectedSpecializationType() const { return InjectedType; } + const TemplateSpecializationType *getInjectedTST() const { + return cast<TemplateSpecializationType>(InjectedType.getTypePtr()); } CXXRecordDecl *getDecl() const { return Decl; } - bool isSugared() const { return true; } - QualType desugar() const { return UnderlyingType; } + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } static bool classof(const Type *T) { return T->getTypeClass() == InjectedClassName; diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 7e8b73c7a5f97..c665073025f72 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -91,7 +91,7 @@ DEPENDENT_TYPE(TemplateTypeParm, Type) NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) NON_CANONICAL_TYPE(QualifiedName, Type) -NON_CANONICAL_TYPE(InjectedClassName, Type) +DEPENDENT_TYPE(InjectedClassName, Type) DEPENDENT_TYPE(DependentName, Type) TYPE(ObjCInterface, Type) TYPE(ObjCObjectPointer, Type) @@ -105,6 +105,8 @@ LAST_TYPE(ObjCObjectPointer) #ifdef LEAF_TYPE LEAF_TYPE(Enum) LEAF_TYPE(Builtin) +LEAF_TYPE(Record) +LEAF_TYPE(InjectedClassName) LEAF_TYPE(ObjCInterface) LEAF_TYPE(TemplateTypeParm) #undef LEAF_TYPE diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h index 553f04d76aec1..cad7e61d553cb 100644 --- a/include/clang/AST/UnresolvedSet.h +++ b/include/clang/AST/UnresolvedSet.h @@ -17,56 +17,7 @@ #include <iterator> #include "llvm/ADT/SmallVector.h" -#include "clang/Basic/Specifiers.h" - -namespace clang { - -class NamedDecl; - -/// A POD class for pairing a NamedDecl* with an access specifier. -/// Can be put into unions. -class DeclAccessPair { - NamedDecl *Ptr; // we'd use llvm::PointerUnion, but it isn't trivial - - enum { Mask = 0x3 }; - -public: - static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS) { - DeclAccessPair p; - p.set(D, AS); - return p; - } - - NamedDecl *getDecl() const { - return (NamedDecl*) (~Mask & (uintptr_t) Ptr); - } - AccessSpecifier getAccess() const { - return AccessSpecifier(Mask & (uintptr_t) Ptr); - } - - void setDecl(NamedDecl *D) { - set(D, getAccess()); - } - void setAccess(AccessSpecifier AS) { - set(getDecl(), AS); - } - void set(NamedDecl *D, AccessSpecifier AS) { - Ptr = reinterpret_cast<NamedDecl*>(uintptr_t(AS) | - reinterpret_cast<uintptr_t>(D)); - } - - operator NamedDecl*() const { return getDecl(); } - NamedDecl *operator->() const { return getDecl(); } -}; -} - -// Take a moment to tell SmallVector that this is POD. -namespace llvm { -template<typename> struct isPodLike; -template<> struct isPodLike<clang::DeclAccessPair> { - static const bool value = true; -}; -} +#include "clang/AST/DeclAccessPair.h" namespace clang { diff --git a/include/clang/AST/UsuallyTinyPtrVector.h b/include/clang/AST/UsuallyTinyPtrVector.h new file mode 100644 index 0000000000000..5ee40e05c9567 --- /dev/null +++ b/include/clang/AST/UsuallyTinyPtrVector.h @@ -0,0 +1,105 @@ +//===-- UsuallyTinyPtrVector.h - Pointer vector class -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the UsuallyTinyPtrVector class, which is a vector that +// optimizes the case where there is only one element. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_USUALLY_TINY_PTR_VECTOR_H +#define LLVM_CLANG_AST_USUALLY_TINY_PTR_VECTOR_H + +#include <vector> + +namespace clang { + +/// \brief A vector class template that is optimized for storing a single +/// pointer element. +template<typename T> +class UsuallyTinyPtrVector { + /// \brief Storage for the vector. + /// + /// When the low bit is zero, this is a T *. When the + /// low bit is one, this is a std::vector<T *> *. + mutable uintptr_t Storage; + + typedef std::vector<T*> vector_type; + +public: + UsuallyTinyPtrVector() : Storage(0) { } + explicit UsuallyTinyPtrVector(T *Element) + : Storage(reinterpret_cast<uintptr_t>(Element)) { } + + bool empty() const { return !Storage; } + + typedef const T **iterator; + iterator begin() const; + iterator end() const; + + void push_back(T *Method); + void Destroy(); +}; + +template<typename T> +typename UsuallyTinyPtrVector<T>::iterator +UsuallyTinyPtrVector<T>::begin() const { + if ((Storage & 0x01) == 0) + return reinterpret_cast<iterator>(&Storage); + + vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01); + return &Vec->front(); +} + + +template<typename T> +typename UsuallyTinyPtrVector<T>::iterator +UsuallyTinyPtrVector<T>::end() const { + if ((Storage & 0x01) == 0) { + if (Storage == 0) + return reinterpret_cast<iterator>(&Storage); + + return reinterpret_cast<iterator>(&Storage) + 1; + } + + vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01); + return &Vec->front() + Vec->size(); +} + +template<typename T> +void UsuallyTinyPtrVector<T>::push_back(T *Element) { + if (Storage == 0) { + // 0 -> 1 element. + Storage = reinterpret_cast<uintptr_t>(Element); + return; + } + + vector_type *Vec; + if ((Storage & 0x01) == 0) { + // 1 -> 2 elements. Allocate a new vector and push the element into that + // vector. + Vec = new vector_type; + Vec->push_back(reinterpret_cast<T *>(Storage)); + Storage = reinterpret_cast<uintptr_t>(Vec) | 0x01; + } else + Vec = reinterpret_cast<vector_type *>(Storage & ~0x01); + + // Add the new element to the vector. + Vec->push_back(Element); +} + +template<typename T> +void UsuallyTinyPtrVector<T>::Destroy() { + if (Storage & 0x01) + delete reinterpret_cast<vector_type *>(Storage & ~0x01); + + Storage = 0; +} + +} +#endif |