diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-14 18:03:49 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-14 18:03:49 +0000 |
commit | 4c8b24812ddcd1dedaca343a6d4e76f91f398981 (patch) | |
tree | 137ebebcae16fb0ce7ab4af456992bbd8d22fced /include/clang/AST | |
parent | 5362a71c02e7d448a8ce98cf00c47e353fba5d04 (diff) | |
download | src-4c8b24812ddcd1dedaca343a6d4e76f91f398981.tar.gz src-4c8b24812ddcd1dedaca343a6d4e76f91f398981.zip |
Update clang to r84119.vendor/clang/clang-r84119
Notes
Notes:
svn path=/vendor/clang/dist/; revision=198092
svn path=/vendor/clang/clang-84119/; revision=198093; tag=vendor/clang/clang-r84119
Diffstat (limited to 'include/clang/AST')
40 files changed, 8192 insertions, 2948 deletions
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h index 5d5abfe011d4..94d258d9e4e6 100644 --- a/include/clang/AST/APValue.h +++ b/include/clang/AST/APValue.h @@ -37,16 +37,16 @@ public: }; private: ValueKind Kind; - - struct ComplexAPSInt { - APSInt Real, Imag; + + struct ComplexAPSInt { + APSInt Real, Imag; ComplexAPSInt() : Real(1), Imag(1) {} }; struct ComplexAPFloat { APFloat Real, Imag; ComplexAPFloat() : Real(0.0), Imag(0.0) {} }; - + struct LV { Expr* Base; uint64_t Offset; @@ -57,16 +57,17 @@ private: Vec() : Elts(0), NumElts(0) {} ~Vec() { delete[] Elts; } }; - + enum { - MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ? + MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ? sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat)) }; - - /// Data - space for the largest member in units of void*. This is an effort - /// to ensure that the APSInt/APFloat values have proper alignment. - void *Data[(MaxSize+sizeof(void*)-1)/sizeof(void*)]; - + + union { + void *Aligner; + char Data[MaxSize]; + }; + public: APValue() : Kind(Uninitialized) {} explicit APValue(const APSInt &I) : Kind(Uninitialized) { @@ -93,7 +94,7 @@ public: ~APValue() { MakeUninit(); } - + ValueKind getKind() const { return Kind; } bool isUninit() const { return Kind == Uninitialized; } bool isInt() const { return Kind == Int; } @@ -102,54 +103,54 @@ public: bool isComplexFloat() const { return Kind == ComplexFloat; } bool isLValue() const { return Kind == LValue; } bool isVector() const { return Kind == Vector; } - + void print(llvm::raw_ostream &OS) const; void dump() const; - + APSInt &getInt() { assert(isInt() && "Invalid accessor"); - return *(APSInt*)(void*)Data; + return *(APSInt*)(char*)Data; } const APSInt &getInt() const { return const_cast<APValue*>(this)->getInt(); } - + APFloat &getFloat() { assert(isFloat() && "Invalid accessor"); - return *(APFloat*)(void*)Data; + return *(APFloat*)(char*)Data; } const APFloat &getFloat() const { return const_cast<APValue*>(this)->getFloat(); } - + APValue &getVectorElt(unsigned i) const { assert(isVector() && "Invalid accessor"); - return ((Vec*)(void*)Data)->Elts[i]; + return ((Vec*)(char*)Data)->Elts[i]; } unsigned getVectorLength() const { assert(isVector() && "Invalid accessor"); return ((Vec*)(void *)Data)->NumElts; } - + APSInt &getComplexIntReal() { assert(isComplexInt() && "Invalid accessor"); - return ((ComplexAPSInt*)(void*)Data)->Real; + return ((ComplexAPSInt*)(char*)Data)->Real; } const APSInt &getComplexIntReal() const { return const_cast<APValue*>(this)->getComplexIntReal(); } - + APSInt &getComplexIntImag() { assert(isComplexInt() && "Invalid accessor"); - return ((ComplexAPSInt*)(void*)Data)->Imag; + return ((ComplexAPSInt*)(char*)Data)->Imag; } const APSInt &getComplexIntImag() const { return const_cast<APValue*>(this)->getComplexIntImag(); } - + APFloat &getComplexFloatReal() { assert(isComplexFloat() && "Invalid accessor"); - return ((ComplexAPFloat*)(void*)Data)->Real; + return ((ComplexAPFloat*)(char*)Data)->Real; } const APFloat &getComplexFloatReal() const { return const_cast<APValue*>(this)->getComplexFloatReal(); @@ -157,7 +158,7 @@ public: APFloat &getComplexFloatImag() { assert(isComplexFloat() && "Invalid accessor"); - return ((ComplexAPFloat*)(void*)Data)->Imag; + return ((ComplexAPFloat*)(char*)Data)->Imag; } const APFloat &getComplexFloatImag() const { return const_cast<APValue*>(this)->getComplexFloatImag(); @@ -171,44 +172,44 @@ public: assert(isLValue() && "Invalid accessor"); return ((const LV*)(const void*)Data)->Offset; } - + void setInt(const APSInt &I) { assert(isInt() && "Invalid accessor"); - *(APSInt*)(void*)Data = I; + *(APSInt*)(char*)Data = I; } void setFloat(const APFloat &F) { assert(isFloat() && "Invalid accessor"); - *(APFloat*)(void*)Data = F; + *(APFloat*)(char*)Data = F; } void setVector(const APValue *E, unsigned N) { assert(isVector() && "Invalid accessor"); - ((Vec*)(void*)Data)->Elts = new APValue[N]; - ((Vec*)(void*)Data)->NumElts = N; + ((Vec*)(char*)Data)->Elts = new APValue[N]; + ((Vec*)(char*)Data)->NumElts = N; for (unsigned i = 0; i != N; ++i) - ((Vec*)(void*)Data)->Elts[i] = E[i]; + ((Vec*)(char*)Data)->Elts[i] = E[i]; } void setComplexInt(const APSInt &R, const APSInt &I) { - assert(R.getBitWidth() == I.getBitWidth() && + assert(R.getBitWidth() == I.getBitWidth() && "Invalid complex int (type mismatch)."); assert(isComplexInt() && "Invalid accessor"); - ((ComplexAPSInt*)(void*)Data)->Real = R; - ((ComplexAPSInt*)(void*)Data)->Imag = I; + ((ComplexAPSInt*)(char*)Data)->Real = R; + ((ComplexAPSInt*)(char*)Data)->Imag = I; } void setComplexFloat(const APFloat &R, const APFloat &I) { - assert(&R.getSemantics() == &I.getSemantics() && + assert(&R.getSemantics() == &I.getSemantics() && "Invalid complex float (type mismatch)."); assert(isComplexFloat() && "Invalid accessor"); - ((ComplexAPFloat*)(void*)Data)->Real = R; - ((ComplexAPFloat*)(void*)Data)->Imag = I; + ((ComplexAPFloat*)(char*)Data)->Real = R; + ((ComplexAPFloat*)(char*)Data)->Imag = I; } void setLValue(Expr *B, uint64_t O) { assert(isLValue() && "Invalid accessor"); - ((LV*)(void*)Data)->Base = B; - ((LV*)(void*)Data)->Offset = O; + ((LV*)(char*)Data)->Base = B; + ((LV*)(char*)Data)->Offset = O; } - + const APValue &operator=(const APValue &RHS); - + private: void MakeUninit(); void MakeInt() { @@ -218,27 +219,27 @@ private: } void MakeFloat() { assert(isUninit() && "Bad state change"); - new ((APFloat*)(void*)Data) APFloat(0.0); + new ((void*)(char*)Data) APFloat(0.0); Kind = Float; } void MakeVector() { assert(isUninit() && "Bad state change"); - new ((Vec*)(void*)Data) Vec(); + new ((void*)(char*)Data) Vec(); Kind = Vector; } void MakeComplexInt() { assert(isUninit() && "Bad state change"); - new ((ComplexAPSInt*)(void*)Data) ComplexAPSInt(); + new ((void*)(char*)Data) ComplexAPSInt(); Kind = ComplexInt; } void MakeComplexFloat() { assert(isUninit() && "Bad state change"); - new ((ComplexAPFloat*)(void*)Data) ComplexAPFloat(); + new ((void*)(char*)Data) ComplexAPFloat(); Kind = ComplexFloat; } void MakeLValue() { assert(isUninit() && "Bad state change"); - new ((LV*)(void*)Data) LV(); + new ((void*)(char*)Data) LV(); Kind = LValue; } }; @@ -247,7 +248,7 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const APValue &V) { V.print(OS); return OS; } - + } // end namespace clang. #endif diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index 6dc7e13d8f70..af6bf30b6882 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -36,27 +36,27 @@ public: ASTConsumer() : SemaConsumer(false) { } virtual ~ASTConsumer() {} - + /// Initialize - This is called to initialize the consumer, providing the /// ASTContext and the Action. virtual void Initialize(ASTContext &Context) {} - + /// HandleTopLevelDecl - Handle the specified top-level declaration. This is /// called by the parser to process every top-level Decl*. Note that D can /// be the head of a chain of Decls (e.g. for `int a, b` the chain will have /// two elements). Use Decl::getNextDeclarator() to walk the chain. virtual void HandleTopLevelDecl(DeclGroupRef D); - + /// HandleTranslationUnit - This method is called when the ASTs for entire /// translation unit have been parsed. - virtual void HandleTranslationUnit(ASTContext &Ctx) {} - + virtual void HandleTranslationUnit(ASTContext &Ctx) {} + /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl /// (e.g. struct, union, enum, class) is completed. This allows the client to /// hack on the type, which can occur at any point in the file (because these /// can be defined in declspecs). virtual void HandleTagDeclDefinition(TagDecl *D) {} - + /// \brief Callback invoked at the end of a translation unit to /// notify the consumer that the given tentative definition should /// be completed. diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 041a0f33ad4d..63f909146e92 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -22,6 +22,7 @@ #include "clang/AST/PrettyPrinter.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" +#include "clang/AST/CanonicalType.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/OwningPtr.h" @@ -43,24 +44,26 @@ namespace clang { class TargetInfo; // Decls class Decl; + class FieldDecl; + class ObjCIvarDecl; + class ObjCIvarRefExpr; class ObjCPropertyDecl; class RecordDecl; class TagDecl; + class TemplateTypeParmDecl; class TranslationUnitDecl; class TypeDecl; class TypedefDecl; - class TemplateTypeParmDecl; - class FieldDecl; - class ObjCIvarRefExpr; - class ObjCIvarDecl; - + class UnresolvedUsingDecl; + class UsingDecl; + namespace Builtin { class Context; } - + /// 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 { +class ASTContext { std::vector<Type*> Types; - llvm::FoldingSet<ExtQualType> ExtQualTypes; + llvm::FoldingSet<ExtQuals> ExtQualNodes; llvm::FoldingSet<ComplexType> ComplexTypes; llvm::FoldingSet<PointerType> PointerTypes; llvm::FoldingSet<BlockPointerType> BlockPointerTypes; @@ -70,17 +73,21 @@ class ASTContext { llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes; llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes; std::vector<VariableArrayType*> VariableArrayTypes; - std::vector<DependentSizedArrayType*> DependentSizedArrayTypes; - std::vector<DependentSizedExtVectorType*> DependentSizedExtVectorTypes; + llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes; + llvm::FoldingSet<DependentSizedExtVectorType> DependentSizedExtVectorTypes; llvm::FoldingSet<VectorType> VectorTypes; llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes; llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes; + llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes; + llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes; llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes; llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes; llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes; llvm::FoldingSet<TypenameType> TypenameTypes; - llvm::FoldingSet<ObjCQualifiedInterfaceType> ObjCQualifiedInterfaceTypes; + llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes; llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; + llvm::FoldingSet<ObjCProtocolListType> ObjCProtocolListTypes; + llvm::FoldingSet<ElaboratedType> ElaboratedTypes; llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; @@ -97,46 +104,109 @@ class ASTContext { llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts; llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*> ObjCLayouts; + /// \brief Mapping from ObjCContainers to their ObjCImplementations. + llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls; + llvm::DenseMap<unsigned, FixedWidthIntType*> SignedFixedWidthIntTypes; llvm::DenseMap<unsigned, FixedWidthIntType*> UnsignedFixedWidthIntTypes; - + /// BuiltinVaListType - built-in va list type. /// This is initially null and set by Sema::LazilyCreateBuiltin when /// a builtin that takes a valist is encountered. QualType BuiltinVaListType; /// ObjCIdType - a pseudo built-in typedef type (set by Sema). - QualType ObjCIdType; - const RecordType *IdStructType; - + QualType ObjCIdTypedefType; + /// ObjCSelType - another pseudo built-in typedef type (set by Sema). QualType ObjCSelType; const RecordType *SelStructType; - + /// ObjCProtoType - another pseudo built-in typedef type (set by Sema). QualType ObjCProtoType; const RecordType *ProtoStructType; /// ObjCClassType - another pseudo built-in typedef type (set by Sema). - QualType ObjCClassType; - const RecordType *ClassStructType; - + QualType ObjCClassTypedefType; + QualType ObjCConstantStringType; RecordDecl *CFConstantStringTypeDecl; RecordDecl *ObjCFastEnumerationStateTypeDecl; - - /// \brief Keeps track of all declaration attributes. + + /// \brief The type for the C FILE type. + TypeDecl *FILEDecl; + + /// \brief The type for the C jmp_buf type. + TypeDecl *jmp_bufDecl; + + /// \brief The type for the C sigjmp_buf type. + TypeDecl *sigjmp_bufDecl; + + /// \brief Keeps track of all declaration attributes. /// /// Since so few decls have attrs, we keep them in a hash map instead of /// wasting space in the Decl class. llvm::DenseMap<const Decl*, Attr*> DeclAttrs; - + + /// \brief Keeps track of the static data member templates from which + /// static data members of class template specializations were instantiated. + /// + /// This data structure stores the mapping from instantiations of static + /// data members to the static data member representations within the + /// class template from which they were instantiated along with the kind + /// of instantiation or specialization (a TemplateSpecializationKind - 1). + /// + /// Given the following example: + /// + /// \code + /// template<typename T> + /// struct X { + /// static T value; + /// }; + /// + /// template<typename T> + /// T X<T>::value = T(17); + /// + /// int *x = &X<int>::value; + /// \endcode + /// + /// This mapping will contain an entry that maps from the VarDecl for + /// X<int>::value to the corresponding VarDecl for X<T>::value (within the + /// class template X) and will be marked TSK_ImplicitInstantiation. + llvm::DenseMap<VarDecl *, MemberSpecializationInfo *> + InstantiatedFromStaticDataMember; + + /// \brief Keeps track of the UnresolvedUsingDecls from which UsingDecls + /// where created during instantiation. + /// + /// For example: + /// \code + /// template<typename T> + /// struct A { + /// void f(); + /// }; + /// + /// template<typename T> + /// struct B : A<T> { + /// using A<T>::f; + /// }; + /// + /// template struct B<int>; + /// \endcode + /// + /// This mapping will contain an entry that maps from the UsingDecl in + /// B<int> to the UnresolvedUsingDecl in B<T>. + llvm::DenseMap<UsingDecl *, UnresolvedUsingDecl *> + InstantiatedFromUnresolvedUsingDecl; + + llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl; + TranslationUnitDecl *TUDecl; /// SourceMgr - The associated SourceManager object. SourceManager &SourceMgr; - + /// LangOpts - The language options used to create the AST associated with /// this ASTContext object. LangOptions LangOpts; @@ -144,17 +214,17 @@ class ASTContext { /// \brief Whether we have already loaded comment source ranges from an /// external source. bool LoadedExternalComments; - + /// MallocAlloc/BumpAlloc - The allocator objects used to create AST objects. bool FreeMemory; llvm::MallocAllocator MallocAlloc; llvm::BumpPtrAllocator BumpAlloc; - + /// \brief Mapping from declarations to their comments, once we have /// already looked up the comment associated with a given declaration. llvm::DenseMap<const Decl *, std::string> DeclComments; - -public: + +public: TargetInfo &Target; IdentifierTable &Idents; SelectorTable &Selectors; @@ -163,41 +233,73 @@ public: llvm::OwningPtr<ExternalASTSource> ExternalSource; clang::PrintingPolicy PrintingPolicy; + // Typedefs which may be provided defining the structure of Objective-C + // pseudo-builtins + QualType ObjCIdRedefinitionType; + QualType ObjCClassRedefinitionType; + /// \brief Source ranges for all of the comments in the source file, /// sorted in order of appearance in the translation unit. std::vector<SourceRange> Comments; - + SourceManager& getSourceManager() { return SourceMgr; } const SourceManager& getSourceManager() const { return SourceMgr; } void *Allocate(unsigned Size, unsigned Align = 8) { return FreeMemory ? MallocAlloc.Allocate(Size, Align) : BumpAlloc.Allocate(Size, Align); } - void Deallocate(void *Ptr) { + void Deallocate(void *Ptr) { if (FreeMemory) - MallocAlloc.Deallocate(Ptr); + MallocAlloc.Deallocate(Ptr); } const LangOptions& getLangOptions() const { return LangOpts; } - - FullSourceLoc getFullLoc(SourceLocation Loc) const { + + FullSourceLoc getFullLoc(SourceLocation Loc) const { return FullSourceLoc(Loc,SourceMgr); } /// \brief Retrieve the attributes for the given declaration. Attr*& getDeclAttrs(const Decl *D) { return DeclAttrs[D]; } - + /// \brief Erase the attributes corresponding to the given declaration. void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); } - + + /// \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. + MemberSpecializationInfo *getInstantiatedFromStaticDataMember(VarDecl *Var); + + /// \brief Note that the static data member \p Inst is an instantiation of + /// the static data member template \p Tmpl of a class template. + void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, + TemplateSpecializationKind TSK); + + /// \brief If this using decl is instantiated from an unresolved using decl, + /// return it. + UnresolvedUsingDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD); + + /// \brief Note that the using decl \p Inst is an instantiation of + /// the unresolved using decl \p Tmpl of a class template. + void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst, + UnresolvedUsingDecl *Tmpl); + + + FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field); + + void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl); + TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } + const char *getCommentForDecl(const Decl *D); - + // Builtin Types. QualType VoidTy; QualType BoolTy; QualType CharTy; - QualType WCharTy; // [C++ 3.9.1p5], integer type in C99. + QualType WCharTy; // [C++ 3.9.1p5], integer type in C99. + QualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99. + QualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99. QualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty; QualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy; QualType UnsignedLongLongTy, UnsignedInt128Ty; @@ -207,6 +309,7 @@ public: QualType OverloadTy; QualType DependentTy; QualType UndeducedAutoTy; + QualType ObjCBuiltinIdTy, ObjCBuiltinClassTy; ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, @@ -232,23 +335,52 @@ public: //===--------------------------------------------------------------------===// // Type Constructors //===--------------------------------------------------------------------===// - - /// getAddSpaceQualType - Return the uniqued reference to the type for an - /// address space qualified type with the specified type and address space. - /// The resulting type has a union of the qualifiers from T and the address - /// space. If T already has an address space specifier, it is silently + +private: + /// getExtQualType - Return a type with extended qualifiers. + QualType getExtQualType(const Type *Base, Qualifiers Quals); + +public: + /// getAddSpaceQualType - Return the uniqued reference to the type for an + /// address space qualified type with the specified type and address space. + /// The resulting type has a union of the qualifiers from T and the address + /// space. If T already has an address space specifier, it is silently /// replaced. QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace); - + /// getObjCGCQualType - Returns the uniqued reference to the type for an /// objc gc qualified type. The retulting type has a union of the qualifiers /// from T and the gc attribute. - QualType getObjCGCQualType(QualType T, QualType::GCAttrTypes gcAttr); - + QualType getObjCGCQualType(QualType T, Qualifiers::GC gcAttr); + + /// getRestrictType - Returns the uniqued reference to the type for a + /// 'restrict' qualified type. The resulting type has a union of the + /// qualifiers from T and 'restrict'. + QualType getRestrictType(QualType T) { + return T.withFastQualifiers(Qualifiers::Restrict); + } + + /// getVolatileType - Returns the uniqued reference to the type for a + /// 'volatile' qualified type. The resulting type has a union of the + /// qualifiers from T and 'volatile'. + QualType getVolatileType(QualType T); + + /// getConstType - Returns the uniqued reference to the type for a + /// 'const' qualified type. The resulting type has a union of the + /// qualifiers from T and 'const'. + /// + /// It can be reasonably expected that this will always be + /// equivalent to calling T.withConst(). + QualType getConstType(QualType T) { return T.withConst(); } + + /// getNoReturnType - Add the noreturn attribute to the given type which must + /// be a FunctionType or a pointer to an allowable type or a BlockPointer. + QualType getNoReturnType(QualType T); + /// getComplexType - Return the uniqued reference to the type for a complex /// number with the specified element type. QualType getComplexType(QualType T); - + /// getPointerType - Return the uniqued reference to the type for a pointer to /// the specified type. QualType getPointerType(QualType T); @@ -274,15 +406,17 @@ public: /// variable array of the specified element type. QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArrayType::ArraySizeModifier ASM, - unsigned EltTypeQuals); - + unsigned EltTypeQuals, + SourceRange Brackets); + /// getDependentSizedArrayType - Returns a non-unique reference to /// the type for a dependently-sized array of the specified element /// type. FIXME: We will need these to be uniqued, or at least /// comparable, at some point. QualType getDependentSizedArrayType(QualType EltTy, Expr *NumElts, ArrayType::ArraySizeModifier ASM, - unsigned EltTypeQuals); + unsigned EltTypeQuals, + SourceRange Brackets); /// getIncompleteArrayType - Returns a unique reference to the type for a /// incomplete array of the specified element type. @@ -295,7 +429,23 @@ public: QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, ArrayType::ArraySizeModifier ASM, unsigned EltTypeQuals); - + + /// getConstantArrayWithExprType - Return a reference to the type for a + /// constant array of the specified element type. + QualType getConstantArrayWithExprType(QualType EltTy, + const llvm::APInt &ArySize, + Expr *ArySizeExpr, + ArrayType::ArraySizeModifier ASM, + unsigned EltTypeQuals, + SourceRange Brackets); + + /// getConstantArrayWithoutExprType - Return a reference to the type + /// for a constant array of the specified element type. + QualType getConstantArrayWithoutExprType(QualType EltTy, + const llvm::APInt &ArySize, + ArrayType::ArraySizeModifier ASM, + unsigned EltTypeQuals); + /// getVectorType - Return the unique reference to a vector type of /// the specified element type and size. VectorType must be a built-in type. QualType getVectorType(QualType VectorType, unsigned NumElts); @@ -309,13 +459,13 @@ public: /// the type for a dependently-sized vector of the specified element /// type. FIXME: We will need these to be uniqued, or at least /// comparable, at some point. - QualType getDependentSizedExtVectorType(QualType VectorType, + QualType getDependentSizedExtVectorType(QualType VectorType, Expr *SizeExpr, SourceLocation AttrLoc); /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'. /// - QualType getFunctionNoProtoType(QualType ResultTy); + QualType getFunctionNoProtoType(QualType ResultTy, bool NoReturn = false); /// getFunctionType - Return a normal function type with a typed argument /// list. isVariadic indicates whether the argument list includes '...'. @@ -323,7 +473,8 @@ public: unsigned NumArgs, bool isVariadic, unsigned TypeQuals, bool hasExceptionSpec = false, bool hasAnyExceptionSpec = false, - unsigned NumExs = 0, const QualType *ExArray = 0); + unsigned NumExs = 0, const QualType *ExArray = 0, + bool NoReturn = false); /// getTypeDeclType - Return the unique reference to the type for /// the specified type declaration. @@ -332,9 +483,8 @@ public: /// getTypedefType - Return the unique reference to the type for the /// specified typename decl. QualType getTypedefType(TypedefDecl *Decl); - QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl); - QualType getTemplateTypeParmType(unsigned Depth, unsigned Index, + QualType getTemplateTypeParmType(unsigned Depth, unsigned Index, bool ParameterPack, IdentifierInfo *Name = 0); @@ -345,37 +495,40 @@ public: QualType getQualifiedNameType(NestedNameSpecifier *NNS, QualType NamedType); - QualType getTypenameType(NestedNameSpecifier *NNS, + QualType getTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo *Name, QualType Canon = QualType()); - QualType getTypenameType(NestedNameSpecifier *NNS, + QualType getTypenameType(NestedNameSpecifier *NNS, const TemplateSpecializationType *TemplateId, QualType Canon = QualType()); + QualType getElaboratedType(QualType UnderlyingType, + ElaboratedType::TagKind Tag); + + QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, + ObjCProtocolDecl **Protocols = 0, + unsigned NumProtocols = 0); /// getObjCObjectPointerType - Return a ObjCObjectPointerType type for the /// given interface decl and the conforming protocol list. - QualType getObjCObjectPointerType(ObjCInterfaceDecl *Decl, + QualType getObjCObjectPointerType(QualType OIT, ObjCProtocolDecl **ProtocolList = 0, unsigned NumProtocols = 0); - - /// getObjCQualifiedInterfaceType - Return a - /// ObjCQualifiedInterfaceType type for the given interface decl and - /// the conforming protocol list. - QualType getObjCQualifiedInterfaceType(ObjCInterfaceDecl *Decl, - ObjCProtocolDecl **ProtocolList, - unsigned NumProtocols); - + + QualType getObjCProtocolListType(QualType T, + ObjCProtocolDecl **Protocols, + unsigned NumProtocols); + /// getTypeOfType - GCC extension. QualType getTypeOfExprType(Expr *e); QualType getTypeOfType(QualType t); - + /// getDecltypeType - C++0x decltype. QualType getDecltypeType(Expr *e); - + /// getTagDeclType - Return the unique reference to the type for the /// specified TagDecl (struct/union/class/enum) decl. - QualType getTagDeclType(TagDecl *Decl); - + QualType getTagDeclType(const TagDecl *Decl); + /// getSizeType - Return the unique type for "size_t" (C99 7.17), defined /// in <stddef.h>. The sizeof operator requires this (C99 6.5.3.4p4). QualType getSizeType() const; @@ -392,15 +545,15 @@ public: /// getUnsignedWCharType - Return the type of "unsigned wchar_t". /// Used when in C++, as a GCC extension. QualType getUnsignedWCharType() const; - + /// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?) /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9). QualType getPointerDiffType() const; - + // getCFConstantStringType - Return the C structure type used to represent // constant CFStrings. - QualType getCFConstantStringType(); - + QualType getCFConstantStringType(); + /// Get the structure type used to representation CFStrings, or NULL /// if it hasn't yet been built. QualType getRawCFConstantStringType() { @@ -412,13 +565,13 @@ public: // This setter/getter represents the ObjC type for an NSConstantString. void setObjCConstantStringInterface(ObjCInterfaceDecl *Decl); - QualType getObjCConstantStringInterface() const { - return ObjCConstantStringType; + QualType getObjCConstantStringInterface() const { + return ObjCConstantStringType; } //// This gets the struct used to keep track of fast enumerations. QualType getObjCFastEnumerationStateType(); - + /// Get the ObjCFastEnumerationState type, or NULL if it hasn't yet /// been built. QualType getRawObjCFastEnumerationStateType() { @@ -429,109 +582,166 @@ public: void setObjCFastEnumerationStateType(QualType T); + /// \brief Set the type for the C FILE type. + void setFILEDecl(TypeDecl *FILEDecl) { this->FILEDecl = FILEDecl; } + + /// \brief Retrieve the C FILE type. + QualType getFILEType() { + if (FILEDecl) + return getTypeDeclType(FILEDecl); + return QualType(); + } + + /// \brief Set the type for the C jmp_buf type. + void setjmp_bufDecl(TypeDecl *jmp_bufDecl) { + this->jmp_bufDecl = jmp_bufDecl; + } + + /// \brief Retrieve the C jmp_buf type. + QualType getjmp_bufType() { + if (jmp_bufDecl) + return getTypeDeclType(jmp_bufDecl); + return QualType(); + } + + /// \brief Set the type for the C sigjmp_buf type. + void setsigjmp_bufDecl(TypeDecl *sigjmp_bufDecl) { + this->sigjmp_bufDecl = sigjmp_bufDecl; + } + + /// \brief Retrieve the C sigjmp_buf type. + QualType getsigjmp_bufType() { + if (sigjmp_bufDecl) + return getTypeDeclType(sigjmp_bufDecl); + return QualType(); + } + /// getObjCEncodingForType - Emit the ObjC type encoding for the /// given type into \arg S. If \arg NameFields is specified then /// record field names are also encoded. - void getObjCEncodingForType(QualType t, std::string &S, + void getObjCEncodingForType(QualType t, std::string &S, const FieldDecl *Field=0); void getLegacyIntegralTypeEncoding(QualType &t) const; - + // Put the string version of type qualifiers into S. - void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT, + void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT, std::string &S) const; - + /// getObjCEncodingForMethodDecl - Return the encoded type for this method /// declaration. void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S); - + /// getObjCEncodingForPropertyDecl - Return the encoded type for /// this method declaration. If non-NULL, Container must be either /// an ObjCCategoryImplDecl or ObjCImplementationDecl; it should /// only be NULL when getting encodings for protocol properties. - void getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, + void getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, const Decl *Container, std::string &S); - + + bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, + ObjCProtocolDecl *rProto); + /// getObjCEncodingTypeSize returns size of type for objective-c encoding /// purpose. int getObjCEncodingTypeSize(QualType t); /// This setter/getter represents the ObjC 'id' type. It is setup lazily, by /// Sema. id is always a (typedef for a) pointer type, a pointer to a struct. - QualType getObjCIdType() const { return ObjCIdType; } + QualType getObjCIdType() const { return ObjCIdTypedefType; } void setObjCIdType(QualType T); - + void setObjCSelType(QualType T); QualType getObjCSelType() const { return ObjCSelType; } - + void setObjCProtoType(QualType QT); QualType getObjCProtoType() const { return ObjCProtoType; } - + /// This setter/getter repreents the ObjC 'Class' type. It is setup lazily, by /// Sema. 'Class' is always a (typedef for a) pointer type, a pointer to a /// struct. - QualType getObjCClassType() const { return ObjCClassType; } + QualType getObjCClassType() const { return ObjCClassTypedefType; } void setObjCClassType(QualType T); - + void setBuiltinVaListType(QualType T); QualType getBuiltinVaListType() const { return BuiltinVaListType; } QualType getFixedWidthIntType(unsigned Width, bool Signed); - TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, + /// getCVRQualifiedType - Returns a type with additional const, + /// volatile, or restrict qualifiers. + QualType getCVRQualifiedType(QualType T, unsigned CVR) { + return getQualifiedType(T, Qualifiers::fromCVRMask(CVR)); + } + + /// getQualifiedType - Returns a type with additional qualifiers. + QualType getQualifiedType(QualType T, Qualifiers Qs) { + if (!Qs.hasNonFastQualifiers()) + return T.withFastQualifiers(Qs.getFastQualifiers()); + QualifierCollector Qc(Qs); + const Type *Ptr = Qc.strip(T); + return getExtQualType(Ptr, Qc); + } + + /// getQualifiedType - Returns a type with additional qualifiers. + QualType getQualifiedType(const Type *T, Qualifiers Qs) { + if (!Qs.hasNonFastQualifiers()) + return QualType(T, Qs.getFastQualifiers()); + return getExtQualType(T, Qs); + } + + TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, TemplateDecl *Template); + TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, + bool TemplateKeyword, + OverloadedFunctionDecl *Template); - TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, + TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, const IdentifierInfo *Name); enum GetBuiltinTypeError { - GE_None, //< No error - GE_Missing_FILE //< Missing the FILE type from <stdio.h> + GE_None, //< No error + GE_Missing_stdio, //< Missing a type from <stdio.h> + GE_Missing_setjmp //< Missing a type from <setjmp.h> }; - + /// GetBuiltinType - Return the type for the specified builtin. QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error); - + private: QualType getFromTargetType(unsigned Type) const; //===--------------------------------------------------------------------===// // Type Predicates. //===--------------------------------------------------------------------===// - -public: - /// isObjCObjectPointerType - Returns true if type is an Objective-C pointer - /// to an object type. This includes "id" and "Class" (two 'special' pointers - /// to struct), Interface* (pointer to ObjCInterfaceType) and id<P> (qualified - /// ID type). - bool isObjCObjectPointerType(QualType Ty) const; +public: /// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's /// garbage collection attribute. /// - QualType::GCAttrTypes getObjCGCAttrKind(const QualType &Ty) const; - + Qualifiers::GC getObjCGCAttrKind(const QualType &Ty) const; + /// isObjCNSObjectType - Return true if this is an NSObject object with /// its NSObject attribute set. bool isObjCNSObjectType(QualType Ty) const; - + //===--------------------------------------------------------------------===// // Type Sizing and Analysis //===--------------------------------------------------------------------===// - + /// getFloatTypeSemantics - Return the APFloat 'semantics' for the specified /// scalar floating point type. const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const; - + /// getTypeInfo - Get the size and alignment of the specified complete type in /// bits. std::pair<uint64_t, unsigned> getTypeInfo(const Type *T); std::pair<uint64_t, unsigned> getTypeInfo(QualType T) { return getTypeInfo(T.getTypePtr()); } - + /// getTypeSize - Return the size of the specified type, in bits. This method /// does not work on incomplete types. uint64_t getTypeSize(QualType T) { @@ -540,7 +750,7 @@ public: uint64_t getTypeSize(const Type *T) { return getTypeInfo(T).first; } - + /// getTypeAlign - Return the ABI-specified alignment of a type, in bits. /// This method does not work on incomplete types. unsigned getTypeAlign(QualType T) { @@ -549,23 +759,23 @@ public: unsigned getTypeAlign(const Type *T) { return getTypeInfo(T).second; } - + /// getPreferredTypeAlign - Return the "preferred" alignment of the specified /// type for the current target in bits. This can be different than the ABI /// alignment in cases where it is beneficial for performance to overalign /// a data type. unsigned getPreferredTypeAlign(const Type *T); - + /// getDeclAlignInBytes - Return the alignment of the specified decl /// that should be returned by __alignof(). Note that bitfields do /// not have a valid alignment, so this method will assert on them. unsigned getDeclAlignInBytes(const Decl *D); - + /// getASTRecordLayout - Get or compute information about the layout of the /// specified record (struct/union/class), which indicates its size and field /// position information. const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D); - + /// getASTObjCInterfaceLayout - Get or compute information about the /// layout of the specified Objective-C interface. const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D); @@ -592,14 +802,14 @@ public: //===--------------------------------------------------------------------===// // Type Operators //===--------------------------------------------------------------------===// - + /// getCanonicalType - Return the canonical (structural) type corresponding to /// the specified potentially non-canonical type. The non-canonical version /// of a type may have many "decorated" versions of types. Decorators can /// include typedefs, 'typeof' operators, etc. The returned type is guaranteed /// to be free of any of these, allowing two canonical types to be compared /// for exact equality with a simple pointer comparison. - QualType getCanonicalType(QualType T); + CanQualType getCanonicalType(QualType T); const Type *getCanonicalType(const Type *T) { return T->getCanonicalTypeInternal().getTypePtr(); } @@ -608,7 +818,7 @@ public: bool hasSameType(QualType T1, QualType T2) { return getCanonicalType(T1) == getCanonicalType(T2); } - + /// \brief Determine whether the given types are equivalent after /// cvr-qualifiers have been removed. bool hasSameUnqualifiedType(QualType T1, QualType T2) { @@ -617,20 +827,7 @@ public: return T1.getUnqualifiedType() == T2.getUnqualifiedType(); } - /// \brief Retrieves the "canonical" declaration of the given declaration. - Decl *getCanonicalDecl(Decl *D); - - /// \brief Retrieves the "canonical" declaration of the given tag - /// declaration. - /// - /// The canonical declaration for the given tag declaration is - /// either the definition of the tag (if it is a complete type) or - /// the first declaration of that tag. - TagDecl *getCanonicalDecl(TagDecl *Tag) { - return cast<TagDecl>(getCanonicalDecl((Decl *)Tag)); - } - - /// \brief Retrieves the "canonical" declaration of + /// \brief Retrieves the "canonical" declaration of /// \brief Retrieves the "canonical" nested name specifier for a /// given nested name specifier. @@ -678,6 +875,13 @@ public: /// types, values, and templates. TemplateName getCanonicalTemplateName(TemplateName Name); + /// \brief Retrieve the "canonical" template argument. + /// + /// The canonical template argument is the simplest template argument + /// (which may be a type, value, expression, or declaration) that + /// expresses the value of the argument. + TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg); + /// Type Query functions. If the type is an instance of the specified class, /// return the Type pointer for the underlying maximally pretty type. This /// is a member of ASTContext because this may need to do some amount of @@ -693,10 +897,17 @@ public: return dyn_cast_or_null<IncompleteArrayType>(getAsArrayType(T)); } - /// getBaseElementType - Returns the innermost element type of a variable - /// length array type. For example, will return "int" for int[m][n] - QualType getBaseElementType(const VariableArrayType *VAT); - + /// getBaseElementType - Returns the innermost element type of an array type. + /// For example, will return "int" for int[m][n] + QualType getBaseElementType(const ArrayType *VAT); + + /// getBaseElementType - Returns the innermost element type of a type + /// (which needn't actually be an array type). + QualType getBaseElementType(QualType QT); + + /// getConstantArrayElementCount - Returns number of constant array elements. + uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const; + /// getArrayDecayedType - Return the properly qualified result of decaying the /// specified array type to a pointer. This operation is non-trivial when /// handling typedefs etc. The canonical type of "T" must be an array type, @@ -704,23 +915,35 @@ public: /// /// See C99 6.7.5.3p7 and C99 6.3.2.1p3. QualType getArrayDecayedType(QualType T); - - /// getIntegerTypeOrder - Returns the highest ranked integer type: + + /// getPromotedIntegerType - Returns the type that Promotable will + /// promote to: C99 6.3.1.1p2, assuming that Promotable is a promotable + /// integer type. + QualType getPromotedIntegerType(QualType PromotableType); + + /// \brief Whether this is a promotable bitfield reference according + /// to C99 6.3.1.1p2, bullet 2 (and GCC extensions). + /// + /// \returns the type this bit-field will promote to, or NULL if no + /// promotion occurs. + QualType isPromotableBitField(Expr *E); + + /// getIntegerTypeOrder - Returns the highest ranked integer type: /// C99 6.3.1.8p1. If LHS > RHS, return 1. If LHS == RHS, return 0. If - /// LHS < RHS, return -1. + /// LHS < RHS, return -1. int getIntegerTypeOrder(QualType LHS, QualType RHS); - + /// getFloatingTypeOrder - Compare the rank of the two specified floating /// point types, ignoring the domain of the type (i.e. 'double' == /// '_Complex double'). If LHS > RHS, return 1. If LHS == RHS, return 0. If - /// LHS < RHS, return -1. + /// LHS < RHS, return -1. int getFloatingTypeOrder(QualType LHS, QualType RHS); - /// getFloatingTypeOfSizeWithinDomain - Returns a real floating - /// point or a complex type (based on typeDomain/typeSize). + /// getFloatingTypeOfSizeWithinDomain - Returns a real floating + /// point or a complex type (based on typeDomain/typeSize). /// 'typeDomain' is a real floating point or complex type. /// 'typeSize' is a real floating point or complex type. - QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize, + QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize, QualType typeDomain) const; private: @@ -732,33 +955,28 @@ public: //===--------------------------------------------------------------------===// // Type Compatibility Predicates //===--------------------------------------------------------------------===// - + /// Compatibility predicates used to check assignment expressions. bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1 - + bool isObjCIdType(QualType T) const { - return T == ObjCIdType; - } - bool isObjCIdStructType(QualType T) const { - if (!IdStructType) // ObjC isn't enabled - return false; - return T->getAsStructureType() == IdStructType; + return T == ObjCIdTypedefType; } bool isObjCClassType(QualType T) const { - return T == ObjCClassType; - } - bool isObjCClassStructType(QualType T) const { - if (!ClassStructType) // ObjC isn't enabled - return false; - return T->getAsStructureType() == ClassStructType; + return T == ObjCClassTypedefType; } bool isObjCSelType(QualType T) const { assert(SelStructType && "isObjCSelType used before 'SEL' type is built"); return T->getAsStructureType() == SelStructType; } + bool QualifiedIdConformsQualifiedId(QualType LHS, QualType RHS); + bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS, + bool ForCompare); // Check the safety of assignment from LHS to RHS - bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS, + bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, + const ObjCObjectPointerType *RHSOPT); + bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS, const ObjCInterfaceType *RHS); bool areComparableObjCPointerTypes(QualType LHS, QualType RHS); @@ -766,6 +984,11 @@ public: QualType mergeTypes(QualType, QualType); QualType mergeFunctionTypes(QualType, QualType); + /// UsualArithmeticConversionsType - handles the various conversions + /// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9) + /// and returns the result type of that conversion. + QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs); + //===--------------------------------------------------------------------===// // Integer Predicates //===--------------------------------------------------------------------===// @@ -782,15 +1005,15 @@ public: //===--------------------------------------------------------------------===// // Type Iterators. //===--------------------------------------------------------------------===// - + typedef std::vector<Type*>::iterator type_iterator; typedef std::vector<Type*>::const_iterator const_type_iterator; - + type_iterator types_begin() { return Types.begin(); } type_iterator types_end() { return Types.end(); } const_type_iterator types_begin() const { return Types.begin(); } - const_type_iterator types_end() const { return Types.end(); } - + const_type_iterator types_end() const { return Types.end(); } + //===--------------------------------------------------------------------===// // Integer Values //===--------------------------------------------------------------------===// @@ -803,15 +1026,37 @@ public: return Res; } + /// \brief Get the implementation of ObjCInterfaceDecl,or NULL if none exists. + ObjCImplementationDecl *getObjCImplementation(ObjCInterfaceDecl *D); + /// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists. + ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D); + + /// \brief Set the implementation of ObjCInterfaceDecl. + void setObjCImplementation(ObjCInterfaceDecl *IFaceD, + ObjCImplementationDecl *ImplD); + /// \brief Set the implementation of ObjCCategoryDecl. + void setObjCImplementation(ObjCCategoryDecl *CatD, + ObjCCategoryImplDecl *ImplD); + + /// \brief Allocate an uninitialized DeclaratorInfo. + /// + /// The caller should initialize the memory held by DeclaratorInfo using + /// the TypeLoc wrappers. + /// + /// \param T the type that will be the basis for type source info. This type + /// should refer to how the declarator was written in source code, not to + /// what type semantic analysis resolved the declarator to. + DeclaratorInfo *CreateDeclaratorInfo(QualType T); + private: ASTContext(const ASTContext&); // DO NOT IMPLEMENT void operator=(const ASTContext&); // DO NOT IMPLEMENT - + void InitBuiltinTypes(); void InitBuiltinType(QualType &R, BuiltinType::Kind K); - + // Return the ObjC type encoding for a given type. - void getObjCEncodingForTypeImpl(QualType t, std::string &S, + void getObjCEncodingForTypeImpl(QualType t, std::string &S, bool ExpandPointedToStructures, bool ExpandStructures, const FieldDecl *Field, @@ -819,7 +1064,7 @@ private: bool EncodingProperty = false); const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D, - const ObjCImplementationDecl *Impl); + const ObjCImplementationDecl *Impl); }; } // end namespace clang diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h index e9f150574b05..abd36f7e5f0f 100644 --- a/include/clang/AST/ASTDiagnostic.h +++ b/include/clang/AST/ASTDiagnostic.h @@ -13,7 +13,7 @@ #include "clang/Basic/Diagnostic.h" namespace clang { - namespace diag { + namespace diag { enum { #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM, #define ASTSTART diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 7d3009b01129..6a5e3666a92c 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -14,6 +14,9 @@ #ifndef LLVM_CLANG_AST_ATTR_H #define LLVM_CLANG_AST_ATTR_H +#include "llvm/Support/Casting.h" +using llvm::dyn_cast; + #include <cassert> #include <cstring> #include <string> @@ -54,22 +57,24 @@ public: DLLImport, Deprecated, Destructor, - FastCall, + FastCall, Format, FormatArg, GNUInline, IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict with + Malloc, + NoDebug, + NoInline, + NonNull, NoReturn, NoThrow, - Nodebug, - Noinline, - NonNull, ObjCException, ObjCNSObject, CFReturnsRetained, // Clang/Checker-specific. NSReturnsRetained, // Clang/Checker-specific. Overloadable, // Clang-specific Packed, + PragmaPack, Pure, Regparm, ReqdWorkGroupSize, // OpenCL-specific @@ -78,14 +83,14 @@ public: StdCall, TransparentUnion, Unavailable, - Unused, + Unused, Used, Visibility, WarnUnusedResult, Weak, WeakImport }; - + private: Attr *Next; Kind AttrKind; @@ -99,16 +104,16 @@ protected: void operator delete(void* data) throw() { assert(0 && "Attrs cannot be released with regular 'delete'."); } - + protected: Attr(Kind AK) : Next(0), AttrKind(AK), Inherited(false) {} virtual ~Attr() { assert(Next == 0 && "Destroy didn't work"); } public: - + void Destroy(ASTContext &C); - + /// \brief Whether this attribute should be merged to new /// declarations. virtual bool isMerged() const { return true; } @@ -119,17 +124,24 @@ public: const Attr *getNext() const { return Next; } void setNext(Attr *next) { Next = next; } + template<typename T> const T *getNext() const { + for (const Attr *attr = getNext(); attr; attr = attr->getNext()) + if (const T *V = dyn_cast<T>(attr)) + return V; + return 0; + } + bool isInherited() const { return Inherited; } void setInherited(bool value) { Inherited = value; } void addAttr(Attr *attr) { assert((attr != 0) && "addAttr(): attr is null"); - + // FIXME: This doesn't preserve the order in any way. attr->Next = Next; Next = attr; } - + // Clone this attribute. virtual Attr* clone(ASTContext &C) const = 0; @@ -146,36 +158,39 @@ public: \ static bool classof(const ATTR##Attr *A) { return true; } \ } -class PackedAttr : public Attr { +DEF_SIMPLE_ATTR(Packed); + +class PragmaPackAttr : public Attr { unsigned Alignment; public: - PackedAttr(unsigned alignment) : Attr(Packed), Alignment(alignment) {} + PragmaPackAttr(unsigned alignment) : Attr(PragmaPack), Alignment(alignment) {} /// getAlignment - The specified alignment in bits. unsigned getAlignment() const { return Alignment; } - virtual Attr* clone(ASTContext &C) const { - return ::new (C) PackedAttr(Alignment); + virtual Attr* clone(ASTContext &C) const { + return ::new (C) PragmaPackAttr(Alignment); } // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() == Packed; + return A->getKind() == PragmaPack; } - static bool classof(const PackedAttr *A) { return true; } + static bool classof(const PragmaPackAttr *A) { return true; } }; - + class AlignedAttr : public Attr { unsigned Alignment; public: AlignedAttr(unsigned alignment) : Attr(Aligned), Alignment(alignment) {} + // FIXME: Should use addressable units, not bits, to match llvm /// getAlignment - The specified alignment in bits. unsigned getAlignment() const { return Alignment; } virtual Attr* clone(ASTContext &C) const { return ::new (C) AlignedAttr(Alignment); } - + // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { return A->getKind() == Aligned; @@ -187,11 +202,11 @@ class AnnotateAttr : public Attr { std::string Annotation; public: AnnotateAttr(const std::string &ann) : Attr(Annotate), Annotation(ann) {} - + const std::string& getAnnotation() const { return Annotation; } virtual Attr* clone(ASTContext &C) const { return ::new (C) AnnotateAttr(Annotation); } - + // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { return A->getKind() == Annotate; @@ -203,11 +218,11 @@ class AsmLabelAttr : public Attr { std::string Label; public: AsmLabelAttr(const std::string &L) : Attr(AsmLabel), Label(L) {} - + const std::string& getLabel() const { return Label; } - + virtual Attr* clone(ASTContext &C) const { return ::new (C) AsmLabelAttr(Label); } - + // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { return A->getKind() == AsmLabel; @@ -237,28 +252,28 @@ public: ConstructorAttr(int p) : Attr(Constructor), priority(p) {} int getPriority() const { return priority; } - + virtual Attr *clone(ASTContext &C) const { return ::new (C) ConstructorAttr(priority); } // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == Constructor; } + static bool classof(const Attr *A) { return A->getKind() == Constructor; } static bool classof(const ConstructorAttr *A) { return true; } -}; - +}; + class DestructorAttr : public Attr { int priority; public: DestructorAttr(int p) : Attr(Destructor), priority(p) {} int getPriority() const { return priority; } - + virtual Attr *clone(ASTContext &C) const { return ::new (C) DestructorAttr(priority); } // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == Destructor; } + static bool classof(const Attr *A) { return A->getKind() == Destructor; } static bool classof(const DestructorAttr *A) { return true; } -}; - +}; + class GNUInlineAttr : public Attr { public: GNUInlineAttr() : Attr(GNUInline) {} @@ -285,15 +300,16 @@ public: static bool classof(const IBOutletAttr *A) { return true; } }; +DEF_SIMPLE_ATTR(Malloc); DEF_SIMPLE_ATTR(NoReturn); -DEF_SIMPLE_ATTR(AnalyzerNoReturn); +DEF_SIMPLE_ATTR(AnalyzerNoReturn); DEF_SIMPLE_ATTR(Deprecated); class SectionAttr : public Attr { std::string Name; public: SectionAttr(const std::string &N) : Attr(Section), Name(N) {} - + const std::string& getName() const { return Name; } virtual Attr *clone(ASTContext &C) const { return ::new (C) SectionAttr(Name); } @@ -307,8 +323,8 @@ public: DEF_SIMPLE_ATTR(Unavailable); DEF_SIMPLE_ATTR(Unused); -DEF_SIMPLE_ATTR(Used); -DEF_SIMPLE_ATTR(Weak); +DEF_SIMPLE_ATTR(Used); +DEF_SIMPLE_ATTR(Weak); DEF_SIMPLE_ATTR(WeakImport); DEF_SIMPLE_ATTR(NoThrow); DEF_SIMPLE_ATTR(Const); @@ -320,14 +336,14 @@ class NonNullAttr : public Attr { public: NonNullAttr(unsigned* arg_nums = 0, unsigned size = 0) : Attr(NonNull), ArgNums(0), Size(0) { - + if (size == 0) return; assert(arg_nums); ArgNums = new unsigned[size]; Size = size; memcpy(ArgNums, arg_nums, sizeof(*ArgNums)*size); } - + virtual ~NonNullAttr() { delete [] ArgNums; } @@ -339,7 +355,7 @@ public: bool isNonNull(unsigned arg) const { return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true; - } + } virtual Attr *clone(ASTContext &C) const { return ::new (C) NonNullAttr(ArgNums, Size); } @@ -359,8 +375,8 @@ public: int getFormatIdx() const { return formatIdx; } int getFirstArg() const { return firstArg; } - virtual Attr *clone(ASTContext &C) const { - return ::new (C) FormatAttr(Type, formatIdx, firstArg); + virtual Attr *clone(ASTContext &C) const { + return ::new (C) FormatAttr(Type, formatIdx, firstArg); } // Implement isa/cast/dyncast/etc. @@ -437,8 +453,8 @@ public: virtual bool isMerged() const { return false; } - virtual Attr *clone(ASTContext &C) const { - return ::new (C) OverloadableAttr; + virtual Attr *clone(ASTContext &C) const { + return ::new (C) OverloadableAttr; } static bool classof(const Attr *A) { return A->getKind() == Overloadable; } @@ -465,15 +481,15 @@ public: }; class FunctionDecl; - + class CleanupAttr : public Attr { FunctionDecl *FD; - + public: CleanupAttr(FunctionDecl *fd) : Attr(Cleanup), FD(fd) {} const FunctionDecl *getFunctionDecl() const { return FD; } - + virtual Attr *clone(ASTContext &C) const { return ::new (C) CleanupAttr(FD); } // Implement isa/cast/dyncast/etc. @@ -481,9 +497,9 @@ public: static bool classof(const CleanupAttr *A) { return true; } }; -DEF_SIMPLE_ATTR(Nodebug); -DEF_SIMPLE_ATTR(WarnUnusedResult); -DEF_SIMPLE_ATTR(Noinline); +DEF_SIMPLE_ATTR(NoDebug); +DEF_SIMPLE_ATTR(WarnUnusedResult); +DEF_SIMPLE_ATTR(NoInline); class RegparmAttr : public Attr { unsigned NumParams; @@ -493,11 +509,11 @@ public: unsigned getNumParams() const { return NumParams; } - virtual Attr *clone(ASTContext &C) const { - return ::new (C) RegparmAttr(NumParams); + virtual Attr *clone(ASTContext &C) const { + return ::new (C) RegparmAttr(NumParams); } - // Implement isa/cast/dyncast/etc. + // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { return A->getKind() == Regparm; } static bool classof(const RegparmAttr *A) { return true; } }; @@ -512,23 +528,23 @@ public: unsigned getYDim() const { return Y; } unsigned getZDim() const { return Z; } - virtual Attr *clone(ASTContext &C) const { - return ::new (C) ReqdWorkGroupSizeAttr(X, Y, Z); + virtual Attr *clone(ASTContext &C) const { + return ::new (C) ReqdWorkGroupSizeAttr(X, Y, Z); } - + // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { return A->getKind() == ReqdWorkGroupSize; } static bool classof(const ReqdWorkGroupSizeAttr *A) { return true; } }; - + // Checker-specific attributes. DEF_SIMPLE_ATTR(CFReturnsRetained); DEF_SIMPLE_ATTR(NSReturnsRetained); #undef DEF_SIMPLE_ATTR - + } // end namespace clang #endif diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h new file mode 100644 index 000000000000..a57bcc184a93 --- /dev/null +++ b/include/clang/AST/CXXInheritance.h @@ -0,0 +1,212 @@ +//===------ CXXInheritance.h - C++ Inheritance ------------------*- 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 routines that help analyzing C++ inheritance hierarchies. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_CXXINHERITANCE_H +#define LLVM_CLANG_AST_CXXINHERITANCE_H + +#include "clang/AST/DeclarationName.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeOrdering.h" +#include "llvm/ADT/SmallVector.h" +#include <list> +#include <map> +#include <cassert> + +namespace clang { + +class CXXBaseSpecifier; +class CXXMethodDecl; +class CXXRecordDecl; +class NamedDecl; + +/// \brief Represents an element in a path from a derived class to a +/// base class. +/// +/// Each step in the path references the link from a +/// derived class to one of its direct base classes, along with a +/// base "number" that identifies which base subobject of the +/// original derived class we are referencing. +struct CXXBasePathElement { + /// \brief The base specifier that states the link from a derived + /// class to a base class, which will be followed by this base + /// path element. + const CXXBaseSpecifier *Base; + + /// \brief The record decl of the class that the base is a base of. + const CXXRecordDecl *Class; + + /// \brief Identifies which base class subobject (of type + /// \c Base->getType()) this base path element refers to. + /// + /// This value is only valid if \c !Base->isVirtual(), because there + /// is no base numbering for the zero or one virtual bases of a + /// given type. + int SubobjectNumber; +}; + +/// \brief Represents a path from a specific derived class +/// (which is not represented as part of the path) to a particular +/// (direct or indirect) base class subobject. +/// +/// Individual elements in the path are described by the \c CXXBasePathElement +/// structure, which captures both the link from a derived class to one of its +/// direct bases and identification describing which base class +/// subobject is being used. +struct CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> { + /// \brief The set of declarations found inside this base class + /// subobject. + DeclContext::lookup_result Decls; +}; + +/// BasePaths - Represents the set of paths from a derived class to +/// one of its (direct or indirect) bases. For example, given the +/// following class hierachy: +/// +/// @code +/// class A { }; +/// class B : public A { }; +/// class C : public A { }; +/// class D : public B, public C{ }; +/// @endcode +/// +/// There are two potential BasePaths to represent paths from D to a +/// base subobject of type A. One path is (D,0) -> (B,0) -> (A,0) +/// and another is (D,0)->(C,0)->(A,1). These two paths actually +/// refer to two different base class subobjects of the same type, +/// so the BasePaths object refers to an ambiguous path. On the +/// other hand, consider the following class hierarchy: +/// +/// @code +/// class A { }; +/// class B : public virtual A { }; +/// class C : public virtual A { }; +/// class D : public B, public C{ }; +/// @endcode +/// +/// Here, there are two potential BasePaths again, (D, 0) -> (B, 0) +/// -> (A,v) and (D, 0) -> (C, 0) -> (A, v), but since both of them +/// refer to the same base class subobject of type A (the virtual +/// one), there is no ambiguity. +class CXXBasePaths { + /// \brief The type from which this search originated. + CXXRecordDecl *Origin; + + /// Paths - The actual set of paths that can be taken from the + /// derived class to the same base class. + std::list<CXXBasePath> Paths; + + /// ClassSubobjects - Records the class subobjects for each class + /// type that we've seen. The first element in the pair says + /// whether we found a path to a virtual base for that class type, + /// while the element contains the number of non-virtual base + /// class subobjects for that class type. The key of the map is + /// the cv-unqualified canonical type of the base class subobject. + std::map<QualType, std::pair<bool, unsigned>, QualTypeOrdering> + ClassSubobjects; + + /// FindAmbiguities - Whether Sema::IsDerivedFrom should try find + /// ambiguous paths while it is looking for a path from a derived + /// type to a base type. + bool FindAmbiguities; + + /// RecordPaths - Whether Sema::IsDerivedFrom should record paths + /// while it is determining whether there are paths from a derived + /// type to a base type. + bool RecordPaths; + + /// DetectVirtual - Whether Sema::IsDerivedFrom should abort the search + /// if it finds a path that goes across a virtual base. The virtual class + /// is also recorded. + bool DetectVirtual; + + /// ScratchPath - A BasePath that is used by Sema::IsDerivedFrom + /// to help build the set of paths. + CXXBasePath ScratchPath; + + /// DetectedVirtual - The base class that is virtual. + const RecordType *DetectedVirtual; + + /// \brief Array of the declarations that have been found. This + /// array is constructed only if needed, e.g., to iterate over the + /// results within LookupResult. + NamedDecl **DeclsFound; + unsigned NumDeclsFound; + + friend class CXXRecordDecl; + + void ComputeDeclsFound(); + +public: + typedef std::list<CXXBasePath>::const_iterator paths_iterator; + typedef NamedDecl **decl_iterator; + + /// BasePaths - Construct a new BasePaths structure to record the + /// paths for a derived-to-base search. + explicit CXXBasePaths(bool FindAmbiguities = true, + bool RecordPaths = true, + bool DetectVirtual = true) + : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths), + DetectVirtual(DetectVirtual), DetectedVirtual(0), DeclsFound(0), + NumDeclsFound(0) { } + + ~CXXBasePaths() { delete [] DeclsFound; } + + paths_iterator begin() const { return Paths.begin(); } + paths_iterator end() const { return Paths.end(); } + + CXXBasePath& front() { return Paths.front(); } + const CXXBasePath& front() const { return Paths.front(); } + + decl_iterator found_decls_begin(); + decl_iterator found_decls_end(); + + /// \brief Determine whether the path from the most-derived type to the + /// given base type is ambiguous (i.e., it refers to multiple subobjects of + /// the same base type). + bool isAmbiguous(QualType BaseType); + + /// \brief Whether we are finding multiple paths to detect ambiguities. + bool isFindingAmbiguities() const { return FindAmbiguities; } + + /// \brief Whether we are recording paths. + bool isRecordingPaths() const { return RecordPaths; } + + /// \brief Specify whether we should be recording paths or not. + void setRecordingPaths(bool RP) { RecordPaths = RP; } + + /// \brief Whether we are detecting virtual bases. + bool isDetectingVirtual() const { return DetectVirtual; } + + /// \brief The virtual base discovered on the path (if we are merely + /// detecting virtuals). + const RecordType* getDetectedVirtual() const { + return DetectedVirtual; + } + + /// \brief Retrieve the type from which this base-paths search + /// began + CXXRecordDecl *getOrigin() const { return Origin; } + void setOrigin(CXXRecordDecl *Rec) { Origin = Rec; } + + /// \brief Clear the base-paths results. + void clear(); + + /// \brief Swap this data structure's contents with another CXXBasePaths + /// object. + void swap(CXXBasePaths &Other); +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h new file mode 100644 index 000000000000..d7ac76dd32e4 --- /dev/null +++ b/include/clang/AST/CanonicalType.h @@ -0,0 +1,721 @@ +//===-- CanonicalType.h - C Language Family Type Representation -*- 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 CanQual class template, which provides access to +// canonical types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_CANONICAL_TYPE_H +#define LLVM_CLANG_AST_CANONICAL_TYPE_H + +#include "clang/AST/Type.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/type_traits.h" +#include <iterator> + +namespace clang { + +template<typename T> class CanProxy; +template<typename T> struct CanProxyAdaptor; + +//----------------------------------------------------------------------------// +// Canonical, qualified type template +//----------------------------------------------------------------------------// + +/// \brief Represents a canonical, potentially-qualified type. +/// +/// The CanQual template is a lightweight smart pointer that provides access +/// to the canonical representation of a type, where all typedefs and other +/// syntactic sugar has been eliminated. A CanQualType may also have various +/// qualifiers (const, volatile, restrict) attached to it. +/// +/// The template type parameter @p T is one of the Type classes (PointerType, +/// BuiltinType, etc.). The type stored within @c CanQual<T> will be of that +/// type (or some subclass of that type). The typedef @c CanQualType is just +/// a shorthand for @c CanQual<Type>. +/// +/// An instance of @c CanQual<T> can be implicitly converted to a +/// @c CanQual<U> when T is derived from U, which essentially provides an +/// implicit upcast. For example, @c CanQual<LValueReferenceType> can be +/// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can +/// be implicitly converted to a QualType, but the reverse operation requires +/// a call to ASTContext::getCanonicalType(). +/// +/// +template<typename T = Type> +class CanQual { + /// \brief The actual, canonical type. + QualType Stored; + +public: + /// \brief Constructs a NULL canonical type. + CanQual() : Stored() { } + + /// \brief Converting constructor that permits implicit upcasting of + /// canonical type pointers. + template<typename U> + CanQual(const CanQual<U>& Other, + typename llvm::enable_if<llvm::is_base_of<T, U>, int>::type = 0); + + /// \brief Implicit conversion to the underlying pointer. + /// + /// Also provides the ability to use canonical types in a boolean context, + /// e.g., + /// @code + /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... } + /// @endcode + operator const T*() const { return getTypePtr(); } + + /// \brief Retrieve the underlying type pointer, which refers to a + /// canonical type. + T *getTypePtr() const { return cast_or_null<T>(Stored.getTypePtr()); } + + /// \brief Implicit conversion to a qualified type. + operator QualType() const { return Stored; } + + /// \brief Retrieve a canonical type pointer with a different static type, + /// upcasting or downcasting as needed. + /// + /// The getAs() function is typically used to try to downcast to a + /// more specific (canonical) type in the type system. For example: + /// + /// @code + /// void f(CanQual<Type> T) { + /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { + /// // look at Ptr's pointee type + /// } + /// } + /// @endcode + /// + /// \returns A proxy pointer to the same type, but with the specified + /// static type (@p U). If the dynamic type is not the specified static type + /// or a derived class thereof, a NULL canonical type. + template<typename U> CanProxy<U> getAs() const; + + /// \brief Overloaded arrow operator that produces a canonical type + /// proxy. + CanProxy<T> operator->() const; + + /// \brief Retrieve all qualifiers. + Qualifiers getQualifiers() const { return Stored.getQualifiers(); } + + /// \brief Retrieve the const/volatile/restrict qualifiers. + unsigned getCVRQualifiers() const { return Stored.getCVRQualifiers(); } + + /// \brief Determines whether this type has any qualifiers + bool hasQualifiers() const { return Stored.hasQualifiers(); } + + bool isConstQualified() const { + return Stored.isConstQualified(); + } + bool isVolatileQualified() const { + return Stored.isVolatileQualified(); + } + bool isRestrictQualified() const { + return Stored.isRestrictQualified(); + } + + /// \brief Retrieve the unqualified form of this type. + CanQual<T> getUnqualifiedType() const; + + CanQual<T> getQualifiedType(unsigned TQs) const { + return CanQual<T>::CreateUnsafe(QualType(getTypePtr(), TQs)); + } + + /// \brief Determines whether this canonical type is more qualified than + /// the @p Other canonical type. + bool isMoreQualifiedThan(CanQual<T> Other) const { + return Stored.isMoreQualifiedThan(Other.Stored); + } + + /// \brief Determines whether this canonical type is at least as qualified as + /// the @p Other canonical type. + bool isAtLeastAsQualifiedAs(CanQual<T> Other) const { + return Stored.isAtLeastAsQualifiedAs(Other.Stored); + } + + /// \brief If the canonical type is a reference type, returns the type that + /// it refers to; otherwise, returns the type itself. + CanQual<Type> getNonReferenceType() const; + + /// \brief Retrieve the internal representation of this canonical type. + void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); } + + /// \brief Construct a canonical type from its internal representation. + static CanQual<T> getFromOpaquePtr(void *Ptr); + + /// \brief Builds a canonical type from a QualType. + /// + /// This routine is inherently unsafe, because it requires the user to + /// ensure that the given type is a canonical type with the correct + // (dynamic) type. + static CanQual<T> CreateUnsafe(QualType Other); +}; + +template<typename T, typename U> +inline bool operator==(CanQual<T> x, CanQual<U> y) { + return x.getAsOpaquePtr() == y.getAsOpaquePtr(); +} + +template<typename T, typename U> +inline bool operator!=(CanQual<T> x, CanQual<U> y) { + return x.getAsOpaquePtr() != y.getAsOpaquePtr(); +} + +/// \brief Represents a canonical, potentially-qualified type. +typedef CanQual<Type> CanQualType; + +//----------------------------------------------------------------------------// +// Internal proxy classes used by canonical types +//----------------------------------------------------------------------------// + +#define LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(Accessor) \ +CanQualType Accessor() const { \ +return CanQualType::CreateUnsafe(this->getTypePtr()->Accessor()); \ +} + +#define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor) \ +Type Accessor() const { return this->getTypePtr()->Accessor(); } + +/// \brief Base class of all canonical proxy types, which is responsible for +/// storing the underlying canonical type and providing basic conversions. +template<typename T> +class CanProxyBase { +protected: + CanQual<T> Stored; + +public: + /// \brief Retrieve the pointer to the underlying Type + T* getTypePtr() const { return Stored.getTypePtr(); } + + /// \brief Implicit conversion to the underlying pointer. + /// + /// Also provides the ability to use canonical type proxies in a Boolean + // context,e.g., + /// @code + /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... } + /// @endcode + operator const T*() const { return this->Stored.getTypePtr(); } + + /// \brief Try to convert the given canonical type to a specific structural + /// type. + template<typename U> CanProxy<U> getAs() const { + return this->Stored.template getAs<U>(); + } + + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type::TypeClass, getTypeClass) + + // Type predicates + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPODType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBooleanType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isCharType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isWideCharType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealFloatingType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyComplexType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFloatingType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArithmeticType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDerivedType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isScalarType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAggregateType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyPointerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidPointerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFunctionPointerType) + 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, isUnionType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType) + + /// \brief Retrieve the proxy-adaptor type. + /// + /// This arrow operator is used when CanProxyAdaptor has been specialized + /// for the given type T. In that case, we reference members of the + /// CanProxyAdaptor specialization. Otherwise, this operator will be hidden + /// by the arrow operator in the primary CanProxyAdaptor template. + const CanProxyAdaptor<T> *operator->() const { + return static_cast<const CanProxyAdaptor<T> *>(this); + } +}; + +/// \brief Replacable canonical proxy adaptor class that provides the link +/// between a canonical type and the accessors of the type. +/// +/// The CanProxyAdaptor is a replaceable class template that is instantiated +/// as part of each canonical proxy type. The primary template merely provides +/// redirection to the underlying type (T), e.g., @c PointerType. One can +/// provide specializations of this class template for each underlying type +/// that provide accessors returning canonical types (@c CanQualType) rather +/// than the more typical @c QualType, to propagate the notion of "canonical" +/// through the system. +template<typename T> +struct CanProxyAdaptor : CanProxyBase<T> { }; + +/// \brief Canonical proxy type returned when retrieving the members of a +/// canonical type or as the result of the @c CanQual<T>::getAs member +/// function. +/// +/// The CanProxy type mainly exists as a proxy through which operator-> will +/// look to either map down to a raw T* (e.g., PointerType*) or to a proxy +/// type that provides canonical-type access to the fields of the type. +template<typename T> +class CanProxy : public CanProxyAdaptor<T> { +public: + /// \brief Build a NULL proxy. + CanProxy() { } + + /// \brief Build a proxy to the given canonical type. + CanProxy(CanQual<T> Stored) { this->Stored = Stored; } + + /// \brief Implicit conversion to the stored canonical type. + operator CanQual<T>() const { return this->Stored; } +}; + +} // end namespace clang + +namespace llvm { + +/// Implement simplify_type for CanQual<T>, so that we can dyn_cast from +/// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc. +/// to return smart pointer (proxies?). +template<typename T> +struct simplify_type<const ::clang::CanQual<T> > { + typedef T* SimpleType; + static SimpleType getSimplifiedValue(const ::clang::CanQual<T> &Val) { + return Val.getTypePtr(); + } +}; +template<typename T> +struct simplify_type< ::clang::CanQual<T> > +: public simplify_type<const ::clang::CanQual<T> > {}; + +// Teach SmallPtrSet that CanQual<T> is "basically a pointer". +template<typename T> +class PointerLikeTypeTraits<clang::CanQual<T> > { +public: + static inline void *getAsVoidPointer(clang::CanQual<T> P) { + return P.getAsOpaquePtr(); + } + static inline clang::CanQual<T> getFromVoidPointer(void *P) { + return clang::CanQual<T>::getFromOpaquePtr(P); + } + // qualifier information is encoded in the low bits. + enum { NumLowBitsAvailable = 0 }; +}; + +} // end namespace llvm + +namespace clang { + +//----------------------------------------------------------------------------// +// Canonical proxy adaptors for canonical type nodes. +//----------------------------------------------------------------------------// + +/// \brief Iterator adaptor that turns an iterator over canonical QualTypes +/// into an iterator over CanQualTypes. +template<typename InputIterator> +class CanTypeIterator { + InputIterator Iter; + +public: + typedef CanQualType value_type; + typedef value_type reference; + typedef CanProxy<Type> pointer; + typedef typename std::iterator_traits<InputIterator>::difference_type + difference_type; + typedef typename std::iterator_traits<InputIterator>::iterator_category + iterator_category; + + CanTypeIterator() : Iter() { } + explicit CanTypeIterator(InputIterator Iter) : Iter(Iter) { } + + // Input iterator + reference operator*() const { + return CanQualType::CreateUnsafe(*Iter); + } + + pointer operator->() const; + + CanTypeIterator &operator++() { + ++Iter; + return *this; + } + + CanTypeIterator operator++(int) { + CanTypeIterator Tmp(*this); + ++Iter; + return Tmp; + } + + friend bool operator==(const CanTypeIterator& X, const CanTypeIterator &Y) { + return X.Iter == Y.Iter; + } + friend bool operator!=(const CanTypeIterator& X, const CanTypeIterator &Y) { + return X.Iter != Y.Iter; + } + + // Bidirectional iterator + CanTypeIterator &operator--() { + --Iter; + return *this; + } + + CanTypeIterator operator--(int) { + CanTypeIterator Tmp(*this); + --Iter; + return Tmp; + } + + // Random access iterator + reference operator[](difference_type n) const { + return CanQualType::CreateUnsafe(Iter[n]); + } + + CanTypeIterator &operator+=(difference_type n) { + Iter += n; + return *this; + } + + CanTypeIterator &operator-=(difference_type n) { + Iter -= n; + return *this; + } + + friend CanTypeIterator operator+(CanTypeIterator X, difference_type n) { + X += n; + return X; + } + + friend CanTypeIterator operator+(difference_type n, CanTypeIterator X) { + X += n; + return X; + } + + friend CanTypeIterator operator-(CanTypeIterator X, difference_type n) { + X -= n; + return X; + } + + friend difference_type operator-(const CanTypeIterator &X, + const CanTypeIterator &Y) { + return X - Y; + } +}; + +template<> +struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) +}; + +template<> +struct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) +}; + +template<> +struct CanProxyAdaptor<BlockPointerType> + : public CanProxyBase<BlockPointerType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) +}; + +template<> +struct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) +}; + +template<> +struct CanProxyAdaptor<LValueReferenceType> + : public CanProxyBase<LValueReferenceType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) +}; + +template<> +struct CanProxyAdaptor<RValueReferenceType> + : public CanProxyBase<RValueReferenceType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) +}; + +template<> +struct CanProxyAdaptor<MemberPointerType> + : public CanProxyBase<MemberPointerType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass) +}; + +template<> +struct CanProxyAdaptor<ArrayType> : public CanProxyBase<ArrayType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, + getSizeModifier) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) +}; + +template<> +struct CanProxyAdaptor<ConstantArrayType> + : public CanProxyBase<ConstantArrayType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, + getSizeModifier) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize) +}; + +template<> +struct CanProxyAdaptor<ConstantArrayWithExprType> + : public CanProxyBase<ConstantArrayWithExprType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, + getSizeModifier) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc) +}; + +template<> +struct CanProxyAdaptor<ConstantArrayWithoutExprType> + : public CanProxyBase<ConstantArrayWithoutExprType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, + getSizeModifier) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize) +}; + +template<> +struct CanProxyAdaptor<IncompleteArrayType> + : public CanProxyBase<IncompleteArrayType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, + getSizeModifier) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) +}; + +template<> +struct CanProxyAdaptor<VariableArrayType> + : public CanProxyBase<VariableArrayType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, + getSizeModifier) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc) +}; + +template<> +struct CanProxyAdaptor<DependentSizedArrayType> + : public CanProxyBase<DependentSizedArrayType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc) +}; + +template<> +struct CanProxyAdaptor<DependentSizedExtVectorType> + : public CanProxyBase<DependentSizedExtVectorType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Expr *, getSizeExpr) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getAttributeLoc) +}; + +template<> +struct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements) +}; + +template<> +struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements) +}; + +template<> +struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) +}; + +template<> +struct CanProxyAdaptor<FunctionNoProtoType> + : public CanProxyBase<FunctionNoProtoType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) +}; + +template<> +struct CanProxyAdaptor<FunctionProtoType> + : public CanProxyBase<FunctionProtoType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs); + CanQualType getArgType(unsigned i) const { + return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i)); + } + + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals) + + typedef CanTypeIterator<FunctionProtoType::arg_type_iterator> + arg_type_iterator; + + arg_type_iterator arg_type_begin() const { + return arg_type_iterator(this->getTypePtr()->arg_type_begin()); + } + + arg_type_iterator arg_type_end() const { + return arg_type_iterator(this->getTypePtr()->arg_type_end()); + } + + // Note: canonical function types never have exception specifications +}; + +template<> +struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) +}; + +template<> +struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> { + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getUnderlyingExpr) + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) +}; + +template<> +struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> { + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) +}; + +template<> +struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> { + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getAddressSpace) +}; + +template<> +struct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> { + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(EnumDecl *, getDecl) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) +}; + +template<> +struct CanProxyAdaptor<TemplateTypeParmType> + : public CanProxyBase<TemplateTypeParmType> { + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getName) +}; + +template<> +struct CanProxyAdaptor<ObjCObjectPointerType> + : public CanProxyBase<ObjCObjectPointerType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceType *, + getInterfaceType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCIdType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCClassType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType) + + typedef ObjCObjectPointerType::qual_iterator qual_iterator; + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) +}; + +//----------------------------------------------------------------------------// +// Method and function definitions +//----------------------------------------------------------------------------// +template<typename T> +inline CanQual<T> CanQual<T>::getUnqualifiedType() const { + return CanQual<T>::CreateUnsafe(Stored.getUnqualifiedType()); +} + +template<typename T> +inline CanQual<Type> CanQual<T>::getNonReferenceType() const { + if (CanQual<ReferenceType> RefType = getAs<ReferenceType>()) + return RefType->getPointeeType(); + else + return *this; +} + +template<typename T> +CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) { + CanQual<T> Result; + Result.Stored.setFromOpaqueValue(Ptr); + assert((!Result || Result.Stored.isCanonical()) + && "Type is not canonical!"); + return Result; +} + +template<typename T> +CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) { + assert((Other.isNull() || Other->isCanonical()) && "Type is not canonical!"); + assert((Other.isNull() || isa<T>(Other.getTypePtr())) && + "Dynamic type does not meet the static type's requires"); + CanQual<T> Result; + Result.Stored = Other; + return Result; +} + +template<typename T> +template<typename U> +CanProxy<U> CanQual<T>::getAs() const { + if (Stored.isNull()) + return CanProxy<U>(); + + if (isa<U>(Stored.getTypePtr())) + return CanQual<U>::CreateUnsafe(Stored); + + return CanProxy<U>(); +} + +template<typename T> +CanProxy<T> CanQual<T>::operator->() const { + return CanProxy<T>(*this); +} + +template<typename InputIterator> +typename CanTypeIterator<InputIterator>::pointer +CanTypeIterator<InputIterator>::operator->() const { + return CanProxy<Type>(*this); +} + +} + + +#endif // LLVM_CLANG_AST_CANONICAL_TYPE_H diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 69a52869d818..7c326dee338c 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -16,6 +16,7 @@ #include "clang/AST/APValue.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/Redeclarable.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" @@ -26,23 +27,45 @@ class Stmt; class CompoundStmt; class StringLiteral; class TemplateArgumentList; +class MemberSpecializationInfo; class FunctionTemplateSpecializationInfo; - +class TypeLoc; + +/// \brief A container of type source information. +/// +/// A client can read the relevant info using TypeLoc wrappers, e.g: +/// @code +/// TypeLoc TL = DeclaratorInfo->getTypeLoc(); +/// if (PointerLoc *PL = dyn_cast<PointerLoc>(&TL)) +/// PL->getStarLoc().print(OS, SrcMgr); +/// @endcode +/// +class DeclaratorInfo { + QualType Ty; + // Contains a memory block after the class, used for type source information, + // allocated by ASTContext. + friend class ASTContext; + DeclaratorInfo(QualType ty) : Ty(ty) { } +public: + /// \brief Return the TypeLoc wrapper for the type source info. + TypeLoc getTypeLoc() const; +}; + /// TranslationUnitDecl - The top declaration context. class TranslationUnitDecl : public Decl, public DeclContext { ASTContext &Ctx; - + explicit TranslationUnitDecl(ASTContext &ctx) : Decl(TranslationUnit, 0, SourceLocation()), DeclContext(TranslationUnit), Ctx(ctx) {} public: ASTContext &getASTContext() const { return Ctx; } - + static TranslationUnitDecl *Create(ASTContext &C); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == TranslationUnit; } - static bool classof(const TranslationUnitDecl *D) { return true; } + static bool classof(const TranslationUnitDecl *D) { return true; } static DeclContext *castToDeclContext(const TranslationUnitDecl *D) { return static_cast<DeclContext *>(const_cast<TranslationUnitDecl*>(D)); } @@ -91,7 +114,7 @@ public: /// manipulation, so it should be called only when performance doesn't matter. /// For simple declarations, getNameAsCString() should suffice. std::string getNameAsString() const { return Name.getAsString(); } - + /// getQualifiedNameAsString - Returns human-readable qualified name for /// declaration, like A::B::i, for i being member of namespace A::B. /// If declaration is not member of context which can be named (record, @@ -99,6 +122,25 @@ public: /// Creating this name is expensive, so it should be called only when /// performance doesn't matter. std::string getQualifiedNameAsString() const; + std::string getQualifiedNameAsString(const PrintingPolicy &Policy) const; + + /// getNameForDiagnostic - Appends a human-readable name for this + /// declaration into the given string. + /// + /// This is the method invoked by Sema when displaying a NamedDecl + /// in a diagnostic. It does not necessarily produce the same + /// result as getNameAsString(); for example, class template + /// specializations are printed with their template arguments. + /// + /// TODO: use an API that doesn't require so many temporary strings + virtual void getNameForDiagnostic(std::string &S, + const PrintingPolicy &Policy, + bool Qualified) const { + if (Qualified) + S += getQualifiedNameAsString(Policy); + else + S += getNameAsString(); + } /// declarationReplaces - Determine whether this declaration, if /// known to be well-formed within its context, will replace the @@ -118,7 +160,7 @@ public: const NamedDecl *getUnderlyingDecl() const { return const_cast<NamedDecl*>(this)->getUnderlyingDecl(); } - + static bool classof(const Decl *D) { return D->getKind() >= NamedFirst && D->getKind() <= NamedLast; } @@ -128,7 +170,7 @@ public: /// NamespaceDecl - Represent a C++ namespace. class NamespaceDecl : public NamedDecl, public DeclContext { SourceLocation LBracLoc, RBracLoc; - + // For extended namespace definitions: // // namespace A { int x; } @@ -139,7 +181,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext { // OrigNamespace points to the original namespace declaration. // OrigNamespace of the first namespace decl points to itself. NamespaceDecl *OrigNamespace, *NextNamespace; - + NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace) { OrigNamespace = this; @@ -148,9 +190,20 @@ class NamespaceDecl : public NamedDecl, public DeclContext { public: static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id); - + virtual void Destroy(ASTContext& C); + // \brief Returns true if this is an anonymous namespace declaration. + // + // For example: + // namespace { + // ... + // }; + // q.v. C++ [namespace.unnamed] + bool isAnonymousNamespace() const { + return !getIdentifier(); + } + NamespaceDecl *getNextNamespace() { return NextNamespace; } const NamespaceDecl *getNextNamespace() const { return NextNamespace; } void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; } @@ -159,7 +212,9 @@ public: return OrigNamespace; } void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; } - + + virtual NamespaceDecl *getCanonicalDecl() { return OrigNamespace; } + virtual SourceRange getSourceRange() const { return SourceRange(getLocation(), RBracLoc); } @@ -168,7 +223,7 @@ public: SourceLocation getRBracLoc() const { return RBracLoc; } void setLBracLoc(SourceLocation LBrace) { LBracLoc = LBrace; } void setRBracLoc(SourceLocation RBrace) { RBracLoc = RBrace; } - + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == Namespace; } static bool classof(const NamespaceDecl *D) { return true; } @@ -180,20 +235,20 @@ public: } }; -/// ValueDecl - Represent the declaration of a variable (in which case it is +/// ValueDecl - Represent the declaration of a variable (in which case it is /// an lvalue) a function (in which case it is a function designator) or -/// an enum constant. +/// an enum constant. class ValueDecl : public NamedDecl { QualType DeclType; protected: ValueDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName N, QualType T) + DeclarationName N, QualType T) : NamedDecl(DK, DC, L, N), DeclType(T) {} public: QualType getType() const { return DeclType; } void setType(QualType newType) { DeclType = newType; } - + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= ValueFirst && D->getKind() <= ValueLast; @@ -201,6 +256,29 @@ public: static bool classof(const ValueDecl *D) { return true; } }; +/// \brief Represents a ValueDecl that came out of a declarator. +/// Contains type source information through DeclaratorInfo. +class DeclaratorDecl : public ValueDecl { + DeclaratorInfo *DeclInfo; + +protected: + DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName N, QualType T, DeclaratorInfo *DInfo) + : ValueDecl(DK, DC, L, N, T), DeclInfo(DInfo) {} + +public: + DeclaratorInfo *getDeclaratorInfo() const { return DeclInfo; } + void setDeclaratorInfo(DeclaratorInfo *DInfo) { DeclInfo = DInfo; } + + SourceLocation getTypeSpecStartLoc() const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() >= DeclaratorFirst && D->getKind() <= DeclaratorLast; + } + static bool classof(const DeclaratorDecl *D) { return true; } +}; + /// \brief Structure used to store a statement, the constant value to /// which it was evaluated (if any), and whether or not the statement /// is an integral constant expression (if known). @@ -222,9 +300,32 @@ struct EvaluatedStmt { APValue Evaluated; }; +// \brief Describes the kind of template specialization that a +// particular template specialization declaration represents. +enum TemplateSpecializationKind { + /// This template specialization was formed from a template-id but + /// has not yet been declared, defined, or instantiated. + TSK_Undeclared = 0, + /// This template specialization was implicitly instantiated from a + /// template. (C++ [temp.inst]). + TSK_ImplicitInstantiation, + /// This template specialization was declared or defined by an + /// explicit specialization (C++ [temp.expl.spec]) or partial + /// specialization (C++ [temp.class.spec]). + TSK_ExplicitSpecialization, + /// This template specialization was instantiated from a template + /// due to an explicit instantiation declaration request + /// (C++0x [temp.explicit]). + TSK_ExplicitInstantiationDeclaration, + /// This template specialization was instantiated from a template + /// due to an explicit instantiation definition request + /// (C++ [temp.explicit]). + TSK_ExplicitInstantiationDefinition +}; + /// VarDecl - An instance of this class is created to represent a variable /// declaration or definition. -class VarDecl : public ValueDecl { +class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> { public: enum StorageClass { None, Auto, Register, Extern, Static, PrivateExtern @@ -236,81 +337,108 @@ public: /// It is illegal to call this function with SC == None. static const char *getStorageClassSpecifierString(StorageClass SC); +protected: + /// \brief Placeholder type used in Init to denote an unparsed C++ default + /// argument. + struct UnparsedDefaultArgument; + + /// \brief Placeholder type used in Init to denote an uninstantiated C++ + /// default argument. + struct UninstantiatedDefaultArgument; + + typedef llvm::PointerUnion4<Stmt *, EvaluatedStmt *, + UnparsedDefaultArgument *, + UninstantiatedDefaultArgument *> InitType; + + /// \brief The initializer for this variable or, for a ParmVarDecl, the + /// C++ default argument. + mutable InitType Init; + private: - mutable llvm::PointerUnion<Stmt *, EvaluatedStmt *> Init; // FIXME: This can be packed into the bitfields in Decl. unsigned SClass : 3; bool ThreadSpecified : 1; - bool HasCXXDirectInit : 1; + bool HasCXXDirectInit : 1; /// DeclaredInCondition - Whether this variable was declared in a /// condition, e.g., if (int x = foo()) { ... }. bool DeclaredInCondition : 1; - /// \brief The previous declaration of this variable. - VarDecl *PreviousDeclaration; - - // Move to DeclGroup when it is implemented. - SourceLocation TypeSpecStartLoc; friend class StmtIteratorBase; protected: VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, StorageClass SC, SourceLocation TSSL = SourceLocation()) - : ValueDecl(DK, DC, L, Id, T), Init(), + QualType T, DeclaratorInfo *DInfo, StorageClass SC) + : DeclaratorDecl(DK, DC, L, Id, T, DInfo), Init(), ThreadSpecified(false), HasCXXDirectInit(false), - DeclaredInCondition(false), PreviousDeclaration(0), - TypeSpecStartLoc(TSSL) { - SClass = SC; + DeclaredInCondition(false) { + SClass = SC; } + + typedef Redeclarable<VarDecl> redeclarable_base; + virtual VarDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + public: + typedef redeclarable_base::redecl_iterator redecl_iterator; + redecl_iterator redecls_begin() const { + return redeclarable_base::redecls_begin(); + } + redecl_iterator redecls_end() const { + return redeclarable_base::redecls_end(); + } + static VarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, StorageClass S, - SourceLocation TypeSpecStartLoc = SourceLocation()); + QualType T, DeclaratorInfo *DInfo, StorageClass S); virtual ~VarDecl(); virtual void Destroy(ASTContext& C); StorageClass getStorageClass() const { return (StorageClass)SClass; } void setStorageClass(StorageClass SC) { SClass = SC; } - - virtual SourceRange getSourceRange() const; - SourceLocation getTypeSpecStartLoc() const { return TypeSpecStartLoc; } - void setTypeSpecStartLoc(SourceLocation SL) { - TypeSpecStartLoc = SL; - } + virtual SourceRange getSourceRange() const; - const Expr *getInit() const { + const Expr *getInit() const { if (Init.isNull()) return 0; const Stmt *S = Init.dyn_cast<Stmt *>(); - if (!S) - S = Init.get<EvaluatedStmt *>()->Value; - - return (const Expr*) S; + if (!S) { + if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>()) + S = ES->Value; + } + return (const Expr*) S; } - Expr *getInit() { + Expr *getInit() { if (Init.isNull()) return 0; Stmt *S = Init.dyn_cast<Stmt *>(); - if (!S) - S = Init.get<EvaluatedStmt *>()->Value; + if (!S) { + if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>()) + S = ES->Value; + } - return (Expr*) S; + return (Expr*) S; } /// \brief Retrieve the address of the initializer expression. Stmt **getInitAddress() { - if (Init.is<Stmt *>()) - return reinterpret_cast<Stmt **>(&Init); // FIXME: ugly hack - return &Init.get<EvaluatedStmt *>()->Value; + if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>()) + return &ES->Value; + + // This union hack tip-toes around strict-aliasing rules. + union { + InitType *InitPtr; + Stmt **StmtPtr; + }; + + InitPtr = &Init; + return StmtPtr; } void setInit(ASTContext &C, Expr *I); - + /// \brief Note that constant evaluation has computed the given /// value for this variable's initializer. void setEvaluatedValue(ASTContext &C, const APValue &Value) const { @@ -325,7 +453,7 @@ public: Eval->WasEvaluated = true; Eval->Evaluated = Value; } - + /// \brief Return the already-evaluated value of this variable's /// initializer, or NULL if the value is not yet known. APValue *getEvaluatedValue() const { @@ -350,7 +478,7 @@ public: /// /// \pre isInitKnownICE() bool isInitICE() const { - assert(isInitKnownICE() && + assert(isInitKnownICE() && "Check whether we already know that the initializer is an ICE"); return Init.get<EvaluatedStmt *>()->IsICE; } @@ -392,7 +520,7 @@ public: bool hasCXXDirectInitializer() const { return HasCXXDirectInit; } - + /// isDeclaredInCondition - Whether this variable was declared as /// part of a condition in an if/switch/while statement, e.g., /// @code @@ -401,27 +529,21 @@ public: bool isDeclaredInCondition() const { return DeclaredInCondition; } - void setDeclaredInCondition(bool InCondition) { - DeclaredInCondition = InCondition; + void setDeclaredInCondition(bool InCondition) { + DeclaredInCondition = InCondition; } - /// getPreviousDeclaration - Return the previous declaration of this - /// variable. - const VarDecl *getPreviousDeclaration() const { return PreviousDeclaration; } - - void setPreviousDeclaration(VarDecl *PrevDecl) { - PreviousDeclaration = PrevDecl; - } + virtual VarDecl *getCanonicalDecl(); /// hasLocalStorage - Returns true if a variable with function scope /// is a non-static local variable. bool hasLocalStorage() const { if (getStorageClass() == None) return !isFileVarDecl(); - + // Return true for: Auto, Register. // Return false for: Extern, Static, PrivateExtern. - + return getStorageClass() <= Register; } @@ -448,7 +570,7 @@ public: return DC->getLookupContext()->isFunctionOrMethod(); return false; } - + /// \brief Determines whether this is a static data member. /// /// This will only be true in C++, and applies to, e.g., the @@ -462,6 +584,24 @@ public: return getDeclContext()->isRecord(); } + /// \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. + VarDecl *getInstantiatedFromStaticDataMember(); + + /// \brief If this variable is a static data member, determine what kind of + /// template specialization or instantiation this is. + TemplateSpecializationKind getTemplateSpecializationKind(); + + /// \brief If this variable is an instantiation of a static data member of a + /// class template specialization, retrieves the member specialization + /// information. + MemberSpecializationInfo *getMemberSpecializationInfo(); + + /// \brief For a static data member that was instantiated from a static + /// data member of a class template, set the template specialiation kind. + void setTemplateSpecializationKind(TemplateSpecializationKind TSK); + /// isFileVarDecl - Returns true for file scoped variable declaration. bool isFileVarDecl() const { if (getKind() != Decl::Var) @@ -471,16 +611,19 @@ public: if (isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx) ) return true; } + if (isStaticDataMember()) + return true; + return false; } /// \brief Determine whether this is a tentative definition of a /// variable in C. bool isTentativeDefinition(ASTContext &Context) const; - + /// \brief Determines whether this variable is a variable with /// external, C linkage. - bool isExternC(ASTContext &Context) const; + bool isExternC() const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { @@ -492,12 +635,12 @@ public: class ImplicitParamDecl : public VarDecl { protected: ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType Tw) - : VarDecl(DK, DC, L, Id, Tw, VarDecl::None) {} + IdentifierInfo *Id, QualType Tw) + : VarDecl(DK, DC, L, Id, Tw, /*DInfo=*/0, VarDecl::None) {} public: static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - QualType T); + SourceLocation L, IdentifierInfo *Id, + QualType T); // Implement isa/cast/dyncast/etc. static bool classof(const ImplicitParamDecl *D) { return true; } static bool classof(const Decl *D) { return D->getKind() == ImplicitParam; } @@ -509,44 +652,72 @@ class ParmVarDecl : public VarDecl { /// FIXME: Also can be paced into the bitfields in Decl. /// in, inout, etc. unsigned objcDeclQualifier : 6; - - /// Default argument, if any. [C++ Only] - Expr *DefaultArg; + + /// \brief Retrieves the fake "value" of an unparsed + static Expr *getUnparsedDefaultArgValue() { + uintptr_t Value = (uintptr_t)-1; + // Mask off the low bits + Value &= ~(uintptr_t)0x07; + return reinterpret_cast<Expr*> (Value); + } + protected: ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, StorageClass S, - Expr *DefArg) - : VarDecl(DK, DC, L, Id, T, S), - objcDeclQualifier(OBJC_TQ_None), DefaultArg(DefArg) {} + IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo, + StorageClass S, Expr *DefArg) + : VarDecl(DK, DC, L, Id, T, DInfo, S), objcDeclQualifier(OBJC_TQ_None) { + setDefaultArg(DefArg); + } public: static ParmVarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,IdentifierInfo *Id, - QualType T, StorageClass S, Expr *DefArg); - + QualType T, DeclaratorInfo *DInfo, + StorageClass S, Expr *DefArg); + ObjCDeclQualifier getObjCDeclQualifier() const { return ObjCDeclQualifier(objcDeclQualifier); } void setObjCDeclQualifier(ObjCDeclQualifier QTVal) { objcDeclQualifier = QTVal; } - - const Expr *getDefaultArg() const { + + const Expr *getDefaultArg() const { assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!"); - return DefaultArg; + assert(!hasUninstantiatedDefaultArg() && + "Default argument is not yet instantiated!"); + return getInit(); } - Expr *getDefaultArg() { + Expr *getDefaultArg() { assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!"); - return DefaultArg; + assert(!hasUninstantiatedDefaultArg() && + "Default argument is not yet instantiated!"); + return getInit(); + } + void setDefaultArg(Expr *defarg) { + Init = reinterpret_cast<Stmt *>(defarg); + } + + /// \brief Retrieve the source range that covers the entire default + /// argument. + SourceRange getDefaultArgRange() const; + void setUninstantiatedDefaultArg(Expr *arg) { + Init = reinterpret_cast<UninstantiatedDefaultArgument *>(arg); + } + Expr *getUninstantiatedDefaultArg() { + return (Expr *)Init.get<UninstantiatedDefaultArgument *>(); + } + const Expr *getUninstantiatedDefaultArg() const { + return (const Expr *)Init.get<UninstantiatedDefaultArgument *>(); } - void setDefaultArg(Expr *defarg) { DefaultArg = defarg; } /// hasDefaultArg - Determines whether this parameter has a default argument, /// either parsed or not. bool hasDefaultArg() const { - return DefaultArg != 0; + return getInit() || hasUnparsedDefaultArg() || + hasUninstantiatedDefaultArg(); } - + /// hasUnparsedDefaultArg - Determines whether this parameter has a /// default argument that has not yet been parsed. This will occur /// during the processing of a C++ class whose member functions have @@ -558,7 +729,11 @@ public: /// }; // x has a regular default argument now /// @endcode bool hasUnparsedDefaultArg() const { - return DefaultArg == reinterpret_cast<Expr *>(-1); + return Init.is<UnparsedDefaultArgument*>(); + } + + bool hasUninstantiatedDefaultArg() const { + return Init.is<UninstantiatedDefaultArgument*>(); } /// setUnparsedDefaultArg - Specify that this parameter has an @@ -566,10 +741,12 @@ public: /// real default argument via setDefaultArg when the class /// definition enclosing the function declaration that owns this /// default argument is completed. - void setUnparsedDefaultArg() { DefaultArg = reinterpret_cast<Expr *>(-1); } + void setUnparsedDefaultArg() { + Init = (UnparsedDefaultArgument *)0; + } QualType getOriginalType() const; - + /// setOwningFunction - Sets the function declaration that owns this /// ParmVarDecl. Since ParmVarDecls are often created before the /// FunctionDecls that own them, this routine is required to update @@ -577,9 +754,9 @@ public: void setOwningFunction(DeclContext *FD) { setDeclContext(FD); } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { + static bool classof(const Decl *D) { return (D->getKind() == ParmVar || - D->getKind() == OriginalParmVar); + D->getKind() == OriginalParmVar); } static bool classof(const ParmVarDecl *D) { return true; } }; @@ -594,15 +771,17 @@ protected: QualType OriginalType; private: OriginalParmVarDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, + IdentifierInfo *Id, QualType T, + DeclaratorInfo *DInfo, QualType OT, StorageClass S, Expr *DefArg) - : ParmVarDecl(OriginalParmVar, DC, L, Id, T, S, DefArg), OriginalType(OT) {} + : ParmVarDecl(OriginalParmVar, DC, L, Id, T, DInfo, S, DefArg), + OriginalType(OT) {} public: static OriginalParmVarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,IdentifierInfo *Id, - QualType T, QualType OT, - StorageClass S, Expr *DefArg); + QualType T, DeclaratorInfo *DInfo, + QualType OT, StorageClass S, Expr *DefArg); void setOriginalType(QualType T) { OriginalType = T; } @@ -610,9 +789,9 @@ public: static bool classof(const Decl *D) { return D->getKind() == OriginalParmVar; } static bool classof(const OriginalParmVarDecl *D) { return true; } }; - + /// FunctionDecl - An instance of this class is created to represent a -/// function declaration or definition. +/// function declaration or definition. /// /// Since a given function can be declared several times in a program, /// there may be several FunctionDecls that correspond to that @@ -621,46 +800,35 @@ public: /// FunctionDecl (e.g., the translation unit); this FunctionDecl /// contains all of the information known about the function. Other, /// previous declarations of the function are available via the -/// getPreviousDeclaration() chain. -class FunctionDecl : public ValueDecl, public DeclContext { +/// getPreviousDeclaration() chain. +class FunctionDecl : public DeclaratorDecl, public DeclContext, + public Redeclarable<FunctionDecl> { public: enum StorageClass { None, Extern, Static, PrivateExtern }; - -private: + +private: /// ParamInfo - new[]'d array of pointers to VarDecls for the formal /// parameters of this function. This is null if a prototype or if there are /// no formals. ParmVarDecl **ParamInfo; - + LazyDeclStmtPtr Body; - - /// PreviousDeclaration - A link to the previous declaration of this - /// same function, NULL if this is the first declaration. For - /// example, in the following code, the PreviousDeclaration can be - /// traversed several times to see all three declarations of the - /// function "f", the last of which is also a definition. - /// - /// int f(int x, int y = 1); - /// int f(int x = 0, int y); - /// int f(int x, int y) { return x + y; } - FunctionDecl *PreviousDeclaration; // FIXME: This can be packed into the bitfields in Decl. // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum unsigned SClass : 2; bool IsInline : 1; - bool C99InlineDefinition : 1; bool IsVirtualAsWritten : 1; bool IsPure : 1; bool HasInheritedPrototype : 1; bool HasWrittenPrototype : 1; bool IsDeleted : 1; + bool IsTrivial : 1; // sunk from CXXMethodDecl + bool IsCopyAssignment : 1; // sunk from CXXMethodDecl + bool HasImplicitReturnZero : 1; - // Move to DeclGroup when it is implemented. - SourceLocation TypeSpecStartLoc; - /// \brief End part of this FunctionDecl's source range. /// /// We could compute the full range in getSourceRange(). However, when we're @@ -672,42 +840,59 @@ private: /// \brief The template or declaration that this declaration /// describes or was instantiated from, respectively. - /// + /// /// For non-templates, this value will be NULL. For function /// declarations that describe a function template, this will be a /// pointer to a FunctionTemplateDecl. For member functions - /// of class template specializations, this will be the - /// FunctionDecl from which the member function was instantiated. - /// For function template specializations, this will be a + /// of class template specializations, this will be a MemberSpecializationInfo + /// pointer containing information about the specialization. + /// For function template specializations, this will be a /// FunctionTemplateSpecializationInfo, which contains information about - /// the template being specialized and the template arguments involved in + /// the template being specialized and the template arguments involved in /// that specialization. - llvm::PointerUnion3<FunctionTemplateDecl*, FunctionDecl*, - FunctionTemplateSpecializationInfo*> + llvm::PointerUnion3<FunctionTemplateDecl *, + MemberSpecializationInfo *, + FunctionTemplateSpecializationInfo *> TemplateOrSpecialization; protected: FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName N, QualType T, - StorageClass S, bool isInline, - SourceLocation TSSL = SourceLocation()) - : ValueDecl(DK, DC, L, N, T), + DeclarationName N, QualType T, DeclaratorInfo *DInfo, + StorageClass S, bool isInline) + : DeclaratorDecl(DK, DC, L, N, T, DInfo), DeclContext(DK), - ParamInfo(0), Body(), PreviousDeclaration(0), - SClass(S), IsInline(isInline), C99InlineDefinition(false), - IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), - HasWrittenPrototype(true), IsDeleted(false), TypeSpecStartLoc(TSSL), + ParamInfo(0), Body(), + SClass(S), IsInline(isInline), + IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), + HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), + IsCopyAssignment(false), + HasImplicitReturnZero(false), EndRangeLoc(L), TemplateOrSpecialization() {} virtual ~FunctionDecl() {} virtual void Destroy(ASTContext& C); + typedef Redeclarable<FunctionDecl> redeclarable_base; + virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + public: + typedef redeclarable_base::redecl_iterator redecl_iterator; + redecl_iterator redecls_begin() const { + return redeclarable_base::redecls_begin(); + } + redecl_iterator redecls_end() const { + return redeclarable_base::redecls_end(); + } + static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, - DeclarationName N, QualType T, + DeclarationName N, QualType T, + DeclaratorInfo *DInfo, StorageClass S = None, bool isInline = false, - bool hasWrittenPrototype = true, - SourceLocation TSStartLoc = SourceLocation()); + bool hasWrittenPrototype = true); + + virtual void getNameForDiagnostic(std::string &S, + const PrintingPolicy &Policy, + bool Qualified) const; virtual SourceRange getSourceRange() const { return SourceRange(getLocation(), EndRangeLoc); @@ -715,9 +900,6 @@ public: void setLocEnd(SourceLocation E) { EndRangeLoc = E; } - - SourceLocation getTypeSpecStartLoc() const { return TypeSpecStartLoc; } - void setTypeSpecStartLoc(SourceLocation TS) { TypeSpecStartLoc = TS; } /// getBody - Retrieve the body (definition) of the function. The /// function body might be in any of the (re-)declarations of this @@ -731,10 +913,6 @@ public: return getBody(Definition); } - /// \brief If the function has a body that is immediately available, - /// return it. - Stmt *getBodyIfAvailable() const; - /// isThisDeclarationADefinition - Returns whether this specific /// declaration of the function is also a definition. This does not /// determine whether the function has been defined (e.g., in a @@ -755,14 +933,30 @@ public: bool isPure() const { return IsPure; } void setPure(bool P = true) { IsPure = P; } + /// Whether this function is "trivial" in some specialized C++ senses. + /// Can only be true for default constructors, copy constructors, + /// copy assignment operators, and destructors. Not meaningful until + /// the class has been fully built by Sema. + bool isTrivial() const { return IsTrivial; } + void setTrivial(bool IT) { IsTrivial = IT; } + + bool isCopyAssignment() const { return IsCopyAssignment; } + void setCopyAssignment(bool CA) { IsCopyAssignment = CA; } + + /// Whether falling off this function implicitly returns null/zero. + /// If a more specific implicit return value is required, front-ends + /// should synthesize the appropriate return statements. + bool hasImplicitReturnZero() const { return HasImplicitReturnZero; } + void setHasImplicitReturnZero(bool IRZ) { HasImplicitReturnZero = IRZ; } + /// \brief Whether this function has a prototype, either because one /// was explicitly written or because it was "inherited" by merging /// a declaration without a prototype with a declaration that has a /// prototype. - bool hasPrototype() const { - return HasWrittenPrototype || HasInheritedPrototype; + bool hasPrototype() const { + return HasWrittenPrototype || HasInheritedPrototype; } - + bool hasWrittenPrototype() const { return HasWrittenPrototype; } void setHasWrittenPrototype(bool P) { HasWrittenPrototype = P; } @@ -798,39 +992,36 @@ public: /// \brief Determines whether this function is a function with /// external, C linkage. - bool isExternC(ASTContext &Context) const; + bool isExternC() const; /// \brief Determines whether this is a global function. bool isGlobal() const; - /// getPreviousDeclaration - Return the previous declaration of this - /// function. - const FunctionDecl *getPreviousDeclaration() const { - return PreviousDeclaration; - } - void setPreviousDeclaration(FunctionDecl * PrevDecl); - unsigned getBuiltinID(ASTContext &Context) const; + virtual const FunctionDecl *getCanonicalDecl() const; + virtual FunctionDecl *getCanonicalDecl(); + + unsigned getBuiltinID() const; unsigned getNumParmVarDeclsFromType() const; - + // Iterator access to formal parameters. unsigned param_size() const { return getNumParams(); } typedef ParmVarDecl **param_iterator; typedef ParmVarDecl * const *param_const_iterator; - + param_iterator param_begin() { return ParamInfo; } param_iterator param_end() { return ParamInfo+param_size(); } - + param_const_iterator param_begin() const { return ParamInfo; } param_const_iterator param_end() const { return ParamInfo+param_size(); } - + /// getNumParams - Return the number of parameters this function must have /// based on its functiontype. This is the length of the PararmInfo array /// after it has been created. unsigned getNumParams() const; - + const ParmVarDecl *getParamDecl(unsigned i) const { assert(i < getNumParams() && "Illegal param #"); return ParamInfo[i]; @@ -847,8 +1038,8 @@ public: /// arguments (in C++). unsigned getMinRequiredArguments() const; - QualType getResultType() const { - return getType()->getAsFunctionType()->getResultType(); + QualType getResultType() const { + return getType()->getAs<FunctionType>()->getResultType(); } StorageClass getStorageClass() const { return StorageClass(SClass); } void setStorageClass(StorageClass SC) { SClass = SC; } @@ -856,27 +1047,11 @@ public: bool isInline() const { return IsInline; } void setInline(bool I) { IsInline = I; } - /// \brief Whether this function is an "inline definition" as - /// defined by C99. - bool isC99InlineDefinition() const { return C99InlineDefinition; } - void setC99InlineDefinition(bool I) { C99InlineDefinition = I; } - - /// \brief Determines whether this function has a gnu_inline - /// attribute that affects its semantics. - /// - /// The gnu_inline attribute only introduces GNU inline semantics - /// when all of the inline declarations of the function are marked - /// gnu_inline. - bool hasActiveGNUInlineAttribute(ASTContext &Context) const; - - /// \brief Determines whether this function is a GNU "extern - /// inline", which is roughly the opposite of a C99 "extern inline" - /// function. - bool isExternGNUInline(ASTContext &Context) const; - + bool isInlineDefinitionExternallyVisible() const; + /// isOverloadedOperator - Whether this function declaration /// represents an C++ overloaded operator, e.g., "operator+". - bool isOverloadedOperator() const { + bool isOverloadedOperator() const { return getOverloadedOperator() != OO_None; }; @@ -903,15 +1078,17 @@ public: /// the FunctionDecl X<T>::A. When a complete definition of /// X<int>::A is required, it will be instantiated from the /// declaration returned by getInstantiatedFromMemberFunction(). - FunctionDecl *getInstantiatedFromMemberFunction() const { - return TemplateOrSpecialization.dyn_cast<FunctionDecl*>(); - } + FunctionDecl *getInstantiatedFromMemberFunction() const; + /// \brief If this function is an instantiation of a member function of a + /// class template specialization, retrieves the member specialization + /// information. + MemberSpecializationInfo *getMemberSpecializationInfo() const; + /// \brief Specify that this record is an instantiation of the - /// member function RD. - void setInstantiationOfMemberFunction(FunctionDecl *RD) { - TemplateOrSpecialization = RD; - } + /// member function FD. + void setInstantiationOfMemberFunction(FunctionDecl *FD, + TemplateSpecializationKind TSK); /// \brief Retrieves the function template that is described by this /// function declaration. @@ -933,20 +1110,34 @@ public: TemplateOrSpecialization = Template; } + /// \brief Determine whether this function is a function template + /// specialization. + bool isFunctionTemplateSpecialization() const { + return getPrimaryTemplate() != 0; + } + + /// \brief If this function is actually a function template specialization, + /// retrieve information about this function template specialization. + /// Otherwise, returns NULL. + FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const { + return TemplateOrSpecialization. + dyn_cast<FunctionTemplateSpecializationInfo*>(); + } + /// \brief Retrieve the primary template that this function template /// specialization either specializes or was instantiated from. /// /// If this function declaration is not a function template specialization, /// returns NULL. FunctionTemplateDecl *getPrimaryTemplate() const; - + /// \brief Retrieve the template arguments used to produce this function /// template specialization from the primary template. /// /// If this function declaration is not a function template specialization, /// returns NULL. - const TemplateArgumentList *getTemplateSpecializationArgs() const; - + const TemplateArgumentList *getTemplateSpecializationArgs() const; + /// \brief Specify that this function declaration is actually a function /// template specialization. /// @@ -957,19 +1148,30 @@ public: /// /// \param TemplateArgs the template arguments that produced this /// function template specialization from the template. + /// + /// \param InsertPos If non-NULL, the position in the function template + /// specialization set where the function template specialization data will + /// be inserted. + /// + /// \param TSK the kind of template specialization this is. void setFunctionTemplateSpecialization(ASTContext &Context, FunctionTemplateDecl *Template, const TemplateArgumentList *TemplateArgs, - void *InsertPos); + void *InsertPos, + TemplateSpecializationKind TSK = TSK_ImplicitInstantiation); - /// \brief Determine whether this is an explicit specialization of a - /// function template or a member function of a class template. - bool isExplicitSpecialization() const; + /// \brief Determine what kind of template instantiation this function + /// represents. + TemplateSpecializationKind getTemplateSpecializationKind() const; - /// \brief Note that this is an explicit specialization of a function template - /// or a member function of a class template. - void setExplicitSpecialization(bool ES); - + /// \brief Determine what kind of template instantiation this function + /// represents. + void setTemplateSpecializationKind(TemplateSpecializationKind TSK); + + /// \brief Determine whether this is or was instantiated from an out-of-line + /// definition of a member function. + bool isOutOfLine() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast; @@ -984,22 +1186,23 @@ public: }; -/// FieldDecl - An instance of this class is created by Sema::ActOnField to +/// FieldDecl - An instance of this class is created by Sema::ActOnField to /// represent a member of a struct/union/class. -class FieldDecl : public ValueDecl { +class FieldDecl : public DeclaratorDecl { // FIXME: This can be packed into the bitfields in Decl. bool Mutable : 1; Expr *BitWidth; protected: - FieldDecl(Kind DK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, Expr *BW, bool Mutable) - : ValueDecl(DK, DC, L, Id, T), Mutable(Mutable), BitWidth(BW) - { } + FieldDecl(Kind DK, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo, + Expr *BW, bool Mutable) + : DeclaratorDecl(DK, DC, L, Id, T, DInfo), Mutable(Mutable), BitWidth(BW) { + } public: - static FieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, Expr *BW, - bool Mutable); + static FieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType T, + DeclaratorInfo *DInfo, Expr *BW, bool Mutable); /// isMutable - Determines whether this field is mutable (C++ only). bool isMutable() const { return Mutable; } @@ -1049,7 +1252,7 @@ public: SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E, const llvm::APSInt &V); - + virtual void Destroy(ASTContext& C); const Expr *getInitExpr() const { return (const Expr*) Init; } @@ -1058,11 +1261,11 @@ public: void setInitExpr(Expr *E) { Init = (Stmt*) E; } void setInitVal(const llvm::APSInt &V) { Val = V; } - + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == EnumConstant; } static bool classof(const EnumConstantDecl *D) { return true; } - + friend class StmtIteratorBase; }; @@ -1104,16 +1307,16 @@ class TypedefDecl : public TypeDecl { /// UnderlyingType - This is the type the typedef is set to. QualType UnderlyingType; TypedefDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T) + IdentifierInfo *Id, QualType T) : TypeDecl(Typedef, DC, L, Id), UnderlyingType(T) {} virtual ~TypedefDecl() {} public: - + static TypedefDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,IdentifierInfo *Id, QualType T); - + QualType getUnderlyingType() const { return UnderlyingType; } void setUnderlyingType(QualType newType) { UnderlyingType = newType; } @@ -1123,16 +1326,17 @@ public: }; class TypedefDecl; - + /// TagDecl - Represents the declaration of a struct/union/class/enum. -class TagDecl : public TypeDecl, public DeclContext { +class TagDecl + : public TypeDecl, public DeclContext, public Redeclarable<TagDecl> { public: - enum TagKind { - TK_struct, - TK_union, - TK_class, - TK_enum - }; + // This is really ugly. + typedef ElaboratedType::TagKind TagKind; + static const TagKind TK_struct = ElaboratedType::TK_struct; + static const TagKind TK_union = ElaboratedType::TK_union; + static const TagKind TK_class = ElaboratedType::TK_class; + static const TagKind TK_enum = ElaboratedType::TK_enum; private: // FIXME: This can be packed into the bitfields in Decl. @@ -1142,21 +1346,48 @@ private: /// IsDefinition - True if this is a definition ("struct foo {};"), false if /// it is a declaration ("struct foo;"). bool IsDefinition : 1; - + /// TypedefForAnonDecl - If a TagDecl is anonymous and part of a typedef, /// this points to the TypedefDecl. Used for mangling. TypedefDecl *TypedefForAnonDecl; - + + SourceLocation TagKeywordLoc; + SourceLocation RBraceLoc; + protected: TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id) - : TypeDecl(DK, DC, L, Id), DeclContext(DK), TypedefForAnonDecl(0) { + IdentifierInfo *Id, TagDecl *PrevDecl, + SourceLocation TKL = SourceLocation()) + : TypeDecl(DK, DC, L, Id), DeclContext(DK), TypedefForAnonDecl(0), + TagKeywordLoc(TKL) { assert((DK != Enum || TK == TK_enum) &&"EnumDecl not matched with TK_enum"); TagDeclKind = TK; IsDefinition = false; + setPreviousDeclaration(PrevDecl); } + + typedef Redeclarable<TagDecl> redeclarable_base; + virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + public: - + typedef redeclarable_base::redecl_iterator redecl_iterator; + redecl_iterator redecls_begin() const { + return redeclarable_base::redecls_begin(); + } + redecl_iterator redecls_end() const { + return redeclarable_base::redecls_end(); + } + + SourceLocation getRBraceLoc() const { return RBraceLoc; } + void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } + + SourceLocation getTagKeywordLoc() const { return TagKeywordLoc; } + void setTagKeywordLoc(SourceLocation TKL) { TagKeywordLoc = TKL; } + + virtual SourceRange getSourceRange() const; + + virtual TagDecl* getCanonicalDecl(); + /// isDefinition - Return true if this decl has its body specified. bool isDefinition() const { return IsDefinition; @@ -1168,7 +1399,7 @@ public: bool isDependentType() const { return isDependentContext(); } /// @brief Starts the definition of this tag declaration. - /// + /// /// This method should be invoked at the beginning of the definition /// of this tag declaration. It will set the tag type into a state /// where it is in the process of being defined. @@ -1177,7 +1408,7 @@ public: /// @brief Completes the definition of this tag declaration. void completeDefinition(); - /// getDefinition - Returns the TagDecl that actually defines this + /// getDefinition - Returns the TagDecl that actually defines this /// struct/union/class/enum. When determining whether or not a /// struct/union/class/enum is completely defined, one should use this method /// as opposed to 'isDefinition'. 'isDefinition' indicates whether or not a @@ -1185,17 +1416,16 @@ public: /// struct/union/class/enum type is defined. This method returns NULL if /// there is no TagDecl that defines the struct/union/class/enum. TagDecl* getDefinition(ASTContext& C) const; - + const char *getKindName() const { - switch (getTagKind()) { - default: assert(0 && "Unknown TagKind!"); - case TK_struct: return "struct"; - case TK_union: return "union"; - case TK_class: return "class"; - case TK_enum: return "enum"; - } + return ElaboratedType::getNameForTagKind(getTagKind()); } + /// getTagKindForTypeSpec - Converts a type specifier (DeclSpec::TST) + /// into a tag kind. It is an error to provide a type specifier + /// which *isn't* a tag kind here. + static TagKind getTagKindForTypeSpec(unsigned TypeSpec); + TagKind getTagKind() const { return TagKind(TagDeclKind); } @@ -1206,10 +1436,10 @@ public: bool isClass() const { return getTagKind() == TK_class; } bool isUnion() const { return getTagKind() == TK_union; } bool isEnum() const { return getTagKind() == TK_enum; } - + TypedefDecl *getTypedefForAnonDecl() const { return TypedefForAnonDecl; } void setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefForAnonDecl = TDD; } - + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= TagFirst && D->getKind() <= TagLast; @@ -1240,15 +1470,19 @@ class EnumDecl : public TagDecl { EnumDecl *InstantiatedFrom; EnumDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id) - : TagDecl(Enum, TK_enum, DC, L, Id), InstantiatedFrom(0) { + IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL) + : TagDecl(Enum, TK_enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { IntegerType = QualType(); } public: + EnumDecl *getCanonicalDecl() { + return cast<EnumDecl>(TagDecl::getCanonicalDecl()); + } + static EnumDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - EnumDecl *PrevDecl); - + SourceLocation TKL, EnumDecl *PrevDecl); + virtual void Destroy(ASTContext& C); /// completeDefinition - When created, the EnumDecl corresponds to a @@ -1257,16 +1491,16 @@ public: /// added (via DeclContext::addDecl). NewType is the new underlying /// type of the enumeration type. void completeDefinition(ASTContext &C, QualType NewType); - + // enumerator_iterator - Iterates through the enumerators of this // enumeration. typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator; - enumerator_iterator enumerator_begin() const { + enumerator_iterator enumerator_begin() const { return enumerator_iterator(this->decls_begin()); } - enumerator_iterator enumerator_end() const { + enumerator_iterator enumerator_end() const { return enumerator_iterator(this->decls_end()); } @@ -1307,18 +1541,24 @@ class RecordDecl : public TagDecl { /// anonymous struct or union. bool AnonymousStructOrUnion : 1; + /// HasObjectMember - This is true if this struct has at least one + /// member containing an object + bool HasObjectMember : 1; + protected: RecordDecl(Kind DK, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id); + SourceLocation L, IdentifierInfo *Id, + RecordDecl *PrevDecl, SourceLocation TKL); virtual ~RecordDecl(); public: static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + SourceLocation TKL = SourceLocation(), RecordDecl* PrevDecl = 0); virtual void Destroy(ASTContext& C); - + bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; } void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; } @@ -1328,7 +1568,7 @@ public: /// type declared, e.g., /// @code /// union { int i; float f; }; - /// @endcode + /// @endcode /// is an anonymous union but neither of the following are: /// @code /// union X { int i; float f; }; @@ -1339,6 +1579,9 @@ public: AnonymousStructOrUnion = Anon; } + bool hasObjectMember() const { return HasObjectMember; } + void setHasObjectMember (bool val) { HasObjectMember = val; } + /// \brief Determines whether this declaration represents the /// injected class name. /// @@ -1354,7 +1597,7 @@ public: /// \endcode bool isInjectedClassName() const; - /// getDefinition - Returns the RecordDecl that actually defines this + /// getDefinition - Returns the RecordDecl that actually defines this /// struct/union/class. When determining whether or not a struct/union/class /// is completely defined, one should use this method as opposed to /// 'isDefinition'. 'isDefinition' indicates whether or not a specific @@ -1364,7 +1607,7 @@ public: RecordDecl* getDefinition(ASTContext& C) const { return cast_or_null<RecordDecl>(TagDecl::getDefinition(C)); } - + // Iterator access to field members. The field iterator only visits // the non-static data members of this class, ignoring any static // data members, functions, constructors, destructors, etc. @@ -1379,7 +1622,7 @@ public: // field_empty - Whether there are any fields (non-static data // members) in this record. - bool field_empty() const { + bool field_empty() const { return field_begin() == field_end(); } @@ -1408,7 +1651,7 @@ public: static bool classof(const Decl *D) { return D->getKind() == FileScopeAsm; } - static bool classof(const FileScopeAsmDecl *D) { return true; } + static bool classof(const FileScopeAsmDecl *D) { return true; } }; /// BlockDecl - This represents a block literal declaration, which is like an @@ -1423,12 +1666,12 @@ class BlockDecl : public Decl, public DeclContext { /// no formals. ParmVarDecl **ParamInfo; unsigned NumParams; - + Stmt *Body; - + protected: BlockDecl(DeclContext *DC, SourceLocation CaretLoc) - : Decl(Block, DC, CaretLoc), DeclContext(Block), + : Decl(Block, DC, CaretLoc), DeclContext(Block), isVariadic(false), ParamInfo(0), NumParams(0), Body(0) {} virtual ~BlockDecl(); @@ -1441,7 +1684,7 @@ public: bool IsVariadic() const { return isVariadic; } void setIsVariadic(bool value) { isVariadic = value; } - + CompoundStmt *getCompoundBody() const { return (CompoundStmt*) Body; } Stmt *getBody() const { return (Stmt*) Body; } void setBody(CompoundStmt *B) { Body = (Stmt*) B; } @@ -1450,14 +1693,14 @@ public: unsigned param_size() const { return getNumParams(); } typedef ParmVarDecl **param_iterator; typedef ParmVarDecl * const *param_const_iterator; - + bool param_empty() const { return NumParams == 0; } param_iterator param_begin() { return ParamInfo; } param_iterator param_end() { return ParamInfo+param_size(); } - + param_const_iterator param_begin() const { return ParamInfo; } param_const_iterator param_end() const { return ParamInfo+param_size(); } - + unsigned getNumParams() const; const ParmVarDecl *getParamDecl(unsigned i) const { assert(i < getNumParams() && "Illegal param #"); @@ -1468,10 +1711,10 @@ public: return ParamInfo[i]; } void setParams(ASTContext& C, ParmVarDecl **NewParamInfo, unsigned NumParams); - + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == Block; } - static bool classof(const BlockDecl *D) { return true; } + static bool classof(const BlockDecl *D) { return true; } static DeclContext *castToDeclContext(const BlockDecl *D) { return static_cast<DeclContext *>(const_cast<BlockDecl*>(D)); } diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 0bce2f84c7ba..9e88871565f1 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -37,6 +37,7 @@ class ObjCCategoryDecl; class ObjCProtocolDecl; class ObjCImplementationDecl; class ObjCCategoryImplDecl; +class ObjCImplDecl; class LinkageSpecDecl; class BlockDecl; class DeclarationName; @@ -59,8 +60,8 @@ public: namespace clang { -/// Decl - This represents one declaration (or definition), e.g. a variable, -/// typedef, function, struct, etc. +/// Decl - This represents one declaration (or definition), e.g. a variable, +/// typedef, function, struct, etc. /// class Decl { public: @@ -68,7 +69,7 @@ public: enum Kind { #define DECL(Derived, Base) Derived, #define DECL_RANGE(CommonBase, Start, End) \ - CommonBase##First = Start, CommonBase##Last = End, + CommonBase##First = Start, CommonBase##Last = End, #define LAST_DECL_RANGE(CommonBase, Start, End) \ CommonBase##First = Start, CommonBase##Last = End #include "clang/AST/DeclNodes.def" @@ -78,7 +79,9 @@ public: /// 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. + /// use additional namespaces for Objective-C entities. We also + /// put C++ friend declarations (of previously-undeclared entities) in + /// shadow namespaces. enum IdentifierNamespace { IDNS_Label = 0x1, IDNS_Tag = 0x2, @@ -86,9 +89,11 @@ public: IDNS_Ordinary = 0x8, IDNS_ObjCProtocol = 0x10, IDNS_ObjCImplementation = 0x20, - IDNS_ObjCCategoryImpl = 0x40 + IDNS_ObjCCategoryImpl = 0x40, + IDNS_OrdinaryFriend = 0x80, + IDNS_TagFriend = 0x100 }; - + /// ObjCDeclQualifier - Qualifier used on types in method declarations /// for remote messaging. They are meant for the arguments though and /// applied to the Decls (ObjCMethodDecl and ParmVarDecl). @@ -101,7 +106,7 @@ public: OBJC_TQ_Byref = 0x10, OBJC_TQ_Oneway = 0x20 }; - + private: /// NextDeclInContext - The next declaration within the same lexical /// DeclContext. These pointers form the linked list that is @@ -114,8 +119,8 @@ private: DeclContext *SemanticDC; DeclContext *LexicalDC; }; - - + + /// DeclCtx - Holds either a DeclContext* or a MultipleDC*. /// For declarations that don't contain C++ scope specifiers, it contains /// the DeclContext where the Decl was declared. @@ -139,16 +144,16 @@ private: inline DeclContext *getSemanticDC() const { return DeclCtx.get<DeclContext*>(); } - + /// Loc - The location that this decl. SourceLocation Loc; - + /// DeclKind - This indicates which class this is. Kind DeclKind : 8; - + /// InvalidDecl - This indicates a semantic error occurred. unsigned int InvalidDecl : 1; - + /// HasAttrs - This indicates whether the decl has attributes or not. unsigned int HasAttrs : 1; @@ -162,23 +167,23 @@ private: protected: /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. - unsigned IdentifierNamespace : 8; - + unsigned IdentifierNamespace : 16; + private: #ifndef NDEBUG void CheckAccessDeclContext() const; #else void CheckAccessDeclContext() const { } #endif - + protected: /// Access - Used by C++ decls for the access specifier. // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum unsigned Access : 2; friend class CXXClassMemberWrapper; - Decl(Kind DK, DeclContext *DC, SourceLocation L) - : NextDeclInContext(0), DeclCtx(DC), + Decl(Kind DK, DeclContext *DC, SourceLocation L) + : NextDeclInContext(0), DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), Access(AS_none) { @@ -201,7 +206,7 @@ public: Kind getKind() const { return DeclKind; } const char *getDeclKindName() const; - + Decl *getNextDeclInContext() { return NextDeclInContext; } const Decl *getNextDeclInContext() const { return NextDeclInContext; } @@ -219,16 +224,18 @@ public: return const_cast<Decl*>(this)->getTranslationUnitDecl(); } + bool isInAnonymousNamespace() const; + ASTContext &getASTContext() const; - + void setAccess(AccessSpecifier AS) { - Access = AS; + Access = AS; CheckAccessDeclContext(); } - - AccessSpecifier getAccess() const { + + AccessSpecifier getAccess() const { CheckAccessDeclContext(); - return AccessSpecifier(Access); + return AccessSpecifier(Access); } bool hasAttrs() const { return HasAttrs; } @@ -246,11 +253,11 @@ public: return V; return 0; } - + template<typename T> bool hasAttr() const { return getAttr<T>() != 0; } - + /// setInvalidDecl - Indicates the Decl had a semantic error. This /// allows for graceful error recovery. void setInvalidDecl(bool Invalid = true) { InvalidDecl = Invalid; } @@ -261,12 +268,12 @@ public: /// was written explicitly in the source code. bool isImplicit() const { return Implicit; } void setImplicit(bool I = true) { Implicit = I; } - + /// \brief Whether this declaration was used, meaning that a definition /// is required. bool isUsed() const { return Used; } void setUsed(bool U = true) { Used = U; } - + unsigned getIdentifierNamespace() const { return IdentifierNamespace; } @@ -275,7 +282,7 @@ public: } static unsigned getIdentifierNamespaceForKind(Kind DK); - + /// getLexicalDeclContext - The declaration context where this Decl was /// lexically declared (LexicalDC). May be different from /// getDeclContext() (SemanticDC). @@ -298,7 +305,7 @@ public: bool isOutOfLine() const { return getLexicalDeclContext() != getDeclContext(); } - + /// setDeclContext - Set both the semantic and lexical DeclContext /// to DC. void setDeclContext(DeclContext *DC); @@ -311,6 +318,72 @@ public: // be defined inside or outside a function etc). bool isDefinedOutsideFunctionOrMethod() const; + /// \brief Retrieves the "canonical" declaration of the given declaration. + virtual Decl *getCanonicalDecl() { return this; } + const Decl *getCanonicalDecl() const { + return const_cast<Decl*>(this)->getCanonicalDecl(); + } + + /// \brief Whether this particular Decl is a canonical one. + bool isCanonicalDecl() const { return getCanonicalDecl() == this; } + +protected: + /// \brief Returns the next redeclaration or itself if this is the only decl. + /// + /// Decl subclasses that can be redeclared should override this method so that + /// Decl::redecl_iterator can iterate over them. + virtual Decl *getNextRedeclaration() { return this; } + +public: + /// \brief Iterates through all the redeclarations of the same decl. + class redecl_iterator { + /// Current - The current declaration. + Decl *Current; + Decl *Starter; + + public: + typedef Decl* value_type; + typedef Decl* reference; + typedef Decl* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + redecl_iterator() : Current(0) { } + explicit redecl_iterator(Decl *C) : Current(C), Starter(C) { } + + reference operator*() const { return Current; } + pointer operator->() const { return Current; } + + redecl_iterator& operator++() { + assert(Current && "Advancing while iterator has reached end"); + // Get either previous decl or latest decl. + Decl *Next = Current->getNextRedeclaration(); + assert(Next && "Should return next redeclaration or itself, never null!"); + Current = (Next != Starter ? Next : 0); + return *this; + } + + redecl_iterator operator++(int) { + redecl_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(redecl_iterator x, redecl_iterator y) { + return x.Current == y.Current; + } + friend bool operator!=(redecl_iterator x, redecl_iterator y) { + return x.Current != y.Current; + } + }; + + /// \brief Returns iterator for all the redeclarations of the same decl. + /// It will iterate at least once (when this decl is the only one). + redecl_iterator redecls_begin() const { + return redecl_iterator(const_cast<Decl*>(this)); + } + redecl_iterator redecls_end() const { return redecl_iterator(); } + /// getBody - If this Decl represents a declaration for a body of code, /// such as a function or method definition, this method returns the /// top-level Stmt* of that body. Otherwise this method returns null. @@ -327,33 +400,71 @@ public: static void addDeclKind(Kind k); static bool CollectingStats(bool Enable = false); static void PrintStats(); - + /// isTemplateParameter - Determines whether this declaration is a /// template parameter. bool isTemplateParameter() const; - + /// isTemplateParameter - Determines whether this declaration is a /// template parameter pack. bool isTemplateParameterPack() const; /// \brief Whether this declaration is a function or function template. bool isFunctionOrFunctionTemplate() const; - + + /// \brief Changes the namespace of this declaration to reflect that it's + /// the object of a friend declaration. + /// + /// These declarations appear in the lexical context of the friending + /// class, but in the semantic context of the actual entity. This property + /// applies only to a specific decl object; other redeclarations of the + /// same entity may not (and probably don't) share this property. + void setObjectOfFriendDecl(bool PreviouslyDeclared) { + unsigned OldNS = IdentifierNamespace; + assert((OldNS == IDNS_Tag || OldNS == IDNS_Ordinary || + OldNS == (IDNS_Tag | IDNS_Ordinary)) + && "unsupported namespace for undeclared friend"); + if (!PreviouslyDeclared) IdentifierNamespace = 0; + + if (OldNS == IDNS_Tag) + IdentifierNamespace |= IDNS_TagFriend; + else + IdentifierNamespace |= IDNS_OrdinaryFriend; + } + + enum FriendObjectKind { + FOK_None, // not a friend object + FOK_Declared, // a friend of a previously-declared entity + FOK_Undeclared // a friend of a previously-undeclared entity + }; + + /// \brief Determines whether this declaration is the object of a + /// friend declaration and, if so, what kind. + /// + /// There is currently no direct way to find the associated FriendDecl. + FriendObjectKind getFriendObjectKind() const { + unsigned mask + = (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend)); + if (!mask) return FOK_None; + return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ? + FOK_Declared : FOK_Undeclared); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *) { return true; } static DeclContext *castToDeclContext(const Decl *); static Decl *castFromDeclContext(const DeclContext *); - + /// Destroy - Call destructors and release memory. virtual void Destroy(ASTContext& C); - void print(llvm::raw_ostream &Out, unsigned Indentation = 0); + void print(llvm::raw_ostream &Out, unsigned Indentation = 0) const; void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy, - unsigned Indentation = 0); + unsigned Indentation = 0) const; static void printGroup(Decl** Begin, unsigned NumDecls, llvm::raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation = 0); - void dump(); + void dump() const; private: const Attr *getAttrsImpl() const; @@ -371,10 +482,10 @@ public: PrettyStackTraceDecl(Decl *theDecl, SourceLocation L, SourceManager &sm, const char *Msg) : TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {} - + virtual void print(llvm::raw_ostream &OS) const; -}; - +}; + /// DeclContext - This is used only as base class of specific decl types that /// can act as declaration contexts. These decls are (only the top classes @@ -386,8 +497,6 @@ public: /// TagDecl /// ObjCMethodDecl /// ObjCContainerDecl -/// ObjCCategoryImplDecl -/// ObjCImplementationDecl /// LinkageSpecDecl /// BlockDecl /// @@ -421,9 +530,9 @@ class DeclContext { mutable Decl *LastDecl; protected: - DeclContext(Decl::Kind K) + DeclContext(Decl::Kind K) : DeclKind(K), ExternalLexicalStorage(false), - ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0), + ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0), LastDecl(0) { } void DestroyDecls(ASTContext &C); @@ -443,7 +552,7 @@ public: const DeclContext *getParent() const { return const_cast<DeclContext*>(this)->getParent(); } - + /// getLexicalParent - Returns the containing lexical DeclContext. May be /// different from getParent, e.g.: /// @@ -458,8 +567,14 @@ public: } const DeclContext *getLexicalParent() const { return const_cast<DeclContext*>(this)->getLexicalParent(); - } + } + DeclContext *getLookupParent(); + + const DeclContext *getLookupParent() const { + return const_cast<DeclContext*>(this)->getLookupParent(); + } + ASTContext &getParentASTContext() const { return cast<Decl>(this)->getASTContext(); } @@ -499,10 +614,10 @@ public: /// context are semantically declared in the nearest enclosing /// non-transparent (opaque) context but are lexically declared in /// this context. For example, consider the enumerators of an - /// enumeration type: + /// enumeration type: /// @code /// enum E { - /// Val1 + /// Val1 /// }; /// @endcode /// Here, E is a transparent context, so its enumerator (Val1) will @@ -512,13 +627,16 @@ public: /// inline namespaces. bool isTransparentContext() const; - bool Encloses(DeclContext *DC) const { - for (; DC; DC = DC->getParent()) - if (DC == this) - return true; - return false; + /// \brief Determine whether this declaration context is equivalent + /// to the declaration context DC. + bool Equals(DeclContext *DC) { + return this->getPrimaryContext() == DC->getPrimaryContext(); } + /// \brief Determine whether this declaration context encloses the + /// declaration context DC. + bool Encloses(DeclContext *DC); + /// getPrimaryContext - There may be many different /// declarations of the same entity (including forward declarations /// of classes, multiple definitions of namespaces, etc.), each with @@ -535,7 +653,7 @@ public: const DeclContext *getLookupContext() const { return const_cast<DeclContext *>(this)->getLookupContext(); } - + /// \brief Retrieve the nearest enclosing namespace context. DeclContext *getEnclosingNamespaceContext(); const DeclContext *getEnclosingNamespaceContext() const { @@ -591,16 +709,16 @@ public: return tmp; } - friend bool operator==(decl_iterator x, decl_iterator y) { + friend bool operator==(decl_iterator x, decl_iterator y) { return x.Current == y.Current; } - friend bool operator!=(decl_iterator x, decl_iterator y) { + friend bool operator!=(decl_iterator x, decl_iterator y) { return x.Current != y.Current; } }; /// decls_begin/decls_end - Iterate over the declarations stored in - /// this context. + /// this context. decl_iterator decls_begin() const; decl_iterator decls_end() const; bool decls_empty() const; @@ -616,7 +734,7 @@ public: /// will either be NULL or will point to a declaration of /// type SpecificDecl. DeclContext::decl_iterator Current; - + /// SkipToNextDecl - Advances the current position up to the next /// declaration of type SpecificDecl that also meets the criteria /// required by Acceptable. @@ -661,13 +779,13 @@ public: ++(*this); return tmp; } - + friend bool operator==(const specific_decl_iterator& x, const specific_decl_iterator& y) { return x.Current == y.Current; } - - friend bool + + friend bool operator!=(const specific_decl_iterator& x, const specific_decl_iterator& y) { return x.Current != y.Current; } @@ -688,7 +806,7 @@ public: /// will either be NULL or will point to a declaration of /// type SpecificDecl. DeclContext::decl_iterator Current; - + /// SkipToNextDecl - Advances the current position up to the next /// declaration of type SpecificDecl that also meets the criteria /// required by Acceptable. @@ -735,13 +853,13 @@ public: ++(*this); return tmp; } - + friend bool operator==(const filtered_decl_iterator& x, const filtered_decl_iterator& y) { return x.Current == y.Current; } - - friend bool + + friend bool operator!=(const filtered_decl_iterator& x, const filtered_decl_iterator& y) { return x.Current != y.Current; } @@ -761,6 +879,14 @@ public: /// semantic context via makeDeclVisibleInContext. void addDecl(Decl *D); + /// @brief Add the declaration D to this context without modifying + /// any lookup tables. + /// + /// This is useful for some operations in dependent contexts where + /// the semantic context might not be dependent; this basically + /// only happens with friends. + void addHiddenDecl(Decl *D); + /// lookup_iterator - An iterator that provides access to the results /// of looking up a name within this context. typedef NamedDecl **lookup_iterator; @@ -795,12 +921,16 @@ public: /// visible from this context, as determined by /// NamedDecl::declarationReplaces, the previous declaration will be /// replaced with D. - void makeDeclVisibleInContext(NamedDecl *D); + /// + /// @param Recoverable true if it's okay to not add this decl to + /// the lookup tables because it can be easily recovered by walking + /// the declaration chains. + void makeDeclVisibleInContext(NamedDecl *D, bool Recoverable = true); /// udir_iterator - Iterates through the using-directives stored /// within this context. typedef UsingDirectiveDecl * const * udir_iterator; - + typedef std::pair<udir_iterator, udir_iterator> udir_iterator_range; udir_iterator_range getUsingDirectives() const; @@ -824,8 +954,8 @@ public: /// \brief State whether this DeclContext has external storage for /// declarations lexically in this context. - void setHasExternalLexicalStorage(bool ES = true) { - ExternalLexicalStorage = ES; + void setHasExternalLexicalStorage(bool ES = true) { + ExternalLexicalStorage = ES; } /// \brief Whether this DeclContext has external storage containing @@ -834,8 +964,8 @@ public: /// \brief State whether this DeclContext has external storage for /// declarations visible in this context. - void setHasExternalVisibleStorage(bool ES = true) { - ExternalVisibleStorage = ES; + void setHasExternalVisibleStorage(bool ES = true) { + ExternalVisibleStorage = ES; } static bool classof(const Decl *D); diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index c523e96e03b0..c858c5c0df78 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -14,46 +14,51 @@ #ifndef LLVM_CLANG_AST_DECLCXX_H #define LLVM_CLANG_AST_DECLCXX_H +#include "clang/AST/Expr.h" #include "clang/AST/Decl.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" namespace clang { class ClassTemplateDecl; -class CXXRecordDecl; +class ClassTemplateSpecializationDecl; +class CXXBasePath; +class CXXBasePaths; class CXXConstructorDecl; -class CXXDestructorDecl; class CXXConversionDecl; +class CXXDestructorDecl; class CXXMethodDecl; -class ClassTemplateSpecializationDecl; - -/// \brief Represents any kind of function declaration, whether it is a +class CXXRecordDecl; +class CXXMemberLookupCriteria; + +/// \brief Represents any kind of function declaration, whether it is a /// concrete function or a function template. class AnyFunctionDecl { NamedDecl *Function; - + AnyFunctionDecl(NamedDecl *ND) : Function(ND) { } - + public: AnyFunctionDecl(FunctionDecl *FD) : Function(FD) { } AnyFunctionDecl(FunctionTemplateDecl *FTD); - - /// \brief Implicily converts any function or function template into a + + /// \brief Implicily converts any function or function template into a /// named declaration. operator NamedDecl *() const { return Function; } - + /// \brief Retrieve the underlying function or function template. NamedDecl *get() const { return Function; } - - static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) { + + static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) { return AnyFunctionDecl(ND); } }; - + } // end namespace clang namespace llvm { - /// Implement simplify_type for AnyFunctionDecl, so that we can dyn_cast from + /// Implement simplify_type for AnyFunctionDecl, so that we can dyn_cast from /// AnyFunctionDecl to any function or function template declaration. template<> struct simplify_type<const ::clang::AnyFunctionDecl> { typedef ::clang::NamedDecl* SimpleType; @@ -63,26 +68,26 @@ namespace llvm { }; template<> struct simplify_type< ::clang::AnyFunctionDecl> : public simplify_type<const ::clang::AnyFunctionDecl> {}; - + // Provide PointerLikeTypeTraits for non-cvr pointers. template<> class PointerLikeTypeTraits< ::clang::AnyFunctionDecl> { public: static inline void *getAsVoidPointer(::clang::AnyFunctionDecl F) { - return F.get(); + return F.get(); } static inline ::clang::AnyFunctionDecl getFromVoidPointer(void *P) { return ::clang::AnyFunctionDecl::getFromNamedDecl( static_cast< ::clang::NamedDecl*>(P)); } - + enum { NumLowBitsAvailable = 2 }; }; - + } // end namespace llvm namespace clang { - + /// OverloadedFunctionDecl - An instance of this class represents a /// set of overloaded functions. All of the functions have the same /// name and occur within the same scope. @@ -127,12 +132,64 @@ public: unsigned size() const { return Functions.size(); } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() == OverloadedFunction; + static bool classof(const Decl *D) { + return D->getKind() == OverloadedFunction; } static bool classof(const OverloadedFunctionDecl *D) { return true; } }; +/// \brief Provides uniform iteration syntax for an overload set, function, +/// or function template. +class OverloadIterator { + /// \brief An overloaded function set, function declaration, or + /// function template declaration. + NamedDecl *D; + + /// \brief If the declaration is an overloaded function set, this is the + /// iterator pointing to the current position within that overloaded + /// function set. + OverloadedFunctionDecl::function_iterator Iter; + +public: + typedef AnyFunctionDecl value_type; + typedef value_type reference; + typedef NamedDecl *pointer; + typedef int difference_type; + typedef std::forward_iterator_tag iterator_category; + + OverloadIterator() : D(0) { } + + OverloadIterator(FunctionDecl *FD) : D(FD) { } + OverloadIterator(FunctionTemplateDecl *FTD) + : D(reinterpret_cast<NamedDecl*>(FTD)) { } + OverloadIterator(OverloadedFunctionDecl *Ovl) + : D(Ovl), Iter(Ovl->function_begin()) { } + + OverloadIterator(NamedDecl *ND); + + reference operator*() const; + + pointer operator->() const { return (**this).get(); } + + OverloadIterator &operator++(); + + OverloadIterator operator++(int) { + OverloadIterator Temp(*this); + ++(*this); + return Temp; + } + + bool Equals(const OverloadIterator &Other) const; +}; + +inline bool operator==(const OverloadIterator &X, const OverloadIterator &Y) { + return X.Equals(Y); +} + +inline bool operator!=(const OverloadIterator &X, const OverloadIterator &Y) { + return !(X == Y); +} + /// CXXBaseSpecifier - A base class of a C++ class. /// /// Each CXXBaseSpecifier represents a single, direct base class (or @@ -162,7 +219,7 @@ class CXXBaseSpecifier { /// struct (false). This determines the mapping from the access /// specifier as written in the source code to the access specifier /// used for semantic analysis. - bool BaseOfClass : 1; + bool BaseOfClass : 1; /// Access - Access specifier as written in the source code (which /// may be AS_none). The actual type of data stored here is an @@ -173,7 +230,7 @@ class CXXBaseSpecifier { /// BaseType - The type of the base class. This will be a class or /// struct (or a typedef of such). QualType BaseType; - + public: CXXBaseSpecifier() { } @@ -183,7 +240,7 @@ public: /// getSourceRange - Retrieves the source range that contains the /// entire base specifier. SourceRange getSourceRange() const { return Range; } - + /// isVirtual - Determines whether the base class is a virtual base /// class (or not). bool isVirtual() const { return Virtual; } @@ -193,11 +250,11 @@ public: /// semantic analysis, so the result can never be AS_none. To /// retrieve the access specifier as written in the source code, use /// getAccessSpecifierAsWritten(). - AccessSpecifier getAccessSpecifier() const { + AccessSpecifier getAccessSpecifier() const { if ((AccessSpecifier)Access == AS_none) return BaseOfClass? AS_private : AS_public; else - return (AccessSpecifier)Access; + return (AccessSpecifier)Access; } /// getAccessSpecifierAsWritten - Retrieves the access specifier as @@ -218,7 +275,7 @@ public: /// to deal with C++-specific things. class CXXRecordDecl : public RecordDecl { /// UserDeclaredConstructor - True when this class has a - /// user-declared constructor. + /// user-declared constructor. bool UserDeclaredConstructor : 1; /// UserDeclaredCopyConstructor - True when this class has a @@ -239,6 +296,12 @@ class CXXRecordDecl : public RecordDecl { /// PlainOldData - True when this class is a POD-type. bool PlainOldData : 1; + /// Empty - true when this class is empty for traits purposes, i.e. has no + /// data members other than 0-width bit-fields, has no virtual function/base, + /// and doesn't inherit from a non-empty class. Doesn't take union-ness into + /// account. + bool Empty : 1; + /// Polymorphic - True when this class is polymorphic, i.e. has at least one /// virtual member or derives from a polymorphic class. bool Polymorphic : 1; @@ -246,12 +309,55 @@ class CXXRecordDecl : public RecordDecl { /// Abstract - True when this class is abstract, i.e. has at least one /// pure virtual function, (that can come from a base class). bool Abstract : 1; - - /// HasTrivialConstructor - True when this class has a trivial constructor + + /// HasTrivialConstructor - True when this class has a trivial constructor. + /// + /// C++ [class.ctor]p5. A constructor is trivial if it is an + /// implicitly-declared default constructor and if: + /// * its class has no virtual functions and no virtual base classes, and + /// * all the direct base classes of its class have trivial constructors, and + /// * for all the nonstatic data members of its class that are of class type + /// (or array thereof), each such class has a trivial constructor. bool HasTrivialConstructor : 1; - - /// HasTrivialDestructor - True when this class has a trivial destructor + + /// HasTrivialCopyConstructor - True when this class has a trivial copy + /// constructor. + /// + /// C++ [class.copy]p6. A copy constructor for class X is trivial + /// if it is implicitly declared and if + /// * class X has no virtual functions and no virtual base classes, and + /// * each direct base class of X has a trivial copy constructor, and + /// * for all the nonstatic data members of X that are of class type (or + /// array thereof), each such class type has a trivial copy constructor; + /// otherwise the copy constructor is non-trivial. + bool HasTrivialCopyConstructor : 1; + + /// HasTrivialCopyAssignment - True when this class has a trivial copy + /// assignment operator. + /// + /// C++ [class.copy]p11. A copy assignment operator for class X is + /// trivial if it is implicitly declared and if + /// * class X has no virtual functions and no virtual base classes, and + /// * each direct base class of X has a trivial copy assignment operator, and + /// * for all the nonstatic data members of X that are of class type (or + /// array thereof), each such class type has a trivial copy assignment + /// operator; + /// otherwise the copy assignment operator is non-trivial. + bool HasTrivialCopyAssignment : 1; + + /// HasTrivialDestructor - True when this class has a trivial destructor. + /// + /// C++ [class.dtor]p3. A destructor is trivial if it is an + /// implicitly-declared destructor and if: + /// * all of the direct base classes of its class have trivial destructors + /// and + /// * for all of the non-static data members of its class that are of class + /// type (or array thereof), each such class has a trivial destructor. bool HasTrivialDestructor : 1; + + /// ComputedVisibleConversions - True when visible conversion functions are + /// already computed and are available. + bool ComputedVisibleConversions : 1; /// Bases - Base classes of this class. /// FIXME: This is wasted space for a union. @@ -260,45 +366,85 @@ class CXXRecordDecl : public RecordDecl { /// NumBases - The number of base class specifiers in Bases. unsigned NumBases; + /// VBases - direct and indirect virtual base classes of this class. + CXXBaseSpecifier *VBases; + + /// NumVBases - The number of virtual base class specifiers in VBases. + unsigned NumVBases; + /// Conversions - Overload set containing the conversion functions /// of this C++ class (but not its inherited conversion /// functions). Each of the entries in this overload set is a - /// CXXConversionDecl. + /// CXXConversionDecl. OverloadedFunctionDecl Conversions; + /// VisibleConversions - Overload set containing the conversion functions + /// of this C++ class and all those inherited conversion functions that + /// are visible in this class. Each of the entries in this overload set is + /// a CXXConversionDecl or a FunctionTemplateDecl. + OverloadedFunctionDecl VisibleConversions; + /// \brief The template or declaration that this declaration /// describes or was instantiated from, respectively. - /// + /// /// For non-templates, this value will be NULL. For record /// declarations that describe a class template, this will be a /// pointer to a ClassTemplateDecl. For member /// classes of class template specializations, this will be the - /// RecordDecl from which the member class was instantiated. - llvm::PointerUnion<ClassTemplateDecl*, CXXRecordDecl*> + /// MemberSpecializationInfo referring to the member class that was + /// instantiated or specialized. + llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*> TemplateOrInstantiation; - + + void getNestedVisibleConversionFunctions(CXXRecordDecl *RD, + const llvm::SmallPtrSet<CanQualType, 8> &TopConversionsTypeSet, + const llvm::SmallPtrSet<CanQualType, 8> &HiddenConversionTypes); + void collectConversionFunctions( + llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet); + protected: CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id); + SourceLocation L, IdentifierInfo *Id, + CXXRecordDecl *PrevDecl, + SourceLocation TKL = SourceLocation()); ~CXXRecordDecl(); public: /// base_class_iterator - Iterator that traverses the base classes - /// of a clas. + /// of a class. typedef CXXBaseSpecifier* base_class_iterator; /// base_class_const_iterator - Iterator that traverses the base - /// classes of a clas. + /// classes of a class. typedef const CXXBaseSpecifier* base_class_const_iterator; + /// reverse_base_class_iterator = Iterator that traverses the base classes + /// of a class in reverse order. + typedef std::reverse_iterator<base_class_iterator> + reverse_base_class_iterator; + + /// reverse_base_class_iterator = Iterator that traverses the base classes + /// of a class in reverse order. + typedef std::reverse_iterator<base_class_const_iterator> + reverse_base_class_const_iterator; + + virtual CXXRecordDecl *getCanonicalDecl() { + return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl()); + } + static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + SourceLocation TKL = SourceLocation(), CXXRecordDecl* PrevDecl=0, bool DelayTypeCreation = false); - + virtual void Destroy(ASTContext& C); - + + bool isDynamicClass() const { + return Polymorphic || NumVBases != 0; + } + /// setBases - Sets the base classes of this struct or class. void setBases(ASTContext &C, CXXBaseSpecifier const * const *Bases, unsigned NumBases); @@ -311,18 +457,78 @@ public: base_class_const_iterator bases_begin() const { return Bases; } base_class_iterator bases_end() { return Bases + NumBases; } base_class_const_iterator bases_end() const { return Bases + NumBases; } + reverse_base_class_iterator bases_rbegin() { + return reverse_base_class_iterator(bases_end()); + } + reverse_base_class_const_iterator bases_rbegin() const { + return reverse_base_class_const_iterator(bases_end()); + } + reverse_base_class_iterator bases_rend() { + return reverse_base_class_iterator(bases_begin()); + } + reverse_base_class_const_iterator bases_rend() const { + return reverse_base_class_const_iterator(bases_begin()); + } + + /// getNumVBases - Retrieves the number of virtual base classes of this + /// class. + unsigned getNumVBases() const { return NumVBases; } + + base_class_iterator vbases_begin() { return VBases; } + base_class_const_iterator vbases_begin() const { return VBases; } + base_class_iterator vbases_end() { return VBases + NumVBases; } + base_class_const_iterator vbases_end() const { return VBases + NumVBases; } + reverse_base_class_iterator vbases_rbegin() { + return reverse_base_class_iterator(vbases_end()); + } + reverse_base_class_const_iterator vbases_rbegin() const { + return reverse_base_class_const_iterator(vbases_end()); + } + reverse_base_class_iterator vbases_rend() { + return reverse_base_class_iterator(vbases_begin()); + } + reverse_base_class_const_iterator vbases_rend() const { + return reverse_base_class_const_iterator(vbases_begin()); + } + + /// Iterator access to method members. The method iterator visits + /// all method members of the class, including non-instance methods, + /// special methods, etc. + typedef specific_decl_iterator<CXXMethodDecl> method_iterator; + + /// method_begin - Method begin iterator. Iterates in the order the methods + /// were declared. + method_iterator method_begin() const { + return method_iterator(decls_begin()); + } + /// method_end - Method end iterator. + method_iterator method_end() const { + return method_iterator(decls_end()); + } + + /// Iterator access to constructor members. + typedef specific_decl_iterator<CXXConstructorDecl> ctor_iterator; + + ctor_iterator ctor_begin() const { + return ctor_iterator(decls_begin()); + } + ctor_iterator ctor_end() const { + return ctor_iterator(decls_end()); + } /// hasConstCopyConstructor - Determines whether this class has a /// copy constructor that accepts a const-qualified argument. bool hasConstCopyConstructor(ASTContext &Context) const; /// getCopyConstructor - Returns the copy constructor for this class - CXXConstructorDecl *getCopyConstructor(ASTContext &Context, + CXXConstructorDecl *getCopyConstructor(ASTContext &Context, unsigned TypeQuals) const; /// hasConstCopyAssignment - Determines whether this class has a /// copy assignment operator that accepts a const-qualified argument. - bool hasConstCopyAssignment(ASTContext &Context) const; + /// It returns its decl in MD if found. + bool hasConstCopyAssignment(ASTContext &Context, + const CXXMethodDecl *&MD) const; /// addedConstructor - Notify the class that another constructor has /// been added. This routine helps maintain information about the @@ -332,7 +538,12 @@ public: /// hasUserDeclaredConstructor - Whether this class has any /// user-declared constructors. When true, a default constructor /// will not be implicitly declared. - bool hasUserDeclaredConstructor() const { return UserDeclaredConstructor; } + bool hasUserDeclaredConstructor() const { + assert((isDefinition() || + cast<RecordType>(getTypeForDecl())->isBeingDefined()) && + "Incomplete record decl!"); + return UserDeclaredConstructor; + } /// hasUserDeclaredCopyConstructor - Whether this class has a /// user-declared copy constructor. When false, a copy constructor @@ -361,22 +572,43 @@ public: /// setUserDeclaredDestructor - Set whether this class has a /// user-declared destructor. If not set by the time the class is /// fully defined, a destructor will be implicitly declared. - void setUserDeclaredDestructor(bool UCD) { - UserDeclaredDestructor = UCD; + void setUserDeclaredDestructor(bool UCD) { + UserDeclaredDestructor = UCD; } /// getConversions - Retrieve the overload set containing all of the /// conversion functions in this class. - OverloadedFunctionDecl *getConversionFunctions() { - return &Conversions; + OverloadedFunctionDecl *getConversionFunctions() { + assert((this->isDefinition() || + cast<RecordType>(getTypeForDecl())->isBeingDefined()) && + "getConversionFunctions() called on incomplete type"); + return &Conversions; } - const OverloadedFunctionDecl *getConversionFunctions() const { - return &Conversions; + const OverloadedFunctionDecl *getConversionFunctions() const { + assert((this->isDefinition() || + cast<RecordType>(getTypeForDecl())->isBeingDefined()) && + "getConversionFunctions() called on incomplete type"); + return &Conversions; } + /// getVisibleConversionFunctions - get all conversion functions visible + /// in current class; including conversion function templates. + OverloadedFunctionDecl *getVisibleConversionFunctions(); + /// addVisibleConversionFunction - Add a new conversion function to the + /// list of visible conversion functions. + void addVisibleConversionFunction(CXXConversionDecl *ConvDecl); + + /// \brief Add a new conversion function template to the list of visible + /// conversion functions. + void addVisibleConversionFunction(FunctionTemplateDecl *ConvDecl); + /// addConversionFunction - Add a new conversion function to the /// list of conversion functions. - void addConversionFunction(ASTContext &Context, CXXConversionDecl *ConvDecl); + void addConversionFunction(CXXConversionDecl *ConvDecl); + + /// \brief Add a new conversion function template to the list of conversion + /// functions. + void addConversionFunction(FunctionTemplateDecl *ConvDecl); /// isAggregate - Whether this class is an aggregate (C++ /// [dcl.init.aggr]), which is a class with no user-declared @@ -397,6 +629,15 @@ public: /// setPOD - Set whether this class is a POD-type (C++ [class]p4). void setPOD(bool POD) { PlainOldData = POD; } + /// isEmpty - Whether this class is empty (C++0x [meta.unary.prop]), which + /// means it has a virtual function, virtual base, data member (other than + /// 0-width bit-field) or inherits from a non-empty class. Does NOT include + /// a check for union-ness. + bool isEmpty() const { return Empty; } + + /// Set whether this class is empty (C++0x [meta.unary.prop]) + void setEmpty(bool Emp) { Empty = Emp; } + /// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]), /// which means that the class contains or inherits a virtual function. bool isPolymorphic() const { return Polymorphic; } @@ -408,26 +649,42 @@ public: /// isAbstract - Whether this class is abstract (C++ [class.abstract]), /// which means that the class contains or inherits a pure virtual function. bool isAbstract() const { return Abstract; } - + /// setAbstract - Set whether this class is abstract (C++ [class.abstract]) void setAbstract(bool Abs) { Abstract = Abs; } - + // hasTrivialConstructor - Whether this class has a trivial constructor // (C++ [class.ctor]p5) bool hasTrivialConstructor() const { return HasTrivialConstructor; } - + // setHasTrivialConstructor - Set whether this class has a trivial constructor // (C++ [class.ctor]p5) void setHasTrivialConstructor(bool TC) { HasTrivialConstructor = TC; } - + + // hasTrivialCopyConstructor - Whether this class has a trivial copy + // constructor (C++ [class.copy]p6) + bool hasTrivialCopyConstructor() const { return HasTrivialCopyConstructor; } + + // setHasTrivialCopyConstructor - Set whether this class has a trivial + // copy constructor (C++ [class.copy]p6) + void setHasTrivialCopyConstructor(bool TC) { HasTrivialCopyConstructor = TC; } + + // hasTrivialCopyAssignment - Whether this class has a trivial copy + // assignment operator (C++ [class.copy]p11) + bool hasTrivialCopyAssignment() const { return HasTrivialCopyAssignment; } + + // setHasTrivialCopyAssignment - Set whether this class has a + // trivial copy assignment operator (C++ [class.copy]p11) + void setHasTrivialCopyAssignment(bool TC) { HasTrivialCopyAssignment = TC; } + // hasTrivialDestructor - Whether this class has a trivial destructor // (C++ [class.dtor]p3) bool hasTrivialDestructor() const { return HasTrivialDestructor; } - + // setHasTrivialDestructor - Set whether this class has a trivial destructor // (C++ [class.dtor]p3) void setHasTrivialDestructor(bool TC) { HasTrivialDestructor = TC; } - + /// \brief If this record is an instantiation of a member class, /// retrieves the member class from which it was instantiated. /// @@ -447,15 +704,17 @@ public: /// the CXXRecordDecl X<T>::A. When a complete definition of /// X<int>::A is required, it will be instantiated from the /// declaration returned by getInstantiatedFromMemberClass(). - CXXRecordDecl *getInstantiatedFromMemberClass() const { - return TemplateOrInstantiation.dyn_cast<CXXRecordDecl*>(); - } - + CXXRecordDecl *getInstantiatedFromMemberClass() const; + + /// \brief If this class is an instantiation of a member class of a + /// class template specialization, retrieves the member specialization + /// information. + MemberSpecializationInfo *getMemberSpecializationInfo() const; + /// \brief Specify that this record is an instantiation of the /// member class RD. - void setInstantiationOfMemberClass(CXXRecordDecl *RD) { - TemplateOrInstantiation = RD; - } + void setInstantiationOfMemberClass(CXXRecordDecl *RD, + TemplateSpecializationKind TSK); /// \brief Retrieves the class template that is described by this /// class declaration. @@ -476,34 +735,150 @@ public: TemplateOrInstantiation = Template; } + /// \brief Determine whether this particular class is a specialization or + /// instantiation of a class template or member class of a class template, + /// and how it was instantiated or specialized. + TemplateSpecializationKind getTemplateSpecializationKind(); + + /// \brief Set the kind of specialization or template instantiation this is. + void setTemplateSpecializationKind(TemplateSpecializationKind TSK); + /// getDefaultConstructor - Returns the default constructor for this class CXXConstructorDecl *getDefaultConstructor(ASTContext &Context); - + /// getDestructor - Returns the destructor decl for this class. const CXXDestructorDecl *getDestructor(ASTContext &Context); - + /// isLocalClass - If the class is a local class [class.local], returns /// the enclosing function declaration. const FunctionDecl *isLocalClass() const { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(getDeclContext())) return RD->isLocalClass(); - + return dyn_cast<FunctionDecl>(getDeclContext()); } + + /// \brief Determine whether this class is derived from the class \p Base. + /// + /// This routine only determines whether this class is derived from \p Base, + /// but does not account for factors that may make a Derived -> Base class + /// ill-formed, such as private/protected inheritance or multiple, ambiguous + /// base class subobjects. + /// + /// \param Base the base class we are searching for. + /// + /// \returns true if this class is derived from Base, false otherwise. + bool isDerivedFrom(CXXRecordDecl *Base); + + /// \brief Determine whether this class is derived from the type \p Base. + /// + /// This routine only determines whether this class is derived from \p Base, + /// but does not account for factors that may make a Derived -> Base class + /// ill-formed, such as private/protected inheritance or multiple, ambiguous + /// base class subobjects. + /// + /// \param Base the base class we are searching for. + /// + /// \param Paths will contain the paths taken from the current class to the + /// given \p Base class. + /// + /// \returns true if this class is derived from Base, false otherwise. + /// + /// \todo add a separate paramaeter to configure IsDerivedFrom, rather than + /// tangling input and output in \p Paths + bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths); + + /// \brief Function type used by lookupInBases() to determine whether a + /// specific base class subobject matches the lookup criteria. + /// + /// \param Specifier the base-class specifier that describes the inheritance + /// from the base class we are trying to match. + /// + /// \param Path the current path, from the most-derived class down to the + /// base named by the \p Specifier. + /// + /// \param UserData a single pointer to user-specified data, provided to + /// lookupInBases(). + /// + /// \returns true if this base matched the search criteria, false otherwise. + typedef bool BaseMatchesCallback(CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + void *UserData); + + /// \brief Look for entities within the base classes of this C++ class, + /// transitively searching all base class subobjects. + /// + /// This routine uses the callback function \p BaseMatches to find base + /// classes meeting some search criteria, walking all base class subobjects + /// and populating the given \p Paths structure with the paths through the + /// inheritance hierarchy that resulted in a match. On a successful search, + /// the \p Paths structure can be queried to retrieve the matching paths and + /// to determine if there were any ambiguities. + /// + /// \param BaseMatches callback function used to determine whether a given + /// base matches the user-defined search criteria. + /// + /// \param UserData user data pointer that will be provided to \p BaseMatches. + /// + /// \param Paths used to record the paths from this class to its base class + /// subobjects that match the search criteria. + /// + /// \returns true if there exists any path from this class to a base class + /// subobject that matches the search criteria. + bool lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData, + CXXBasePaths &Paths); + + /// \brief Base-class lookup callback that determines whether the given + /// base class specifier refers to a specific class declaration. + /// + /// This callback can be used with \c lookupInBases() to determine whether + /// a given derived class has is a base class subobject of a particular type. + /// The user data pointer should refer to the canonical CXXRecordDecl of the + /// base class that we are searching for. + static bool FindBaseClass(CXXBaseSpecifier *Specifier, CXXBasePath &Path, + void *BaseRecord); + + /// \brief Base-class lookup callback that determines whether there exists + /// a tag with the given name. + /// + /// This callback can be used with \c lookupInBases() to find tag members + /// of the given name within a C++ class hierarchy. The user data pointer + /// is an opaque \c DeclarationName pointer. + static bool FindTagMember(CXXBaseSpecifier *Specifier, CXXBasePath &Path, + void *Name); + + /// \brief Base-class lookup callback that determines whether there exists + /// a member with the given name. + /// + /// This callback can be used with \c lookupInBases() to find members + /// of the given name within a C++ class hierarchy. The user data pointer + /// is an opaque \c DeclarationName pointer. + static bool FindOrdinaryMember(CXXBaseSpecifier *Specifier, CXXBasePath &Path, + void *Name); + + /// \brief Base-class lookup callback that determines whether there exists + /// a member with the given name that can be used in a nested-name-specifier. + /// + /// This callback can be used with \c lookupInBases() to find membes of + /// the given name within a C++ class hierarchy that can occur within + /// nested-name-specifiers. + static bool FindNestedNameSpecifierMember(CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + void *UserData); /// viewInheritance - Renders and displays an inheritance diagram /// for this C++ class and all of its base classes (transitively) using /// GraphViz. void viewInheritance(ASTContext& Context) const; - static bool classof(const Decl *D) { - return D->getKind() == CXXRecord || + static bool classof(const Decl *D) { + return D->getKind() == CXXRecord || D->getKind() == ClassTemplateSpecialization || - D->getKind() == ClassTemplatePartialSpecialization; + D->getKind() == ClassTemplatePartialSpecialization; } static bool classof(const CXXRecordDecl *D) { return true; } - static bool classof(const ClassTemplateSpecializationDecl *D) { - return true; + static bool classof(const ClassTemplateSpecializationDecl *D) { + return true; } }; @@ -512,42 +887,60 @@ public: class CXXMethodDecl : public FunctionDecl { protected: CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L, - DeclarationName N, QualType T, + DeclarationName N, QualType T, DeclaratorInfo *DInfo, bool isStatic, bool isInline) - : FunctionDecl(DK, RD, L, N, T, (isStatic ? Static : None), + : FunctionDecl(DK, RD, L, N, T, DInfo, (isStatic ? Static : None), isInline) {} public: static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, - QualType T, bool isStatic = false, + QualType T, DeclaratorInfo *DInfo, + bool isStatic = false, bool isInline = false); - + bool isStatic() const { return getStorageClass() == Static; } bool isInstance() const { return !isStatic(); } - bool isVirtual() const { - return isVirtualAsWritten() || - (begin_overridden_methods() != end_overridden_methods()); - } + bool isVirtual() const { + CXXMethodDecl *CD = + cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl()); - /// - void addOverriddenMethod(const CXXMethodDecl *MD); + if (CD->isVirtualAsWritten()) + return true; + + return (CD->begin_overridden_methods() != CD->end_overridden_methods()); + } - typedef const CXXMethodDecl ** method_iterator; + /// \brief Determine whether this is a usual deallocation function + /// (C++ [basic.stc.dynamic.deallocation]p2), which is an overloaded + /// delete or delete[] operator with a particular signature. + bool isUsualDeallocationFunction() const; + const CXXMethodDecl *getCanonicalDecl() const { + return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl()); + } + CXXMethodDecl *getCanonicalDecl() { + return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl()); + } + + /// + void addOverriddenMethod(const CXXMethodDecl *MD); + + typedef const CXXMethodDecl ** method_iterator; + method_iterator begin_overridden_methods() const; method_iterator end_overridden_methods() const; - + /// getParent - Returns the parent of this method declaration, which /// is the class in which this method is defined. - const CXXRecordDecl *getParent() const { - return cast<CXXRecordDecl>(FunctionDecl::getParent()); + const CXXRecordDecl *getParent() const { + return cast<CXXRecordDecl>(FunctionDecl::getParent()); } - + /// getParent - Returns the parent of this method declaration, which /// is the class in which this method is defined. - CXXRecordDecl *getParent() { + CXXRecordDecl *getParent() { return const_cast<CXXRecordDecl *>( cast<CXXRecordDecl>(FunctionDecl::getParent())); } @@ -557,11 +950,11 @@ public: QualType getThisType(ASTContext &C) const; unsigned getTypeQualifiers() const { - return getType()->getAsFunctionProtoType()->getTypeQuals(); + return getType()->getAs<FunctionProtoType>()->getTypeQuals(); } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { + static bool classof(const Decl *D) { return D->getKind() >= CXXMethod && D->getKind() <= CXXConversion; } static bool classof(const CXXMethodDecl *D) { return true; } @@ -589,38 +982,63 @@ class CXXBaseOrMemberInitializer { uintptr_t BaseOrMember; /// Args - The arguments used to initialize the base or member. - Expr **Args; + Stmt **Args; unsigned NumArgs; - + + /// \brief Stores either the constructor to call to initialize this base or + /// member (a CXXConstructorDecl pointer), or stores the anonymous union of + /// which the initialized value is a member. + /// + /// When the value is a FieldDecl pointer, 'BaseOrMember' is class's + /// anonymous union data member, this field holds the FieldDecl for the + /// member of the anonymous union being initialized. + /// @code + /// struct X { + /// X() : au_i1(123) {} + /// union { + /// int au_i1; + /// float au_f1; + /// }; + /// }; + /// @endcode + /// In above example, BaseOrMember holds the field decl. for anonymous union + /// and AnonUnionMember holds field decl for au_i1. + llvm::PointerUnion<CXXConstructorDecl *, FieldDecl *> CtorOrAnonUnion; + /// IdLoc - Location of the id in ctor-initializer list. SourceLocation IdLoc; + /// RParenLoc - Location of the right paren of the ctor-initializer. + SourceLocation RParenLoc; + public: /// CXXBaseOrMemberInitializer - Creates a new base-class initializer. - explicit + explicit CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs, - SourceLocation L); + CXXConstructorDecl *C, + SourceLocation L, SourceLocation R); /// CXXBaseOrMemberInitializer - Creates a new member initializer. - explicit + explicit CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs, - SourceLocation L); + CXXConstructorDecl *C, + SourceLocation L, SourceLocation R); /// ~CXXBaseOrMemberInitializer - Destroy the base or member initializer. ~CXXBaseOrMemberInitializer(); /// arg_iterator - Iterates through the member initialization /// arguments. - typedef Expr **arg_iterator; + typedef ExprIterator arg_iterator; /// arg_const_iterator - Iterates through the member initialization /// arguments. - typedef Expr * const * arg_const_iterator; + typedef ConstExprIterator const_arg_iterator; /// getBaseOrMember - get the generic 'member' representing either the field /// or a base class. void* getBaseOrMember() const { return reinterpret_cast<void*>(BaseOrMember); } - + /// isBaseInitializer - Returns true when this initializer is /// initializing a base class. bool isBaseInitializer() const { return (BaseOrMember & 0x1) != 0; } @@ -633,8 +1051,8 @@ public: /// type used to specify the initializer. The resulting type will be /// a class type or a typedef of a class type. If this is not a base /// class initializer, returns NULL. - Type *getBaseClass() { - if (isBaseInitializer()) + Type *getBaseClass() { + if (isBaseInitializer()) return reinterpret_cast<Type*>(BaseOrMember & ~0x01); else return 0; @@ -644,8 +1062,8 @@ public: /// type used to specify the initializer. The resulting type will be /// a class type or a typedef of a class type. If this is not a base /// class initializer, returns NULL. - const Type *getBaseClass() const { - if (isBaseInitializer()) + const Type *getBaseClass() const { + if (isBaseInitializer()) return reinterpret_cast<const Type*>(BaseOrMember & ~0x01); else return 0; @@ -654,24 +1072,40 @@ public: /// getMember - If this is a member initializer, returns the /// declaration of the non-static data member being /// initialized. Otherwise, returns NULL. - FieldDecl *getMember() { + FieldDecl *getMember() { if (isMemberInitializer()) - return reinterpret_cast<FieldDecl *>(BaseOrMember); + return reinterpret_cast<FieldDecl *>(BaseOrMember); else return 0; } + void setMember(FieldDecl * anonUnionField) { + BaseOrMember = reinterpret_cast<uintptr_t>(anonUnionField); + } + + FieldDecl *getAnonUnionMember() const { + return CtorOrAnonUnion.dyn_cast<FieldDecl *>(); + } + void setAnonUnionMember(FieldDecl *anonMember) { + CtorOrAnonUnion = anonMember; + } + + const CXXConstructorDecl *getConstructor() const { + return CtorOrAnonUnion.dyn_cast<CXXConstructorDecl *>(); + } + SourceLocation getSourceLocation() const { return IdLoc; } - - /// begin() - Retrieve an iterator to the first initializer argument. - arg_iterator begin() { return Args; } - /// begin() - Retrieve an iterator to the first initializer argument. - arg_const_iterator begin() const { return Args; } + SourceLocation getRParenLoc() const { return RParenLoc; } - /// end() - Retrieve an iterator past the last initializer argument. - arg_iterator end() { return Args + NumArgs; } - /// end() - Retrieve an iterator past the last initializer argument. - arg_const_iterator end() const { return Args + NumArgs; } + /// arg_begin() - Retrieve an iterator to the first initializer argument. + arg_iterator arg_begin() { return Args; } + /// arg_begin() - Retrieve an iterator to the first initializer argument. + const_arg_iterator const_arg_begin() const { return Args; } + + /// arg_end() - Retrieve an iterator past the last initializer argument. + arg_iterator arg_end() { return Args + NumArgs; } + /// arg_end() - Retrieve an iterator past the last initializer argument. + const_arg_iterator const_arg_end() const { return Args + NumArgs; } /// getNumArgs - Determine the number of arguments used to /// initialize the member or base. @@ -680,7 +1114,7 @@ public: /// CXXConstructorDecl - Represents a C++ constructor within a /// class. For example: -/// +/// /// @code /// class X { /// public: @@ -698,82 +1132,86 @@ class CXXConstructorDecl : public CXXMethodDecl { /// explicitly defaulted (i.e., defined with " = default") will have /// @c !Implicit && ImplicitlyDefined. bool ImplicitlyDefined : 1; - + /// Support for base and member initializers. - /// BaseOrMemberInitializers - The arguments used to initialize the base + /// BaseOrMemberInitializers - The arguments used to initialize the base /// or member. CXXBaseOrMemberInitializer **BaseOrMemberInitializers; unsigned NumBaseOrMemberInitializers; - + CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L, - DeclarationName N, QualType T, + DeclarationName N, QualType T, DeclaratorInfo *DInfo, bool isExplicit, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXConstructor, RD, L, N, T, false, isInline), + : CXXMethodDecl(CXXConstructor, RD, L, N, T, DInfo, false, isInline), Explicit(isExplicit), ImplicitlyDefined(false), - BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) { + BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) { setImplicit(isImplicitlyDeclared); } virtual void Destroy(ASTContext& C); - + public: static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, - QualType T, bool isExplicit, + QualType T, DeclaratorInfo *DInfo, + bool isExplicit, bool isInline, bool isImplicitlyDeclared); - /// isExplicit - Whether this constructor was marked "explicit" or not. + /// isExplicit - Whether this constructor was marked "explicit" or not. bool isExplicit() const { return Explicit; } /// isImplicitlyDefined - Whether this constructor was implicitly /// 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 { - assert(isThisDeclarationADefinition() && + bool isImplicitlyDefined(ASTContext &C) const { + assert(isThisDeclarationADefinition() && "Can only get the implicit-definition flag once the " "constructor has been defined"); - return ImplicitlyDefined; + return ImplicitlyDefined; } /// setImplicitlyDefined - Set whether this constructor was /// implicitly defined or not. - void setImplicitlyDefined(bool ID) { - assert(isThisDeclarationADefinition() && + void setImplicitlyDefined(bool ID) { + assert(isThisDeclarationADefinition() && "Can only set the implicit-definition flag once the constructor " "has been defined"); - ImplicitlyDefined = ID; + ImplicitlyDefined = ID; } - + /// init_iterator - Iterates through the member/base initializer list. typedef CXXBaseOrMemberInitializer **init_iterator; - + /// init_const_iterator - Iterates through the memberbase initializer list. typedef CXXBaseOrMemberInitializer * const * init_const_iterator; - - /// begin() - Retrieve an iterator to the first initializer. - init_iterator begin() { return BaseOrMemberInitializers; } + + /// init_begin() - Retrieve an iterator to the first initializer. + init_iterator init_begin() { return BaseOrMemberInitializers; } /// begin() - Retrieve an iterator to the first initializer. - init_const_iterator begin() const { return BaseOrMemberInitializers; } - - /// end() - Retrieve an iterator past the last initializer. - init_iterator end() { - return BaseOrMemberInitializers + NumBaseOrMemberInitializers; + init_const_iterator init_begin() const { return BaseOrMemberInitializers; } + + /// init_end() - Retrieve an iterator past the last initializer. + init_iterator init_end() { + return BaseOrMemberInitializers + NumBaseOrMemberInitializers; } /// end() - Retrieve an iterator past the last initializer. - init_const_iterator end() const { - return BaseOrMemberInitializers + NumBaseOrMemberInitializers; + init_const_iterator init_end() const { + return BaseOrMemberInitializers + NumBaseOrMemberInitializers; } - + /// getNumArgs - Determine the number of arguments used to /// initialize the member or base. - unsigned getNumBaseOrMemberInitializers() const { - return NumBaseOrMemberInitializers; + unsigned getNumBaseOrMemberInitializers() const { + return NumBaseOrMemberInitializers; + } + + void setNumBaseOrMemberInitializers(unsigned numBaseOrMemberInitializers) { + NumBaseOrMemberInitializers = numBaseOrMemberInitializers; + } + + void setBaseOrMemberInitializers(CXXBaseOrMemberInitializer ** initializers) { + BaseOrMemberInitializers = initializers; } - - void setBaseOrMemberInitializers(ASTContext &C, - CXXBaseOrMemberInitializer **Initializers, - unsigned NumInitializers); - /// isDefaultConstructor - Whether this constructor is a default /// constructor (C++ [class.ctor]p5), which can be used to /// default-initialize a class of this type. @@ -804,10 +1242,10 @@ public: /// isConvertingConstructor - Whether this constructor is a /// converting constructor (C++ [class.conv.ctor]), which can be /// used for user-defined conversions. - bool isConvertingConstructor() const; + bool isConvertingConstructor(bool AllowExplicit) const; // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { + static bool classof(const Decl *D) { return D->getKind() == CXXConstructor; } static bool classof(const CXXConstructorDecl *D) { return true; } @@ -815,7 +1253,7 @@ public: /// CXXDestructorDecl - Represents a C++ destructor within a /// class. For example: -/// +/// /// @code /// class X { /// public: @@ -823,6 +1261,13 @@ public: /// }; /// @endcode class CXXDestructorDecl : public CXXMethodDecl { +public: + enum KindOfObjectToDestroy { + VBASE = 0x1, + DRCTNONVBASE = 0x2, + ANYBASE = 0x3 + }; +private: /// ImplicitlyDefined - Whether this destructor was implicitly /// defined by the compiler. When false, the destructor was defined /// by the user. In C++03, this flag will have the same value as @@ -831,40 +1276,141 @@ class CXXDestructorDecl : public CXXMethodDecl { /// @c !Implicit && ImplicitlyDefined. bool ImplicitlyDefined : 1; + /// Support for base and member destruction. + /// BaseOrMemberDestructions - The arguments used to destruct the base + /// or member. Each uintptr_t value represents one of base classes (either + /// virtual or direct non-virtual base), or non-static data member + /// to be destroyed. The low two bits encode the kind of object + /// being destroyed. + uintptr_t *BaseOrMemberDestructions; + unsigned NumBaseOrMemberDestructions; + CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXDestructor, RD, L, N, T, false, isInline), - ImplicitlyDefined(false) { + : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*DInfo=*/0, false, isInline), + ImplicitlyDefined(false), + BaseOrMemberDestructions(0), NumBaseOrMemberDestructions(0) { setImplicit(isImplicitlyDeclared); } + virtual void Destroy(ASTContext& C); public: static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, - QualType T, bool isInline, + QualType T, bool isInline, bool isImplicitlyDeclared); /// isImplicitlyDefined - Whether this destructor was implicitly /// defined. If false, then this destructor was defined by the /// user. This operation can only be invoked if the destructor has /// already been defined. - bool isImplicitlyDefined() const { - assert(isThisDeclarationADefinition() && + bool isImplicitlyDefined() const { + assert(isThisDeclarationADefinition() && "Can only get the implicit-definition flag once the destructor has been defined"); - return ImplicitlyDefined; + return ImplicitlyDefined; } /// setImplicitlyDefined - Set whether this destructor was /// implicitly defined or not. - void setImplicitlyDefined(bool ID) { - assert(isThisDeclarationADefinition() && + void setImplicitlyDefined(bool ID) { + assert(isThisDeclarationADefinition() && "Can only set the implicit-definition flag once the destructor has been defined"); - ImplicitlyDefined = ID; + ImplicitlyDefined = ID; + } + + /// destr_iterator - Iterates through the member/base destruction list. + + /// destr_const_iterator - Iterates through the member/base destruction list. + typedef uintptr_t const destr_const_iterator; + + /// destr_begin() - Retrieve an iterator to the first destructed member/base. + uintptr_t* destr_begin() { + return BaseOrMemberDestructions; + } + /// destr_begin() - Retrieve an iterator to the first destructed member/base. + uintptr_t* destr_begin() const { + return BaseOrMemberDestructions; + } + + /// destr_end() - Retrieve an iterator past the last destructed member/base. + uintptr_t* destr_end() { + return BaseOrMemberDestructions + NumBaseOrMemberDestructions; + } + /// destr_end() - Retrieve an iterator past the last destructed member/base. + uintptr_t* destr_end() const { + return BaseOrMemberDestructions + NumBaseOrMemberDestructions; + } + + /// getNumBaseOrMemberDestructions - Number of base and non-static members + /// to destroy. + unsigned getNumBaseOrMemberDestructions() const { + return NumBaseOrMemberDestructions; + } + + /// setNumBaseOrMemberDestructions - Set number of base and non-static members + /// to destroy. + void setNumBaseOrMemberDestructions(unsigned numBaseOrMemberDestructions) { + NumBaseOrMemberDestructions = numBaseOrMemberDestructions; + } + + /// getBaseOrMemberToDestroy - get the generic 'member' representing either + /// the field or a base class. + uintptr_t* getBaseOrMemberToDestroy() const { + return BaseOrMemberDestructions; + } + + /// setBaseOrMemberToDestroy - set the generic 'member' representing either + /// the field or a base class. + void setBaseOrMemberDestructions(uintptr_t* baseOrMemberDestructions) { + BaseOrMemberDestructions = baseOrMemberDestructions; + } + + /// isVbaseToDestroy - returns true, if object is virtual base. + bool isVbaseToDestroy(uintptr_t Vbase) const { + return (Vbase & VBASE) != 0; + } + /// isDirectNonVBaseToDestroy - returns true, if object is direct non-virtual + /// base. + bool isDirectNonVBaseToDestroy(uintptr_t DrctNonVbase) const { + return (DrctNonVbase & DRCTNONVBASE) != 0; + } + /// isAnyBaseToDestroy - returns true, if object is any base (virtual or + /// direct non-virtual) + bool isAnyBaseToDestroy(uintptr_t AnyBase) const { + return (AnyBase & ANYBASE) != 0; + } + /// isMemberToDestroy - returns true if object is a non-static data member. + bool isMemberToDestroy(uintptr_t Member) const { + return (Member & ANYBASE) == 0; + } + /// getAnyBaseClassToDestroy - Get the type for the given base class object. + Type *getAnyBaseClassToDestroy(uintptr_t Base) const { + if (isAnyBaseToDestroy(Base)) + return reinterpret_cast<Type*>(Base & ~0x03); + return 0; + } + /// getMemberToDestroy - Get the member for the given object. + FieldDecl *getMemberToDestroy(uintptr_t Member) const { + if (isMemberToDestroy(Member)) + return reinterpret_cast<FieldDecl *>(Member); + return 0; + } + /// getVbaseClassToDestroy - Get the virtual base. + Type *getVbaseClassToDestroy(uintptr_t Vbase) const { + if (isVbaseToDestroy(Vbase)) + return reinterpret_cast<Type*>(Vbase & ~0x01); + return 0; + } + /// getDirectNonVBaseClassToDestroy - Get the virtual base. + Type *getDirectNonVBaseClassToDestroy(uintptr_t Base) const { + if (isDirectNonVBaseToDestroy(Base)) + return reinterpret_cast<Type*>(Base & ~0x02); + return 0; } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { + static bool classof(const Decl *D) { return D->getKind() == CXXDestructor; } static bool classof(const CXXDestructorDecl *D) { return true; } @@ -872,7 +1418,7 @@ public: /// CXXConversionDecl - Represents a C++ conversion function within a /// class. For example: -/// +/// /// @code /// class X { /// public: @@ -886,16 +1432,16 @@ class CXXConversionDecl : public CXXMethodDecl { bool Explicit : 1; CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L, - DeclarationName N, QualType T, + DeclarationName N, QualType T, DeclaratorInfo *DInfo, bool isInline, bool isExplicit) - : CXXMethodDecl(CXXConversion, RD, L, N, T, false, isInline), + : CXXMethodDecl(CXXConversion, RD, L, N, T, DInfo, false, isInline), Explicit(isExplicit) { } public: static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, - QualType T, bool isInline, - bool isExplicit); + QualType T, DeclaratorInfo *DInfo, + bool isInline, bool isExplicit); /// isExplicit - Whether this is an explicit conversion operator /// (C++0x only). Explicit conversion operators are only considered @@ -904,17 +1450,81 @@ public: /// getConversionType - Returns the type that this conversion /// function is converting to. - QualType getConversionType() const { - return getType()->getAsFunctionType()->getResultType(); + QualType getConversionType() const { + return getType()->getAs<FunctionType>()->getResultType(); } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { + static bool classof(const Decl *D) { return D->getKind() == CXXConversion; } static bool classof(const CXXConversionDecl *D) { return true; } }; +/// FriendDecl - Represents the declaration of a friend entity, +/// which can be a function, a type, or a templated function or type. +// For example: +/// +/// @code +/// template <typename T> class A { +/// friend int foo(T); +/// friend class B; +/// friend T; // only in C++0x +/// template <typename U> friend class C; +/// template <typename U> friend A& operator+=(A&, const U&) { ... } +/// }; +/// @endcode +/// +/// The semantic context of a friend decl is its declaring class. +class FriendDecl : public Decl { +public: + typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion; + +private: + // The declaration that's a friend of this class. + FriendUnion Friend; + + // Location of the 'friend' specifier. + SourceLocation FriendLoc; + + FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend, + SourceLocation FriendL) + : Decl(Decl::Friend, DC, L), + Friend(Friend), + FriendLoc(FriendL) { + } + +public: + static FriendDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, FriendUnion Friend_, + SourceLocation FriendL); + + /// If this friend declaration names an (untemplated but + /// possibly dependent) type, return the type; otherwise + /// return null. This is used only for C++0x's unelaborated + /// friend type declarations. + Type *getFriendType() const { + return Friend.dyn_cast<Type*>(); + } + + /// If this friend declaration doesn't name an unelaborated + /// type, return the inner declaration. + NamedDecl *getFriendDecl() const { + return Friend.dyn_cast<NamedDecl*>(); + } + + /// Retrieves the location of the 'friend' keyword. + SourceLocation getFriendLoc() const { + return FriendLoc; + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() == Decl::Friend; + } + static bool classof(const FriendDecl *D) { return true; } +}; + /// LinkageSpecDecl - This represents a linkage specification. For example: /// extern "C" void foo(); /// @@ -934,14 +1544,14 @@ private: /// HadBraces - Whether this linkage specification had curly braces or not. bool HadBraces : 1; - LinkageSpecDecl(DeclContext *DC, SourceLocation L, LanguageIDs lang, + LinkageSpecDecl(DeclContext *DC, SourceLocation L, LanguageIDs lang, bool Braces) - : Decl(LinkageSpec, DC, L), + : Decl(LinkageSpec, DC, L), DeclContext(LinkageSpec), Language(lang), HadBraces(Braces) { } public: - static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, LanguageIDs Lang, + static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, LanguageIDs Lang, bool Braces); LanguageIDs getLanguage() const { return Language; } @@ -1008,8 +1618,8 @@ class UsingDirectiveDecl : public NamedDecl { NamespaceDecl *Nominated, DeclContext *CommonAncestor) : NamedDecl(Decl::UsingDirective, DC, L, getName()), - NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange), - Qualifier(Qualifier), IdentLoc(IdentLoc), + NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange), + Qualifier(Qualifier), IdentLoc(IdentLoc), NominatedNamespace(Nominated? Nominated->getOriginalNamespace() : 0), CommonAncestor(CommonAncestor) { } @@ -1074,20 +1684,20 @@ class NamespaceAliasDecl : public NamedDecl { /// \brief The nested-name-specifier that precedes the namespace /// name, if any. NestedNameSpecifier *Qualifier; - + /// IdentLoc - Location of namespace identifier. SourceLocation IdentLoc; - - /// Namespace - The Decl that this alias points to. Can either be a + + /// Namespace - The Decl that this alias points to. Can either be a /// NamespaceDecl or a NamespaceAliasDecl. NamedDecl *Namespace; - - NamespaceAliasDecl(DeclContext *DC, SourceLocation L, - SourceLocation AliasLoc, IdentifierInfo *Alias, + + NamespaceAliasDecl(DeclContext *DC, SourceLocation L, + SourceLocation AliasLoc, IdentifierInfo *Alias, SourceRange QualifierRange, NestedNameSpecifier *Qualifier, SourceLocation IdentLoc, NamedDecl *Namespace) - : NamedDecl(Decl::NamespaceAlias, DC, L, Alias), AliasLoc(AliasLoc), + : NamedDecl(Decl::NamespaceAlias, DC, L, Alias), AliasLoc(AliasLoc), QualifierRange(QualifierRange), Qualifier(Qualifier), IdentLoc(IdentLoc), Namespace(Namespace) { } @@ -1106,7 +1716,7 @@ public: return cast<NamespaceDecl>(Namespace); } - + const NamespaceDecl *getNamespace() const { return const_cast<NamespaceAliasDecl*>(this)->getNamespace(); } @@ -1115,14 +1725,14 @@ public: /// may either be a NamespaceDecl or a NamespaceAliasDecl. NamedDecl *getAliasedNamespace() const { return Namespace; } - static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, SourceLocation AliasLoc, - IdentifierInfo *Alias, + static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, SourceLocation AliasLoc, + IdentifierInfo *Alias, SourceRange QualifierRange, NestedNameSpecifier *Qualifier, - SourceLocation IdentLoc, + SourceLocation IdentLoc, NamedDecl *Namespace); - + static bool classof(const Decl *D) { return D->getKind() == Decl::NamespaceAlias; } @@ -1132,20 +1742,23 @@ public: /// UsingDecl - Represents a C++ using-declaration. For example: /// using someNameSpace::someIdentifier; class UsingDecl : public NamedDecl { - /// \brief The source range that covers the nested-name-specifier /// preceding the declaration name. SourceRange NestedNameRange; + /// \brief The source location of the target declaration name. SourceLocation TargetNameLocation; + /// \brief The source location of the "using" location itself. SourceLocation UsingLocation; + /// \brief Target declaration. NamedDecl* TargetDecl; - /// \brief Target declaration. + + /// \brief Target nested name specifier. NestedNameSpecifier* TargetNestedNameDecl; - // Had 'typename' keyword. + // \brief Has 'typename' keyword. bool IsTypeName; UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR, @@ -1154,7 +1767,7 @@ class UsingDecl : public NamedDecl { : NamedDecl(Decl::Using, DC, L, Target->getDeclName()), NestedNameRange(NNR), TargetNameLocation(TargetNL), UsingLocation(UL), TargetDecl(Target), - TargetNestedNameDecl(TargetNNS), IsTypeName(IsTypeNameArg) { + TargetNestedNameDecl(TargetNNS), IsTypeName(IsTypeNameArg) { this->IdentifierNamespace = TargetDecl->getIdentifierNamespace(); } @@ -1162,23 +1775,23 @@ public: /// \brief Returns the source range that covers the nested-name-specifier /// preceding the namespace name. SourceRange getNestedNameRange() { return NestedNameRange; } - + /// \brief Returns the source location of the target declaration name. SourceLocation getTargetNameLocation() { return TargetNameLocation; } - + /// \brief Returns the source location of the "using" location itself. SourceLocation getUsingLocation() { return UsingLocation; } - + /// \brief getTargetDecl - Returns target specified by using-decl. NamedDecl *getTargetDecl() { return TargetDecl; } const NamedDecl *getTargetDecl() const { return TargetDecl; } - + /// \brief Get target nested name declaration. - NestedNameSpecifier* getTargetNestedNameDecl() { - return TargetNestedNameDecl; + NestedNameSpecifier* getTargetNestedNameDecl() { + return TargetNestedNameDecl; } - - /// isTypeName - Return true if using decl had 'typename'. + + /// isTypeName - Return true if using decl has 'typename'. bool isTypeName() const { return IsTypeName; } static UsingDecl *Create(ASTContext &C, DeclContext *DC, @@ -1191,27 +1804,85 @@ public: } static bool classof(const UsingDecl *D) { return true; } }; - + +/// UnresolvedUsingDecl - Represents a using declaration whose name can not +/// yet be resolved. +class UnresolvedUsingDecl : public NamedDecl { + /// \brief The source range that covers the nested-name-specifier + /// preceding the declaration name. + SourceRange TargetNestedNameRange; + + /// \brief The source location of the target declaration name. + SourceLocation TargetNameLocation; + + NestedNameSpecifier *TargetNestedNameSpecifier; + + DeclarationName TargetName; + + // \brief Has 'typename' keyword. + bool IsTypeName; + + UnresolvedUsingDecl(DeclContext *DC, SourceLocation UsingLoc, + SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, DeclarationName TargetName, + bool IsTypeNameArg) + : NamedDecl(Decl::UnresolvedUsing, DC, UsingLoc, TargetName), + TargetNestedNameRange(TargetNNR), TargetNameLocation(TargetNameLoc), + TargetNestedNameSpecifier(TargetNNS), TargetName(TargetName), + IsTypeName(IsTypeNameArg) { } + +public: + /// \brief Returns the source range that covers the nested-name-specifier + /// preceding the namespace name. + SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } + + /// \brief Get target nested name declaration. + NestedNameSpecifier* getTargetNestedNameSpecifier() { + return TargetNestedNameSpecifier; + } + + /// \brief Returns the source location of the target declaration name. + SourceLocation getTargetNameLocation() const { return TargetNameLocation; } + + /// \brief Returns the source location of the target declaration name. + DeclarationName getTargetName() const { return TargetName; } + + bool isTypeName() const { return IsTypeName; } + + static UnresolvedUsingDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation UsingLoc, + SourceRange TargetNNR, + NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, + DeclarationName TargetName, + bool IsTypeNameArg); + + static bool classof(const Decl *D) { + return D->getKind() == Decl::UnresolvedUsing; + } + static bool classof(const UnresolvedUsingDecl *D) { return true; } +}; + /// StaticAssertDecl - Represents a C++0x static_assert declaration. class StaticAssertDecl : public Decl { Expr *AssertExpr; StringLiteral *Message; - StaticAssertDecl(DeclContext *DC, SourceLocation L, + StaticAssertDecl(DeclContext *DC, SourceLocation L, Expr *assertexpr, StringLiteral *message) : Decl(StaticAssert, DC, L), AssertExpr(assertexpr), Message(message) { } - + public: static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, Expr *AssertExpr, StringLiteral *Message); - + Expr *getAssertExpr() { return AssertExpr; } const Expr *getAssertExpr() const { return AssertExpr; } - + StringLiteral *getMessage() { return Message; } const StringLiteral *getMessage() const { return Message; } - + virtual ~StaticAssertDecl(); virtual void Destroy(ASTContext& C); @@ -1225,7 +1896,7 @@ public: /// into a diagnostic with <<. const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, AccessSpecifier AS); - + } // end namespace clang #endif diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index 6c1231c0a73d..d9e40d478907 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -57,13 +57,13 @@ public: Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03); } } - + ~StoredDeclsList() { // If this is a vector-form, free the vector. if (VectorTy *Vector = getAsVector()) delete Vector; } - + StoredDeclsList &operator=(const StoredDeclsList &RHS) { if (VectorTy *Vector = getAsVector()) delete Vector; @@ -74,9 +74,9 @@ public: } return *this; } - + bool isNull() const { return (Data & ~0x03) == 0; } - + NamedDecl *getAsDecl() const { if ((Data & 0x03) != DK_Decl) return 0; @@ -135,27 +135,27 @@ public: DeclContext::lookup_result getLookupResult(ASTContext &Context) { if (isNull()) return DeclContext::lookup_result(0, 0); - + if (hasDeclarationIDs()) materializeDecls(Context); // If we have a single NamedDecl, return it. if (getAsDecl()) { assert(!isNull() && "Empty list isn't allowed"); - + // Data is a raw pointer to a NamedDecl*, return it. void *Ptr = &Data; return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1); } - + assert(getAsVector() && "Must have a vector at this point"); VectorTy &Vector = *getAsVector(); - + // Otherwise, we have a range result. - return DeclContext::lookup_result((NamedDecl **)&Vector[0], + return DeclContext::lookup_result((NamedDecl **)&Vector[0], (NamedDecl **)&Vector[0]+Vector.size()); } - + /// HandleRedeclaration - If this is a redeclaration of an existing decl, /// replace the old one with D and return true. Otherwise return false. bool HandleRedeclaration(ASTContext &Context, NamedDecl *D) { @@ -169,7 +169,7 @@ public: setOnlyValue(D); return true; } - + // Determine if this declaration is actually a redeclaration. VectorTy &Vec = *getAsVector(); for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end(); @@ -183,10 +183,10 @@ public: return false; } - + /// AddSubsequentDecl - This is called on the second and later decl when it is /// not a redeclaration to merge it into the appropriate place in our list. - /// + /// void AddSubsequentDecl(NamedDecl *D) { assert(!hasDeclarationIDs() && "Must materialize before adding decls"); @@ -197,7 +197,7 @@ public: VT->push_back(reinterpret_cast<uintptr_t>(OldD)); Data = reinterpret_cast<uintptr_t>(VT) | DK_Decl_Vector; } - + VectorTy &Vec = *getAsVector(); if (isa<UsingDirectiveDecl>(D) || D->getIdentifierNamespace() == Decl::IDNS_Tag) @@ -217,4 +217,4 @@ typedef llvm::DenseMap<DeclarationName, StoredDeclsList> StoredDeclsMap; } // end namespace clang -#endif +#endif diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h index 15a8adef8e57..790ea3ca0662 100644 --- a/include/clang/AST/DeclGroup.h +++ b/include/clang/AST/DeclGroup.h @@ -18,7 +18,7 @@ #include <cassert> namespace clang { - + class ASTContext; class Decl; class DeclGroup; @@ -27,7 +27,7 @@ class DeclGroupIterator; class DeclGroup { // FIXME: Include a TypeSpecifier object. unsigned NumDecls; - + private: DeclGroup() : NumDecls(0) {} DeclGroup(unsigned numdecls, Decl** decls); @@ -38,34 +38,34 @@ public: unsigned size() const { return NumDecls; } - Decl*& operator[](unsigned i) { + Decl*& operator[](unsigned i) { assert (i < NumDecls && "Out-of-bounds access."); return *((Decl**) (this+1)); } - - Decl* const& operator[](unsigned i) const { + + Decl* const& operator[](unsigned i) const { assert (i < NumDecls && "Out-of-bounds access."); return *((Decl* const*) (this+1)); } }; - + class DeclGroupRef { // Note this is not a PointerIntPair because we need the address of the // non-group case to be valid as a Decl** for iteration. - enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 }; + enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 }; Decl* D; Kind getKind() const { return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask); - } - -public: + } + +public: DeclGroupRef() : D(0) {} - + explicit DeclGroupRef(Decl* d) : D(d) {} explicit DeclGroupRef(DeclGroup* dg) : D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {} - + static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { if (NumDecls == 0) return DeclGroupRef(); @@ -73,10 +73,10 @@ public: return DeclGroupRef(Decls[0]); return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls)); } - + typedef Decl** iterator; typedef Decl* const * const_iterator; - + bool isNull() const { return D == 0; } bool isSingleDecl() const { return getKind() == SingleDeclKind; } bool isDeclGroup() const { return getKind() == DeclGroupKind; } @@ -88,7 +88,7 @@ public: const Decl *getSingleDecl() const { return const_cast<DeclGroupRef*>(this)->getSingleDecl(); } - + DeclGroup &getDeclGroup() { assert(isDeclGroup() && "Isn't a declgroup"); return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask)); @@ -96,7 +96,7 @@ public: const DeclGroup &getDeclGroup() const { return const_cast<DeclGroupRef*>(this)->getDeclGroup(); } - + iterator begin() { if (isSingleDecl()) return D ? &D : 0; @@ -109,13 +109,13 @@ public: DeclGroup &G = getDeclGroup(); return &G[0] + G.size(); } - + const_iterator begin() const { if (isSingleDecl()) return D ? &D : 0; return &getDeclGroup()[0]; } - + const_iterator end() const { if (isSingleDecl()) return D ? &D+1 : 0; @@ -130,7 +130,7 @@ public: return X; } }; - + } // end clang namespace namespace llvm { diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def index 1e4440357b65..79a0d368288c 100644 --- a/include/clang/AST/DeclNodes.def +++ b/include/clang/AST/DeclNodes.def @@ -91,39 +91,43 @@ ABSTRACT_DECL(Named, Decl) DECL(TemplateTypeParm, TypeDecl) ABSTRACT_DECL(Value, NamedDecl) DECL(EnumConstant, ValueDecl) - DECL(Function, ValueDecl) - DECL(CXXMethod, FunctionDecl) - DECL(CXXConstructor, CXXMethodDecl) - DECL(CXXDestructor, CXXMethodDecl) - DECL(CXXConversion, CXXMethodDecl) - DECL(Field, ValueDecl) - DECL(ObjCIvar, FieldDecl) - DECL(ObjCAtDefsField, FieldDecl) - DECL(Var, ValueDecl) - DECL(ImplicitParam, VarDecl) - DECL(ParmVar, VarDecl) - DECL(OriginalParmVar, ParmVarDecl) - DECL(NonTypeTemplateParm, VarDecl) + ABSTRACT_DECL(Declarator, ValueDecl) + DECL(Function, DeclaratorDecl) + DECL(CXXMethod, FunctionDecl) + DECL(CXXConstructor, CXXMethodDecl) + DECL(CXXDestructor, CXXMethodDecl) + DECL(CXXConversion, CXXMethodDecl) + DECL(Field, DeclaratorDecl) + DECL(ObjCIvar, FieldDecl) + DECL(ObjCAtDefsField, FieldDecl) + DECL(Var, DeclaratorDecl) + DECL(ImplicitParam, VarDecl) + DECL(ParmVar, VarDecl) + DECL(OriginalParmVar, ParmVarDecl) + DECL(NonTypeTemplateParm, VarDecl) DECL(Template, NamedDecl) DECL(FunctionTemplate, TemplateDecl) DECL(ClassTemplate, TemplateDecl) DECL(TemplateTemplateParm, TemplateDecl) DECL(Using, NamedDecl) + DECL(UnresolvedUsing, NamedDecl) DECL(ObjCMethod, NamedDecl) DECL(ObjCContainer, NamedDecl) DECL(ObjCCategory, ObjCContainerDecl) DECL(ObjCProtocol, ObjCContainerDecl) DECL(ObjCInterface, ObjCContainerDecl) + ABSTRACT_DECL(ObjCImpl, ObjCContainerDecl) + DECL(ObjCCategoryImpl, ObjCImplDecl) + DECL(ObjCImplementation, ObjCImplDecl) DECL(ObjCProperty, NamedDecl) DECL(ObjCCompatibleAlias, NamedDecl) - ABSTRACT_DECL(ObjCImpl, NamedDecl) - DECL(ObjCCategoryImpl, ObjCImplDecl) - DECL(ObjCImplementation, ObjCImplDecl) DECL(LinkageSpec, Decl) DECL(ObjCPropertyImpl, Decl) DECL(ObjCForwardProtocol, Decl) DECL(ObjCClass, Decl) DECL(FileScopeAsm, Decl) +DECL(Friend, Decl) +DECL(FriendTemplate, Decl) DECL(StaticAssert, Decl) LAST_DECL(Block, Decl) @@ -132,21 +136,20 @@ DECL_CONTEXT(TranslationUnit) DECL_CONTEXT(Namespace) DECL_CONTEXT(LinkageSpec) DECL_CONTEXT(ObjCMethod) -DECL_CONTEXT(ObjCCategoryImpl) -DECL_CONTEXT(ObjCImplementation) DECL_CONTEXT_BASE(Tag) DECL_CONTEXT_BASE(Function) DECL_CONTEXT_BASE(ObjCContainer) LAST_DECL_CONTEXT(Block) // Declaration ranges -DECL_RANGE(Named, OverloadedFunction, ObjCImplementation) -DECL_RANGE(ObjCContainer, ObjCContainer, ObjCInterface) +DECL_RANGE(Named, OverloadedFunction, ObjCCompatibleAlias) +DECL_RANGE(ObjCContainer, ObjCContainer, ObjCImplementation) DECL_RANGE(Field, Field, ObjCAtDefsField) DECL_RANGE(Type, Typedef, TemplateTypeParm) DECL_RANGE(Tag, Enum, ClassTemplatePartialSpecialization) 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(ObjCImpl, ObjCCategoryImpl, ObjCImplementation) diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 2fcdaa3e2959..2b12bb5c1b6d 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -43,17 +43,17 @@ public: ~ObjCListBase() { assert(List == 0 && "Destroy should have been called before dtor"); } - + void Destroy(ASTContext &Ctx); - + unsigned size() const { return NumElts; } bool empty() const { return NumElts == 0; } - + protected: void set(void *const* InList, unsigned Elts, ASTContext &Ctx); }; - - + + /// ObjCList - This is a simple template class used to hold various lists of /// decls etc, which is heavily used by the ObjC front-end. This only use case /// this supports is setting the list all at once and then reading elements out @@ -64,30 +64,30 @@ public: void set(T* const* InList, unsigned Elts, ASTContext &Ctx) { ObjCListBase::set(reinterpret_cast<void*const*>(InList), Elts, Ctx); } - + typedef T* const * iterator; iterator begin() const { return (iterator)List; } iterator end() const { return (iterator)List+NumElts; } - + T* operator[](unsigned Idx) const { assert(Idx < NumElts && "Invalid access"); return (T*)List[Idx]; } }; - + /// ObjCMethodDecl - Represents an instance or class method declaration. /// ObjC methods can be declared within 4 contexts: class interfaces, /// categories, protocols, and class implementations. While C++ member -/// functions leverage C syntax, Objective-C method syntax is modeled after -/// Smalltalk (using colons to specify argument types/expressions). +/// functions leverage C syntax, Objective-C method syntax is modeled after +/// Smalltalk (using colons to specify argument types/expressions). /// Here are some brief examples: /// /// Setter/getter instance methods: /// - (void)setMenu:(NSMenu *)menu; -/// - (NSMenu *)menu; -/// +/// - (NSMenu *)menu; +/// /// Instance method that takes 2 NSView arguments: /// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView; /// @@ -106,27 +106,27 @@ private: /// instance (true) or class (false) method. bool IsInstance : 1; bool IsVariadic : 1; - + // Synthesized declaration method for a property setter/getter bool IsSynthesized : 1; - + // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum /// @required/@optional unsigned DeclImplementation : 2; - + // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum /// in, inout, etc. unsigned objcDeclQualifier : 6; - + // Type of this method. QualType MethodDeclType; /// ParamInfo - List of pointers to VarDecls for the formal parameters of this /// Method. ObjCList<ParmVarDecl> ParamInfo; - + /// List of attributes for this method declaration. - SourceLocation EndLoc; // the location of the ';' or '{'. - + SourceLocation EndLoc; // the location of the ';' or '}'. + // The following are only used for method definitions, null otherwise. // FIXME: space savings opportunity, consider a sub-class. Stmt *Body; @@ -137,7 +137,7 @@ private: /// CmdDecl - Decl for the implicit _cmd parameter. This is lazily /// constructed by createImplicitParams. ImplicitParamDecl *CmdDecl; - + ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, QualType T, DeclContext *contextDecl, @@ -150,48 +150,55 @@ private: IsInstance(isInstance), IsVariadic(isVariadic), IsSynthesized(isSynthesized), DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), - MethodDeclType(T), + MethodDeclType(T), EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {} virtual ~ObjCMethodDecl() {} - + + /// \brief A definition will return its interface declaration. + /// An interface declaration will return its definition. + /// Otherwise it will return itself. + virtual ObjCMethodDecl *getNextRedeclaration(); + public: - + /// Destroy - Call destructors and release memory. virtual void Destroy(ASTContext& C); static ObjCMethodDecl *Create(ASTContext &C, - SourceLocation beginLoc, + SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, QualType T, DeclContext *contextDecl, bool isInstance = true, bool isVariadic = false, bool isSynthesized = false, ImplementationControl impControl = None); - + + virtual ObjCMethodDecl *getCanonicalDecl(); + ObjCDeclQualifier getObjCDeclQualifier() const { return ObjCDeclQualifier(objcDeclQualifier); } void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; } - + // Location information, modeled after the Stmt API. SourceLocation getLocStart() const { return getLocation(); } SourceLocation getLocEnd() const { return EndLoc; } void setEndLoc(SourceLocation Loc) { EndLoc = Loc; } - SourceRange getSourceRange() const { - return SourceRange(getLocation(), EndLoc); + virtual SourceRange getSourceRange() const { + return SourceRange(getLocation(), EndLoc); } - + ObjCInterfaceDecl *getClassInterface(); const ObjCInterfaceDecl *getClassInterface() const { return const_cast<ObjCMethodDecl*>(this)->getClassInterface(); } - + Selector getSelector() const { return getDeclName().getObjCSelector(); } - unsigned getSynthesizedMethodSize() const; + QualType getResultType() const { return MethodDeclType; } void setResultType(QualType T) { MethodDeclType = T; } - + // Iterator access to formal parameters. unsigned param_size() const { return ParamInfo.size(); } typedef ObjCList<ParmVarDecl>::iterator param_iterator; @@ -212,7 +219,7 @@ public: arg_type_iterator arg_type_end() const { return llvm::map_iterator(param_end(), deref_fun(&ParmVarDecl::getType)); } - + /// createImplicitParams - Used to lazily create the self and cmd /// implict parameters. This must be called prior to using getSelfDecl() /// or getCmdDecl(). The call is ignored if the implicit paramters @@ -223,31 +230,34 @@ public: void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; } ImplicitParamDecl * getCmdDecl() const { return CmdDecl; } void setCmdDecl(ImplicitParamDecl *CD) { CmdDecl = CD; } - + bool isInstanceMethod() const { return IsInstance; } void setInstanceMethod(bool isInst) { IsInstance = isInst; } bool isVariadic() const { return IsVariadic; } void setVariadic(bool isVar) { IsVariadic = isVar; } - + bool isClassMethod() const { return !IsInstance; } bool isSynthesized() const { return IsSynthesized; } void setSynthesized(bool isSynth) { IsSynthesized = isSynth; } - + // Related to protocols declared in @protocol - void setDeclImplementation(ImplementationControl ic) { - DeclImplementation = ic; + void setDeclImplementation(ImplementationControl ic) { + DeclImplementation = ic; } - ImplementationControl getImplementationControl() const { - return ImplementationControl(DeclImplementation); + ImplementationControl getImplementationControl() const { + return ImplementationControl(DeclImplementation); } - virtual Stmt *getBody() const { - return (Stmt*) Body; + virtual Stmt *getBody() const { + return (Stmt*) Body; } CompoundStmt *getCompoundBody() { return (CompoundStmt*)Body; } void setBody(Stmt *B) { Body = B; } + /// \brief Returns whether this specific method is a definition. + bool isThisDeclarationADefinition() const { return Body; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == ObjCMethod; } static bool classof(const ObjCMethodDecl *D) { return true; } @@ -263,9 +273,9 @@ public: struct ObjCMethodList { ObjCMethodDecl *Method; ObjCMethodList *Next; - + ObjCMethodList() { - Method = 0; + Method = 0; Next = 0; } ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) { @@ -275,15 +285,14 @@ struct ObjCMethodList { }; /// ObjCContainerDecl - Represents a container for method declarations. -/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl, and -/// ObjCProtocolDecl. -/// FIXME: Use for ObjC implementation decls. +/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl, +/// ObjCProtocolDecl, and ObjCImplDecl. /// class ObjCContainerDecl : public NamedDecl, public DeclContext { SourceLocation AtEndLoc; // marks the end of the method container. public: - ObjCContainerDecl(Kind DK, DeclContext *DC, SourceLocation L, + ObjCContainerDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id) : NamedDecl(DK, DC, L, Id), DeclContext(DK) {} @@ -291,24 +300,24 @@ public: // Iterator access to properties. typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator; - prop_iterator prop_begin() const { + prop_iterator prop_begin() const { return prop_iterator(decls_begin()); } - prop_iterator prop_end() const { + prop_iterator prop_end() const { return prop_iterator(decls_end()); } - + // Iterator access to instance/class methods. typedef specific_decl_iterator<ObjCMethodDecl> method_iterator; - method_iterator meth_begin() const { + method_iterator meth_begin() const { return method_iterator(decls_begin()); } - method_iterator meth_end() const { + method_iterator meth_end() const { return method_iterator(decls_end()); } - typedef filtered_decl_iterator<ObjCMethodDecl, - &ObjCMethodDecl::isInstanceMethod> + typedef filtered_decl_iterator<ObjCMethodDecl, + &ObjCMethodDecl::isInstanceMethod> instmeth_iterator; instmeth_iterator instmeth_begin() const { return instmeth_iterator(decls_begin()); @@ -317,8 +326,8 @@ public: return instmeth_iterator(decls_end()); } - typedef filtered_decl_iterator<ObjCMethodDecl, - &ObjCMethodDecl::isClassMethod> + typedef filtered_decl_iterator<ObjCMethodDecl, + &ObjCMethodDecl::isClassMethod> classmeth_iterator; classmeth_iterator classmeth_begin() const { return classmeth_iterator(decls_begin()); @@ -328,23 +337,28 @@ public: } // Get the local instance/class method declared in this interface. - ObjCMethodDecl *getInstanceMethod(Selector Sel) const; - ObjCMethodDecl *getClassMethod(Selector Sel) const; + ObjCMethodDecl *getMethod(Selector Sel, bool isInstance) const; + ObjCMethodDecl *getInstanceMethod(Selector Sel) const { + return getMethod(Sel, true/*isInstance*/); + } + ObjCMethodDecl *getClassMethod(Selector Sel) const { + return getMethod(Sel, false/*isInstance*/); + } ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const; - ObjCMethodDecl *getMethod(Selector Sel, bool isInstance) const { - return isInstance ? getInstanceMethod(Sel) : getClassMethod(Sel); - } - ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const; // Marks the end of the container. SourceLocation getAtEndLoc() const { return AtEndLoc; } void setAtEndLoc(SourceLocation L) { AtEndLoc = L; } - + + virtual SourceRange getSourceRange() const { + return SourceRange(getLocation(), getAtEndLoc()); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { - return D->getKind() >= ObjCContainerFirst && + return D->getKind() >= ObjCContainerFirst && D->getKind() <= ObjCContainerLast; } static bool classof(const ObjCContainerDecl *D) { return true; } @@ -360,11 +374,11 @@ public: /// ObjCInterfaceDecl - Represents an ObjC class declaration. For example: /// /// // MostPrimitive declares no super class (not particularly useful). -/// @interface MostPrimitive +/// @interface MostPrimitive /// // no instance variables or methods. /// @end /// -/// // NSResponder inherits from NSObject & implements NSCoding (a protocol). +/// // NSResponder inherits from NSObject & implements NSCoding (a protocol). /// @interface NSResponder : NSObject <NSCoding> /// { // instance variables are represented by ObjCIvarDecl. /// id nextResponder; // nextResponder instance variable. @@ -383,32 +397,32 @@ class ObjCInterfaceDecl : public ObjCContainerDecl { /// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType mutable Type *TypeForDecl; friend class ASTContext; - + /// Class's super class. ObjCInterfaceDecl *SuperClass; - + /// Protocols referenced in interface header declaration ObjCList<ObjCProtocolDecl> ReferencedProtocols; - + /// Instance variables in the interface. ObjCList<ObjCIvarDecl> IVars; - + /// List of categories defined for this class. /// FIXME: Why is this a linked list?? ObjCCategoryDecl *CategoryList; - + bool ForwardDecl:1; // declared with @class. bool InternalInterface:1; // true - no @interface for @implementation - + SourceLocation ClassLoc; // location of the class identifier. SourceLocation SuperClassLoc; // location of the super class identifier. SourceLocation EndLoc; // marks the '>', '}', or identifier. ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, SourceLocation CLoc, bool FD, bool isInternal); - + virtual ~ObjCInterfaceDecl() {} - + public: /// Destroy - Call destructors and release memory. @@ -416,16 +430,27 @@ public: static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation atLoc, - IdentifierInfo *Id, + IdentifierInfo *Id, SourceLocation ClassLoc = SourceLocation(), bool ForwardDecl = false, bool isInternal = false); - const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const { - return ReferencedProtocols; + const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const { + return ReferencedProtocols; } - + + ObjCImplementationDecl *getImplementation() const; + void setImplementation(ObjCImplementationDecl *ImplD); + ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const; + // Get the local instance/class method declared in a category. + ObjCMethodDecl *getCategoryInstanceMethod(Selector Sel) const; + ObjCMethodDecl *getCategoryClassMethod(Selector Sel) const; + ObjCMethodDecl *getCategoryMethod(Selector Sel, bool isInstance) const { + return isInstance ? getInstanceMethod(Sel) + : getClassMethod(Sel); + } + typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator; protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();} protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } @@ -436,29 +461,34 @@ public: ivar_iterator ivar_end() const { return IVars.end(); } unsigned ivar_size() const { return IVars.size(); } bool ivar_empty() const { return IVars.empty(); } - + /// setProtocolList - Set the list of protocols that this interface /// implements. void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num, ASTContext &C) { ReferencedProtocols.set(List, Num, C); } - + + /// mergeClassExtensionProtocolList - Merge class extension's protocol list + /// into the protocol list for this class. + void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List, unsigned Num, + ASTContext &C); + void setIVarList(ObjCIvarDecl * const *List, unsigned Num, ASTContext &C) { IVars.set(List, Num, C); } bool isForwardDecl() const { return ForwardDecl; } void setForwardDecl(bool val) { ForwardDecl = val; } - + ObjCInterfaceDecl *getSuperClass() const { return SuperClass; } void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; } - + ObjCCategoryDecl* getCategoryList() const { return CategoryList; } - void setCategoryList(ObjCCategoryDecl *category) { + void setCategoryList(ObjCCategoryDecl *category) { CategoryList = category; } - + /// isSuperClassOf - Return true if this class is the specified class or is a /// super class of the specified interface class. bool isSuperClassOf(const ObjCInterfaceDecl *I) const { @@ -470,7 +500,7 @@ public: } return false; } - + ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName, ObjCInterfaceDecl *&ClassDeclared); ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) { @@ -480,26 +510,41 @@ public: // Lookup a method. First, we search locally. If a method isn't // found, we search referenced protocols and class categories. - ObjCMethodDecl *lookupInstanceMethod(Selector Sel); - ObjCMethodDecl *lookupClassMethod(Selector Sel); + ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance) const; + ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const { + return lookupMethod(Sel, true/*isInstance*/); + } + ObjCMethodDecl *lookupClassMethod(Selector Sel) const { + return lookupMethod(Sel, false/*isInstance*/); + } ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName); + + // Lookup a method in the classes implementation hierarchy. + ObjCMethodDecl *lookupPrivateInstanceMethod(const Selector &Sel); - // Location information, modeled after the Stmt API. + // Location information, modeled after the Stmt API. SourceLocation getLocStart() const { return getLocation(); } // '@'interface SourceLocation getLocEnd() const { return EndLoc; } void setLocEnd(SourceLocation LE) { EndLoc = LE; }; - + void setClassLoc(SourceLocation Loc) { ClassLoc = Loc; } SourceLocation getClassLoc() const { return ClassLoc; } void setSuperClassLoc(SourceLocation Loc) { SuperClassLoc = Loc; } SourceLocation getSuperClassLoc() const { return SuperClassLoc; } - + /// isImplicitInterfaceDecl - check that this is an implicitly declared /// ObjCInterfaceDecl node. This is for legacy objective-c @implementation /// declaration without an @interface declaration. bool isImplicitInterfaceDecl() const { return InternalInterface; } void setImplicitInterfaceDecl(bool val) { InternalInterface = val; } - + + /// ClassImplementsProtocol - Checks that 'lProto' protocol + /// has been implemented in IDecl class, its super class or categories (if + /// lookupCategory is true). + bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, + bool lookupCategory, + bool RHSIsQualifiedID = false); + // Low-level accessor Type *getTypeForDecl() const { return TypeForDecl; } void setTypeForDecl(Type *TD) const { TypeForDecl = TD; } @@ -528,18 +573,19 @@ public: enum AccessControl { None, Private, Protected, Public, Package }; - + private: ObjCIvarDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, AccessControl ac, Expr *BW) - : FieldDecl(ObjCIvar, DC, L, Id, T, BW, /*Mutable=*/false), + QualType T, DeclaratorInfo *DInfo, AccessControl ac, Expr *BW) + : FieldDecl(ObjCIvar, DC, L, Id, T, DInfo, BW, /*Mutable=*/false), DeclAccess(ac) {} - + public: static ObjCIvarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, + DeclaratorInfo *DInfo, AccessControl ac, Expr *BW = NULL); - + void setAccessControl(AccessControl ac) { DeclAccess = ac; } AccessControl getAccessControl() const { return AccessControl(DeclAccess); } @@ -547,7 +593,7 @@ public: AccessControl getCanonicalAccessControl() const { return DeclAccess == None ? Protected : AccessControl(DeclAccess); } - + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == ObjCIvar; } static bool classof(const ObjCIvarDecl *D) { return true; } @@ -556,21 +602,23 @@ private: unsigned DeclAccess : 3; }; - + /// ObjCAtDefsFieldDecl - Represents a field declaration created by an /// @defs(...). class ObjCAtDefsFieldDecl : public FieldDecl { private: ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, Expr *BW) - : FieldDecl(ObjCAtDefsField, DC, L, Id, T, BW, /*Mutable=*/false) {} - + : FieldDecl(ObjCAtDefsField, DC, L, Id, T, + /*DInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ? + BW, /*Mutable=*/false) {} + public: static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, Expr *BW); - + virtual void Destroy(ASTContext& C); // Implement isa/cast/dyncast/etc. @@ -579,8 +627,8 @@ public: }; /// ObjCProtocolDecl - Represents a protocol declaration. ObjC protocols -/// declare a pure abstract type (i.e no instance variables are permitted). -/// Protocols orginally drew inspiration from C++ pure virtual functions (a C++ +/// declare a pure abstract type (i.e no instance variables are permitted). +/// Protocols orginally drew inspiration from C++ pure virtual functions (a C++ /// feature with nice semantics and lousy syntax:-). Here is an example: /// /// @protocol NSDraggingInfo <refproto1, refproto2> @@ -597,7 +645,7 @@ public: /// /// ObjC protocols inspired Java interfaces. Unlike Java, ObjC classes and /// protocols are in distinct namespaces. For example, Cocoa defines both -/// an NSObject protocol and class (which isn't allowed in Java). As a result, +/// an NSObject protocol and class (which isn't allowed in Java). As a result, /// protocols are referenced using angle brackets as follows: /// /// id <NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo; @@ -605,78 +653,83 @@ public: class ObjCProtocolDecl : public ObjCContainerDecl { /// Referenced protocols ObjCList<ObjCProtocolDecl> ReferencedProtocols; - + bool isForwardProtoDecl; // declared with @protocol. - + SourceLocation EndLoc; // marks the '>' or identifier. - + ObjCProtocolDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) - : ObjCContainerDecl(ObjCProtocol, DC, L, Id), + : ObjCContainerDecl(ObjCProtocol, DC, L, Id), isForwardProtoDecl(true) { } - + virtual ~ObjCProtocolDecl() {} - + public: - static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC, + static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id); /// Destroy - Call destructors and release memory. virtual void Destroy(ASTContext& C); - - const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const { + + const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const { return ReferencedProtocols; } typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator; protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();} protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } unsigned protocol_size() const { return ReferencedProtocols.size(); } - + /// setProtocolList - Set the list of protocols that this interface /// implements. void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num, ASTContext &C) { ReferencedProtocols.set(List, Num, C); } - + ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName); - + // Lookup a method. First, we search locally. If a method isn't // found, we search referenced protocols and class categories. - ObjCMethodDecl *lookupInstanceMethod(Selector Sel); - ObjCMethodDecl *lookupClassMethod(Selector Sel); - + ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance) const; + ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const { + return lookupMethod(Sel, true/*isInstance*/); + } + ObjCMethodDecl *lookupClassMethod(Selector Sel) const { + return lookupMethod(Sel, false/*isInstance*/); + } + bool isForwardDecl() const { return isForwardProtoDecl; } void setForwardDecl(bool val) { isForwardProtoDecl = val; } - // Location information, modeled after the Stmt API. + // Location information, modeled after the Stmt API. SourceLocation getLocStart() const { return getLocation(); } // '@'protocol SourceLocation getLocEnd() const { return EndLoc; } void setLocEnd(SourceLocation LE) { EndLoc = LE; }; - + static bool classof(const Decl *D) { return D->getKind() == ObjCProtocol; } static bool classof(const ObjCProtocolDecl *D) { return true; } }; - + /// ObjCClassDecl - Specifies a list of forward class declarations. For example: /// /// @class NSCursor, NSImage, NSPasteboard, NSWindow; /// class ObjCClassDecl : public Decl { ObjCList<ObjCInterfaceDecl> ForwardDecls; - - ObjCClassDecl(DeclContext *DC, SourceLocation L, + + ObjCClassDecl(DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *const *Elts, unsigned nElts, ASTContext &C); virtual ~ObjCClassDecl() {} public: - + /// Destroy - Call destructors and release memory. virtual void Destroy(ASTContext& C); - + static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, - ObjCInterfaceDecl *const *Elts = 0, + ObjCInterfaceDecl *const *Elts = 0, unsigned nElts = 0); - + typedef ObjCList<ObjCInterfaceDecl>::iterator iterator; iterator begin() const { return ForwardDecls.begin(); } iterator end() const { return ForwardDecls.end(); } @@ -686,33 +739,33 @@ public: void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, unsigned Num) { ForwardDecls.set(List, Num, C); } - + static bool classof(const Decl *D) { return D->getKind() == ObjCClass; } static bool classof(const ObjCClassDecl *D) { return true; } }; /// ObjCForwardProtocolDecl - Specifies a list of forward protocol declarations. /// For example: -/// +/// /// @protocol NSTextInput, NSChangeSpelling, NSDraggingInfo; -/// +/// class ObjCForwardProtocolDecl : public Decl { ObjCList<ObjCProtocolDecl> ReferencedProtocols; - + ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L, ObjCProtocolDecl *const *Elts, unsigned nElts, - ASTContext &C); + ASTContext &C); virtual ~ObjCForwardProtocolDecl() {} - + public: static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, + SourceLocation L, ObjCProtocolDecl *const *Elts = 0, unsigned Num = 0); /// Destroy - Call destructors and release memory. virtual void Destroy(ASTContext& C); - + typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator; protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();} protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } @@ -731,7 +784,7 @@ public: /// ObjCCategoryDecl - Represents a category declaration. A category allows /// you to add methods to an existing class (without subclassing or modifying -/// the original class interface or implementation:-). Categories don't allow +/// the original class interface or implementation:-). Categories don't allow /// you to add instance data. The following example adds "myMethod" to all /// NSView's within a process: /// @@ -743,51 +796,54 @@ public: /// several files (a feature more naturally supported in C++). /// /// Categories were originally inspired by dynamic languages such as Common -/// Lisp and Smalltalk. More traditional class-based languages (C++, Java) +/// Lisp and Smalltalk. More traditional class-based languages (C++, Java) /// don't support this level of dynamism, which is both powerful and dangerous. /// class ObjCCategoryDecl : public ObjCContainerDecl { /// Interface belonging to this category ObjCInterfaceDecl *ClassInterface; - + /// referenced protocols in this category. ObjCList<ObjCProtocolDecl> ReferencedProtocols; - + /// Next category belonging to this class. /// FIXME: this should not be a singly-linked list. Move storage elsewhere. ObjCCategoryDecl *NextClassCategory; - + SourceLocation EndLoc; // marks the '>' or identifier. - + ObjCCategoryDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) : ObjCContainerDecl(ObjCCategory, DC, L, Id), ClassInterface(0), NextClassCategory(0){ } public: - + static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id); - + ObjCInterfaceDecl *getClassInterface() { return ClassInterface; } const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } void setClassInterface(ObjCInterfaceDecl *IDecl) { ClassInterface = IDecl; } - + + ObjCCategoryImplDecl *getImplementation() const; + void setImplementation(ObjCCategoryImplDecl *ImplD); + /// setProtocolList - Set the list of protocols that this interface /// implements. void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num, ASTContext &C) { ReferencedProtocols.set(List, Num, C); } - - const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const { + + const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const { return ReferencedProtocols; } - + typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator; protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();} protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } unsigned protocol_size() const { return ReferencedProtocols.size(); } - + ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; } void setNextClassCategory(ObjCCategoryDecl *Cat) { NextClassCategory = Cat; @@ -796,98 +852,67 @@ public: NextClassCategory = ClassInterface->getCategoryList(); ClassInterface->setCategoryList(this); } - // Location information, modeled after the Stmt API. + // Location information, modeled after the Stmt API. SourceLocation getLocStart() const { return getLocation(); } // '@'interface SourceLocation getLocEnd() const { return EndLoc; } void setLocEnd(SourceLocation LE) { EndLoc = LE; }; - + static bool classof(const Decl *D) { return D->getKind() == ObjCCategory; } static bool classof(const ObjCCategoryDecl *D) { return true; } }; -class ObjCImplDecl : public NamedDecl, public DeclContext { +class ObjCImplDecl : public ObjCContainerDecl { /// Class interface for this category implementation ObjCInterfaceDecl *ClassInterface; - - SourceLocation EndLoc; - + protected: ObjCImplDecl(Kind DK, DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *classInterface) - : NamedDecl(DK, DC, L, - classInterface? classInterface->getDeclName() - : DeclarationName()), - DeclContext(DK), ClassInterface(classInterface) {} - + : ObjCContainerDecl(DK, DC, L, + classInterface? classInterface->getIdentifier() : 0), + ClassInterface(classInterface) {} + public: virtual ~ObjCImplDecl() {} - + const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } ObjCInterfaceDecl *getClassInterface() { return ClassInterface; } - void setClassInterface(ObjCInterfaceDecl *IFace) { ClassInterface = IFace; } + void setClassInterface(ObjCInterfaceDecl *IFace); - void addInstanceMethod(ObjCMethodDecl *method) { + void addInstanceMethod(ObjCMethodDecl *method) { // FIXME: Context should be set correctly before we get here. method->setLexicalDeclContext(this); - addDecl(method); + addDecl(method); } - void addClassMethod(ObjCMethodDecl *method) { + void addClassMethod(ObjCMethodDecl *method) { // FIXME: Context should be set correctly before we get here. method->setLexicalDeclContext(this); - addDecl(method); + addDecl(method); } - - // Get the local instance/class method declared in this interface. - ObjCMethodDecl *getInstanceMethod(Selector Sel) const; - ObjCMethodDecl *getClassMethod(Selector Sel) const; - ObjCMethodDecl *getMethod(Selector Sel, bool isInstance) const { - return isInstance ? getInstanceMethod(Sel) - : getClassMethod(Sel); - } - + void addPropertyImplementation(ObjCPropertyImplDecl *property); - + ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId) const; ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const; // Iterator access to properties. typedef specific_decl_iterator<ObjCPropertyImplDecl> propimpl_iterator; - propimpl_iterator propimpl_begin() const { + propimpl_iterator propimpl_begin() const { return propimpl_iterator(decls_begin()); } - propimpl_iterator propimpl_end() const { + propimpl_iterator propimpl_end() const { return propimpl_iterator(decls_end()); } - typedef filtered_decl_iterator<ObjCMethodDecl, - &ObjCMethodDecl::isInstanceMethod> - instmeth_iterator; - instmeth_iterator instmeth_begin() const { - return instmeth_iterator(decls_begin()); - } - instmeth_iterator instmeth_end() const { - return instmeth_iterator(decls_end()); - } - - typedef filtered_decl_iterator<ObjCMethodDecl, - &ObjCMethodDecl::isClassMethod> - classmeth_iterator; - classmeth_iterator classmeth_begin() const { - return classmeth_iterator(decls_begin()); - } - classmeth_iterator classmeth_end() const { - return classmeth_iterator(decls_end()); + static bool classof(const Decl *D) { + return D->getKind() >= ObjCImplFirst && D->getKind() <= ObjCImplLast; } - - // Location information, modeled after the Stmt API. - SourceLocation getLocStart() const { return getLocation(); } - SourceLocation getLocEnd() const { return EndLoc; } - void setLocEnd(SourceLocation LE) { EndLoc = LE; }; + static bool classof(const ObjCImplDecl *D) { return true; } }; - -/// ObjCCategoryImplDecl - An object of this class encapsulates a category -/// @implementation declaration. If a category class has declaration of a -/// property, its implementation must be specified in the category's + +/// ObjCCategoryImplDecl - An object of this class encapsulates a category +/// @implementation declaration. If a category class has declaration of a +/// property, its implementation must be specified in the category's /// @implementation declaration. Example: /// @interface I @end /// @interface I(CATEGORY) @@ -909,34 +934,30 @@ public: static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, ObjCInterfaceDecl *classInterface); - + /// getIdentifier - Get the identifier that names the class /// interface associated with this implementation. - IdentifierInfo *getIdentifier() const { - return Id; + IdentifierInfo *getIdentifier() const { + return Id; } void setIdentifier(IdentifierInfo *II) { Id = II; } + ObjCCategoryDecl *getCategoryClass() const; + /// getNameAsCString - Get the name of identifier for the class /// interface associated with this implementation as a C string /// (const char*). const char *getNameAsCString() const { return Id ? Id->getName() : ""; } - + /// @brief Get the name of the class associated with this interface. std::string getNameAsString() const { return Id ? Id->getName() : ""; } - + static bool classof(const Decl *D) { return D->getKind() == ObjCCategoryImpl;} static bool classof(const ObjCCategoryImplDecl *D) { return true; } - static DeclContext *castToDeclContext(const ObjCCategoryImplDecl *D) { - return static_cast<DeclContext *>(const_cast<ObjCCategoryImplDecl*>(D)); - } - static ObjCCategoryImplDecl *castFromDeclContext(const DeclContext *DC) { - return static_cast<ObjCCategoryImplDecl *>(const_cast<DeclContext*>(DC)); - } }; /// ObjCImplementationDecl - Represents a class definition - this is where @@ -948,30 +969,30 @@ public: /// @end /// @endcode /// -/// Typically, instance variables are specified in the class interface, +/// Typically, instance variables are specified in the class interface, /// *not* in the implementation. Nevertheless (for legacy reasons), we /// allow instance variables to be specified in the implementation. When /// specified, they need to be *identical* to the interface. /// -class ObjCImplementationDecl : public ObjCImplDecl { +class ObjCImplementationDecl : public ObjCImplDecl { /// Implementation Class's super class. ObjCInterfaceDecl *SuperClass; - - ObjCImplementationDecl(DeclContext *DC, SourceLocation L, + + ObjCImplementationDecl(DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl) - : ObjCImplDecl(ObjCImplementation, DC, L, classInterface), + : ObjCImplDecl(ObjCImplementation, DC, L, classInterface), SuperClass(superDecl){} -public: - static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, +public: + static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl); - + /// getIdentifier - Get the identifier that names the class /// interface associated with this implementation. - IdentifierInfo *getIdentifier() const { - return getClassInterface()->getIdentifier(); + IdentifierInfo *getIdentifier() const { + return getClassInterface()->getIdentifier(); } /// getNameAsCString - Get the name of identifier for the class @@ -989,41 +1010,35 @@ public: const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; } ObjCInterfaceDecl *getSuperClass() { return SuperClass; } - + void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; } - + typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; - ivar_iterator ivar_begin() const { - return ivar_iterator(decls_begin()); + ivar_iterator ivar_begin() const { + return ivar_iterator(decls_begin()); } - ivar_iterator ivar_end() const { + ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); } - unsigned ivar_size() const { + unsigned ivar_size() const { return std::distance(ivar_begin(), ivar_end()); } - bool ivar_empty() const { + bool ivar_empty() const { return ivar_begin() == ivar_end(); } - + static bool classof(const Decl *D) { return D->getKind() == ObjCImplementation; } static bool classof(const ObjCImplementationDecl *D) { return true; } - static DeclContext *castToDeclContext(const ObjCImplementationDecl *D) { - return static_cast<DeclContext *>(const_cast<ObjCImplementationDecl*>(D)); - } - static ObjCImplementationDecl *castFromDeclContext(const DeclContext *DC) { - return static_cast<ObjCImplementationDecl *>(const_cast<DeclContext*>(DC)); - } }; -/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is +/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is /// declared as @compatibility_alias alias class. class ObjCCompatibleAliasDecl : public NamedDecl { /// Class that this is an alias of. ObjCInterfaceDecl *AliasedClass; - + ObjCCompatibleAliasDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, ObjCInterfaceDecl* aliasedClass) : NamedDecl(ObjCCompatibleAlias, DC, L, Id), AliasedClass(aliasedClass) {} @@ -1035,12 +1050,12 @@ public: const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; } ObjCInterfaceDecl *getClassInterface() { return AliasedClass; } void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; } - + static bool classof(const Decl *D) { return D->getKind() == ObjCCompatibleAlias; } static bool classof(const ObjCCompatibleAliasDecl *D) { return true; } - + }; /// ObjCPropertyDecl - Represents one property declaration in an interface. @@ -1050,13 +1065,13 @@ public: class ObjCPropertyDecl : public NamedDecl { public: enum PropertyAttributeKind { - OBJC_PR_noattr = 0x00, - OBJC_PR_readonly = 0x01, + OBJC_PR_noattr = 0x00, + OBJC_PR_readonly = 0x01, OBJC_PR_getter = 0x02, - OBJC_PR_assign = 0x04, - OBJC_PR_readwrite = 0x08, + OBJC_PR_assign = 0x04, + OBJC_PR_readwrite = 0x08, OBJC_PR_retain = 0x10, - OBJC_PR_copy = 0x20, + OBJC_PR_copy = 0x20, OBJC_PR_nonatomic = 0x40, OBJC_PR_setter = 0x80 }; @@ -1066,27 +1081,27 @@ public: private: QualType DeclType; unsigned PropertyAttributes : 8; - + // @required/@optional unsigned PropertyImplementation : 2; - + Selector GetterName; // getter name of NULL if no getter Selector SetterName; // setter name of NULL if no setter - + ObjCMethodDecl *GetterMethodDecl; // Declaration of getter instance method ObjCMethodDecl *SetterMethodDecl; // Declaration of setter instance method ObjCIvarDecl *PropertyIvarDecl; // Synthesize ivar for this property - ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T) : NamedDecl(ObjCProperty, DC, L, Id), DeclType(T), PropertyAttributes(OBJC_PR_noattr), PropertyImplementation(None), - GetterName(Selector()), + GetterName(Selector()), SetterName(Selector()), GetterMethodDecl(0), SetterMethodDecl(0) , PropertyIvarDecl(0) {} public: - static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, + static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, QualType T, PropertyControl propControl = None); QualType getType() const { return DeclType; } @@ -1095,14 +1110,14 @@ public: PropertyAttributeKind getPropertyAttributes() const { return PropertyAttributeKind(PropertyAttributes); } - void setPropertyAttributes(PropertyAttributeKind PRVal) { + void setPropertyAttributes(PropertyAttributeKind PRVal) { PropertyAttributes |= PRVal; } void makeitReadWriteAttribute(void) { PropertyAttributes &= ~OBJC_PR_readonly; PropertyAttributes |= OBJC_PR_readwrite; - } + } // Helper methods for accessing attributes. @@ -1124,38 +1139,38 @@ public: Selector getGetterName() const { return GetterName; } void setGetterName(Selector Sel) { GetterName = Sel; } - + Selector getSetterName() const { return SetterName; } void setSetterName(Selector Sel) { SetterName = Sel; } - + ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; } void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; } ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; } void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; } - + // Related to @optional/@required declared in @protocol void setPropertyImplementation(PropertyControl pc) { PropertyImplementation = pc; } PropertyControl getPropertyImplementation() const { return PropertyControl(PropertyImplementation); - } - + } + void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { PropertyIvarDecl = Ivar; } ObjCIvarDecl *getPropertyIvarDecl() const { return PropertyIvarDecl; } - + static bool classof(const Decl *D) { return D->getKind() == ObjCProperty; } static bool classof(const ObjCPropertyDecl *D) { return true; } }; -/// ObjCPropertyImplDecl - Represents implementation declaration of a property +/// ObjCPropertyImplDecl - Represents implementation declaration of a property /// in a class or category implementation block. For example: /// @synthesize prop1 = ivar1; /// @@ -1174,21 +1189,24 @@ private: ObjCIvarDecl *PropertyIvarDecl; ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L, - ObjCPropertyDecl *property, - Kind PK, + ObjCPropertyDecl *property, + Kind PK, ObjCIvarDecl *ivarDecl) - : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc), + : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl) { assert (PK == Dynamic || PropertyIvarDecl); } - + public: static ObjCPropertyImplDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation atLoc, SourceLocation L, - ObjCPropertyDecl *property, - Kind PK, + SourceLocation atLoc, SourceLocation L, + ObjCPropertyDecl *property, + Kind PK, ObjCIvarDecl *ivarDecl); + virtual SourceRange getSourceRange() const { + return SourceRange(AtLoc, getLocation()); + } SourceLocation getLocStart() const { return AtLoc; } void setAtLoc(SourceLocation Loc) { AtLoc = Loc; } @@ -1200,7 +1218,7 @@ public: Kind getPropertyImplementation() const { return PropertyIvarDecl ? Synthesize : Dynamic; } - + ObjCIvarDecl *getPropertyIvarDecl() const { return PropertyIvarDecl; } @@ -1209,7 +1227,7 @@ public: static bool classof(const Decl *D) { return D->getKind() == ObjCPropertyImpl; } - static bool classof(const ObjCPropertyImplDecl *D) { return true; } + static bool classof(const ObjCPropertyImplDecl *D) { return true; } }; } // end namespace clang diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 5d0fe158e054..8d44676124fb 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -49,38 +49,38 @@ class TemplateParameterList { unsigned NumParams; TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, - Decl **Params, unsigned NumParams, + NamedDecl **Params, unsigned NumParams, SourceLocation RAngleLoc); public: - static TemplateParameterList *Create(ASTContext &C, + static TemplateParameterList *Create(ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, - Decl **Params, + NamedDecl **Params, unsigned NumParams, SourceLocation RAngleLoc); /// iterator - Iterates through the template parameters in this list. - typedef Decl** iterator; + typedef NamedDecl** iterator; /// const_iterator - Iterates through the template parameters in this list. - typedef Decl* const* const_iterator; + typedef NamedDecl* const* const_iterator; - iterator begin() { return reinterpret_cast<Decl **>(this + 1); } + iterator begin() { return reinterpret_cast<NamedDecl **>(this + 1); } const_iterator begin() const { - return reinterpret_cast<Decl * const *>(this + 1); + return reinterpret_cast<NamedDecl * const *>(this + 1); } iterator end() { return begin() + NumParams; } const_iterator end() const { return begin() + NumParams; } unsigned size() const { return NumParams; } - Decl* getParam(unsigned Idx) { + NamedDecl* getParam(unsigned Idx) { assert(Idx < size() && "Template parameter index out-of-range"); return begin()[Idx]; } - const Decl* getParam(unsigned Idx) const { + const NamedDecl* getParam(unsigned Idx) const { assert(Idx < size() && "Template parameter index out-of-range"); return begin()[Idx]; } @@ -115,10 +115,10 @@ class TemplateArgument { bool CopyArgs; } Args; }; - + /// \brief Location of the beginning of this template argument. SourceLocation StartLoc; - + public: /// \brief The type of template argument we're storing. enum ArgKind { @@ -133,21 +133,21 @@ public: /// The template argument is a value- or type-dependent expression /// stored in an Expr*. Expression = 4, - + /// The template argument is actually a parameter pack. Arguments are stored /// in the Args struct. Pack = 5 } Kind; - + /// \brief Construct an empty, invalid template argument. TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { } - + /// \brief Construct a template type argument. TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) { TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); StartLoc = Loc; } - + /// \brief Construct a template argument that refers to a /// declaration, which is either an external declaration or a /// template declaration. @@ -156,7 +156,7 @@ public: TypeOrValue = reinterpret_cast<uintptr_t>(D); StartLoc = Loc; } - + /// \brief Construct an integral constant template argument. TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value, QualType Type) @@ -165,14 +165,14 @@ public: Integer.Type = Type.getAsOpaquePtr(); StartLoc = Loc; } - - /// \brief Construct a template argument that is an expression. + + /// \brief Construct a template argument that is an expression. /// /// This form of template argument only occurs in template argument /// lists used for dependent types and for expression; it will not /// occur in a non-dependent, canonical template argument list. TemplateArgument(Expr *E); - + /// \brief Copy constructor for a template argument. TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) { if (Kind == Integral) { @@ -188,27 +188,27 @@ public: TypeOrValue = Other.TypeOrValue; StartLoc = Other.StartLoc; } - + TemplateArgument& operator=(const TemplateArgument& Other) { // FIXME: Does not provide the strong guarantee for exception // safety. using llvm::APSInt; - + // FIXME: Handle Packs assert(Kind != Pack && "FIXME: Handle packs"); assert(Other.Kind != Pack && "FIXME: Handle packs"); - + if (Kind == Other.Kind && Kind == Integral) { // Copy integral values. *this->getAsIntegral() = *Other.getAsIntegral(); - Integer.Type = Other.Integer.Type; + Integer.Type = Other.Integer.Type; } else { // Destroy the current integral value, if that's what we're holding. if (Kind == Integral) getAsIntegral()->~APSInt(); - + Kind = Other.Kind; - + if (Other.Kind == Integral) { new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); Integer.Type = Other.Integer.Type; @@ -216,133 +216,131 @@ public: TypeOrValue = Other.TypeOrValue; } StartLoc = Other.StartLoc; - + return *this; } - + ~TemplateArgument() { using llvm::APSInt; - + if (Kind == Integral) getAsIntegral()->~APSInt(); else if (Kind == Pack && Args.CopyArgs) delete[] Args.Args; } - + /// \brief Return the kind of stored template argument. ArgKind getKind() const { return Kind; } - + /// \brief Determine whether this template argument has no value. bool isNull() const { return Kind == Null; } - + /// \brief Retrieve the template argument as a type. QualType getAsType() const { if (Kind != Type) return QualType(); - - return QualType::getFromOpaquePtr( - reinterpret_cast<void*>(TypeOrValue)); + + return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue)); } - + /// \brief Retrieve the template argument as a declaration. Decl *getAsDecl() const { if (Kind != Declaration) return 0; return reinterpret_cast<Decl *>(TypeOrValue); } - + /// \brief Retrieve the template argument as an integral value. llvm::APSInt *getAsIntegral() { if (Kind != Integral) return 0; return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]); } - + const llvm::APSInt *getAsIntegral() const { return const_cast<TemplateArgument*>(this)->getAsIntegral(); } - + /// \brief Retrieve the type of the integral value. QualType getIntegralType() const { if (Kind != Integral) return QualType(); - + return QualType::getFromOpaquePtr(Integer.Type); } - + void setIntegralType(QualType T) { - assert(Kind == Integral && + assert(Kind == Integral && "Cannot set the integral type of a non-integral template argument"); Integer.Type = T.getAsOpaquePtr(); }; - + /// \brief Retrieve the template argument as an expression. Expr *getAsExpr() const { if (Kind != Expression) return 0; - + return reinterpret_cast<Expr *>(TypeOrValue); } - + /// \brief Iterator that traverses the elements of a template argument pack. typedef const TemplateArgument * pack_iterator; - - /// \brief Iterator referencing the first argument of a template argument + + /// \brief Iterator referencing the first argument of a template argument /// pack. pack_iterator pack_begin() const { assert(Kind == Pack); return Args.Args; } - + /// \brief Iterator referencing one past the last argument of a template /// argument pack. pack_iterator pack_end() const { assert(Kind == Pack); return Args.Args + Args.NumArgs; } - + /// \brief The number of template arguments in the given template argument /// pack. unsigned pack_size() const { assert(Kind == Pack); return Args.NumArgs; } - + /// \brief Retrieve the location where the template argument starts. SourceLocation getLocation() const { return StartLoc; } - + /// \brief Construct a template argument pack. void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs); - + /// \brief Used to insert TemplateArguments into FoldingSets. - void Profile(llvm::FoldingSetNodeID &ID) const { + void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const { ID.AddInteger(Kind); switch (Kind) { case Null: break; - + case Type: getAsType().Profile(ID); break; - + case Declaration: - ID.AddPointer(getAsDecl()); // FIXME: Must be canonical! + ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); break; - + case Integral: getAsIntegral()->Profile(ID); getIntegralType().Profile(ID); break; - + case Expression: - // FIXME: We need a canonical representation of expressions. - ID.AddPointer(getAsExpr()); + getAsExpr()->Profile(ID, Context, true); break; - + case Pack: ID.AddInteger(Args.NumArgs); for (unsigned I = 0; I != Args.NumArgs; ++I) - Args.Args[I].Profile(ID); + Args.Args[I].Profile(ID, Context); } } }; @@ -352,47 +350,47 @@ class TemplateArgumentListBuilder { TemplateArgument *StructuredArgs; unsigned MaxStructuredArgs; unsigned NumStructuredArgs; - + TemplateArgument *FlatArgs; unsigned MaxFlatArgs; unsigned NumFlatArgs; - + bool AddingToPack; unsigned PackBeginIndex; - + public: TemplateArgumentListBuilder(const TemplateParameterList *Parameters, unsigned NumTemplateArgs) - : StructuredArgs(0), MaxStructuredArgs(Parameters->size()), - NumStructuredArgs(0), FlatArgs(0), + : StructuredArgs(0), MaxStructuredArgs(Parameters->size()), + NumStructuredArgs(0), FlatArgs(0), MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0), AddingToPack(false), PackBeginIndex(0) { } - + void Append(const TemplateArgument& Arg); void BeginPack(); void EndPack(); - + void ReleaseArgs(); - - unsigned flatSize() const { + + unsigned flatSize() const { return NumFlatArgs; } const TemplateArgument *getFlatArguments() const { return FlatArgs; } - + unsigned structuredSize() const { // If we don't have any structured args, just reuse the flat size. if (!StructuredArgs) return flatSize(); - + return NumStructuredArgs; } const TemplateArgument *getStructuredArguments() const { // If we don't have any structured args, just reuse the flat args. if (!StructuredArgs) return getFlatArguments(); - + return StructuredArgs; } }; @@ -408,44 +406,47 @@ class TemplateArgumentList { /// The integer value will be non-zero to indicate that this /// template argument list does not own the pointer. llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments; - + /// \brief The number of template arguments in this template /// argument list. unsigned NumFlatArguments; - + llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments; unsigned NumStructuredArguments; - + public: TemplateArgumentList(ASTContext &Context, TemplateArgumentListBuilder &Builder, bool TakeArgs); + + /// \brief Produces a shallow copy of the given template argument list + TemplateArgumentList(const TemplateArgumentList &Other); ~TemplateArgumentList(); - + /// \brief Retrieve the template argument at a given index. - const TemplateArgument &get(unsigned Idx) const { + const TemplateArgument &get(unsigned Idx) const { assert(Idx < NumFlatArguments && "Invalid template argument index"); return getFlatArgumentList()[Idx]; } - + /// \brief Retrieve the template argument at a given index. const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); } - + /// \brief Retrieve the number of template arguments in this /// template argument list. unsigned size() const { return NumFlatArguments; } - + /// \brief Retrieve the number of template arguments in the /// flattened template argument list. unsigned flat_size() const { return NumFlatArguments; } - + /// \brief Retrieve the flattened template argument list. - const TemplateArgument *getFlatArgumentList() const { + const TemplateArgument *getFlatArgumentList() const { return FlatArguments.getPointer(); } }; - + //===----------------------------------------------------------------------===// // Kinds of Templates //===----------------------------------------------------------------------===// @@ -459,15 +460,13 @@ protected: // This is probably never used. TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(0) - { } + : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(0) { } // Construct a template decl with the given name and parameters. // Used when there is not templated element (tt-params, alias?). TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(Params) - { } + : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(Params) { } // Construct a template decl with name, parameters, and templated element. TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, @@ -499,82 +498,161 @@ protected: NamedDecl *TemplatedDecl; TemplateParameterList* TemplateParams; }; - -/// \brief Provides information about a function template specialization, + +/// \brief Provides information about a function template specialization, /// which is a FunctionDecl that has been explicitly specialization or /// instantiated from a function template. class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode { public: - /// \brief The function template specialization that this structure + /// \brief The function template specialization that this structure /// describes. FunctionDecl *Function; - - /// \brief The function template from which this function template + + /// \brief The function template from which this function template /// specialization was generated. /// - /// The bit will be 0 for an implicit instantiation, 1 for an explicit - /// specialization. - llvm::PointerIntPair<FunctionTemplateDecl *, 1> Template; - + /// The two bits are contain the top 4 values of TemplateSpecializationKind. + llvm::PointerIntPair<FunctionTemplateDecl *, 2> Template; + /// \brief The template arguments used to produce the function template /// specialization from the function template. const TemplateArgumentList *TemplateArguments; + + /// \brief The point at which this function template specialization was + /// first instantiated. + SourceLocation PointOfInstantiation; /// \brief Retrieve the template from which this function was specialized. FunctionTemplateDecl *getTemplate() const { return Template.getPointer(); } + + /// \brief Determine what kind of template specialization this is. + TemplateSpecializationKind getTemplateSpecializationKind() const { + return (TemplateSpecializationKind)(Template.getInt() + 1); + } + + /// \brief Set the template specialization kind. + void setTemplateSpecializationKind(TemplateSpecializationKind TSK) { + assert(TSK != TSK_Undeclared && + "Cannot encode TSK_Undeclared for a function template specialization"); + Template.setInt(TSK - 1); + } + + /// \brief Retrieve the first point of instantiation of this function + /// template specialization. + /// + /// The point of instantiation may be an invalid source location if this + /// function has yet to be instantiated. + SourceLocation getPointOfInstantiation() const { + return PointOfInstantiation; + } - /// \brief Determine whether this is an explicit specialization. - bool isExplicitSpecialization() const { return Template.getInt(); } - - /// \brief Set whether this is an explicit specialization or an implicit - /// instantiation. - void setExplicitSpecialization(bool ES) { - Template.setInt(ES); + /// \brief Set the (first) point of instantiation of this function template + /// specialization. + void setPointOfInstantiation(SourceLocation POI) { + PointOfInstantiation = POI; } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, TemplateArguments->getFlatArgumentList(), - TemplateArguments->flat_size()); + Profile(ID, TemplateArguments->getFlatArgumentList(), + TemplateArguments->flat_size(), + Function->getASTContext()); } - - static void - Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs) { + + static void + Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, ASTContext &Context) { ID.AddInteger(NumTemplateArgs); for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg) - TemplateArgs[Arg].Profile(ID); - } + TemplateArgs[Arg].Profile(ID, Context); + } +}; + +/// \brief Provides information a specialization of a member of a class +/// template, which may be a member function, static data member, or +/// member class. +class MemberSpecializationInfo { + // The member declaration from which this member was instantiated, and the + // manner in which the instantiation occurred (in the lower two bits). + llvm::PointerIntPair<NamedDecl *, 2> MemberAndTSK; + + // The point at which this member was first instantiated. + SourceLocation PointOfInstantiation; + +public: + explicit + MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK) + : MemberAndTSK(IF, TSK - 1), PointOfInstantiation() { + assert(TSK != TSK_Undeclared && + "Cannot encode undeclared template specializations for members"); + } + + /// \brief Retrieve the member declaration from which this member was + /// instantiated. + NamedDecl *getInstantiatedFrom() const { return MemberAndTSK.getPointer(); } + + /// \brief Determine what kind of template specialization this is. + TemplateSpecializationKind getTemplateSpecializationKind() const { + return (TemplateSpecializationKind)(MemberAndTSK.getInt() + 1); + } + + /// \brief Set the template specialization kind. + void setTemplateSpecializationKind(TemplateSpecializationKind TSK) { + assert(TSK != TSK_Undeclared && + "Cannot encode undeclared template specializations for members"); + MemberAndTSK.setInt(TSK - 1); + } + + /// \brief Retrieve the first point of instantiation of this member. + /// If the point of instantiation is an invalid location, then this member + /// has not yet been instantiated. + SourceLocation getPointOfInstantiation() const { + return PointOfInstantiation; + } + + /// \brief Set the first point of instantiation. + void setPointOfInstantiation(SourceLocation POI) { + PointOfInstantiation = POI; + } }; /// Declaration of a template function. -class FunctionTemplateDecl : public TemplateDecl { +class FunctionTemplateDecl : public TemplateDecl { protected: /// \brief Data that is common to all of the declarations of a given /// function template. struct Common { + Common() : InstantiatedFromMember(0, false) { } + /// \brief The function template specializations for this function /// template, including explicit specializations and instantiations. llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations; + + /// \brief The member function template from which this was most + /// directly instantiated (or null). + /// + /// The boolean value indicates whether this member function template + /// was explicitly specialized. + llvm::PointerIntPair<FunctionTemplateDecl*, 1, bool> InstantiatedFromMember; }; - + /// \brief A pointer to the previous declaration (if this is a redeclaration) /// or to the data that is common to all declarations of this function /// template. llvm::PointerUnion<Common*, FunctionTemplateDecl*> CommonOrPrev; - - /// \brief Retrieves the "common" pointer shared by all + + /// \brief Retrieves the "common" pointer shared by all /// (re-)declarations of the same function template. Calling this routine /// may implicitly allocate memory for the common pointer. Common *getCommonPtr(); - + FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl), CommonOrPrev((Common*)0) { } - + public: void Destroy(ASTContext &C); - + /// Get the underlying function declaration of the template. FunctionDecl *getTemplatedDecl() const { return static_cast<FunctionDecl*>(TemplatedDecl); @@ -585,7 +663,7 @@ public: llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() { return getCommonPtr()->Specializations; } - + /// \brief Retrieve the previous declaration of this function template, or /// NULL if no such declaration exists. const FunctionTemplateDecl *getPreviousDeclaration() const { @@ -597,12 +675,71 @@ public: FunctionTemplateDecl *getPreviousDeclaration() { return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>(); } - + /// \brief Set the previous declaration of this function template. void setPreviousDeclaration(FunctionTemplateDecl *Prev) { if (Prev) CommonOrPrev = Prev; } + + virtual FunctionTemplateDecl *getCanonicalDecl(); + + /// \brief Retrieve the member function template that this function template + /// was instantiated from. + /// + /// This routine will return non-NULL for member function templates of + /// class templates. For example, given: + /// + /// \code + /// template <typename T> + /// struct X { + /// template <typename U> void f(); + /// }; + /// \endcode + /// + /// X<int>::A<float> is a CXXMethodDecl (whose parent is X<int>, a + /// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will + /// return X<int>::f, a FunctionTemplateDecl (whose parent is again + /// X<int>) for which getInstantiatedFromMemberTemplate() will return + /// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a + /// ClassTemplateDecl). + /// + /// \returns NULL if this is not an instantiation of a member function + /// template. + FunctionTemplateDecl *getInstantiatedFromMemberTemplate() { + return getCommonPtr()->InstantiatedFromMember.getPointer(); + } + + void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *FTD) { + assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); + getCommonPtr()->InstantiatedFromMember.setPointer(FTD); + } + + /// \brief Determines whether this template was a specialization of a + /// member template. + /// + /// In the following example, the function template \c X<int>::f is a + /// member specialization. + /// + /// \code + /// template<typename T> + /// struct X { + /// template<typename U> void f(T, U); + /// }; + /// + /// template<> template<typename T> + /// void X<int>::f(int, T); + /// \endcode + bool isMemberSpecialization() { + return getCommonPtr()->InstantiatedFromMember.getInt(); + } + + /// \brief Note that this member template is a specialization. + void setMemberSpecialization() { + assert(getCommonPtr()->InstantiatedFromMember.getPointer() && + "Only member templates can be member template specializations"); + getCommonPtr()->InstantiatedFromMember.setInt(true); + } /// Create a template function node. static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, @@ -629,8 +766,7 @@ public: /// the occurrence within the parameter list. /// This class is inheritedly privately by different kinds of template /// parameters and is not part of the Decl hierarchy. Just a facility. -class TemplateParmPosition -{ +class TemplateParmPosition { protected: // FIXME: This should probably never be called, but it's here as TemplateParmPosition() @@ -652,7 +788,7 @@ public: /// Get the position of the template parameter within its parameter list. unsigned getPosition() const { return Position; } - + /// Get the index of the template parameter within its parameter list. unsigned getIndex() const { return Position; } }; @@ -681,10 +817,10 @@ class TemplateTypeParmDecl : public TypeDecl { /// \brief The default template argument, if any. QualType DefaultArgument; - TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, bool Typename, QualType Type, bool ParameterPack) : TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename), - InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() { + InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() { TypeForDecl = Type.getTypePtr(); } @@ -745,21 +881,20 @@ class NonTypeTemplateParmDecl NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, - SourceLocation TSSL = SourceLocation()) - : VarDecl(NonTypeTemplateParm, DC, L, Id, T, VarDecl::None, TSSL), - TemplateParmPosition(D, P), DefaultArgument(0) + DeclaratorInfo *DInfo) + : VarDecl(NonTypeTemplateParm, DC, L, Id, T, DInfo, VarDecl::None), + TemplateParmPosition(D, P), DefaultArgument(0) { } public: static NonTypeTemplateParmDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, QualType T, - SourceLocation TypeSpecStartLoc = SourceLocation()); + unsigned P, IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo); using TemplateParmPosition::getDepth; using TemplateParmPosition::getPosition; using TemplateParmPosition::getIndex; - + /// \brief Determine whether this template parameter has a default /// argument. bool hasDefaultArgument() const { return DefaultArgument; } @@ -811,7 +946,7 @@ public: using TemplateParmPosition::getDepth; using TemplateParmPosition::getPosition; using TemplateParmPosition::getIndex; - + /// \brief Determine whether this template parameter has a default /// argument. bool hasDefaultArgument() const { return DefaultArgument; } @@ -834,24 +969,6 @@ public: static bool classof(const TemplateTemplateParmDecl *D) { return true; } }; -// \brief Describes the kind of template specialization that a -// particular template specialization declaration represents. -enum TemplateSpecializationKind { - /// This template specialization was formed from a template-id but - /// has not yet been declared, defined, or instantiated. - TSK_Undeclared = 0, - /// This template specialization was declared or defined by an - /// explicit specialization (C++ [temp.expl.spec]) or partial - /// specialization (C++ [temp.class.spec]). - TSK_ExplicitSpecialization, - /// This template specialization was implicitly instantiated from a - /// template. (C++ [temp.inst]). - TSK_ImplicitInstantiation, - /// This template specialization was instantiated from a template - /// due to an explicit instantiation request (C++ [temp.explicit]). - TSK_ExplicitInstantiation -}; - /// \brief Represents a class template specialization, which refers to /// a class template with a given set of template arguments. /// @@ -861,28 +978,47 @@ enum TemplateSpecializationKind { /// /// \code /// template<typename T> class array; -/// -/// template<> +/// +/// template<> /// class array<bool> { }; // class template specialization array<bool> /// \endcode -class ClassTemplateSpecializationDecl +class ClassTemplateSpecializationDecl : public CXXRecordDecl, public llvm::FoldingSetNode { + + /// \brief Structure that stores information about a class template + /// specialization that was instantiated from a class template partial + /// specialization. + struct SpecializedPartialSpecialization { + /// \brief The class template partial specialization from which this + /// class template specialization was instantiated. + ClassTemplatePartialSpecializationDecl *PartialSpecialization; + + /// \brief The template argument list deduced for the class template + /// partial specialization itself. + TemplateArgumentList *TemplateArgs; + }; + /// \brief The template that this specialization specializes - ClassTemplateDecl *SpecializedTemplate; + llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *> + SpecializedTemplate; /// \brief The template arguments used to describe this specialization. TemplateArgumentList TemplateArgs; + /// \brief The point where this template was instantiated (if any) + SourceLocation PointOfInstantiation; + /// \brief The kind of specialization this declaration refers to. /// Really a value of type TemplateSpecializationKind. - unsigned SpecializationKind : 2; + unsigned SpecializationKind : 3; protected: ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, DeclContext *DC, SourceLocation L, ClassTemplateDecl *SpecializedTemplate, - TemplateArgumentListBuilder &Builder); - + TemplateArgumentListBuilder &Builder, + ClassTemplateSpecializationDecl *PrevDecl); + public: static ClassTemplateSpecializationDecl * Create(ASTContext &Context, DeclContext *DC, SourceLocation L, @@ -890,12 +1026,18 @@ public: TemplateArgumentListBuilder &Builder, ClassTemplateSpecializationDecl *PrevDecl); + virtual void Destroy(ASTContext& C); + + virtual void getNameForDiagnostic(std::string &S, + const PrintingPolicy &Policy, + bool Qualified) const; + /// \brief Retrieve the template that this specialization specializes. - ClassTemplateDecl *getSpecializedTemplate() const { - return SpecializedTemplate; - } + ClassTemplateDecl *getSpecializedTemplate() const; - const TemplateArgumentList &getTemplateArgs() const { + /// \brief Retrieve the template arguments of the class template + /// specialization. + const TemplateArgumentList &getTemplateArgs() const { return TemplateArgs; } @@ -909,6 +1051,67 @@ public: SpecializationKind = TSK; } + /// \brief Get the point of instantiation (if any), or null if none. + SourceLocation getPointOfInstantiation() const { + return PointOfInstantiation; + } + + void setPointOfInstantiation(SourceLocation Loc) { + assert(Loc.isValid() && "point of instantiation must be valid!"); + PointOfInstantiation = Loc; + } + + /// \brief If this class template specialization is an instantiation of + /// a template (rather than an explicit specialization), return the + /// class template or class template partial specialization from which it + /// was instantiated. + llvm::PointerUnion<ClassTemplateDecl *, + ClassTemplatePartialSpecializationDecl *> + getInstantiatedFrom() const { + if (getSpecializationKind() != TSK_ImplicitInstantiation && + getSpecializationKind() != TSK_ExplicitInstantiationDefinition && + getSpecializationKind() != TSK_ExplicitInstantiationDeclaration) + return (ClassTemplateDecl*)0; + + if (SpecializedPartialSpecialization *PartialSpec + = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) + return PartialSpec->PartialSpecialization; + + return const_cast<ClassTemplateDecl*>( + SpecializedTemplate.get<ClassTemplateDecl*>()); + } + + /// \brief Retrieve the set of template arguments that should be used + /// to instantiate members of the class template or class template partial + /// specialization from which this class template specialization was + /// instantiated. + /// + /// \returns For a class template specialization instantiated from the primary + /// template, this function will return the same template arguments as + /// getTemplateArgs(). For a class template specialization instantiated from + /// a class template partial specialization, this function will return the + /// deduced template arguments for the class template partial specialization + /// itself. + const TemplateArgumentList &getTemplateInstantiationArgs() const { + if (SpecializedPartialSpecialization *PartialSpec + = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) + return *PartialSpec->TemplateArgs; + + return getTemplateArgs(); + } + + /// \brief Note that this class template specialization is actually an + /// instantiation of the given class template partial specialization whose + /// template arguments have been deduced. + void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec, + TemplateArgumentList *TemplateArgs) { + SpecializedPartialSpecialization *PS + = new (getASTContext()) SpecializedPartialSpecialization(); + PS->PartialSpecialization = PartialSpec; + PS->TemplateArgs = TemplateArgs; + SpecializedTemplate = PS; + } + /// \brief Sets the type of this specialization as it was written by /// the user. This will be a class template specialization type. void setTypeAsWritten(QualType T) { @@ -916,18 +1119,19 @@ public: } void Profile(llvm::FoldingSetNodeID &ID) const { - Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size()); + Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size(), + getASTContext()); } - static void - Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs) { + static void + Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, ASTContext &Context) { ID.AddInteger(NumTemplateArgs); for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg) - TemplateArgs[Arg].Profile(ID); + TemplateArgs[Arg].Profile(ID, Context); } - static bool classof(const Decl *D) { + static bool classof(const Decl *D) { return D->getKind() == ClassTemplateSpecialization || D->getKind() == ClassTemplatePartialSpecialization; } @@ -941,19 +1145,21 @@ public: } }; -class ClassTemplatePartialSpecializationDecl - : public ClassTemplateSpecializationDecl -{ - /// \brief The list of template parameters +class ClassTemplatePartialSpecializationDecl + : public ClassTemplateSpecializationDecl { + /// \brief The list of template parameters TemplateParameterList* TemplateParams; ClassTemplatePartialSpecializationDecl(ASTContext &Context, DeclContext *DC, SourceLocation L, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, - TemplateArgumentListBuilder &Builder) - : ClassTemplateSpecializationDecl(Context, ClassTemplatePartialSpecialization, - DC, L, SpecializedTemplate, Builder), + TemplateArgumentListBuilder &Builder, + ClassTemplatePartialSpecializationDecl *PrevDecl) + : ClassTemplateSpecializationDecl(Context, + ClassTemplatePartialSpecialization, + DC, L, SpecializedTemplate, Builder, + PrevDecl), TemplateParams(Params) { } public: @@ -971,7 +1177,7 @@ public: // FIXME: Add Profile support! - static bool classof(const Decl *D) { + static bool classof(const Decl *D) { return D->getKind() == ClassTemplatePartialSpecialization; } @@ -986,29 +1192,41 @@ protected: /// \brief Data that is common to all of the declarations of a given /// class template. struct Common { + Common() : InstantiatedFromMember(0, 0) {} + /// \brief The class template specializations for this class /// template, including explicit specializations and instantiations. llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations; /// \brief The class template partial specializations for this class /// template. - llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> + llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> PartialSpecializations; /// \brief The injected-class-name type for this class template. QualType InjectedClassNameType; + + /// \brief The templated member class from which this was most + /// directly instantiated (or null). + /// + /// The boolean value indicates whether this member class template + /// was explicitly specialized. + llvm::PointerIntPair<ClassTemplateDecl *, 1, bool> InstantiatedFromMember; }; + // FIXME: Combine PreviousDeclaration with CommonPtr, as in + // FunctionTemplateDecl. + /// \brief Previous declaration of this class template. ClassTemplateDecl *PreviousDeclaration; /// \brief Pointer to the data that is common to all of the /// declarations of this class template. - /// + /// /// The first declaration of a class template (e.g., the declaration /// with no "previous declaration") owns this pointer. Common *CommonPtr; - + ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl, ClassTemplateDecl *PrevDecl, Common *CommonPtr) @@ -1028,6 +1246,8 @@ public: return PreviousDeclaration; } + virtual ClassTemplateDecl *getCanonicalDecl(); + /// Create a class template node. static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -1048,6 +1268,16 @@ public: return CommonPtr->PartialSpecializations; } + /// \brief Find a class template partial specialization with the given + /// type T. + /// + /// \brief A dependent type that names a specialization of this class + /// template. + /// + /// \returns the class template partial specialization that exactly matches + /// the type \p T, or NULL if no such partial specialization exists. + ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T); + /// \brief Retrieve the type of the injected-class-name for this /// class template. /// @@ -1064,6 +1294,61 @@ public: /// \endcode QualType getInjectedClassNameType(ASTContext &Context); + /// \brief Retrieve the member class template that this class template was + /// derived from. + /// + /// This routine will return non-NULL for templated member classes of + /// class templates. For example, given: + /// + /// \code + /// template <typename T> + /// struct X { + /// template <typename U> struct A {}; + /// }; + /// \endcode + /// + /// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent + /// is X<int>, also a CTSD) for which getSpecializedTemplate() will + /// return X<int>::A<U>, a TemplateClassDecl (whose parent is again + /// X<int>) for which getInstantiatedFromMemberTemplate() will return + /// X<T>::A<U>, a TemplateClassDecl (whose parent is X<T>, also a TCD). + /// + /// \returns null if this is not an instantiation of a member class template. + ClassTemplateDecl *getInstantiatedFromMemberTemplate() const { + return CommonPtr->InstantiatedFromMember.getPointer(); + } + + void setInstantiatedFromMemberTemplate(ClassTemplateDecl *CTD) { + assert(!CommonPtr->InstantiatedFromMember.getPointer()); + CommonPtr->InstantiatedFromMember.setPointer(CTD); + } + + /// \brief Determines whether this template was a specialization of a + /// member template. + /// + /// In the following example, the member template \c X<int>::Inner is a + /// member specialization. + /// + /// \code + /// template<typename T> + /// struct X { + /// template<typename U> struct Inner; + /// }; + /// + /// template<> template<typename T> + /// struct X<int>::Inner { /* ... */ }; + /// \endcode + bool isMemberSpecialization() { + return CommonPtr->InstantiatedFromMember.getInt(); + } + + /// \brief Note that this member template is a specialization. + void setMemberSpecialization() { + assert(CommonPtr->InstantiatedFromMember.getPointer() && + "Only member templates can be member template specializations"); + CommonPtr->InstantiatedFromMember.setInt(true); + } + // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return D->getKind() == ClassTemplate; } @@ -1073,8 +1358,87 @@ public: virtual void Destroy(ASTContext& C); }; +/// Declaration of a friend template. For example: +/// +/// template <typename T> class A { +/// friend class MyVector<T>; // not a friend template +/// template <typename U> friend class B; // friend template +/// template <typename U> friend class Foo<T>::Nested; // friend template +class FriendTemplateDecl : public Decl { +public: + typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion; + +private: + // The number of template parameters; always non-zero. + unsigned NumParams; + + // The parameter list. + TemplateParameterList **Params; + + // The declaration that's a friend of this class. + FriendUnion Friend; + + // Location of the 'friend' specifier. + SourceLocation FriendLoc; + + + FriendTemplateDecl(DeclContext *DC, SourceLocation Loc, + unsigned NParams, + TemplateParameterList **Params, + FriendUnion Friend, + SourceLocation FriendLoc) + : Decl(Decl::FriendTemplate, DC, Loc), + NumParams(NParams), + Params(Params), + Friend(Friend), + FriendLoc(FriendLoc) + {} + +public: + static FriendTemplateDecl *Create(ASTContext &Context, + DeclContext *DC, SourceLocation Loc, + unsigned NParams, + TemplateParameterList **Params, + FriendUnion Friend, + SourceLocation FriendLoc); + + /// If this friend declaration names a templated type (or + /// a dependent member type of a templated type), return that + /// type; otherwise return null. + Type *getFriendType() const { + return Friend.dyn_cast<Type*>(); + } + + /// If this friend declaration names a templated function (or + /// a member function of a templated type), return that type; + /// otherwise return null. + NamedDecl *getFriendDecl() const { + return Friend.dyn_cast<NamedDecl*>(); + } + + /// Retrieves the location of the 'friend' keyword. + SourceLocation getFriendLoc() const { + return FriendLoc; + } + + TemplateParameterList *getTemplateParameterList(unsigned i) const { + assert(i <= NumParams); + return Params[i]; + } + + unsigned getNumTemplateParameters() const { + return NumParams; + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() == Decl::FriendTemplate; + } + static bool classof(const FriendTemplateDecl *D) { return true; } +}; + /// Implementation of inline functions that require the template declarations -inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD) +inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD) : Function(FTD) { } } /* end of namespace clang */ diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index db140999b045..ed4ac6b5d4e7 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -15,6 +15,8 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/AST/Type.h" +#include "clang/AST/CanonicalType.h" +#include "clang/Basic/PartialDiagnostic.h" namespace llvm { template <typename T> struct DenseMapInfo; @@ -100,7 +102,7 @@ private: /// CXXSpecialName, returns a pointer to it. Otherwise, returns /// a NULL pointer. CXXSpecialName *getAsCXXSpecialName() const { - if (getNameKind() >= CXXConstructorName && + if (getNameKind() >= CXXConstructorName && getNameKind() <= CXXConversionFunctionName) return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask); return 0; @@ -115,16 +117,16 @@ private: // Construct a declaration name from the name of a C++ constructor, // destructor, or conversion function. - DeclarationName(CXXSpecialName *Name) - : Ptr(reinterpret_cast<uintptr_t>(Name)) { + DeclarationName(CXXSpecialName *Name) + : Ptr(reinterpret_cast<uintptr_t>(Name)) { assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXSpecialName"); Ptr |= StoredDeclarationNameExtra; } // Construct a declaration name from the name of a C++ overloaded // operator. - DeclarationName(CXXOperatorIdName *Name) - : Ptr(reinterpret_cast<uintptr_t>(Name)) { + DeclarationName(CXXOperatorIdName *Name) + : Ptr(reinterpret_cast<uintptr_t>(Name)) { assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXOperatorId"); Ptr |= StoredDeclarationNameExtra; } @@ -144,8 +146,8 @@ public: DeclarationName() : Ptr(0) { } // Construct a declaration name from an IdentifierInfo *. - DeclarationName(const IdentifierInfo *II) - : Ptr(reinterpret_cast<uintptr_t>(II)) { + DeclarationName(const IdentifierInfo *II) + : Ptr(reinterpret_cast<uintptr_t>(II)) { assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo"); } @@ -157,8 +159,8 @@ public: // operator bool() - Evaluates true when this declaration name is // non-empty. - operator bool() const { - return ((Ptr & PtrMask) != 0) || + operator bool() const { + return ((Ptr & PtrMask) != 0) || (reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask)); } @@ -170,10 +172,10 @@ public: bool isObjCOneArgSelector() const { return getStoredNameKind() == StoredObjCOneArgSelector; } - + /// getNameKind - Determine what kind of name this is. NameKind getNameKind() const; - + /// getName - Retrieve the human-readable string for this name. std::string getAsString() const; @@ -181,7 +183,7 @@ public: /// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in /// this declaration name, or NULL if this declaration name isn't a /// simple identifier. - IdentifierInfo *getAsIdentifierInfo() const { + IdentifierInfo *getAsIdentifierInfo() const { if (isIdentifier()) return reinterpret_cast<IdentifierInfo *>(Ptr); return 0; @@ -195,12 +197,18 @@ public: /// an opaque pointer. void *getAsOpaquePtr() const { return reinterpret_cast<void*>(Ptr); } + static DeclarationName getFromOpaquePtr(void *P) { + DeclarationName N; + N.Ptr = reinterpret_cast<uintptr_t> (P); + return N; + } + static DeclarationName getFromOpaqueInteger(uintptr_t P) { DeclarationName N; N.Ptr = P; return N; } - + /// getCXXNameType - If this name is one of the C++ names (of a /// constructor, destructor, or conversion function), return the /// type associated with that name. @@ -290,32 +298,32 @@ public: /// getCXXConstructorName - Returns the name of a C++ constructor /// for the given Type. - DeclarationName getCXXConstructorName(QualType Ty) { + DeclarationName getCXXConstructorName(CanQualType Ty) { return getCXXSpecialName(DeclarationName::CXXConstructorName, Ty); } /// getCXXDestructorName - Returns the name of a C++ destructor /// for the given Type. - DeclarationName getCXXDestructorName(QualType Ty) { + DeclarationName getCXXDestructorName(CanQualType Ty) { return getCXXSpecialName(DeclarationName::CXXDestructorName, Ty); } /// getCXXConversionFunctionName - Returns the name of a C++ /// conversion function for the given Type. - DeclarationName getCXXConversionFunctionName(QualType Ty) { + DeclarationName getCXXConversionFunctionName(CanQualType Ty) { return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty); } /// getCXXSpecialName - Returns a declaration name for special kind /// of C++ name, e.g., for a constructor, destructor, or conversion /// function. - DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind, - QualType Ty); + DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind, + CanQualType Ty); /// getCXXOperatorName - Get the name of the overloadable C++ /// operator corresponding to Op. DeclarationName getCXXOperatorName(OverloadedOperatorKind Op); -}; +}; /// Insertion operator for diagnostics. This allows sending DeclarationName's /// into a diagnostic with <<. @@ -325,7 +333,15 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, Diagnostic::ak_declarationname); return DB; } - + +/// Insertion operator for partial diagnostics. This allows binding +/// DeclarationName's into a partial diagnostic with <<. +inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + DeclarationName N) { + PD.AddTaggedVal(N.getAsOpaqueInteger(), + Diagnostic::ak_declarationname); + return PD; +} } // end namespace clang @@ -344,7 +360,7 @@ struct DenseMapInfo<clang::DeclarationName> { static unsigned getHashValue(clang::DeclarationName); - static inline bool + static inline bool isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) { return LHS == RHS; } diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 6a1046e6d03f..d5dff5065d49 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -20,6 +20,7 @@ #include "llvm/ADT/APSInt.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include <vector> namespace clang { @@ -42,20 +43,20 @@ class Expr : public Stmt { QualType TR; protected: - /// TypeDependent - Whether this expression is type-dependent + /// TypeDependent - Whether this expression is type-dependent /// (C++ [temp.dep.expr]). bool TypeDependent : 1; - /// ValueDependent - Whether this expression is value-dependent + /// ValueDependent - Whether this expression is value-dependent /// (C++ [temp.dep.constexpr]). bool ValueDependent : 1; // FIXME: Eventually, this constructor should go away and we should // require every subclass to provide type/value-dependence // information. - Expr(StmtClass SC, QualType T) + Expr(StmtClass SC, QualType T) : Stmt(SC), TypeDependent(false), ValueDependent(false) { - setType(T); + setType(T); } Expr(StmtClass SC, QualType T, bool TD, bool VD) @@ -66,9 +67,18 @@ protected: /// \brief Construct an empty expression. explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { } -public: +public: + /// \brief Increases the reference count for this expression. + /// + /// Invoke the Retain() operation when this expression + /// is being shared by another owner. + Expr *Retain() { + Stmt::Retain(); + return this; + } + QualType getType() const { return TR; } - void setType(QualType t) { + void setType(QualType t) { // In C++, the type of an expression is always adjusted so that it // will not have reference type an expression will never have // reference type (C++ [expr]p6). Use @@ -76,16 +86,16 @@ public: // type. Additionally, inspect Expr::isLvalue to determine whether // an expression that is adjusted in this manner should be // considered an lvalue. - assert((TR.isNull() || !TR->isReferenceType()) && + assert((TR.isNull() || !TR->isReferenceType()) && "Expressions can't have reference type"); - TR = t; + TR = t; } /// isValueDependent - Determines whether this expression is /// value-dependent (C++ [temp.dep.constexpr]). For example, the /// array bound of "Chars" in the following example is - /// value-dependent. + /// value-dependent. /// @code /// template<int Size, char (&Chars)[Size]> struct meta_string; /// @endcode @@ -100,7 +110,7 @@ public: /// example, the expressions "x" and "x + y" are type-dependent in /// the following code, but "y" is not type-dependent: /// @code - /// template<typename T> + /// template<typename T> /// void add(T x, int y) { /// x + y; /// } @@ -118,14 +128,14 @@ public: /// getExprLoc - Return the preferred location for the arrow when diagnosing /// a problem with a generic expression. virtual SourceLocation getExprLoc() const { return getLocStart(); } - + /// isUnusedResultAWarning - Return true if this immediate expression should /// be warned about if the result is unused. If so, fill in Loc and Ranges /// with location to warn on and the source range[s] to report with the /// warning. bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, SourceRange &R2) const; - + /// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or /// incomplete type other than void. Nonarray expressions that can be lvalues: /// - name, where name must be a variable @@ -150,10 +160,10 @@ public: // Same as above, but excluding checks for non-object and void types in C isLvalueResult isLvalueInternal(ASTContext &Ctx) const; - + /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, /// does not have an incomplete type, does not have a const-qualified type, - /// and if it is a structure or union, does not have any member (including, + /// and if it is a structure or union, does not have any member (including, /// recursively, any member or element of all contained aggregates or unions) /// with a const-qualified type. /// @@ -177,7 +187,7 @@ public: }; isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = 0) const; - + /// \brief If this expression refers to a bit-field, retrieve the /// declaration of that bit-field. FieldDecl *getBitField(); @@ -185,7 +195,7 @@ public: const FieldDecl *getBitField() const { return const_cast<Expr*>(this)->getBitField(); } - + /// 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 @@ -200,16 +210,16 @@ public: /// isConstantInitializer - Returns true if this expression is a constant /// initializer, which can be emitted at compile-time. bool isConstantInitializer(ASTContext &Ctx) const; - + /// EvalResult is a struct with detailed info about an evaluated expression. struct EvalResult { /// Val - This is the value the expression can be folded to. APValue Val; - + /// HasSideEffects - Whether the evaluated expression has side effects. /// For example, (f() && 0) can be folded, but it still has side effects. bool HasSideEffects; - + /// Diag - If the expression is unfoldable, then Diag contains a note /// diagnostic indicating why it's not foldable. DiagLoc indicates a caret /// position for the error, and DiagExpr is the expression that caused @@ -221,7 +231,7 @@ public: unsigned Diag; const Expr *DiagExpr; SourceLocation DiagLoc; - + EvalResult() : HasSideEffects(false), Diag(0), DiagExpr(0) {} }; @@ -239,25 +249,41 @@ public: /// must be called on an expression that constant folds to an integer. llvm::APSInt EvaluateAsInt(ASTContext &Ctx) const; - /// EvaluateAsLValue - Evaluate an expression to see if it's a valid LValue. + /// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue + /// with link time known address. bool EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const; + /// EvaluateAsAnyLValue - The same as EvaluateAsLValue, except that it + /// also succeeds on stack based, immutable address lvalues. + bool EvaluateAsAnyLValue(EvalResult &Result, ASTContext &Ctx) const; + + /// \brief Enumeration used to describe how \c isNullPointerConstant() + /// should cope with value-dependent expressions. + enum NullPointerConstantValueDependence { + /// \brief Specifies that the expression should never be value-dependent. + NPC_NeverValueDependent = 0, + + /// \brief Specifies that a value-dependent expression of integral or + /// dependent type should be considered a null pointer constant. + NPC_ValueDependentIsNull, + + /// \brief Specifies that a value-dependent expression should be considered + /// to never be a null pointer constant. + NPC_ValueDependentIsNotNull + }; + /// isNullPointerConstant - C99 6.3.2.3p3 - Return true if this is either an /// integer constant expression with the value zero, or if this is one that is /// cast to void*. - bool isNullPointerConstant(ASTContext &Ctx) const; - - /// hasGlobalStorage - Return true if this expression has static storage - /// duration. This means that the address of this expression is a link-time - /// constant. - bool hasGlobalStorage() const; + bool isNullPointerConstant(ASTContext &Ctx, + NullPointerConstantValueDependence NPC) const; /// isOBJCGCCandidate - Return true if this expression may be used in a read/ - /// write barrier. + /// write barrier. bool isOBJCGCCandidate(ASTContext &Ctx) const; - + /// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return - /// its subexpression. If that subexpression is also a ParenExpr, + /// 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(); @@ -265,12 +291,12 @@ public: /// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr /// or CastExprs, returning their operand. Expr *IgnoreParenCasts(); - + /// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the /// value (including ptr->int casts of the same size). Strip off any /// ParenExpr or CastExprs, returning their operand. Expr *IgnoreParenNoopCasts(ASTContext &Ctx); - + const Expr* IgnoreParens() const { return const_cast<Expr*>(this)->IgnoreParens(); } @@ -280,18 +306,18 @@ public: const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const { return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx); } - + static bool hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs); static bool hasAnyValueDependentArguments(Expr** Exprs, unsigned NumExprs); - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { return T->getStmtClass() >= firstExprConstant && - T->getStmtClass() <= lastExprConstant; + T->getStmtClass() <= lastExprConstant; } static bool classof(const Expr *) { return true; } }; - + //===----------------------------------------------------------------------===// // Primary Expressions. //===----------------------------------------------------------------------===// @@ -299,7 +325,7 @@ public: /// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function, /// enum, etc. class DeclRefExpr : public Expr { - NamedDecl *D; + NamedDecl *D; SourceLocation Loc; protected: @@ -315,14 +341,14 @@ protected: public: // FIXME: Eventually, this constructor will go away and all clients // will have to provide the type- and value-dependent flags. - DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l) : + DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l) : Expr(DeclRefExprClass, t), D(d), Loc(l) {} - DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) : + DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) : Expr(DeclRefExprClass, t, TD, VD), D(d), Loc(l) {} - + /// \brief Construct an empty declaration reference expression. - explicit DeclRefExpr(EmptyShell Empty) + explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) { } NamedDecl *getDecl() { return D; } @@ -332,14 +358,14 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } virtual SourceRange getSourceRange() const { return SourceRange(Loc); } - - static bool classof(const Stmt *T) { + + static bool classof(const Stmt *T) { return T->getStmtClass() == DeclRefExprClass || T->getStmtClass() == CXXConditionDeclExprClass || - T->getStmtClass() == QualifiedDeclRefExprClass; + T->getStmtClass() == QualifiedDeclRefExprClass; } static bool classof(const DeclRefExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -353,38 +379,35 @@ public: Function, PrettyFunction }; - + private: SourceLocation Loc; IdentType Type; public: - PredefinedExpr(SourceLocation l, QualType type, IdentType IT) - : Expr(PredefinedExprClass, type), Loc(l), Type(IT) {} - + PredefinedExpr(SourceLocation l, QualType type, IdentType IT) + : Expr(PredefinedExprClass, type, type->isDependentType(), + type->isDependentType()), Loc(l), Type(IT) {} + /// \brief Construct an empty predefined expression. - explicit PredefinedExpr(EmptyShell Empty) + explicit PredefinedExpr(EmptyShell Empty) : Expr(PredefinedExprClass, Empty) { } - PredefinedExpr* Clone(ASTContext &C) const; - IdentType getIdentType() const { return Type; } void setIdentType(IdentType IT) { Type = IT; } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - // FIXME: The logic for computing the value of a predefined expr should go - // into a method here that takes the inner-most code decl (a block, function - // or objc method) that the expr lives in. This would allow sema and codegen - // to be consistent for things like sizeof(__func__) etc. - + static std::string ComputeName(ASTContext &Context, IdentType IT, + const Decl *CurrentDecl); + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == PredefinedExprClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == PredefinedExprClass; } static bool classof(const PredefinedExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -394,7 +417,7 @@ class IntegerLiteral : public Expr { llvm::APInt Value; SourceLocation Loc; public: - // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy, + // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy, // or UnsignedLongLongTy IntegerLiteral(const llvm::APInt &V, QualType type, SourceLocation l) : Expr(IntegerLiteralClass, type), Value(V), Loc(l) { @@ -402,11 +425,9 @@ public: } /// \brief Construct an empty integer literal. - explicit IntegerLiteral(EmptyShell Empty) + explicit IntegerLiteral(EmptyShell Empty) : Expr(IntegerLiteralClass, Empty) { } - IntegerLiteral* Clone(ASTContext &C) const; - const llvm::APInt &getValue() const { return Value; } virtual SourceRange getSourceRange() const { return SourceRange(Loc); } @@ -416,11 +437,11 @@ public: void setValue(const llvm::APInt &Val) { Value = Val; } void setLocation(SourceLocation Location) { Loc = Location; } - static bool classof(const Stmt *T) { - return T->getStmtClass() == IntegerLiteralClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == IntegerLiteralClass; } static bool classof(const IntegerLiteral *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -439,21 +460,19 @@ public: /// \brief Construct an empty character literal. CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { } - CharacterLiteral* Clone(ASTContext &C) const; - - SourceLocation getLoc() const { return Loc; } + SourceLocation getLocation() const { return Loc; } bool isWide() const { return IsWide; } - + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } - + unsigned getValue() const { return Value; } void setLocation(SourceLocation Location) { Loc = Location; } void setWide(bool W) { IsWide = W; } void setValue(unsigned Val) { Value = Val; } - static bool classof(const Stmt *T) { - return T->getStmtClass() == CharacterLiteralClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == CharacterLiteralClass; } static bool classof(const CharacterLiteral *) { return true; } @@ -467,16 +486,14 @@ class FloatingLiteral : public Expr { bool IsExact : 1; SourceLocation Loc; public: - FloatingLiteral(const llvm::APFloat &V, bool isexact, + FloatingLiteral(const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L) - : Expr(FloatingLiteralClass, Type), Value(V), IsExact(isexact), Loc(L) {} + : Expr(FloatingLiteralClass, Type), Value(V), IsExact(isexact), Loc(L) {} /// \brief Construct an empty floating-point literal. - explicit FloatingLiteral(EmptyShell Empty) + explicit FloatingLiteral(EmptyShell Empty) : Expr(FloatingLiteralClass, Empty), Value(0.0) { } - FloatingLiteral* Clone(ASTContext &C) const; - const llvm::APFloat &getValue() const { return Value; } void setValue(const llvm::APFloat &Val) { Value = Val; } @@ -487,7 +504,7 @@ public: /// double. Note that this may cause loss of precision, but is useful for /// debugging dumps, etc. double getValueAsApproximateDouble() const; - + SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } @@ -495,14 +512,14 @@ public: // into a method here that takes the inner-most code decl (a block, function // or objc method) that the expr lives in. This would allow sema and codegen // to be consistent for things like sizeof(__func__) etc. - + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == FloatingLiteralClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == FloatingLiteralClass; } static bool classof(const FloatingLiteral *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -518,23 +535,21 @@ class ImaginaryLiteral : public Expr { public: ImaginaryLiteral(Expr *val, QualType Ty) : Expr(ImaginaryLiteralClass, Ty), Val(val) {} - + /// \brief Build an empty imaginary literal. - explicit ImaginaryLiteral(EmptyShell Empty) + explicit ImaginaryLiteral(EmptyShell Empty) : Expr(ImaginaryLiteralClass, Empty) { } const Expr *getSubExpr() const { return cast<Expr>(Val); } Expr *getSubExpr() { return cast<Expr>(Val); } void setSubExpr(Expr *E) { Val = E; } - ImaginaryLiteral* Clone(ASTContext &C) const; - virtual SourceRange getSourceRange() const { return Val->getSourceRange(); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ImaginaryLiteralClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == ImaginaryLiteralClass; } static bool classof(const ImaginaryLiteral *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -564,6 +579,10 @@ class StringLiteral : public Expr { SourceLocation TokLocs[1]; StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty) {} + +protected: + virtual void DoDestroy(ASTContext &C); + public: /// This is the "fully general" constructor that allows representation of /// strings formed from multiple concatenated tokens. @@ -572,7 +591,7 @@ public: const SourceLocation *Loc, unsigned NumStrs); /// Simple constructor for string literals made from one token. - static StringLiteral *Create(ASTContext &C, const char *StrData, + static StringLiteral *Create(ASTContext &C, const char *StrData, unsigned ByteLength, bool Wide, QualType Ty, SourceLocation Loc) { return Create(C, StrData, ByteLength, Wide, Ty, &Loc, 1); @@ -581,33 +600,35 @@ public: /// \brief Construct an empty string literal. static StringLiteral *CreateEmpty(ASTContext &C, unsigned NumStrs); - StringLiteral* Clone(ASTContext &C) const; - void Destroy(ASTContext &C); - + llvm::StringRef getString() const { + return llvm::StringRef(StrData, ByteLength); + } + // FIXME: These are deprecated, replace with StringRef. const char *getStrData() const { return StrData; } unsigned getByteLength() const { return ByteLength; } /// \brief Sets the string data to the given string data. - void setStrData(ASTContext &C, const char *Str, unsigned Len); + void setString(ASTContext &C, llvm::StringRef Str); bool isWide() const { return IsWide; } void setWide(bool W) { IsWide = W; } bool containsNonAsciiOrNull() const { - for (unsigned i = 0; i < getByteLength(); ++i) - if (!isascii(getStrData()[i]) || !getStrData()[i]) + llvm::StringRef Str = getString(); + for (unsigned i = 0, e = Str.size(); i != e; ++i) + if (!isascii(Str[i]) || !Str[i]) return true; return false; } /// getNumConcatenated - Get the number of string literal tokens that were /// concatenated in translation phase #6 to form this string literal. unsigned getNumConcatenated() const { return NumConcatenated; } - + SourceLocation getStrTokenLoc(unsigned TokNum) const { assert(TokNum < NumConcatenated && "Invalid tok number"); return TokLocs[TokNum]; } - void setStrTokenLoc(unsigned TokNum, SourceLocation L) { + void setStrTokenLoc(unsigned TokNum, SourceLocation L) { assert(TokNum < NumConcatenated && "Invalid tok number"); TokLocs[TokNum] = L; } @@ -616,14 +637,14 @@ public: tokloc_iterator tokloc_begin() const { return TokLocs; } tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; } - virtual SourceRange getSourceRange() const { - return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]); + virtual SourceRange getSourceRange() const { + return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == StringLiteralClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == StringLiteralClass; } static bool classof(const StringLiteral *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -637,11 +658,11 @@ class ParenExpr : public Expr { public: ParenExpr(SourceLocation l, SourceLocation r, Expr *val) : Expr(ParenExprClass, val->getType(), - val->isTypeDependent(), val->isValueDependent()), + val->isTypeDependent(), val->isValueDependent()), L(l), R(r), Val(val) {} - + /// \brief Construct an empty parenthesized expression. - explicit ParenExpr(EmptyShell Empty) + explicit ParenExpr(EmptyShell Empty) : Expr(ParenExprClass, Empty) { } const Expr *getSubExpr() const { return cast<Expr>(Val); } @@ -658,11 +679,11 @@ public: SourceLocation getRParen() const { return R; } void setRParen(SourceLocation Loc) { R = Loc; } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ParenExprClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == ParenExprClass; } static bool classof(const ParenExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -680,7 +701,7 @@ public: /// later returns zero in the type of the operand. /// /// __builtin_offsetof(type, a.b[10]) is represented as a unary operator whose -/// subexpression is a compound literal with the various MemberExpr and +/// subexpression is a compound literal with the various MemberExpr and /// ArraySubscriptExpr's applied to it. /// class UnaryOperator : public Expr { @@ -700,16 +721,16 @@ private: Stmt *Val; Opcode Opc; SourceLocation Loc; -public: +public: UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l) : Expr(UnaryOperatorClass, type, input->isTypeDependent() && opc != OffsetOf, - input->isValueDependent()), + input->isValueDependent()), Val(input), Opc(opc), Loc(l) {} /// \brief Build an empty unary operator. - explicit UnaryOperator(EmptyShell Empty) + explicit UnaryOperator(EmptyShell Empty) : Expr(UnaryOperatorClass, Empty), Opc(AddrOf) { } Opcode getOpcode() const { return Opc; } @@ -738,7 +759,8 @@ public: bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; } bool isOffsetOfOp() const { return Opc == OffsetOf; } static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; } - + bool isArithmeticOp() const { return isArithmeticOp(Opc); } + /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it /// corresponds to, e.g. "sizeof" or "[pre]++" static const char *getOpcodeStr(Opcode Op); @@ -758,12 +780,12 @@ public: return SourceRange(Loc, Val->getLocEnd()); } virtual SourceLocation getExprLoc() const { return Loc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == UnaryOperatorClass; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnaryOperatorClass; } static bool classof(const UnaryOperator *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -779,8 +801,12 @@ class SizeOfAlignOfExpr : public Expr { Stmt *Ex; } Argument; SourceLocation OpLoc, RParenLoc; + +protected: + virtual void DoDestroy(ASTContext& C); + public: - SizeOfAlignOfExpr(bool issizeof, QualType T, + SizeOfAlignOfExpr(bool issizeof, QualType T, QualType resultType, SourceLocation op, SourceLocation rp) : Expr(SizeOfAlignOfExprClass, resultType, @@ -791,7 +817,7 @@ public: Argument.Ty = T.getAsOpaquePtr(); } - SizeOfAlignOfExpr(bool issizeof, Expr *E, + SizeOfAlignOfExpr(bool issizeof, Expr *E, QualType resultType, SourceLocation op, SourceLocation rp) : Expr(SizeOfAlignOfExprClass, resultType, @@ -806,8 +832,6 @@ public: explicit SizeOfAlignOfExpr(EmptyShell Empty) : Expr(SizeOfAlignOfExprClass, Empty) { } - virtual void Destroy(ASTContext& C); - bool isSizeOf() const { return isSizeof; } void setSizeof(bool S) { isSizeof = S; } @@ -825,9 +849,9 @@ public: } void setArgument(Expr *E) { Argument.Ex = E; isType = false; } - void setArgument(QualType T) { - Argument.Ty = T.getAsOpaquePtr(); - isType = true; + void setArgument(QualType T) { + Argument.Ty = T.getAsOpaquePtr(); + isType = true; } /// Gets the argument type, or the type of the argument expression, whichever @@ -846,11 +870,11 @@ public: return SourceRange(OpLoc, RParenLoc); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == SizeOfAlignOfExprClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == SizeOfAlignOfExprClass; } static bool classof(const SizeOfAlignOfExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -863,7 +887,7 @@ public: /// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting. class ArraySubscriptExpr : public Expr { enum { LHS, RHS, END_EXPR=2 }; - Stmt* SubExprs[END_EXPR]; + Stmt* SubExprs[END_EXPR]; SourceLocation RBracketLoc; public: ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t, @@ -875,7 +899,7 @@ public: SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; } - + /// \brief Create an empty array subscript expression. explicit ArraySubscriptExpr(EmptyShell Shell) : Expr(ArraySubscriptExprClass, Shell) { } @@ -896,37 +920,37 @@ public: Expr *getRHS() { return cast<Expr>(SubExprs[RHS]); } const Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } void setRHS(Expr *E) { SubExprs[RHS] = E; } - - Expr *getBase() { + + Expr *getBase() { return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS()); } - - const Expr *getBase() const { + + const Expr *getBase() const { return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS()); } - - Expr *getIdx() { + + Expr *getIdx() { return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS()); } - + const Expr *getIdx() const { return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS()); - } - - virtual SourceRange getSourceRange() const { + } + + virtual SourceRange getSourceRange() const { return SourceRange(getLHS()->getLocStart(), RBracketLoc); } - + SourceLocation getRBracketLoc() const { return RBracketLoc; } void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } virtual SourceLocation getExprLoc() const { return getBase()->getExprLoc(); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ArraySubscriptExprClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == ArraySubscriptExprClass; } static bool classof(const ArraySubscriptExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -934,9 +958,9 @@ public: /// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]). -/// CallExpr itself represents a normal function call, e.g., "f(x, 2)", +/// CallExpr itself represents a normal function call, e.g., "f(x, 2)", /// while its subclasses may represent alternative syntax that (semantically) -/// results in a function call. For example, CXXOperatorCallExpr is +/// results in a function call. For example, CXXOperatorCallExpr is /// a subclass for overloaded operator calls that use operator syntax, e.g., /// "str1 + str2" to resolve to a function call. class CallExpr : public Expr { @@ -944,31 +968,37 @@ class CallExpr : public Expr { Stmt **SubExprs; unsigned NumArgs; SourceLocation RParenLoc; - + protected: // This version of the constructor is for derived classes. CallExpr(ASTContext& C, StmtClass SC, Expr *fn, Expr **args, unsigned numargs, QualType t, SourceLocation rparenloc); - + + virtual void DoDestroy(ASTContext& C); + public: - CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t, + CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t, SourceLocation rparenloc); - + /// \brief Build an empty call expression. - CallExpr(ASTContext &C, EmptyShell Empty); + CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty); ~CallExpr() {} - - void Destroy(ASTContext& C); - + const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); } Expr *getCallee() { return cast<Expr>(SubExprs[FN]); } void setCallee(Expr *F) { SubExprs[FN] = F; } - + + /// \brief If the callee is a FunctionDecl, return it. Otherwise return 0. + FunctionDecl *getDirectCallee(); + const FunctionDecl *getDirectCallee() const { + return const_cast<CallExpr*>(this)->getDirectCallee(); + } + /// getNumArgs - Return the number of actual arguments to this call. /// unsigned getNumArgs() const { return NumArgs; } - + /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) { assert(Arg < NumArgs && "Arg access out of range!"); @@ -978,26 +1008,26 @@ public: assert(Arg < NumArgs && "Arg access out of range!"); return cast<Expr>(SubExprs[Arg+ARGS_START]); } - + /// setArg - Set the specified argument. void setArg(unsigned Arg, Expr *ArgExpr) { assert(Arg < NumArgs && "Arg access out of range!"); SubExprs[Arg+ARGS_START] = ArgExpr; } - + /// setNumArgs - This changes the number of arguments present in this call. /// Any orphaned expressions are deleted by this, and any new operands are set /// to null. void setNumArgs(ASTContext& C, unsigned NumArgs); - + 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+getNumArgs(); } const_arg_iterator arg_begin() const { return SubExprs+ARGS_START; } const_arg_iterator arg_end() const { return SubExprs+ARGS_START+getNumArgs();} - + /// getNumCommas - Return the number of commas that must have been present in /// this function call. unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; } @@ -1005,23 +1035,23 @@ public: /// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If /// not, return 0. unsigned isBuiltinCall(ASTContext &Context) const; - - /// getCallReturnType - Get the return type of the call expr. This is not - /// always the type of the expr itself, if the return type is a reference + + /// getCallReturnType - Get the return type of the call expr. This is not + /// always the type of the expr itself, if the return type is a reference /// type. QualType getCallReturnType() const; - + SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - virtual SourceRange getSourceRange() const { + virtual SourceRange getSourceRange() const { return SourceRange(getCallee()->getLocStart(), RParenLoc); } - - static bool classof(const Stmt *T) { + + static bool classof(const Stmt *T) { return T->getStmtClass() == CallExprClass || T->getStmtClass() == CXXOperatorCallExprClass || - T->getStmtClass() == CXXMemberCallExprClass; + T->getStmtClass() == CXXMemberCallExprClass; } static bool classof(const CallExpr *) { return true; } static bool classof(const CXXOperatorCallExpr *) { return true; } @@ -1032,31 +1062,131 @@ public: virtual child_iterator child_end(); }; +/// \brief Represents the qualifier that may precede a C++ name, e.g., the +/// "std::" in "std::sort". +struct NameQualifier { + /// \brief The nested name specifier. + NestedNameSpecifier *NNS; + + /// \brief The source range covered by the nested name specifier. + SourceRange Range; +}; + +/// \brief Represents an explicit template argument list in C++, e.g., +/// the "<int>" in "sort<int>". +struct ExplicitTemplateArgumentList { + /// \brief The source location of the left angle bracket ('<'); + SourceLocation LAngleLoc; + + /// \brief The source location of the right angle bracket ('>'); + SourceLocation RAngleLoc; + + /// \brief The number of template arguments in TemplateArgs. + /// The actual template arguments (if any) are stored after the + /// ExplicitTemplateArgumentList structure. + unsigned NumTemplateArgs; + + /// \brief Retrieve the template arguments + TemplateArgument *getTemplateArgs() { + return reinterpret_cast<TemplateArgument *> (this + 1); + } + + /// \brief Retrieve the template arguments + const TemplateArgument *getTemplateArgs() const { + return reinterpret_cast<const TemplateArgument *> (this + 1); + } +}; + /// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F. /// class MemberExpr : public Expr { /// Base - the expression for the base pointer or structure references. In /// X.F, this is "X". Stmt *Base; - + /// MemberDecl - This is the decl being referenced by the field/member name. /// In X.F, this is the decl referenced by F. NamedDecl *MemberDecl; - + /// MemberLoc - This is the location of the member name. SourceLocation MemberLoc; - + /// IsArrow - True if this is "X->F", false if this is "X.F". - bool IsArrow; + bool IsArrow : 1; + + /// \brief True if this member expression used a nested-name-specifier to + /// refer to the member, e.g., "x->Base::f". When true, a NameQualifier + /// structure is allocated immediately after the MemberExpr. + bool HasQualifier : 1; + + /// \brief True if this member expression specified a template argument list + /// explicitly, e.g., x->f<int>. When true, an ExplicitTemplateArgumentList + /// structure (and its TemplateArguments) are allocated immediately after + /// the MemberExpr or, if the member expression also has a qualifier, after + /// the NameQualifier structure. + bool HasExplicitTemplateArgumentList : 1; + + /// \brief Retrieve the qualifier that preceded the member name, if any. + NameQualifier *getMemberQualifier() { + if (!HasQualifier) + return 0; + + return reinterpret_cast<NameQualifier *> (this + 1); + } + + /// \brief Retrieve the qualifier that preceded the member name, if any. + const NameQualifier *getMemberQualifier() const { + return const_cast<MemberExpr *>(this)->getMemberQualifier(); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { + if (!HasExplicitTemplateArgumentList) + return 0; + + if (!HasQualifier) + return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + + return reinterpret_cast<ExplicitTemplateArgumentList *>( + getMemberQualifier() + 1); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { + return const_cast<MemberExpr *>(this)->getExplicitTemplateArgumentList(); + } + + MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual, + SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l, + bool has_explicit, SourceLocation langle, + const TemplateArgument *targs, unsigned numtargs, + SourceLocation rangle, QualType ty); + public: MemberExpr(Expr *base, bool isarrow, NamedDecl *memberdecl, SourceLocation l, - QualType ty) - : Expr(MemberExprClass, ty, + QualType ty) + : Expr(MemberExprClass, ty, base->isTypeDependent(), base->isValueDependent()), - Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow) {} + Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow), + HasQualifier(false), HasExplicitTemplateArgumentList(false) {} /// \brief Build an empty member reference expression. - explicit MemberExpr(EmptyShell Empty) : Expr(MemberExprClass, Empty) { } + explicit MemberExpr(EmptyShell Empty) + : Expr(MemberExprClass, Empty), HasQualifier(false), + HasExplicitTemplateArgumentList(false) { } + + static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, + NestedNameSpecifier *qual, SourceRange qualrange, + NamedDecl *memberdecl, + SourceLocation l, + bool has_explicit, + SourceLocation langle, + const TemplateArgument *targs, + unsigned numtargs, + SourceLocation rangle, + QualType ty); void setBase(Expr *E) { Base = E; } Expr *getBase() const { return cast<Expr>(Base); } @@ -1068,6 +1198,73 @@ public: NamedDecl *getMemberDecl() const { return MemberDecl; } void setMemberDecl(NamedDecl *D) { MemberDecl = D; } + /// \brief Determines whether this member expression actually had + /// a C++ nested-name-specifier prior to the name of the member, e.g., + /// x->Base::foo. + bool hasQualifier() const { return HasQualifier; } + + /// \brief If the member name was qualified, retrieves the source range of + /// the nested-name-specifier that precedes the member name. Otherwise, + /// returns an empty source range. + SourceRange getQualifierRange() const { + if (!HasQualifier) + return SourceRange(); + + return getMemberQualifier()->Range; + } + + /// \brief If the member name was qualified, retrieves the + /// nested-name-specifier that precedes the member name. Otherwise, returns + /// NULL. + NestedNameSpecifier *getQualifier() const { + if (!HasQualifier) + return 0; + + return getMemberQualifier()->NNS; + } + + /// \brief Determines whether this member expression actually had a C++ + /// template argument list explicitly specified, e.g., x.f<int>. + bool hasExplicitTemplateArgumentList() { + return HasExplicitTemplateArgumentList; + } + + /// \brief Retrieve the location of the left angle bracket following the + /// member name ('<'), if any. + SourceLocation getLAngleLoc() const { + if (!HasExplicitTemplateArgumentList) + return SourceLocation(); + + return getExplicitTemplateArgumentList()->LAngleLoc; + } + + /// \brief Retrieve the template arguments provided as part of this + /// template-id. + const TemplateArgument *getTemplateArgs() const { + if (!HasExplicitTemplateArgumentList) + return 0; + + return getExplicitTemplateArgumentList()->getTemplateArgs(); + } + + /// \brief Retrieve the number of template arguments provided as part of this + /// template-id. + unsigned getNumTemplateArgs() const { + if (!HasExplicitTemplateArgumentList) + return 0; + + return getExplicitTemplateArgumentList()->NumTemplateArgs; + } + + /// \brief Retrieve the location of the right angle bracket following the + /// template arguments ('>'). + SourceLocation getRAngleLoc() const { + if (!HasExplicitTemplateArgumentList) + return SourceLocation(); + + return getExplicitTemplateArgumentList()->RAngleLoc; + } + bool isArrow() const { return IsArrow; } void setArrow(bool A) { IsArrow = A; } @@ -1079,25 +1276,29 @@ public: virtual SourceRange getSourceRange() const { // If we have an implicit base (like a C++ implicit this), // make sure not to return its location + SourceLocation EndLoc = MemberLoc; + if (HasExplicitTemplateArgumentList) + EndLoc = getRAngleLoc(); + SourceLocation BaseLoc = getBase()->getLocStart(); if (BaseLoc.isInvalid()) - return SourceRange(MemberLoc, MemberLoc); - return SourceRange(BaseLoc, MemberLoc); + return SourceRange(MemberLoc, EndLoc); + return SourceRange(BaseLoc, EndLoc); } - + virtual SourceLocation getExprLoc() const { return MemberLoc; } - static bool classof(const Stmt *T) { - return T->getStmtClass() == MemberExprClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == MemberExprClass; } static bool classof(const MemberExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; -/// CompoundLiteralExpr - [C99 6.5.2.5] +/// CompoundLiteralExpr - [C99 6.5.2.5] /// class CompoundLiteralExpr : public Expr { /// LParenLoc - If non-null, this is the location of the left paren in a @@ -1111,7 +1312,7 @@ public: bool fileScope) : Expr(CompoundLiteralExprClass, ty), LParenLoc(lparenloc), Init(init), FileScope(fileScope) {} - + /// \brief Construct an empty compound literal. explicit CompoundLiteralExpr(EmptyShell Empty) : Expr(CompoundLiteralExprClass, Empty) { } @@ -1135,11 +1336,11 @@ public: return SourceRange(LParenLoc, Init->getLocEnd()); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == CompoundLiteralExprClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == CompoundLiteralExprClass; } static bool classof(const CompoundLiteralExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -1150,28 +1351,85 @@ public: /// representation in the source code (ExplicitCastExpr's derived /// classes). class CastExpr : public Expr { +public: + /// CastKind - the kind of cast this represents. + enum CastKind { + /// CK_Unknown - Unknown cast kind. + /// FIXME: The goal is to get rid of this and make all casts have a + /// kind so that the AST client doesn't have to try to figure out what's + /// going on. + CK_Unknown, + + /// CK_BitCast - Used for reinterpret_cast. + CK_BitCast, + + /// CK_NoOp - Used for const_cast. + CK_NoOp, + + /// CK_DerivedToBase - Derived to base class casts. + CK_DerivedToBase, + + /// CK_Dynamic - Dynamic cast. + CK_Dynamic, + + /// CK_ToUnion - Cast to union (GCC extension). + CK_ToUnion, + + /// CK_ArrayToPointerDecay - Array to pointer decay. + CK_ArrayToPointerDecay, + + // CK_FunctionToPointerDecay - Function to pointer decay. + CK_FunctionToPointerDecay, + + /// CK_NullToMemberPointer - Null pointer to member pointer. + CK_NullToMemberPointer, + + /// CK_BaseToDerivedMemberPointer - Member pointer in base class to + /// member pointer in derived class. + CK_BaseToDerivedMemberPointer, + + /// CK_UserDefinedConversion - Conversion using a user defined type + /// conversion function. + CK_UserDefinedConversion, + + /// CK_ConstructorConversion - Conversion by constructor + CK_ConstructorConversion, + + /// CK_IntegralToPointer - Integral to pointer + CK_IntegralToPointer, + + /// CK_PointerToIntegral - Pointer to integral + CK_PointerToIntegral + }; + +private: + CastKind Kind; Stmt *Op; protected: - CastExpr(StmtClass SC, QualType ty, Expr *op) : + CastExpr(StmtClass SC, QualType ty, const CastKind kind, Expr *op) : Expr(SC, ty, // Cast expressions are type-dependent if the type is // dependent (C++ [temp.dep.expr]p3). ty->isDependentType(), // Cast expressions are value-dependent if the type is // dependent or if the subexpression is value-dependent. - ty->isDependentType() || (op && op->isValueDependent())), - Op(op) {} - + ty->isDependentType() || (op && op->isValueDependent())), + Kind(kind), Op(op) {} + /// \brief Construct an empty cast. - CastExpr(StmtClass SC, EmptyShell Empty) + CastExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) { } - + public: + CastKind getCastKind() const { return Kind; } + void setCastKind(CastKind K) { Kind = K; } + const char *getCastKindName() const; + Expr *getSubExpr() { return cast<Expr>(Op); } const Expr *getSubExpr() const { return cast<Expr>(Op); } void setSubExpr(Expr *E) { Op = E; } - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { StmtClass SC = T->getStmtClass(); if (SC >= CXXNamedCastExprClass && SC <= CXXFunctionalCastExprClass) return true; @@ -1182,7 +1440,7 @@ public: return false; } static bool classof(const CastExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -1200,7 +1458,7 @@ public: /// @code /// class Base { }; /// class Derived : public Base { }; -/// void f(Derived d) { +/// void f(Derived d) { /// Base& b = d; // initializer is an ImplicitCastExpr to an lvalue of type Base /// } /// @endcode @@ -1209,11 +1467,11 @@ class ImplicitCastExpr : public CastExpr { bool LvalueCast; public: - ImplicitCastExpr(QualType ty, Expr *op, bool Lvalue) : - CastExpr(ImplicitCastExprClass, ty, op), LvalueCast(Lvalue) { } + ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, bool Lvalue) : + CastExpr(ImplicitCastExprClass, ty, kind, op), LvalueCast(Lvalue) { } /// \brief Construct an empty implicit cast. - explicit ImplicitCastExpr(EmptyShell Shell) + explicit ImplicitCastExpr(EmptyShell Shell) : CastExpr(ImplicitCastExprClass, Shell) { } @@ -1227,14 +1485,14 @@ public: /// setLvalueCast - Set whether this cast produces an lvalue. void setLvalueCast(bool Lvalue) { LvalueCast = Lvalue; } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ImplicitCastExprClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == ImplicitCastExprClass; } static bool classof(const ImplicitCastExpr *) { return true; } }; /// ExplicitCastExpr - An explicit cast written in the source -/// code. +/// code. /// /// This class is effectively an abstract class, because it provides /// the basic representation of an explicitly-written cast without @@ -1255,11 +1513,12 @@ class ExplicitCastExpr : public CastExpr { QualType TypeAsWritten; protected: - ExplicitCastExpr(StmtClass SC, QualType exprTy, Expr *op, QualType writtenTy) - : CastExpr(SC, exprTy, op), TypeAsWritten(writtenTy) {} + ExplicitCastExpr(StmtClass SC, QualType exprTy, CastKind kind, + Expr *op, QualType writtenTy) + : CastExpr(SC, exprTy, kind, op), TypeAsWritten(writtenTy) {} /// \brief Construct an empty explicit cast. - ExplicitCastExpr(StmtClass SC, EmptyShell Shell) + ExplicitCastExpr(StmtClass SC, EmptyShell Shell) : CastExpr(SC, Shell) { } public: @@ -1268,7 +1527,7 @@ public: QualType getTypeAsWritten() const { return TypeAsWritten; } void setTypeAsWritten(QualType T) { TypeAsWritten = T; } - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { StmtClass SC = T->getStmtClass(); if (SC >= ExplicitCastExprClass && SC <= CStyleCastExprClass) return true; @@ -1287,13 +1546,13 @@ class CStyleCastExpr : public ExplicitCastExpr { SourceLocation LPLoc; // the location of the left paren SourceLocation RPLoc; // the location of the right paren public: - CStyleCastExpr(QualType exprTy, Expr *op, QualType writtenTy, - SourceLocation l, SourceLocation r) : - ExplicitCastExpr(CStyleCastExprClass, exprTy, op, writtenTy), + CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op, QualType writtenTy, + SourceLocation l, SourceLocation r) : + ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, writtenTy), LPLoc(l), RPLoc(r) {} /// \brief Construct an empty C-style explicit cast. - explicit CStyleCastExpr(EmptyShell Shell) + explicit CStyleCastExpr(EmptyShell Shell) : ExplicitCastExpr(CStyleCastExprClass, Shell) { } SourceLocation getLParenLoc() const { return LPLoc; } @@ -1305,8 +1564,8 @@ public: virtual SourceRange getSourceRange() const { return SourceRange(LPLoc, getSubExpr()->getSourceRange().getEnd()); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == CStyleCastExprClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == CStyleCastExprClass; } static bool classof(const CStyleCastExpr *) { return true; } }; @@ -1358,22 +1617,22 @@ private: Stmt* SubExprs[END_EXPR]; Opcode Opc; SourceLocation OpLoc; -public: - +public: + BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, SourceLocation opLoc) : Expr(BinaryOperatorClass, ResTy, lhs->isTypeDependent() || rhs->isTypeDependent(), - lhs->isValueDependent() || rhs->isValueDependent()), + lhs->isValueDependent() || rhs->isValueDependent()), Opc(opc), OpLoc(opLoc) { SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; - assert(!isCompoundAssignmentOp() && + assert(!isCompoundAssignmentOp() && "Use ArithAssignBinaryOperator for compound assignments"); } /// \brief Construct an empty binary operator. - explicit BinaryOperator(EmptyShell Empty) + explicit BinaryOperator(EmptyShell Empty) : Expr(BinaryOperatorClass, Empty), Opc(Comma) { } SourceLocation getOperatorLoc() const { return OpLoc; } @@ -1390,7 +1649,7 @@ public: virtual SourceRange getSourceRange() const { return SourceRange(getLHS()->getLocStart(), getRHS()->getLocEnd()); } - + /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it /// corresponds to, e.g. "<<=". static const char *getOpcodeStr(Opcode Op); @@ -1412,19 +1671,19 @@ public: static bool isRelationalOp(Opcode Opc) { return Opc >= LT && Opc <= GE; } bool isRelationalOp() const { return isRelationalOp(Opc); } - static bool isEqualityOp(Opcode Opc) { return Opc == EQ || Opc == NE; } + static bool isEqualityOp(Opcode Opc) { return Opc == EQ || Opc == NE; } bool isEqualityOp() const { return isEqualityOp(Opc); } - + static bool isLogicalOp(Opcode Opc) { return Opc == LAnd || Opc == LOr; } bool isLogicalOp() const { return isLogicalOp(Opc); } bool isAssignmentOp() const { return Opc >= Assign && Opc <= OrAssign; } bool isCompoundAssignmentOp() const { return Opc > Assign && Opc <= OrAssign;} bool isShiftAssignOp() const { return Opc == ShlAssign || Opc == ShrAssign; } - - static bool classof(const Stmt *S) { + + static bool classof(const Stmt *S) { return S->getStmtClass() == BinaryOperatorClass || - S->getStmtClass() == CompoundAssignOperatorClass; + S->getStmtClass() == CompoundAssignOperatorClass; } static bool classof(const BinaryOperator *) { return true; } @@ -1440,7 +1699,7 @@ protected: SubExprs[RHS] = rhs; } - BinaryOperator(StmtClass SC, EmptyShell Empty) + BinaryOperator(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty), Opc(MulAssign) { } }; @@ -1461,7 +1720,7 @@ public: : BinaryOperator(lhs, rhs, opc, ResType, OpLoc, true), ComputationLHSType(CompLHSType), ComputationResultType(CompResultType) { - assert(isCompoundAssignmentOp() && + assert(isCompoundAssignmentOp() && "Only should be used for compound assignments"); } @@ -1479,8 +1738,8 @@ public: void setComputationResultType(QualType T) { ComputationResultType = T; } static bool classof(const CompoundAssignOperator *) { return true; } - static bool classof(const Stmt *S) { - return S->getStmtClass() == CompoundAssignOperatorClass; + static bool classof(const Stmt *S) { + return S->getStmtClass() == CompoundAssignOperatorClass; } }; @@ -1490,16 +1749,20 @@ public: class ConditionalOperator : public Expr { enum { COND, LHS, RHS, END_EXPR }; Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides. + SourceLocation QuestionLoc, ColonLoc; public: - ConditionalOperator(Expr *cond, Expr *lhs, Expr *rhs, QualType t) + ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs, + SourceLocation CLoc, Expr *rhs, QualType t) : Expr(ConditionalOperatorClass, t, // FIXME: the type of the conditional operator doesn't // depend on the type of the conditional, but the standard // seems to imply that it could. File a bug! ((lhs && lhs->isTypeDependent()) || (rhs && rhs->isTypeDependent())), - (cond->isValueDependent() || + (cond->isValueDependent() || (lhs && lhs->isValueDependent()) || - (rhs && rhs->isValueDependent()))) { + (rhs && rhs->isValueDependent()))), + QuestionLoc(QLoc), + ColonLoc(CLoc) { SubExprs[COND] = cond; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; @@ -1519,29 +1782,35 @@ public: // will be the same as getLHS() except a GCC extension allows the left // subexpression to be omitted, and instead of the condition be returned. // e.g: x ?: y is shorthand for x ? x : y, except that the expression "x" - // is only evaluated once. + // is only evaluated once. Expr *getTrueExpr() const { return cast<Expr>(SubExprs[LHS] ? SubExprs[LHS] : SubExprs[COND]); } - + // getTrueExpr - Return the subexpression representing the value of the ?: // expression if the condition evaluates to false. This is the same as getRHS. Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); } - + Expr *getLHS() const { return cast_or_null<Expr>(SubExprs[LHS]); } void setLHS(Expr *E) { SubExprs[LHS] = E; } Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } void setRHS(Expr *E) { SubExprs[RHS] = E; } + SourceLocation getQuestionLoc() const { return QuestionLoc; } + void setQuestionLoc(SourceLocation L) { QuestionLoc = L; } + + SourceLocation getColonLoc() const { return ColonLoc; } + void setColonLoc(SourceLocation L) { ColonLoc = L; } + virtual SourceRange getSourceRange() const { return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd()); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ConditionalOperatorClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == ConditionalOperatorClass; } static bool classof(const ConditionalOperator *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -1555,9 +1824,9 @@ public: AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelStmt *L, QualType t) : Expr(AddrLabelExprClass, t), AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {} - + /// \brief Build an empty address of a label expression. - explicit AddrLabelExpr(EmptyShell Empty) + explicit AddrLabelExpr(EmptyShell Empty) : Expr(AddrLabelExprClass, Empty) { } SourceLocation getAmpAmpLoc() const { return AmpAmpLoc; } @@ -1568,15 +1837,15 @@ public: virtual SourceRange getSourceRange() const { return SourceRange(AmpAmpLoc, LabelLoc); } - + LabelStmt *getLabel() const { return Label; } void setLabel(LabelStmt *S) { Label = S; } static bool classof(const Stmt *T) { - return T->getStmtClass() == AddrLabelExprClass; + return T->getStmtClass() == AddrLabelExprClass; } static bool classof(const AddrLabelExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -1592,7 +1861,7 @@ public: StmtExpr(CompoundStmt *substmt, QualType T, SourceLocation lp, SourceLocation rp) : Expr(StmtExprClass, T), SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { } - + /// \brief Build an empty statement expression. explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { } @@ -1603,17 +1872,17 @@ public: virtual SourceRange getSourceRange() const { return SourceRange(LParenLoc, RParenLoc); } - + SourceLocation getLParenLoc() const { return LParenLoc; } void setLParenLoc(SourceLocation L) { LParenLoc = L; } SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - + static bool classof(const Stmt *T) { - return T->getStmtClass() == StmtExprClass; + return T->getStmtClass() == StmtExprClass; } static bool classof(const StmtExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -1628,8 +1897,8 @@ class TypesCompatibleExpr : public Expr { QualType Type2; SourceLocation BuiltinLoc, RParenLoc; public: - TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc, - QualType t1, QualType t2, SourceLocation RP) : + TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc, + QualType t1, QualType t2, SourceLocation RP) : Expr(TypesCompatibleExprClass, ReturnType), Type1(t1), Type2(t2), BuiltinLoc(BLoc), RParenLoc(RP) {} @@ -1641,21 +1910,21 @@ public: void setArgType1(QualType T) { Type1 = T; } QualType getArgType2() const { return Type2; } void setArgType2(QualType T) { Type2 = T; } - + SourceLocation getBuiltinLoc() const { return BuiltinLoc; } void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } - + SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - + virtual SourceRange getSourceRange() const { return SourceRange(BuiltinLoc, RParenLoc); } static bool classof(const Stmt *T) { - return T->getStmtClass() == TypesCompatibleExprClass; + return T->getStmtClass() == TypesCompatibleExprClass; } static bool classof(const TypesCompatibleExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -1677,25 +1946,28 @@ class ShuffleVectorExpr : public Expr { Stmt **SubExprs; unsigned NumExprs; +protected: + virtual void DoDestroy(ASTContext &C); + public: - ShuffleVectorExpr(Expr **args, unsigned nexpr, - QualType Type, SourceLocation BLoc, - SourceLocation RP) : + ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr, + QualType Type, SourceLocation BLoc, + SourceLocation RP) : Expr(ShuffleVectorExprClass, Type), BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(nexpr) { - - SubExprs = new Stmt*[nexpr]; + + SubExprs = new (C) Stmt*[nexpr]; for (unsigned i = 0; i < nexpr; i++) SubExprs[i] = args[i]; } /// \brief Build an empty vector-shuffle expression. - explicit ShuffleVectorExpr(EmptyShell Empty) + explicit ShuffleVectorExpr(EmptyShell Empty) : Expr(ShuffleVectorExprClass, Empty), SubExprs(0) { } SourceLocation getBuiltinLoc() const { return BuiltinLoc; } void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } - + SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } @@ -1703,19 +1975,17 @@ public: return SourceRange(BuiltinLoc, RParenLoc); } static bool classof(const Stmt *T) { - return T->getStmtClass() == ShuffleVectorExprClass; + return T->getStmtClass() == ShuffleVectorExprClass; } static bool classof(const ShuffleVectorExpr *) { return true; } - - ~ShuffleVectorExpr() { - delete [] SubExprs; - } - + + ~ShuffleVectorExpr() {} + /// getNumSubExprs - Return the size of the SubExprs array. This includes the /// constant expression, the actual arguments passed in, and the function /// pointers. unsigned getNumSubExprs() const { return NumExprs; } - + /// getExpr - Return the Expr at the specified index. Expr *getExpr(unsigned Index) { assert((Index < NumExprs) && "Arg access out of range!"); @@ -1726,20 +1996,20 @@ public: return cast<Expr>(SubExprs[Index]); } - void setExprs(Expr ** Exprs, unsigned NumExprs); + void setExprs(ASTContext &C, Expr ** Exprs, unsigned NumExprs); unsigned getShuffleMaskIdx(ASTContext &Ctx, unsigned N) { assert((N < NumExprs - 2) && "Shuffle idx out of range!"); return getExpr(N+2)->EvaluateAsInt(Ctx).getZExtValue(); } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// ChooseExpr - GNU builtin-in function __builtin_choose_expr. -/// This AST node is similar to the conditional operator (?:) in C, with +/// This AST node is similar to the conditional operator (?:) in C, with /// the following exceptions: /// - the test expression must be a integer constant expression. /// - the expression returned acts like the chosen subexpression in every @@ -1753,13 +2023,13 @@ class ChooseExpr : public Expr { SourceLocation BuiltinLoc, RParenLoc; public: ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, QualType t, - SourceLocation RP) - : Expr(ChooseExprClass, t), + SourceLocation RP, bool TypeDependent, bool ValueDependent) + : Expr(ChooseExprClass, t, TypeDependent, ValueDependent), BuiltinLoc(BLoc), RParenLoc(RP) { SubExprs[COND] = cond; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; - } + } /// \brief Build an empty __builtin_choose_expr. explicit ChooseExpr(EmptyShell Empty) : Expr(ChooseExprClass, Empty) { } @@ -1783,7 +2053,7 @@ public: SourceLocation getBuiltinLoc() const { return BuiltinLoc; } void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } - + SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } @@ -1791,10 +2061,10 @@ public: return SourceRange(BuiltinLoc, RParenLoc); } static bool classof(const Stmt *T) { - return T->getStmtClass() == ChooseExprClass; + return T->getStmtClass() == ChooseExprClass; } static bool classof(const ChooseExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -1811,14 +2081,12 @@ class GNUNullExpr : public Expr { SourceLocation TokenLoc; public: - GNUNullExpr(QualType Ty, SourceLocation Loc) + GNUNullExpr(QualType Ty, SourceLocation Loc) : Expr(GNUNullExprClass, Ty), TokenLoc(Loc) { } /// \brief Build an empty GNU __null expression. explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { } - GNUNullExpr* Clone(ASTContext &C) const; - /// getTokenLocation - The location of the __null token. SourceLocation getTokenLocation() const { return TokenLoc; } void setTokenLocation(SourceLocation L) { TokenLoc = L; } @@ -1827,10 +2095,10 @@ public: return SourceRange(TokenLoc); } static bool classof(const Stmt *T) { - return T->getStmtClass() == GNUNullExprClass; + return T->getStmtClass() == GNUNullExprClass; } static bool classof(const GNUNullExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -1846,7 +2114,7 @@ public: Val(e), BuiltinLoc(BLoc), RParenLoc(RPLoc) { } - + /// \brief Create an empty __builtin_va_start expression. explicit VAArgExpr(EmptyShell Empty) : Expr(VAArgExprClass, Empty) { } @@ -1856,23 +2124,23 @@ public: SourceLocation getBuiltinLoc() const { return BuiltinLoc; } void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } - + SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } virtual SourceRange getSourceRange() const { return SourceRange(BuiltinLoc, RParenLoc); - } + } static bool classof(const Stmt *T) { return T->getStmtClass() == VAArgExprClass; } static bool classof(const VAArgExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); - virtual child_iterator child_end(); + virtual child_iterator child_end(); }; - + /// @brief Describes an C or C++ initializer list. /// /// InitListExpr describes an initializer list, which can be used to @@ -1911,9 +2179,10 @@ public: /// return NULL, indicating that the current initializer list also /// serves as its syntactic form. class InitListExpr : public Expr { + // FIXME: Eliminate this vector in favor of ASTContext allocation std::vector<Stmt *> InitExprs; SourceLocation LBraceLoc, RBraceLoc; - + /// Contains the initializer list that describes the syntactic form /// written in the source code. InitListExpr *SyntacticForm; @@ -1932,27 +2201,27 @@ public: /// \brief Build an empty initializer list. explicit InitListExpr(EmptyShell Empty) : Expr(InitListExprClass, Empty) { } - + unsigned getNumInits() const { return InitExprs.size(); } - - const Expr* getInit(unsigned Init) const { + + const Expr* getInit(unsigned Init) const { assert(Init < getNumInits() && "Initializer access out of range!"); return cast_or_null<Expr>(InitExprs[Init]); } - - Expr* getInit(unsigned Init) { + + Expr* getInit(unsigned Init) { assert(Init < getNumInits() && "Initializer access out of range!"); return cast_or_null<Expr>(InitExprs[Init]); } - - void setInit(unsigned Init, Expr *expr) { + + void setInit(unsigned Init, Expr *expr) { assert(Init < getNumInits() && "Initializer access out of range!"); InitExprs[Init] = expr; } /// \brief Reserve space for some number of initializers. void reserveInits(unsigned NumInits); - + /// @brief Specify the number of initializers /// /// If there are more than @p NumInits initializers, the remaining @@ -1984,7 +2253,7 @@ public: bool isExplicit() { return LBraceLoc.isValid() && RBraceLoc.isValid(); } - + SourceLocation getLBraceLoc() const { return LBraceLoc; } void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; } SourceLocation getRBraceLoc() const { return RBraceLoc; } @@ -1993,30 +2262,30 @@ public: /// @brief Retrieve the initializer list that describes the /// syntactic form of the initializer. /// - /// + /// InitListExpr *getSyntacticForm() const { return SyntacticForm; } void setSyntacticForm(InitListExpr *Init) { SyntacticForm = Init; } bool hadArrayRangeDesignator() const { return HadArrayRangeDesignator; } - void sawArrayRangeDesignator(bool ARD = true) { + void sawArrayRangeDesignator(bool ARD = true) { HadArrayRangeDesignator = ARD; } virtual SourceRange getSourceRange() const { return SourceRange(LBraceLoc, RBraceLoc); - } + } static bool classof(const Stmt *T) { - return T->getStmtClass() == InitListExprClass; + return T->getStmtClass() == InitListExprClass; } static bool classof(const InitListExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); - + typedef std::vector<Stmt *>::iterator iterator; typedef std::vector<Stmt *>::reverse_iterator reverse_iterator; - + iterator begin() { return InitExprs.begin(); } iterator end() { return InitExprs.end(); } reverse_iterator rbegin() { return InitExprs.rbegin(); } @@ -2030,7 +2299,7 @@ public: /// designators, or GNU array-range designators) followed by an /// expression that initializes the field or element(s) that the /// designators refer to. For example, given: -/// +/// /// @code /// struct point { /// double x; @@ -2070,7 +2339,7 @@ private: unsigned NumSubExprs : 16; - DesignatedInitExpr(QualType Ty, unsigned NumDesignators, + DesignatedInitExpr(QualType Ty, unsigned NumDesignators, const Designator *Designators, SourceLocation EqualOrColonLoc, bool GNUSyntax, Expr **IndexExprs, unsigned NumIndexExprs, @@ -2080,6 +2349,9 @@ private: : Expr(DesignatedInitExprClass, EmptyShell()), NumDesignators(0), Designators(0), NumSubExprs(NumSubExprs) { } +protected: + virtual void DoDestroy(ASTContext &C); + public: /// A field designator, e.g., ".x". struct FieldDesignator { @@ -2090,10 +2362,10 @@ public: /// IdentifierInfo*. After semantic analysis has resolved that /// name, the field designator will instead store a FieldDecl*. uintptr_t NameOrField; - + /// The location of the '.' in the designated initializer. unsigned DotLoc; - + /// The location of the field name in the designated initializer. unsigned FieldLoc; }; @@ -2109,7 +2381,7 @@ public: /// indices. Only valid for GNU array-range designators. unsigned EllipsisLoc; /// The location of the ']' terminating the array range designator. - unsigned RBracketLoc; + unsigned RBracketLoc; }; /// @brief Represents a single C99 designator. @@ -2138,8 +2410,8 @@ public: Designator() {} /// @brief Initializes a field designator. - Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc, - SourceLocation FieldLoc) + Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc, + SourceLocation FieldLoc) : Kind(FieldDesignator) { Field.NameOrField = reinterpret_cast<uintptr_t>(FieldName) | 0x01; Field.DotLoc = DotLoc.getRawEncoding(); @@ -2147,7 +2419,7 @@ public: } /// @brief Initializes an array designator. - Designator(unsigned Index, SourceLocation LBracketLoc, + Designator(unsigned Index, SourceLocation LBracketLoc, SourceLocation RBracketLoc) : Kind(ArrayDesignator) { ArrayOrRange.Index = Index; @@ -2157,7 +2429,7 @@ public: } /// @brief Initializes a GNU array-range designator. - Designator(unsigned Index, SourceLocation LBracketLoc, + Designator(unsigned Index, SourceLocation LBracketLoc, SourceLocation EllipsisLoc, SourceLocation RBracketLoc) : Kind(ArrayRangeDesignator) { ArrayOrRange.Index = Index; @@ -2227,7 +2499,7 @@ public: } }; - static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators, + static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators, unsigned NumDesignators, Expr **IndexExprs, unsigned NumIndexExprs, SourceLocation EqualOrColonLoc, @@ -2241,8 +2513,8 @@ public: // Iterator access to the designators. typedef Designator* designators_iterator; designators_iterator designators_begin() { return Designators; } - designators_iterator designators_end() { - return Designators + NumDesignators; + designators_iterator designators_end() { + return Designators + NumDesignators; } Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; } @@ -2264,7 +2536,7 @@ public: void setGNUSyntax(bool GNU) { GNUSyntax = GNU; } /// @brief Retrieve the initializer value. - Expr *getInit() const { + Expr *getInit() const { return cast<Expr>(*const_cast<DesignatedInitExpr*>(this)->child_begin()); } @@ -2294,21 +2566,19 @@ public: /// \brief Replaces the designator at index @p Idx with the series /// of designators in [First, Last). - void ExpandDesignator(unsigned Idx, const Designator *First, + void ExpandDesignator(unsigned Idx, const Designator *First, const Designator *Last); virtual SourceRange getSourceRange() const; - virtual void Destroy(ASTContext &C); - static bool classof(const Stmt *T) { - return T->getStmtClass() == DesignatedInitExprClass; + return T->getStmtClass() == DesignatedInitExprClass; } static bool classof(const DesignatedInitExpr *) { return true; } // Iterators virtual child_iterator child_begin(); - virtual child_iterator child_end(); + virtual child_iterator child_end(); }; /// \brief Represents an implicitly-generated value initialization of @@ -2319,16 +2589,16 @@ public: /// initializations not explicitly specified by the user. /// /// \see InitListExpr -class ImplicitValueInitExpr : public Expr { +class ImplicitValueInitExpr : public Expr { public: - explicit ImplicitValueInitExpr(QualType ty) + explicit ImplicitValueInitExpr(QualType ty) : Expr(ImplicitValueInitExprClass, ty) { } /// \brief Construct an empty implicit value initialization. explicit ImplicitValueInitExpr(EmptyShell Empty) : Expr(ImplicitValueInitExprClass, Empty) { } - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { return T->getStmtClass() == ImplicitValueInitExprClass; } static bool classof(const ImplicitValueInitExpr *) { return true; } @@ -2337,13 +2607,60 @@ public: return SourceRange(); } - ImplicitValueInitExpr *Clone(ASTContext &C) const; + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +class ParenListExpr : public Expr { + Stmt **Exprs; + unsigned NumExprs; + SourceLocation LParenLoc, RParenLoc; + +protected: + virtual void DoDestroy(ASTContext& C); + +public: + ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs, + unsigned numexprs, SourceLocation rparenloc); + + ~ParenListExpr() {} + + /// \brief Build an empty paren list. + //explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } + + unsigned getNumExprs() const { return NumExprs; } + + const Expr* getExpr(unsigned Init) const { + assert(Init < getNumExprs() && "Initializer access out of range!"); + return cast_or_null<Expr>(Exprs[Init]); + } + + Expr* getExpr(unsigned Init) { + assert(Init < getNumExprs() && "Initializer access out of range!"); + return cast_or_null<Expr>(Exprs[Init]); + } + + Expr **getExprs() { return reinterpret_cast<Expr **>(Exprs); } + + SourceLocation getLParenLoc() const { return LParenLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + + virtual SourceRange getSourceRange() const { + return SourceRange(LParenLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == ParenListExprClass; + } + static bool classof(const ParenListExpr *) { return true; } // Iterators virtual child_iterator child_begin(); - virtual child_iterator child_end(); + virtual child_iterator child_end(); }; + //===----------------------------------------------------------------------===// // Clang Extensions //===----------------------------------------------------------------------===// @@ -2363,9 +2680,9 @@ class ExtVectorElementExpr : public Expr { public: ExtVectorElementExpr(QualType ty, Expr *base, IdentifierInfo &accessor, SourceLocation loc) - : Expr(ExtVectorElementExprClass, ty), + : Expr(ExtVectorElementExprClass, ty), Base(base), Accessor(&accessor), AccessorLoc(loc) {} - + /// \brief Build an empty vector element expression. explicit ExtVectorElementExpr(EmptyShell Empty) : Expr(ExtVectorElementExprClass, Empty) { } @@ -2382,28 +2699,28 @@ public: /// getNumElements - Get the number of components being selected. unsigned getNumElements() const; - + /// containsDuplicateElements - Return true if any element access is /// repeated. bool containsDuplicateElements() const; - + /// getEncodedElementAccess - Encode the elements accessed into an llvm /// aggregate Constant of ConstantInt(s). void getEncodedElementAccess(llvm::SmallVectorImpl<unsigned> &Elts) const; - + virtual SourceRange getSourceRange() const { return SourceRange(getBase()->getLocStart(), AccessorLoc); } - + /// isArrow - Return true if the base expression is a pointer to vector, /// return false if the base expression is a vector. bool isArrow() const; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ExtVectorElementExprClass; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ExtVectorElementExprClass; } static bool classof(const ExtVectorElementExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -2418,7 +2735,7 @@ protected: bool HasBlockDeclRefExprs; public: BlockExpr(BlockDecl *BD, QualType ty, bool hasBlockDeclRefExprs) - : Expr(BlockExprClass, ty), + : Expr(BlockExprClass, ty), TheBlock(BD), HasBlockDeclRefExprs(hasBlockDeclRefExprs) {} /// \brief Build an empty block expression. @@ -2445,25 +2762,25 @@ public: bool hasBlockDeclRefExprs() const { return HasBlockDeclRefExprs; } void setHasBlockDeclRefExprs(bool BDRE) { HasBlockDeclRefExprs = BDRE; } - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { return T->getStmtClass() == BlockExprClass; } static bool classof(const BlockExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; - + /// BlockDeclRefExpr - A reference to a declared variable, function, /// enum, etc. class BlockDeclRefExpr : public Expr { - ValueDecl *D; + ValueDecl *D; SourceLocation Loc; bool IsByRef : 1; bool ConstQualAdded : 1; public: - BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef, + BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef, bool constAdded = false) : Expr(BlockDeclRefExprClass, t), D(d), Loc(l), IsByRef(ByRef), ConstQualAdded(constAdded) {} @@ -2472,7 +2789,7 @@ public: // block. explicit BlockDeclRefExpr(EmptyShell Empty) : Expr(BlockDeclRefExprClass, Empty) { } - + ValueDecl *getDecl() { return D; } const ValueDecl *getDecl() const { return D; } void setDecl(ValueDecl *VD) { D = VD; } @@ -2481,18 +2798,18 @@ public: void setLocation(SourceLocation L) { Loc = L; } virtual SourceRange getSourceRange() const { return SourceRange(Loc); } - + bool isByRef() const { return IsByRef; } void setByRef(bool BR) { IsByRef = BR; } - + bool isConstQualAdded() const { return ConstQualAdded; } void setConstQualAdded(bool C) { ConstQualAdded = C; } - static bool classof(const Stmt *T) { - return T->getStmtClass() == BlockDeclRefExprClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == BlockDeclRefExprClass; } static bool classof(const BlockDeclRefExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 7d76a49d1267..3f66b1f40bfc 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -22,6 +22,7 @@ namespace clang { class CXXConstructorDecl; class CXXDestructorDecl; + class CXXMethodDecl; class CXXTemporary; //===--------------------------------------------------------------------===// @@ -46,15 +47,19 @@ class CXXOperatorCallExpr : public CallExpr { OverloadedOperatorKind Operator; public: - CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn, - Expr **args, unsigned numargs, QualType t, + CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn, + Expr **args, unsigned numargs, QualType t, SourceLocation operatorloc) : CallExpr(C, CXXOperatorCallExprClass, fn, args, numargs, t, operatorloc), Operator(Op) {} + explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) : + CallExpr(C, CXXOperatorCallExprClass, Empty) { } + /// getOperator - Returns the kind of overloaded operator that this /// expression refers to. OverloadedOperatorKind getOperator() const { return Operator; } + void setOperator(OverloadedOperatorKind Kind) { Operator = Kind; } /// getOperatorLoc - Returns the location of the operator symbol in /// the expression. When @c getOperator()==OO_Call, this is the @@ -64,9 +69,9 @@ public: SourceLocation getOperatorLoc() const { return getRParenLoc(); } virtual SourceRange getSourceRange() const; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXOperatorCallExprClass; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXOperatorCallExprClass; } static bool classof(const CXXOperatorCallExpr *) { return true; } }; @@ -90,7 +95,7 @@ public: /// operation would return "x". Expr *getImplicitObjectArgument(); - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXMemberCallExprClass; } static bool classof(const CXXMemberCallExpr *) { return true; } @@ -108,9 +113,9 @@ private: SourceLocation Loc; // the location of the casting op protected: - CXXNamedCastExpr(StmtClass SC, QualType ty, Expr *op, QualType writtenTy, - SourceLocation l) - : ExplicitCastExpr(SC, ty, op, writtenTy), Loc(l) {} + CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op, + QualType writtenTy, SourceLocation l) + : ExplicitCastExpr(SC, ty, kind, op, writtenTy), Loc(l) {} public: const char *getCastName() const; @@ -123,7 +128,7 @@ public: virtual SourceRange getSourceRange() const { return SourceRange(Loc, getSubExpr()->getSourceRange().getEnd()); } - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { switch (T->getStmtClass()) { case CXXNamedCastExprClass: case CXXStaticCastExprClass: @@ -139,32 +144,34 @@ public: }; /// CXXStaticCastExpr - A C++ @c static_cast expression (C++ [expr.static.cast]). -/// +/// /// This expression node represents a C++ static cast, e.g., /// @c static_cast<int>(1.0). class CXXStaticCastExpr : public CXXNamedCastExpr { public: - CXXStaticCastExpr(QualType ty, Expr *op, QualType writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXStaticCastExprClass, ty, op, writtenTy, l) {} + CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op, + QualType writtenTy, SourceLocation l) + : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, writtenTy, l) {} - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXStaticCastExprClass; } static bool classof(const CXXStaticCastExpr *) { return true; } }; /// CXXDynamicCastExpr - A C++ @c dynamic_cast expression -/// (C++ [expr.dynamic.cast]), which may perform a run-time check to +/// (C++ [expr.dynamic.cast]), which may perform a run-time check to /// determine how to perform the type cast. -/// +/// /// This expression node represents a dynamic cast, e.g., /// @c dynamic_cast<Derived*>(BasePtr). class CXXDynamicCastExpr : public CXXNamedCastExpr { public: - CXXDynamicCastExpr(QualType ty, Expr *op, QualType writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, op, writtenTy, l) {} + CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op, QualType writtenTy, + SourceLocation l) + : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, writtenTy, l) {} - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDynamicCastExprClass; } static bool classof(const CXXDynamicCastExpr *) { return true; } @@ -173,16 +180,17 @@ public: /// CXXReinterpretCastExpr - A C++ @c reinterpret_cast expression (C++ /// [expr.reinterpret.cast]), which provides a differently-typed view /// of a value but performs no actual work at run time. -/// +/// /// This expression node represents a reinterpret cast, e.g., /// @c reinterpret_cast<int>(VoidPtr). class CXXReinterpretCastExpr : public CXXNamedCastExpr { public: - CXXReinterpretCastExpr(QualType ty, Expr *op, QualType writtenTy, - SourceLocation l) - : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, op, writtenTy, l) {} + CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op, + QualType writtenTy, SourceLocation l) + : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, + writtenTy, l) {} - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXReinterpretCastExprClass; } static bool classof(const CXXReinterpretCastExpr *) { return true; } @@ -190,41 +198,39 @@ public: /// CXXConstCastExpr - A C++ @c const_cast expression (C++ [expr.const.cast]), /// which can remove type qualifiers but does not change the underlying value. -/// +/// /// This expression node represents a const cast, e.g., /// @c const_cast<char*>(PtrToConstChar). class CXXConstCastExpr : public CXXNamedCastExpr { public: - CXXConstCastExpr(QualType ty, Expr *op, QualType writtenTy, + CXXConstCastExpr(QualType ty, Expr *op, QualType writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXConstCastExprClass, ty, op, writtenTy, l) {} + : CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op, writtenTy, l) {} - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConstCastExprClass; } static bool classof(const CXXConstCastExpr *) { return true; } }; /// CXXBoolLiteralExpr - [C++ 2.13.5] C++ Boolean Literal. -/// +/// class CXXBoolLiteralExpr : public Expr { bool Value; SourceLocation Loc; public: - CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) : + CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) : Expr(CXXBoolLiteralExprClass, Ty), Value(val), Loc(l) {} - CXXBoolLiteralExpr* Clone(ASTContext &C) const; - bool getValue() const { return Value; } virtual SourceRange getSourceRange() const { return SourceRange(Loc); } - - static bool classof(const Stmt *T) { + + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXBoolLiteralExprClass; } static bool classof(const CXXBoolLiteralExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -237,8 +243,6 @@ public: CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) : Expr(CXXNullPtrLiteralExprClass, Ty), Loc(l) {} - CXXNullPtrLiteralExpr* Clone(ASTContext &C) const; - virtual SourceRange getSourceRange() const { return SourceRange(Loc); } static bool classof(const Stmt *T) { @@ -318,7 +322,7 @@ class CXXThisExpr : public Expr { SourceLocation Loc; public: - CXXThisExpr(SourceLocation L, QualType Type) + CXXThisExpr(SourceLocation L, QualType Type) : Expr(CXXThisExprClass, Type, // 'this' is type-dependent if the class type of the enclosing // member function is dependent (C++ [temp.dep.expr]p2) @@ -327,7 +331,7 @@ public: virtual SourceRange getSourceRange() const { return SourceRange(Loc); } - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXThisExprClass; } static bool classof(const CXXThisExpr *) { return true; } @@ -379,14 +383,20 @@ public: /// supply arguments for all of the parameters. class CXXDefaultArgExpr : public Expr { ParmVarDecl *Param; + +protected: + CXXDefaultArgExpr(StmtClass SC, ParmVarDecl *param) + : Expr(SC, param->hasUnparsedDefaultArg() ? + param->getType().getNonReferenceType() + : param->getDefaultArg()->getType()), + Param(param) { } + public: // Param is the parameter whose default argument is used by this // expression. - explicit CXXDefaultArgExpr(ParmVarDecl *param) - : Expr(CXXDefaultArgExprClass, - param->hasUnparsedDefaultArg()? param->getType().getNonReferenceType() - : param->getDefaultArg()->getType()), - Param(param) { } + static CXXDefaultArgExpr *Create(ASTContext &C, ParmVarDecl *Param) { + return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Param); + } // Retrieve the parameter that the argument was created from. const ParmVarDecl *getParam() const { return Param; } @@ -416,36 +426,39 @@ public: class CXXTemporary { /// Destructor - The destructor that needs to be called. const CXXDestructorDecl *Destructor; - + CXXTemporary(const CXXDestructorDecl *destructor) : Destructor(destructor) { } ~CXXTemporary() { } public: - static CXXTemporary *Create(ASTContext &C, + static CXXTemporary *Create(ASTContext &C, const CXXDestructorDecl *Destructor); - void Destroy(ASTContext &C); - + + void Destroy(ASTContext &Ctx); + const CXXDestructorDecl *getDestructor() const { return Destructor; } }; -/// CXXBindTemporaryExpr - Represents binding an expression to a temporary, +/// CXXBindTemporaryExpr - Represents binding an expression to a temporary, /// so its destructor can be called later. class CXXBindTemporaryExpr : public Expr { CXXTemporary *Temp; - + Stmt *SubExpr; - CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr) + CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr) : Expr(CXXBindTemporaryExprClass, subexpr->getType()), Temp(temp), SubExpr(subexpr) { } - ~CXXBindTemporaryExpr() { } + ~CXXBindTemporaryExpr() { } + +protected: + virtual void DoDestroy(ASTContext &C); public: - static CXXBindTemporaryExpr *Create(ASTContext &C, CXXTemporary *Temp, + static CXXBindTemporaryExpr *Create(ASTContext &C, CXXTemporary *Temp, Expr* SubExpr); - void Destroy(ASTContext &C); - + CXXTemporary *getTemporary() { return Temp; } const CXXTemporary *getTemporary() const { return Temp; } @@ -453,7 +466,9 @@ public: Expr *getSubExpr() { return cast<Expr>(SubExpr); } void setSubExpr(Expr *E) { SubExpr = E; } - virtual SourceRange getSourceRange() const { return SourceRange(); } + virtual SourceRange getSourceRange() const { + return SubExpr->getSourceRange(); + } // Implement isa/cast/dyncast/etc. static bool classof(const Stmt *T) { @@ -471,32 +486,38 @@ class CXXConstructExpr : public Expr { CXXConstructorDecl *Constructor; bool Elidable; - + Stmt **Args; unsigned NumArgs; - protected: - CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, + CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, CXXConstructorDecl *d, bool elidable, Expr **args, unsigned numargs); - ~CXXConstructExpr() { } + ~CXXConstructExpr() { } + + virtual void DoDestroy(ASTContext &C); public: + /// \brief Construct an empty C++ construction expression that will store + /// \p numargs arguments. + CXXConstructExpr(EmptyShell Empty, ASTContext &C, unsigned numargs); + static CXXConstructExpr *Create(ASTContext &C, QualType T, - CXXConstructorDecl *D, bool Elidable, + CXXConstructorDecl *D, bool Elidable, Expr **Args, unsigned NumArgs); - - void Destroy(ASTContext &C); - - CXXConstructorDecl* getConstructor() const { return Constructor; } + + CXXConstructorDecl* getConstructor() const { return Constructor; } + void setConstructor(CXXConstructorDecl *C) { Constructor = C; } + /// \brief Whether this construction is elidable. bool isElidable() const { return Elidable; } - + void setElidable(bool E) { Elidable = E; } + typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; - + arg_iterator arg_begin() { return Args; } arg_iterator arg_end() { return Args + NumArgs; } const_arg_iterator arg_begin() const { return Args; } @@ -504,14 +525,36 @@ public: unsigned getNumArgs() const { return NumArgs; } - virtual SourceRange getSourceRange() const { return SourceRange(); } + /// getArg - Return the specified argument. + Expr *getArg(unsigned Arg) { + assert(Arg < NumArgs && "Arg access out of range!"); + return cast<Expr>(Args[Arg]); + } + const Expr *getArg(unsigned Arg) const { + assert(Arg < NumArgs && "Arg access out of range!"); + return cast<Expr>(Args[Arg]); + } + + /// setArg - Set the specified argument. + void setArg(unsigned Arg, Expr *ArgExpr) { + assert(Arg < NumArgs && "Arg access out of range!"); + Args[Arg] = ArgExpr; + } + + virtual SourceRange getSourceRange() const { + // FIXME: Should we know where the parentheses are, if there are any? + if (NumArgs == 0) + return SourceRange(); + + return SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd()); + } - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConstructExprClass || T->getStmtClass() == CXXTemporaryObjectExprClass; } static bool classof(const CXXConstructExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -524,20 +567,21 @@ class CXXFunctionalCastExpr : public ExplicitCastExpr { SourceLocation TyBeginLoc; SourceLocation RParenLoc; public: - CXXFunctionalCastExpr(QualType ty, QualType writtenTy, - SourceLocation tyBeginLoc, Expr *castExpr, - SourceLocation rParenLoc) : - ExplicitCastExpr(CXXFunctionalCastExprClass, ty, castExpr, writtenTy), - TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} + CXXFunctionalCastExpr(QualType ty, QualType writtenTy, + SourceLocation tyBeginLoc, CastKind kind, + Expr *castExpr, SourceLocation rParenLoc) + : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr, + writtenTy), + TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } - + virtual SourceRange getSourceRange() const { return SourceRange(TyBeginLoc, RParenLoc); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXFunctionalCastExprClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXFunctionalCastExprClass; } static bool classof(const CXXFunctionalCastExpr *) { return true; } }; @@ -545,7 +589,7 @@ public: /// @brief Represents a C++ functional cast expression that builds a /// temporary object. /// -/// This expression type represents a C++ "functional" cast +/// This expression type represents a C++ "functional" cast /// (C++[expr.type.conv]) with N != 1 arguments that invokes a /// constructor to build a temporary object. If N == 0 but no /// constructor will be called (because the functional cast is @@ -566,12 +610,12 @@ class CXXTemporaryObjectExpr : public CXXConstructExpr { SourceLocation RParenLoc; public: - CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons, - QualType writtenTy, SourceLocation tyBeginLoc, - Expr **Args,unsigned NumArgs, + CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons, + QualType writtenTy, SourceLocation tyBeginLoc, + Expr **Args,unsigned NumArgs, SourceLocation rParenLoc); - ~CXXTemporaryObjectExpr() { } + ~CXXTemporaryObjectExpr() { } SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } @@ -579,7 +623,7 @@ public: virtual SourceRange getSourceRange() const { return SourceRange(TyBeginLoc, RParenLoc); } - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXTemporaryObjectExprClass; } static bool classof(const CXXTemporaryObjectExpr *) { return true; } @@ -596,30 +640,28 @@ class CXXZeroInitValueExpr : public Expr { public: CXXZeroInitValueExpr(QualType ty, SourceLocation tyBeginLoc, - SourceLocation rParenLoc ) : + SourceLocation rParenLoc ) : Expr(CXXZeroInitValueExprClass, ty, false, false), TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} - + SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } /// @brief Whether this initialization expression was /// implicitly-generated. - bool isImplicit() const { - return TyBeginLoc.isInvalid() && RParenLoc.isInvalid(); + bool isImplicit() const { + return TyBeginLoc.isInvalid() && RParenLoc.isInvalid(); } virtual SourceRange getSourceRange() const { return SourceRange(TyBeginLoc, RParenLoc); } - - CXXZeroInitValueExpr* Clone(ASTContext &C) const; - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXZeroInitValueExprClass; } static bool classof(const CXXZeroInitValueExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -634,28 +676,26 @@ class CXXConditionDeclExpr : public DeclRefExpr { public: CXXConditionDeclExpr(SourceLocation startLoc, SourceLocation eqLoc, VarDecl *var) - : DeclRefExpr(CXXConditionDeclExprClass, var, + : DeclRefExpr(CXXConditionDeclExprClass, var, var->getType().getNonReferenceType(), startLoc, var->getType()->isDependentType(), /*FIXME:integral constant?*/ var->getType()->isDependentType()) {} - virtual void Destroy(ASTContext& Ctx); - SourceLocation getStartLoc() const { return getLocation(); } - + VarDecl *getVarDecl() { return cast<VarDecl>(getDecl()); } const VarDecl *getVarDecl() const { return cast<VarDecl>(getDecl()); } virtual SourceRange getSourceRange() const { return SourceRange(getStartLoc(), getVarDecl()->getInit()->getLocEnd()); } - - static bool classof(const Stmt *T) { + + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConditionDeclExprClass; } static bool classof(const CXXConditionDeclExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -707,7 +747,7 @@ public: QualType getAllocatedType() const { assert(getType()->isPointerType()); - return getType()->getAsPointerType()->getPointeeType(); + return getType()->getAs<PointerType>()->getPointeeType(); } FunctionDecl *getOperatorNew() const { return OperatorNew; } @@ -831,6 +871,108 @@ public: virtual child_iterator child_end(); }; +/// \brief Represents a C++ pseudo-destructor (C++ [expr.pseudo]). +/// +/// Example: +/// +/// \code +/// template<typename T> +/// void destroy(T* ptr) { +/// ptr->~T(); +/// } +/// \endcode +/// +/// When the template is parsed, the expression \c ptr->~T will be stored as +/// a member reference expression. If it then instantiated with a scalar type +/// as a template argument for T, the resulting expression will be a +/// pseudo-destructor expression. +class CXXPseudoDestructorExpr : public Expr { + /// \brief The base expression (that is being destroyed). + Stmt *Base; + + /// \brief Whether the operator was an arrow ('->'); otherwise, it was a + /// period ('.'). + bool IsArrow : 1; + + /// \brief The location of the '.' or '->' operator. + SourceLocation OperatorLoc; + + /// \brief The nested-name-specifier that follows the operator, if present. + NestedNameSpecifier *Qualifier; + + /// \brief The source range that covers the nested-name-specifier, if + /// present. + SourceRange QualifierRange; + + /// \brief The type being destroyed. + QualType DestroyedType; + + /// \brief The location of the type after the '~'. + SourceLocation DestroyedTypeLoc; + +public: + CXXPseudoDestructorExpr(ASTContext &Context, + Expr *Base, bool isArrow, SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + QualType DestroyedType, + SourceLocation DestroyedTypeLoc) + : Expr(CXXPseudoDestructorExprClass, + Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0, + false, 0)), + /*isTypeDependent=*/false, + /*isValueDependent=*/Base->isValueDependent()), + Base(static_cast<Stmt *>(Base)), IsArrow(isArrow), + OperatorLoc(OperatorLoc), Qualifier(Qualifier), + QualifierRange(QualifierRange), DestroyedType(DestroyedType), + DestroyedTypeLoc(DestroyedTypeLoc) { } + + void setBase(Expr *E) { Base = E; } + Expr *getBase() const { return cast<Expr>(Base); } + + /// \brief Determines whether this member expression actually had + /// a C++ nested-name-specifier prior to the name of the member, e.g., + /// x->Base::foo. + bool hasQualifier() const { return Qualifier != 0; } + + /// \brief If the member name was qualified, retrieves the source range of + /// the nested-name-specifier that precedes the member name. Otherwise, + /// returns an empty source range. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// \brief If the member name was qualified, retrieves the + /// nested-name-specifier that precedes the member name. Otherwise, returns + /// NULL. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + /// \brief Determine whether this pseudo-destructor expression was written + /// using an '->' (otherwise, it used a '.'). + bool isArrow() const { return IsArrow; } + void setArrow(bool A) { IsArrow = A; } + + /// \brief Retrieve the location of the '.' or '->' operator. + SourceLocation getOperatorLoc() const { return OperatorLoc; } + + /// \brief Retrieve the type that is being destroyed. + QualType getDestroyedType() const { return DestroyedType; } + + /// \brief Retrieve the location of the type being destroyed. + SourceLocation getDestroyedTypeLoc() const { return DestroyedTypeLoc; } + + virtual SourceRange getSourceRange() const { + return SourceRange(Base->getLocStart(), DestroyedTypeLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXPseudoDestructorExprClass; + } + static bool classof(const CXXPseudoDestructorExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + /// \brief Represents the name of a function that has not been /// resolved to any declaration. /// @@ -848,7 +990,7 @@ public: /// } /// @endcode class UnresolvedFunctionNameExpr : public Expr { - /// The name that was present in the source + /// The name that was present in the source DeclarationName Name; /// The location of this name in the source code @@ -867,9 +1009,7 @@ public: virtual SourceRange getSourceRange() const { return SourceRange(Loc); } - UnresolvedFunctionNameExpr* Clone(ASTContext &C) const; - - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { return T->getStmtClass() == UnresolvedFunctionNameExprClass; } static bool classof(const UnresolvedFunctionNameExpr *) { return true; } @@ -909,7 +1049,7 @@ public: QualType getQueriedType() const { return QueriedType; } - bool EvaluateTrait() const; + bool EvaluateTrait(ASTContext&) const; static bool classof(const Stmt *T) { return T->getStmtClass() == UnaryTypeTraitExprClass; @@ -934,9 +1074,9 @@ class QualifiedDeclRefExpr : public DeclRefExpr { NestedNameSpecifier *NNS; public: - QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, + QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD, SourceRange R, NestedNameSpecifier *NNS) - : DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD), + : DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD), QualifierRange(R), NNS(NNS) { } /// \brief Retrieve the source range of the nested-name-specifier. @@ -946,8 +1086,8 @@ public: /// declaration. NestedNameSpecifier *getQualifier() const { return NNS; } - virtual SourceRange getSourceRange() const { - return SourceRange(QualifierRange.getBegin(), getLocation()); + virtual SourceRange getSourceRange() const { + return SourceRange(QualifierRange.getBegin(), getLocation()); } static bool classof(const Stmt *T) { @@ -985,11 +1125,16 @@ class UnresolvedDeclRefExpr : public Expr { /// declaration name. NestedNameSpecifier *NNS; + /// \brief Whether this expr is an address of (&) operand. + bool IsAddressOfOperand; + public: UnresolvedDeclRefExpr(DeclarationName N, QualType T, SourceLocation L, - SourceRange R, NestedNameSpecifier *NNS) - : Expr(UnresolvedDeclRefExprClass, T, true, true), - Name(N), Loc(L), QualifierRange(R), NNS(NNS) { } + SourceRange R, NestedNameSpecifier *NNS, + bool IsAddressOfOperand) + : Expr(UnresolvedDeclRefExprClass, T, true, true), + Name(N), Loc(L), QualifierRange(R), NNS(NNS), + IsAddressOfOperand(IsAddressOfOperand) { } /// \brief Retrieve the name that this expression refers to. DeclarationName getDeclName() const { return Name; } @@ -1004,8 +1149,11 @@ public: /// declaration. NestedNameSpecifier *getQualifier() const { return NNS; } - virtual SourceRange getSourceRange() const { - return SourceRange(QualifierRange.getBegin(), getLocation()); + /// \brief Retrieve whether this is an address of (&) operand. + + bool isAddressOfOperand() const { return IsAddressOfOperand; } + virtual SourceRange getSourceRange() const { + return SourceRange(QualifierRange.getBegin(), getLocation()); } static bool classof(const Stmt *T) { @@ -1017,40 +1165,42 @@ public: virtual StmtIterator child_end(); }; -/// \brief An expression that refers to a C++ template-id, such as -/// @c isa<FunctionDecl>. +/// \brief An expression that refers to a C++ template-id, such as +/// @c isa<FunctionDecl>. class TemplateIdRefExpr : public Expr { /// \brief If this template-id was qualified-id, e.g., @c std::sort<int>, /// this nested name specifier contains the @c std::. NestedNameSpecifier *Qualifier; - + /// \brief If this template-id was a qualified-id, e.g., @c std::sort<int>, /// this covers the source code range of the @c std::. SourceRange QualifierRange; - + /// \brief The actual template to which this template-id refers. TemplateName Template; - + /// \brief The source location of the template name. SourceLocation TemplateNameLoc; /// \brief The source location of the left angle bracket ('<'); SourceLocation LAngleLoc; - + /// \brief The source location of the right angle bracket ('>'); SourceLocation RAngleLoc; - + /// \brief The number of template arguments in TemplateArgs. unsigned NumTemplateArgs; - + TemplateIdRefExpr(QualType T, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, TemplateName Template, SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, + SourceLocation LAngleLoc, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc); - + + virtual void DoDestroy(ASTContext &Context); + public: static TemplateIdRefExpr * Create(ASTContext &Context, QualType T, @@ -1058,77 +1208,77 @@ public: TemplateName Template, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc); - - void Destroy(ASTContext &Context); - + /// \brief Retrieve the nested name specifier used to qualify the name of /// this template-id, e.g., the "std::sort" in @c std::sort<int>, or NULL /// if this template-id was an unqualified-id. NestedNameSpecifier *getQualifier() const { return Qualifier; } - + /// \brief Retrieve the source range describing the nested name specifier /// used to qualified the name of this template-id, if the name was qualified. SourceRange getQualifierRange() const { return QualifierRange; } - + /// \brief Retrieve the name of the template referenced, e.g., "sort" in /// @c std::sort<int>; TemplateName getTemplateName() const { return Template; } - + /// \brief Retrieve the location of the name of the template referenced, e.g., /// the location of "sort" in @c std::sort<int>. SourceLocation getTemplateNameLoc() const { return TemplateNameLoc; } - - /// \brief Retrieve the location of the left angle bracket following the + + /// \brief Retrieve the location of the left angle bracket following the /// template name ('<'). SourceLocation getLAngleLoc() const { return LAngleLoc; } - + /// \brief Retrieve the template arguments provided as part of this /// template-id. - const TemplateArgument *getTemplateArgs() const { + const TemplateArgument *getTemplateArgs() const { return reinterpret_cast<const TemplateArgument *>(this + 1); } - + /// \brief Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { return NumTemplateArgs; } - - /// \brief Retrieve the location of the right angle bracket following the + + /// \brief Retrieve the location of the right angle bracket following the /// template arguments ('>'). SourceLocation getRAngleLoc() const { return RAngleLoc; } - + virtual SourceRange getSourceRange() const { return SourceRange(Qualifier? QualifierRange.getBegin() : TemplateNameLoc, RAngleLoc); } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); - - static bool classof(const Stmt *T) { + + static bool classof(const Stmt *T) { return T->getStmtClass() == TemplateIdRefExprClass; } static bool classof(const TemplateIdRefExpr *) { return true; } }; - + class CXXExprWithTemporaries : public Expr { Stmt *SubExpr; - + CXXTemporary **Temps; unsigned NumTemps; bool ShouldDestroyTemps; - - CXXExprWithTemporaries(Expr *SubExpr, CXXTemporary **Temps, + + CXXExprWithTemporaries(Expr *SubExpr, CXXTemporary **Temps, unsigned NumTemps, bool ShouldDestroyTemps); ~CXXExprWithTemporaries(); - + +protected: + virtual void DoDestroy(ASTContext &C); + public: static CXXExprWithTemporaries *Create(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps, unsigned NumTemps, bool ShouldDestroyTemporaries); - void Destroy(ASTContext &C); - + unsigned getNumTemporaries() const { return NumTemps; } CXXTemporary *getTemporary(unsigned i) { assert(i < NumTemps && "Index out of range"); @@ -1138,16 +1288,18 @@ public: assert(i < NumTemps && "Index out of range"); return Temps[i]; } - + bool shouldDestroyTemporaries() const { return ShouldDestroyTemps; } - + void removeLastTemporary() { NumTemps--; } - + Expr *getSubExpr() { return cast<Expr>(SubExpr); } const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } void setSubExpr(Expr *E) { SubExpr = E; } - virtual SourceRange getSourceRange() const { return SourceRange(); } + virtual SourceRange getSourceRange() const { + return SubExpr->getSourceRange(); + } // Implement isa/cast/dyncast/etc. static bool classof(const Stmt *T) { @@ -1196,7 +1348,7 @@ class CXXUnresolvedConstructExpr : public Expr { /// \brief The number of arguments used to construct the type. unsigned NumArgs; - + CXXUnresolvedConstructExpr(SourceLocation TyBegin, QualType T, SourceLocation LParenLoc, @@ -1205,7 +1357,7 @@ class CXXUnresolvedConstructExpr : public Expr { SourceLocation RParenLoc); public: - static CXXUnresolvedConstructExpr *Create(ASTContext &C, + static CXXUnresolvedConstructExpr *Create(ASTContext &C, SourceLocation TyBegin, QualType T, SourceLocation LParenLoc, @@ -1247,7 +1399,7 @@ public: virtual SourceRange getSourceRange() const { return SourceRange(TyBeginLoc, RParenLoc); } - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXUnresolvedConstructExprClass; } static bool classof(const CXXUnresolvedConstructExpr *) { return true; } @@ -1257,37 +1409,108 @@ public: virtual child_iterator child_end(); }; -/// \brief +/// \brief Represents a C++ member access expression where the actual member +/// referenced could not be resolved, e.g., because the base expression or the +/// member name was dependent. class CXXUnresolvedMemberExpr : public Expr { /// \brief The expression for the base pointer or class reference, /// e.g., the \c x in x.f. Stmt *Base; - + /// \brief Whether this member expression used the '->' operator or /// the '.' operator. - bool IsArrow; + bool IsArrow : 1; + + /// \brief Whether this member expression has explicitly-specified template + /// arguments. + bool HasExplicitTemplateArgumentList : 1; /// \brief The location of the '->' or '.' operator. SourceLocation OperatorLoc; + /// \brief The nested-name-specifier that precedes the member name, if any. + NestedNameSpecifier *Qualifier; + + /// \brief The source range covering the nested name specifier. + SourceRange QualifierRange; + + /// \brief In a qualified member access expression such as t->Base::f, this + /// member stores the resolves of name lookup in the context of the member + /// access expression, to be used at instantiation time. + /// + /// FIXME: This member, along with the Qualifier and QualifierRange, could + /// be stuck into a structure that is optionally allocated at the end of + /// the CXXUnresolvedMemberExpr, to save space in the common case. + NamedDecl *FirstQualifierFoundInScope; + /// \brief The member to which this member expression refers, which /// can be name, overloaded operator, or destructor. - /// FIXME: could also be a template-id, and we might have a - /// nested-name-specifier as well. + /// FIXME: could also be a template-id DeclarationName Member; /// \brief The location of the member name. SourceLocation MemberLoc; + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { + if (!HasExplicitTemplateArgumentList) + return 0; + + return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { + return const_cast<CXXUnresolvedMemberExpr *>(this) + ->getExplicitTemplateArgumentList(); + } + + CXXUnresolvedMemberExpr(ASTContext &C, + Expr *Base, bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *FirstQualifierFoundInScope, + DeclarationName Member, + SourceLocation MemberLoc, + bool HasExplicitTemplateArgs, + SourceLocation LAngleLoc, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceLocation RAngleLoc); + public: - CXXUnresolvedMemberExpr(ASTContext &C, - Expr *Base, bool IsArrow, + CXXUnresolvedMemberExpr(ASTContext &C, + Expr *Base, bool IsArrow, SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *FirstQualifierFoundInScope, DeclarationName Member, SourceLocation MemberLoc) - : Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true), - Base(Base), IsArrow(IsArrow), OperatorLoc(OperatorLoc), - Member(Member), MemberLoc(MemberLoc) { } + : Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true), + Base(Base), IsArrow(IsArrow), HasExplicitTemplateArgumentList(false), + OperatorLoc(OperatorLoc), + Qualifier(Qualifier), QualifierRange(QualifierRange), + FirstQualifierFoundInScope(FirstQualifierFoundInScope), + Member(Member), MemberLoc(MemberLoc) { } + + static CXXUnresolvedMemberExpr * + Create(ASTContext &C, + Expr *Base, bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *FirstQualifierFoundInScope, + DeclarationName Member, + SourceLocation MemberLoc, + bool HasExplicitTemplateArgs, + SourceLocation LAngleLoc, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceLocation RAngleLoc); /// \brief Retrieve the base object of this member expressions, /// e.g., the \c x in \c x.m. @@ -1303,6 +1526,29 @@ public: SourceLocation getOperatorLoc() const { return OperatorLoc; } void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } + /// \brief Retrieve the nested-name-specifier that qualifies the member + /// name. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + /// \brief Retrieve the source range covering the nested-name-specifier + /// that qualifies the member name. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// \brief Retrieve the first part of the nested-name-specifier that was + /// found in the scope of the member access expression when the member access + /// was initially parsed. + /// + /// This function only returns a useful result when member access expression + /// uses a qualified member name, e.g., "x.Base::f". Here, the declaration + /// returned by this function describes what was found by unqualified name + /// lookup for the identifier "Base" within the scope of the member access + /// expression itself. At template instantiation time, this information is + /// combined with the results of name lookup into the type of the object + /// expression itself (the class type of x). + NamedDecl *getFirstQualifierFoundInScope() const { + return FirstQualifierFoundInScope; + } + /// \brief Retrieve the name of the member that this expression /// refers to. DeclarationName getMember() const { return Member; } @@ -1313,11 +1559,58 @@ public: SourceLocation getMemberLoc() const { return MemberLoc; } void setMemberLoc(SourceLocation L) { MemberLoc = L; } + /// \brief Determines whether this member expression actually had a C++ + /// template argument list explicitly specified, e.g., x.f<int>. + bool hasExplicitTemplateArgumentList() { + return HasExplicitTemplateArgumentList; + } + + /// \brief Retrieve the location of the left angle bracket following the + /// member name ('<'), if any. + SourceLocation getLAngleLoc() const { + if (!HasExplicitTemplateArgumentList) + return SourceLocation(); + + return getExplicitTemplateArgumentList()->LAngleLoc; + } + + /// \brief Retrieve the template arguments provided as part of this + /// template-id. + const TemplateArgument *getTemplateArgs() const { + if (!HasExplicitTemplateArgumentList) + return 0; + + return getExplicitTemplateArgumentList()->getTemplateArgs(); + } + + /// \brief Retrieve the number of template arguments provided as part of this + /// template-id. + unsigned getNumTemplateArgs() const { + if (!HasExplicitTemplateArgumentList) + return 0; + + return getExplicitTemplateArgumentList()->NumTemplateArgs; + } + + /// \brief Retrieve the location of the right angle bracket following the + /// template arguments ('>'). + SourceLocation getRAngleLoc() const { + if (!HasExplicitTemplateArgumentList) + return SourceLocation(); + + return getExplicitTemplateArgumentList()->RAngleLoc; + } + virtual SourceRange getSourceRange() const { + if (HasExplicitTemplateArgumentList) + return SourceRange(Base->getSourceRange().getBegin(), + getRAngleLoc()); + return SourceRange(Base->getSourceRange().getBegin(), MemberLoc); } - static bool classof(const Stmt *T) { + + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXUnresolvedMemberExprClass; } static bool classof(const CXXUnresolvedMemberExpr *) { return true; } diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index e00833b5820e..0613f4c095f8 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -22,7 +22,7 @@ namespace clang { class ASTContext; class ObjCMethodDecl; class ObjCPropertyDecl; - + /// ObjCStringLiteral, used for Objective-C string literals /// i.e. @"foo". class ObjCStringLiteral : public Expr { @@ -34,8 +34,6 @@ public: explicit ObjCStringLiteral(EmptyShell Empty) : Expr(ObjCStringLiteralClass, Empty) {} - ObjCStringLiteral* Clone(ASTContext &C) const; - StringLiteral *getString() { return cast<StringLiteral>(String); } const StringLiteral *getString() const { return cast<StringLiteral>(String); } void setString(StringLiteral *S) { String = S; } @@ -43,20 +41,20 @@ public: SourceLocation getAtLoc() const { return AtLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } - virtual SourceRange getSourceRange() const { + virtual SourceRange getSourceRange() const { return SourceRange(AtLoc, String->getLocEnd()); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCStringLiteralClass; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCStringLiteralClass; } - static bool classof(const ObjCStringLiteral *) { return true; } - + static bool classof(const ObjCStringLiteral *) { return true; } + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; - + /// ObjCEncodeExpr, used for @encode in Objective-C. @encode has the same type /// and behavior as StringLiteral except that the string initializer is obtained /// from ASTContext with the encoding type as an argument. @@ -64,32 +62,32 @@ class ObjCEncodeExpr : public Expr { QualType EncType; SourceLocation AtLoc, RParenLoc; public: - ObjCEncodeExpr(QualType T, QualType ET, + ObjCEncodeExpr(QualType T, QualType ET, SourceLocation at, SourceLocation rp) - : Expr(ObjCEncodeExprClass, T, ET->isDependentType(), + : Expr(ObjCEncodeExprClass, T, ET->isDependentType(), ET->isDependentType()), EncType(ET), AtLoc(at), RParenLoc(rp) {} - + explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){} - + SourceLocation getAtLoc() const { return AtLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - + QualType getEncodedType() const { return EncType; } void setEncodedType(QualType T) { EncType = T; } - + virtual SourceRange getSourceRange() const { return SourceRange(AtLoc, RParenLoc); } - + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCEncodeExprClass; } static bool classof(const ObjCEncodeExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -106,11 +104,9 @@ public: explicit ObjCSelectorExpr(EmptyShell Empty) : Expr(ObjCSelectorExprClass, Empty) {} - ObjCSelectorExpr *Clone(ASTContext &C) const; - Selector getSelector() const { return SelName; } void setSelector(Selector S) { SelName = S; } - + SourceLocation getAtLoc() const { return AtLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } @@ -119,26 +115,26 @@ public: virtual SourceRange getSourceRange() const { return SourceRange(AtLoc, RParenLoc); } - + /// getNumArgs - Return the number of actual arguments to this call. unsigned getNumArgs() const { return SelName.getNumArgs(); } - + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCSelectorExprClass; } static bool classof(const ObjCSelectorExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; - + /// ObjCProtocolExpr used for protocol expression in Objective-C. This is used /// as: @protocol(foo), as in: /// obj conformsToProtocol:@protocol(foo)] /// The return type is "Protocol*". -class ObjCProtocolExpr : public Expr { - ObjCProtocolDecl *TheProtocol; +class ObjCProtocolExpr : public Expr { + ObjCProtocolDecl *TheProtocol; SourceLocation AtLoc, RParenLoc; public: ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, @@ -148,11 +144,9 @@ public: explicit ObjCProtocolExpr(EmptyShell Empty) : Expr(ObjCProtocolExprClass, Empty) {} - ObjCProtocolExpr *Clone(ASTContext &C) const; - ObjCProtocolDecl *getProtocol() const { return TheProtocol; } void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; } - + SourceLocation getAtLoc() const { return AtLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } @@ -161,12 +155,12 @@ public: virtual SourceRange getSourceRange() const { return SourceRange(AtLoc, RParenLoc); } - + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCProtocolExprClass; } static bool classof(const ObjCProtocolExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -179,44 +173,44 @@ class ObjCIvarRefExpr : public Expr { Stmt *Base; bool IsArrow:1; // True if this is "X->F", false if this is "X.F". bool IsFreeIvar:1; // True if ivar reference has no base (self assumed). - + public: ObjCIvarRefExpr(ObjCIvarDecl *d, - QualType t, SourceLocation l, Expr *base=0, - bool arrow = false, bool freeIvar = false) : + QualType t, SourceLocation l, Expr *base=0, + bool arrow = false, bool freeIvar = false) : Expr(ObjCIvarRefExprClass, t), D(d), Loc(l), Base(base), IsArrow(arrow), IsFreeIvar(freeIvar) {} - + explicit ObjCIvarRefExpr(EmptyShell Empty) : Expr(ObjCIvarRefExprClass, Empty) {} ObjCIvarDecl *getDecl() { return D; } const ObjCIvarDecl *getDecl() const { return D; } void setDecl(ObjCIvarDecl *d) { D = d; } - + const Expr *getBase() const { return cast<Expr>(Base); } Expr *getBase() { return cast<Expr>(Base); } void setBase(Expr * base) { Base = base; } - + bool isArrow() const { return IsArrow; } bool isFreeIvar() const { return IsFreeIvar; } void setIsArrow(bool A) { IsArrow = A; } void setIsFreeIvar(bool A) { IsFreeIvar = A; } - + SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - virtual SourceRange getSourceRange() const { + virtual SourceRange getSourceRange() const { return isFreeIvar() ? SourceRange(Loc) - : SourceRange(getBase()->getLocStart(), Loc); + : SourceRange(getBase()->getLocStart(), Loc); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCIvarRefExprClass; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCIvarRefExprClass; } static bool classof(const ObjCIvarRefExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -231,113 +225,129 @@ private: SourceLocation IdLoc; Stmt *Base; public: - ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, + ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, SourceLocation l, Expr *base) : Expr(ObjCPropertyRefExprClass, t), AsProperty(PD), IdLoc(l), Base(base) { } - + explicit ObjCPropertyRefExpr(EmptyShell Empty) : Expr(ObjCPropertyRefExprClass, Empty) {} ObjCPropertyDecl *getProperty() const { return AsProperty; } void setProperty(ObjCPropertyDecl *D) { AsProperty = D; } - + const Expr *getBase() const { return cast<Expr>(Base); } Expr *getBase() { return cast<Expr>(Base); } void setBase(Expr *base) { Base = base; } - + SourceLocation getLocation() const { return IdLoc; } void setLocation(SourceLocation L) { IdLoc = L; } virtual SourceRange getSourceRange() const { return SourceRange(getBase()->getLocStart(), IdLoc); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCPropertyRefExprClass; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCPropertyRefExprClass; } static bool classof(const ObjCPropertyRefExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; -/// ObjCKVCRefExpr - A dot-syntax expression to access "implicit" properties -/// (i.e. methods following the property naming convention). KVC stands for -/// Key Value Encoding, a generic concept for accessing or setting a 'Key' -/// value for an object. -/// -class ObjCKVCRefExpr : public Expr { +/// ObjCImplicitSetterGetterRefExpr - A dot-syntax expression to access two +/// methods; one to set a value to an 'ivar' (Setter) and the other to access +/// an 'ivar' (Setter). +/// An example for use of this AST is: +/// @code +/// @interface Test { } +/// - (Test *)crash; +/// - (void)setCrash: (Test*)value; +/// @end +/// void foo(Test *p1, Test *p2) +/// { +/// p2.crash = p1.crash; // Uses ObjCImplicitSetterGetterRefExpr AST +/// } +/// @endcode +class ObjCImplicitSetterGetterRefExpr : public Expr { + /// Setter - Setter method user declared for setting its 'ivar' to a value ObjCMethodDecl *Setter; + /// Getter - Getter method user declared for accessing 'ivar' it controls. ObjCMethodDecl *Getter; - SourceLocation Loc; + /// Location of the member in the dot syntax notation. This is location + /// of the getter method. + SourceLocation MemberLoc; // FIXME: Swizzle these into a single pointer. Stmt *Base; - ObjCInterfaceDecl *ClassProp; + ObjCInterfaceDecl *InterfaceDecl; + /// Location of the receiver class in the dot syntax notation + /// used to call a class method setter/getter. SourceLocation ClassLoc; - + public: - ObjCKVCRefExpr(ObjCMethodDecl *getter, - QualType t, + ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter, + QualType t, ObjCMethodDecl *setter, SourceLocation l, Expr *base) - : Expr(ObjCKVCRefExprClass, t), Setter(setter), - Getter(getter), Loc(l), Base(base), ClassProp(0), + : Expr(ObjCImplicitSetterGetterRefExprClass, t), Setter(setter), + Getter(getter), MemberLoc(l), Base(base), InterfaceDecl(0), ClassLoc(SourceLocation()) { } - ObjCKVCRefExpr(ObjCMethodDecl *getter, - QualType t, + ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter, + QualType t, ObjCMethodDecl *setter, SourceLocation l, ObjCInterfaceDecl *C, SourceLocation CL) - : Expr(ObjCKVCRefExprClass, t), Setter(setter), - Getter(getter), Loc(l), Base(0), ClassProp(C), ClassLoc(CL) { + : Expr(ObjCImplicitSetterGetterRefExprClass, t), Setter(setter), + Getter(getter), MemberLoc(l), Base(0), InterfaceDecl(C), ClassLoc(CL) { } - explicit ObjCKVCRefExpr(EmptyShell Empty) : Expr(ObjCKVCRefExprClass, Empty){} + explicit ObjCImplicitSetterGetterRefExpr(EmptyShell Empty) + : Expr(ObjCImplicitSetterGetterRefExprClass, Empty){} ObjCMethodDecl *getGetterMethod() const { return Getter; } ObjCMethodDecl *getSetterMethod() const { return Setter; } - ObjCInterfaceDecl *getClassProp() const { return ClassProp; } + ObjCInterfaceDecl *getInterfaceDecl() const { return InterfaceDecl; } void setGetterMethod(ObjCMethodDecl *D) { Getter = D; } void setSetterMethod(ObjCMethodDecl *D) { Setter = D; } - void setClassProp(ObjCInterfaceDecl *D) { ClassProp = D; } - + void setInterfaceDecl(ObjCInterfaceDecl *D) { InterfaceDecl = D; } + virtual SourceRange getSourceRange() const { if (Base) - return SourceRange(getBase()->getLocStart(), Loc); - return SourceRange(ClassLoc, Loc); + return SourceRange(getBase()->getLocStart(), MemberLoc); + return SourceRange(ClassLoc, MemberLoc); } const Expr *getBase() const { return cast_or_null<Expr>(Base); } Expr *getBase() { return cast_or_null<Expr>(Base); } void setBase(Expr *base) { Base = base; } - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } + + SourceLocation getLocation() const { return MemberLoc; } + void setLocation(SourceLocation L) { MemberLoc = L; } SourceLocation getClassLoc() const { return ClassLoc; } void setClassLoc(SourceLocation L) { ClassLoc = L; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCKVCRefExprClass; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCImplicitSetterGetterRefExprClass; } - static bool classof(const ObjCKVCRefExpr *) { return true; } - + static bool classof(const ObjCImplicitSetterGetterRefExpr *) { return true; } + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; - + class ObjCMessageExpr : public Expr { // SubExprs - The receiver and arguments of the message expression. Stmt **SubExprs; - + // NumArgs - The number of arguments (not including the receiver) to the // message expression. unsigned NumArgs; - + // A unigue name for this message. Selector SelName; - - // A method prototype for this message (optional). + + // 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; @@ -350,7 +360,7 @@ class ObjCMessageExpr : public Expr { // Bit-swizzling flags. enum { IsInstMeth=0, IsClsMethDeclUnknown, IsClsMethDeclKnown, Flags=0x3 }; unsigned getFlag() const { return (uintptr_t) SubExprs[RECEIVER] & Flags; } - + public: /// This constructor is used to represent class messages where the /// ObjCInterfaceDecl* of the receiver is not known. @@ -366,28 +376,28 @@ public: QualType retType, ObjCMethodDecl *methDecl, SourceLocation LBrac, SourceLocation RBrac, Expr **ArgExprs, unsigned NumArgs); - + // constructor for instance messages. ObjCMessageExpr(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) {} - + ~ObjCMessageExpr() { delete [] SubExprs; } - + /// 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() { + 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(); } @@ -395,36 +405,36 @@ public: void setReceiver(Expr *rec) { SubExprs[RECEIVER] = rec; } Selector getSelector() const { return SelName; } void setSelector(Selector S) { SelName = S; } - + const ObjCMethodDecl *getMethodDecl() const { return MethodProto; } ObjCMethodDecl *getMethodDecl() { return MethodProto; } void setMethodDecl(ObjCMethodDecl *MD) { MethodProto = MD; } - + typedef std::pair<ObjCInterfaceDecl*, IdentifierInfo*> ClassInfo; - + /// 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; + /// was available when this ObjCMessageExpr object was constructed. + ClassInfo getClassInfo() const; void setClassInfo(const ClassInfo &C); - + /// getClassName - For class methods, this returns the invoked class, - /// and returns NULL otherwise. For instance methods, use getReceiver. + /// and returns NULL otherwise. For instance methods, use getReceiver. IdentifierInfo *getClassName() const { return getClassInfo().second; } - + /// getNumArgs - Return the number of actual arguments to this call. unsigned getNumArgs() const { return NumArgs; } - void setNumArgs(unsigned nArgs) { - NumArgs = nArgs; + void setNumArgs(unsigned nArgs) { + NumArgs = nArgs; // FIXME: should always allocate SubExprs via the ASTContext's // allocator. if (!SubExprs) SubExprs = new Stmt* [NumArgs + 1]; } - + /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) { assert(Arg < NumArgs && "Arg access out of range!"); @@ -439,13 +449,13 @@ public: assert(Arg < NumArgs && "Arg access out of range!"); SubExprs[Arg+ARGS_START] = ArgExpr; } - + SourceLocation getLeftLoc() const { return LBracloc; } SourceLocation getRightLoc() const { return RBracloc; } void setLeftLoc(SourceLocation L) { LBracloc = L; } void setRightLoc(SourceLocation L) { RBracloc = L; } - + void setSourceRange(SourceRange R) { LBracloc = R.getBegin(); RBracloc = R.getEnd(); @@ -458,14 +468,14 @@ public: return T->getStmtClass() == ObjCMessageExprClass; } static bool classof(const ObjCMessageExpr *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); - + 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]; } @@ -477,16 +487,16 @@ public: class ObjCSuperExpr : public Expr { SourceLocation Loc; public: - ObjCSuperExpr(SourceLocation L, QualType Type) + ObjCSuperExpr(SourceLocation L, QualType Type) : Expr(ObjCSuperExprClass, Type), Loc(L) { } explicit ObjCSuperExpr(EmptyShell Empty) : Expr(ObjCSuperExprClass, Empty) {} SourceLocation getLoc() const { return Loc; } void setLoc(SourceLocation L) { Loc = L; } - + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } - static bool classof(const Stmt *T) { + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCSuperExprClass; } static bool classof(const ObjCSuperExpr *) { return true; } @@ -496,6 +506,52 @@ public: virtual child_iterator child_end(); }; +/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type. +/// (similiar in spirit to MemberExpr). +class ObjCIsaExpr : public Expr { + /// Base - the expression for the base object pointer. + Stmt *Base; + + /// IsaMemberLoc - This is the location of the 'isa'. + SourceLocation IsaMemberLoc; + + /// IsArrow - True if this is "X->F", false if this is "X.F". + bool IsArrow; +public: + ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty) + : Expr(ObjCIsaExprClass, ty), + Base(base), IsaMemberLoc(l), IsArrow(isarrow) {} + + /// \brief Build an empty expression. + explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) { } + + void setBase(Expr *E) { Base = E; } + Expr *getBase() const { return cast<Expr>(Base); } + + bool isArrow() const { return IsArrow; } + void setArrow(bool A) { IsArrow = A; } + + /// getMemberLoc - Return the location of the "member", in X->F, it is the + /// location of 'F'. + SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; } + void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(getBase()->getLocStart(), IsaMemberLoc); + } + + virtual SourceLocation getExprLoc() const { return IsaMemberLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCIsaExprClass; + } + static bool classof(const ObjCIsaExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + } // end namespace clang #endif diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 6f862a55d4ba..0670d1a62094 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -33,7 +33,7 @@ struct VisibleDeclaration { /// \brief The name of the declarations. DeclarationName Name; - /// \brief The ID numbers of all of the declarations with this name. + /// \brief The ID numbers of all of the declarations with this name. /// /// These declarations have not necessarily been de-serialized. llvm::SmallVector<unsigned, 4> Declarations; @@ -65,7 +65,7 @@ public: /// replaced with the sorted set of source ranges corresponding to /// comments in the source code. virtual void ReadComments(std::vector<SourceRange> &Comments) = 0; - + /// \brief Resolve a type ID into a type, potentially building a new /// type. virtual QualType GetType(uint32_t ID) = 0; @@ -151,7 +151,7 @@ public: this->Ptr = reinterpret_cast<uint64_t>(Ptr); return *this; } - + LazyOffsetPtr &operator=(uint64_t Offset) { assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); if (Offset == 0) @@ -177,7 +177,7 @@ public: /// \returns a pointer to the AST node. T* get(ExternalASTSource *Source) const { if (isOffset()) { - assert(Source && + assert(Source && "Cannot deserialize a lazy pointer without an AST source"); Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1)); } diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index b304cc8e8a04..1594b090fea5 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H #define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H +#include "clang/Basic/Diagnostic.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" @@ -26,7 +27,7 @@ namespace clang { class ASTContext; class NamespaceDecl; class IdentifierInfo; -class PrintingPolicy; +struct PrintingPolicy; class Type; class LangOptions; @@ -80,8 +81,8 @@ private: /// \brief Copy constructor used internally to clone nested name /// specifiers. - NestedNameSpecifier(const NestedNameSpecifier &Other) - : llvm::FoldingSetNode(Other), Prefix(Other.Prefix), + NestedNameSpecifier(const NestedNameSpecifier &Other) + : llvm::FoldingSetNode(Other), Prefix(Other.Prefix), Specifier(Other.Specifier) { } @@ -89,7 +90,7 @@ private: /// \brief Either find or insert the given nested name specifier /// mockup in the given context. - static NestedNameSpecifier *FindOrInsert(ASTContext &Context, + static NestedNameSpecifier *FindOrInsert(ASTContext &Context, const NestedNameSpecifier &Mockup); public: @@ -98,20 +99,28 @@ public: /// The prefix must be dependent, since nested name specifiers /// referencing an identifier are only permitted when the identifier /// cannot be resolved. - static NestedNameSpecifier *Create(ASTContext &Context, - NestedNameSpecifier *Prefix, + static NestedNameSpecifier *Create(ASTContext &Context, + NestedNameSpecifier *Prefix, IdentifierInfo *II); /// \brief Builds a nested name specifier that names a namespace. - static NestedNameSpecifier *Create(ASTContext &Context, - NestedNameSpecifier *Prefix, + static NestedNameSpecifier *Create(ASTContext &Context, + NestedNameSpecifier *Prefix, NamespaceDecl *NS); /// \brief Builds a nested name specifier that names a type. - static NestedNameSpecifier *Create(ASTContext &Context, - NestedNameSpecifier *Prefix, + static NestedNameSpecifier *Create(ASTContext &Context, + NestedNameSpecifier *Prefix, bool Template, Type *T); + /// \brief Builds a specifier that consists of just an identifier. + /// + /// The nested-name-specifier is assumed to be dependent, but has no + /// prefix because the prefix is implied by something outside of the + /// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent + /// type. + static NestedNameSpecifier *Create(ASTContext &Context, IdentifierInfo *II); + /// \brief Returns the nested name specifier representing the global /// scope. static NestedNameSpecifier *GlobalSpecifier(ASTContext &Context); @@ -126,10 +135,10 @@ public: NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); } /// \brief Determine what kind of nested name specifier is stored. - SpecifierKind getKind() const { + SpecifierKind getKind() const { if (Specifier == 0) return Global; - return (SpecifierKind)Prefix.getInt(); + return (SpecifierKind)Prefix.getInt(); } /// \brief Retrieve the identifier stored in this nested name @@ -140,7 +149,7 @@ public: return 0; } - + /// \brief Retrieve the namespace stored in this nested name /// specifier. NamespaceDecl *getAsNamespace() const { @@ -152,7 +161,7 @@ public: /// \brief Retrieve the type stored in this nested name specifier. Type *getAsType() const { - if (Prefix.getInt() == TypeSpec || + if (Prefix.getInt() == TypeSpec || Prefix.getInt() == TypeSpecWithTemplate) return (Type *)Specifier; @@ -179,6 +188,15 @@ public: void dump(const LangOptions &LO); }; +/// Insertion operator for diagnostics. This allows sending NestedNameSpecifiers +/// into a diagnostic with <<. +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + NestedNameSpecifier *NNS) { + DB.AddTaggedVal(reinterpret_cast<intptr_t>(NNS), + Diagnostic::ak_nestednamespec); + return DB; +} + } #endif diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h index c669991ccc08..f826e1117b66 100644 --- a/include/clang/AST/ParentMap.h +++ b/include/clang/AST/ParentMap.h @@ -17,7 +17,7 @@ namespace clang { class Stmt; class Expr; - + class ParentMap { void* Impl; public: @@ -30,7 +30,7 @@ public: const Stmt *getParent(const Stmt* S) const { return getParent(const_cast<Stmt*>(S)); } - + const Stmt *getParentIgnoreParens(const Stmt *S) const { return getParentIgnoreParens(const_cast<Stmt*>(S)); } @@ -38,13 +38,13 @@ public: bool hasParent(Stmt* S) const { return getParent(S) != 0; } - + bool isConsumedExpr(Expr *E) const; - + bool isConsumedExpr(const Expr *E) const { return isConsumedExpr(const_cast<Expr*>(E)); } }; - + } // end clang namespace #endif diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index 6ad3a6bcc276..0635ec5dcd51 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -34,9 +34,10 @@ public: /// declarations should be printed. struct PrintingPolicy { /// \brief Create a default printing policy for C. - PrintingPolicy(const LangOptions &LO) + PrintingPolicy(const LangOptions &LO) : Indentation(2), LangOpts(LO), SuppressSpecifiers(false), - SuppressTag(false), SuppressTagKind(false), Dump(false) { } + SuppressTag(false), SuppressTagKind(false), SuppressScope(false), + Dump(false), ConstantArraySizeAsWritten(false) { } /// \brief The number of spaces to use to indent each line. unsigned Indentation : 8; @@ -74,11 +75,32 @@ struct PrintingPolicy { /// kind of tag, e.g., "struct", "union", "enum". bool SuppressTagKind : 1; + /// \brief Suppresses printing of scope specifiers. + bool SuppressScope : 1; + /// \brief True when we are "dumping" rather than "pretty-printing", /// where dumping involves printing the internal details of the AST /// and pretty-printing involves printing something similar to /// source code. bool Dump : 1; + + /// \brief Whether we should print the sizes of constant array expressions + /// as written in the sources. + /// + /// This flag is determines whether arrays types declared as + /// + /// \code + /// int a[4+10*10]; + /// char a[] = "A string"; + /// \endcode + /// + /// will be printed as written or as follows: + /// + /// \code + /// int a[104]; + /// char a[9] = "A string"; + /// \endcode + bool ConstantArraySizeAsWritten : 1; }; } // end namespace clang diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index ab184563da23..7490b1d66b3e 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -18,83 +18,175 @@ namespace clang { class ASTContext; + class FieldDecl; class RecordDecl; + class CXXRecordDecl; -/// ASTRecordLayout - +/// ASTRecordLayout - /// This class contains layout information for one RecordDecl, /// which is a struct/union/class. The decl represented must be a definition, -/// not a forward declaration. -/// This class is also used to contain layout information for one +/// not a forward declaration. +/// This class is also used to contain layout information for one /// ObjCInterfaceDecl. FIXME - Find appropriate name. /// These objects are managed by ASTContext. class ASTRecordLayout { - uint64_t Size; // Size of record in bits. - uint64_t NextOffset; // Next available offset + /// Size - Size of record in bits. + uint64_t Size; + + /// DataSize - Size of record in bits without tail padding. + uint64_t DataSize; + + /// FieldOffsets - Array of field offsets in bits. uint64_t *FieldOffsets; - unsigned Alignment; // Alignment of record in bits. - unsigned FieldCount; // Number of fields + + // Alignment - Alignment of record in bits. + unsigned Alignment; + + // FieldCount - Number of fields. + unsigned FieldCount; + + struct CXXRecordLayoutInfo { + /// NonVirtualSize - The non-virtual size (in bits) of an object, which is + /// the size of the object without virtual bases. + uint64_t NonVirtualSize; + + /// NonVirtualAlign - The non-virtual alignment (in bits) of an object, + /// which is the alignment of the object without virtual bases. + uint64_t NonVirtualAlign; + + /// PrimaryBase - The primary base for our vtable. + const CXXRecordDecl *PrimaryBase; + /// PrimaryBase - Wether or not the primary base was a virtual base. + bool PrimaryBaseWasVirtual; + + /// BaseOffsets - Contains a map from base classes to their offset. + /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) + llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsets; + + /// VBaseOffsets - Contains a map from vbase classes to their offset. + /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) + llvm::DenseMap<const CXXRecordDecl *, uint64_t> VBaseOffsets; + }; + + /// CXXInfo - If the record layout is for a C++ record, this will have + /// C++ specific information about the record. + CXXRecordLayoutInfo *CXXInfo; + friend class ASTContext; + friend class ASTRecordLayoutBuilder; - ASTRecordLayout(uint64_t S = 0, unsigned A = 8) - : Size(S), NextOffset(S), Alignment(A), FieldCount(0) {} - ~ASTRecordLayout() { - delete [] FieldOffsets; + ASTRecordLayout(uint64_t size, unsigned alignment, unsigned datasize, + const uint64_t *fieldoffsets, unsigned fieldcount) + : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment), + FieldCount(fieldcount), CXXInfo(0) { + if (FieldCount > 0) { + FieldOffsets = new uint64_t[FieldCount]; + for (unsigned i = 0; i < FieldCount; ++i) + FieldOffsets[i] = fieldoffsets[i]; + } } - /// Initialize record layout. N is the number of fields in this record. - void InitializeLayout(unsigned N) { - FieldCount = N; - FieldOffsets = new uint64_t[N]; - } + // Constructor for C++ records. + ASTRecordLayout(uint64_t size, unsigned alignment, uint64_t datasize, + const uint64_t *fieldoffsets, unsigned fieldcount, + uint64_t nonvirtualsize, unsigned nonvirtualalign, + const CXXRecordDecl *PB, bool PBVirtual, + const std::pair<const CXXRecordDecl *, uint64_t> *bases, + unsigned numbases, + const std::pair<const CXXRecordDecl *, uint64_t> *vbases, + unsigned numvbases) + : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment), + FieldCount(fieldcount), CXXInfo(new CXXRecordLayoutInfo) { + if (FieldCount > 0) { + FieldOffsets = new uint64_t[FieldCount]; + for (unsigned i = 0; i < FieldCount; ++i) + FieldOffsets[i] = fieldoffsets[i]; + } - /// Finalize record layout. Adjust record size based on the alignment. - void FinalizeLayout(bool ForceNonEmpty = false) { - // In C++, records cannot be of size 0. - if (ForceNonEmpty && Size == 0) - Size = 8; - // Finally, round the size of the record up to the alignment of the - // record itself. - Size = (Size + (Alignment-1)) & ~(Alignment-1); + CXXInfo->PrimaryBase = PB; + CXXInfo->PrimaryBaseWasVirtual = PBVirtual; + CXXInfo->NonVirtualSize = nonvirtualsize; + CXXInfo->NonVirtualAlign = nonvirtualalign; + for (unsigned i = 0; i != numbases; ++i) + CXXInfo->BaseOffsets[bases[i].first] = bases[i].second; + for (unsigned i = 0; i != numvbases; ++i) + CXXInfo->VBaseOffsets[vbases[i].first] = vbases[i].second; } - void SetFieldOffset(unsigned FieldNo, uint64_t Offset) { - assert (FieldNo < FieldCount && "Invalid Field No"); - FieldOffsets[FieldNo] = Offset; + ~ASTRecordLayout() { + delete [] FieldOffsets; + delete CXXInfo; } - void SetAlignment(unsigned A) { Alignment = A; } - - /// LayoutField - Field layout. StructPacking is the specified - /// packing alignment (maximum alignment) in bits to use for the - /// structure, or 0 if no packing alignment is specified. - void LayoutField(const FieldDecl *FD, unsigned FieldNo, - bool IsUnion, unsigned StructPacking, - ASTContext &Context); - ASTRecordLayout(const ASTRecordLayout&); // DO NOT IMPLEMENT void operator=(const ASTRecordLayout&); // DO NOT IMPLEMENT public: - + /// getAlignment - Get the record alignment in bits. unsigned getAlignment() const { return Alignment; } /// getSize - Get the record size in bits. uint64_t getSize() const { return Size; } - + /// getFieldCount - Get the number of fields in the layout. unsigned getFieldCount() const { return FieldCount; } - + /// getFieldOffset - Get the offset of the given field index, in /// bits. uint64_t getFieldOffset(unsigned FieldNo) const { assert (FieldNo < FieldCount && "Invalid Field No"); return FieldOffsets[FieldNo]; } - - /// getNextOffset - Get the next available (unused) offset in the - /// structure, in bits. - uint64_t getNextOffset() const { - return NextOffset; + + /// getDataSize() - Get the record data size, which is the record size + /// without tail padding, in bits. + uint64_t getDataSize() const { + return DataSize; + } + + /// getNonVirtualSize - Get the non-virtual size (in bits) of an object, + /// which is the size of the object without virtual bases. + uint64_t getNonVirtualSize() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + + return CXXInfo->NonVirtualSize; + } + + /// getNonVirtualSize - Get the non-virtual alignment (in bits) of an object, + /// which is the alignment of the object without virtual bases. + unsigned getNonVirtualAlign() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + + return CXXInfo->NonVirtualAlign; + } + + /// getPrimaryBase - Get the primary base. + const CXXRecordDecl *getPrimaryBase() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + + return CXXInfo->PrimaryBase; + } + /// getPrimaryBaseWasVirtual - Indicates if the primary base was virtual. + bool getPrimaryBaseWasVirtual() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + + return CXXInfo->PrimaryBaseWasVirtual; + } + + /// getBaseClassOffset - Get the offset, in bits, for the given base class. + uint64_t getBaseClassOffset(const CXXRecordDecl *Base) const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!"); + + return CXXInfo->BaseOffsets[Base]; + } + + /// getVBaseClassOffset - Get the offset, in bits, for the given base class. + uint64_t getVBaseClassOffset(const CXXRecordDecl *VBase) const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!"); + + return CXXInfo->VBaseOffsets[VBase]; } }; diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h new file mode 100644 index 000000000000..458af1f14423 --- /dev/null +++ b/include/clang/AST/Redeclarable.h @@ -0,0 +1,162 @@ +//===-- Redeclarable.h - Base for Decls that can be redeclared -*- 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 Redeclarable interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_REDECLARABLE_H +#define LLVM_CLANG_AST_REDECLARABLE_H + +#include "llvm/ADT/PointerIntPair.h" + +namespace clang { + +/// \brief Provides common interface for the Decls that can be redeclared. +template<typename decl_type> +class Redeclarable { + +protected: + struct DeclLink : public llvm::PointerIntPair<decl_type *, 1, bool> { + DeclLink(decl_type *D, bool isLatest) + : llvm::PointerIntPair<decl_type *, 1, bool>(D, isLatest) { } + + typedef llvm::PointerIntPair<decl_type *, 1, bool> base_type; + + bool NextIsPrevious() const { return base_type::getInt() == false; } + bool NextIsLatest() const { return base_type::getInt() == true; } + decl_type *getNext() const { return base_type::getPointer(); } + }; + + struct PreviousDeclLink : public DeclLink { + PreviousDeclLink(decl_type *D) : DeclLink(D, false) { } + }; + + struct LatestDeclLink : public DeclLink { + LatestDeclLink(decl_type *D) : DeclLink(D, true) { } + }; + + /// \brief Points to the next redeclaration in the chain. + /// + /// If NextIsPrevious() is true, this is a link to the previous declaration + /// of this same Decl. If NextIsLatest() is true, this is the first + /// declaration and Link points to the latest declaration. For example: + /// + /// #1 int f(int x, int y = 1); // <pointer to #3, true> + /// #2 int f(int x = 0, int y); // <pointer to #1, false> + /// #3 int f(int x, int y) { return x + y; } // <pointer to #2, false> + /// + /// If there is only one declaration, it is <pointer to self, true> + DeclLink RedeclLink; + +public: + Redeclarable() : RedeclLink(LatestDeclLink(static_cast<decl_type*>(this))) { } + + /// \brief Return the previous declaration of this declaration or NULL if this + /// is the first declaration. + decl_type *getPreviousDeclaration() { + if (RedeclLink.NextIsPrevious()) + return RedeclLink.getNext(); + return 0; + } + const decl_type *getPreviousDeclaration() const { + return const_cast<decl_type *>( + static_cast<const decl_type*>(this))->getPreviousDeclaration(); + } + + /// \brief Return the first declaration of this declaration or itself if this + /// is the only declaration. + decl_type *getFirstDeclaration() { + decl_type *D = static_cast<decl_type*>(this); + while (D->getPreviousDeclaration()) + D = D->getPreviousDeclaration(); + return D; + } + + /// \brief Return the first declaration of this declaration or itself if this + /// is the only declaration. + const decl_type *getFirstDeclaration() const { + const decl_type *D = static_cast<const decl_type*>(this); + while (D->getPreviousDeclaration()) + D = D->getPreviousDeclaration(); + return D; + } + + /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the + /// first and only declaration. + void setPreviousDeclaration(decl_type *PrevDecl) { + decl_type *First; + + if (PrevDecl) { + // Point to previous. + RedeclLink = PreviousDeclLink(PrevDecl); + First = PrevDecl->getFirstDeclaration(); + assert(First->RedeclLink.NextIsLatest() && "Expected first"); + } else { + // Make this first. + First = static_cast<decl_type*>(this); + } + + // First one will point to this one as latest. + First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this)); + } + + /// \brief Iterates through all the redeclarations of the same decl. + class redecl_iterator { + /// Current - The current declaration. + decl_type *Current; + decl_type *Starter; + + public: + typedef decl_type* value_type; + typedef decl_type* reference; + typedef decl_type* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + redecl_iterator() : Current(0) { } + explicit redecl_iterator(decl_type *C) : Current(C), Starter(C) { } + + reference operator*() const { return Current; } + pointer operator->() const { return Current; } + + redecl_iterator& operator++() { + assert(Current && "Advancing while iterator has reached end"); + // Get either previous decl or latest decl. + decl_type *Next = Current->RedeclLink.getNext(); + Current = (Next != Starter ? Next : 0); + return *this; + } + + redecl_iterator operator++(int) { + redecl_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(redecl_iterator x, redecl_iterator y) { + return x.Current == y.Current; + } + friend bool operator!=(redecl_iterator x, redecl_iterator y) { + return x.Current != y.Current; + } + }; + + /// \brief Returns iterator for all the redeclarations of the same decl. + /// It will iterate at least once (when this decl is the only one). + redecl_iterator redecls_begin() const { + return redecl_iterator(const_cast<decl_type*>( + static_cast<const decl_type*>(this))); + } + redecl_iterator redecls_end() const { return redecl_iterator(); } +}; + +} + +#endif diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 0a64dafd4e2c..411f215e912e 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -21,11 +21,14 @@ #include "clang/AST/StmtIterator.h" #include "clang/AST/DeclGroup.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/iterator.h" #include "clang/AST/ASTContext.h" #include <string> using llvm::dyn_cast_or_null; +namespace llvm { + class FoldingSetNodeID; +} + namespace clang { class ASTContext; class Expr; @@ -36,21 +39,21 @@ namespace clang { class SourceManager; class StringLiteral; class SwitchStmt; - + //===----------------------------------------------------------------------===// // ExprIterator - Iterators for iterating over Stmt* arrays that contain // only Expr*. This is needed because AST nodes use Stmt* arrays to store // references to children (to be compatible with StmtIterator). //===----------------------------------------------------------------------===// - + class Stmt; class Expr; - + class ExprIterator { Stmt** I; public: ExprIterator(Stmt** i) : I(i) {} - ExprIterator() : I(0) {} + ExprIterator() : I(0) {} ExprIterator& operator++() { ++I; return *this; } ExprIterator operator-(size_t i) { return I-i; } ExprIterator operator+(size_t i) { return I+i; } @@ -64,12 +67,12 @@ namespace clang { bool operator>(const ExprIterator& R) const { return I > R.I; } bool operator>=(const ExprIterator& R) const { return I >= R.I; } }; - + class ConstExprIterator { Stmt* const * I; public: ConstExprIterator(Stmt* const* i) : I(i) {} - ConstExprIterator() : I(0) {} + ConstExprIterator() : I(0) {} ConstExprIterator& operator++() { ++I; return *this; } ConstExprIterator operator+(size_t i) { return I+i; } ConstExprIterator operator-(size_t i) { return I-i; } @@ -81,12 +84,12 @@ namespace clang { bool operator!=(const ConstExprIterator& R) const { return I != R.I; } bool operator>(const ConstExprIterator& R) const { return I > R.I; } bool operator>=(const ConstExprIterator& R) const { return I >= R.I; } - }; - + }; + //===----------------------------------------------------------------------===// // AST classes for statements. //===----------------------------------------------------------------------===// - + /// Stmt - This represents one statement. /// class Stmt { @@ -101,7 +104,11 @@ public: #include "clang/AST/StmtNodes.def" }; private: - const StmtClass sClass; + /// \brief The statement class. + const unsigned sClass : 8; + + /// \brief The reference count for this statement. + unsigned RefCount : 24; // Make vanilla 'new' and 'delete' illegal for Stmts. protected: @@ -112,20 +119,20 @@ protected: void operator delete(void* data) throw() { assert(0 && "Stmts cannot be released with regular 'delete'."); } - + public: // Only allow allocation of Stmts using the allocator in ASTContext - // or by doing a placement new. + // or by doing a placement new. void* operator new(size_t bytes, ASTContext& C, unsigned alignment = 16) throw() { return ::operator new(bytes, C, alignment); } - + void* operator new(size_t bytes, ASTContext* C, unsigned alignment = 16) throw() { return ::operator new(bytes, *C, alignment); } - + void* operator new(size_t bytes, void* mem) throw() { return mem; } @@ -145,23 +152,48 @@ protected: /// DestroyChildren - Invoked by destructors of subclasses of Stmt to /// recursively release child AST nodes. void DestroyChildren(ASTContext& Ctx); - + /// \brief Construct an empty statement. - explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC) { + explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC), RefCount(1) { if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); } + /// \brief Virtual method that performs the actual destruction of + /// this statement. + /// + /// Subclasses should override this method (not Destroy()) to + /// provide class-specific destruction. + virtual void DoDestroy(ASTContext &Ctx); + public: - Stmt(StmtClass SC) : sClass(SC) { + Stmt(StmtClass SC) : sClass(SC), RefCount(1) { if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); } virtual ~Stmt() {} - - virtual void Destroy(ASTContext &Ctx); - StmtClass getStmtClass() const { return sClass; } + /// \brief Destroy the current statement and its children. + void Destroy(ASTContext &Ctx) { + assert(RefCount >= 1); + if (--RefCount == 0) + DoDestroy(Ctx); + } + + /// \brief Increases the reference count for this statement. + /// + /// Invoke the Retain() operation when this statement or expression + /// is being shared by another owner. + Stmt *Retain() { + assert(RefCount >= 1); + ++RefCount; + return this; + } + + StmtClass getStmtClass() const { + assert(RefCount >= 1 && "Referencing already-destroyed statement!"); + return (StmtClass)sClass; + } const char *getStmtClassName() const; - + /// SourceLocation tokens are not useful in isolation - they are low level /// value objects created/interpreted by SourceManager. We assume AST /// clients will have a pointer to the respective SourceManager. @@ -187,23 +219,23 @@ public: /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST /// back to its original source language syntax. void dumpPretty(ASTContext& Context) const; - void printPretty(llvm::raw_ostream &OS, PrinterHelper *Helper, + void printPretty(llvm::raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation = 0) const { printPretty(OS, *(ASTContext*)0, Helper, Policy, Indentation); } void printPretty(llvm::raw_ostream &OS, ASTContext &Context, - PrinterHelper *Helper, + PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation = 0) const; - + /// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only /// works on systems with GraphViz (Mac OS X) or dot+gv installed. void viewAST() const; - + // Implement isa<T> support. - static bool classof(const Stmt *) { return true; } - + static bool classof(const Stmt *) { return true; } + /// hasImplicitControlFlow - Some statements (e.g. short circuited operations) /// contain implicit control-flow in the order their subexpressions /// are evaluated. This predicate returns true if this statement has @@ -216,46 +248,60 @@ public: /// AST node. This permits easy iteration over all nodes in the AST. typedef StmtIterator child_iterator; typedef ConstStmtIterator const_child_iterator; - + virtual child_iterator child_begin() = 0; virtual child_iterator child_end() = 0; - + const_child_iterator child_begin() const { return const_child_iterator(const_cast<Stmt*>(this)->child_begin()); } - + const_child_iterator child_end() const { return const_child_iterator(const_cast<Stmt*>(this)->child_end()); } + + /// \brief Produce a unique representation of the given statement. + /// + /// \brief ID once the profiling operation is complete, will contain + /// the unique representation of the given statement. + /// + /// \brief Context the AST context in which the statement resides + /// + /// \brief Canonical whether the profile should be based on the canonical + /// representation of this statement (e.g., where non-type template + /// parameters are identified by index/level rather than their + /// declaration pointers) or the exact representation of the statement as + /// written in the source. + void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, + bool Canonical); }; /// DeclStmt - Adaptor class for mixing declarations with statements and /// expressions. For example, CompoundStmt mixes statements, expressions -/// and declarations (variables, types). Another example is ForStmt, where +/// and declarations (variables, types). Another example is ForStmt, where /// the first statement can be an expression or a declaration. /// class DeclStmt : public Stmt { DeclGroupRef DG; SourceLocation StartLoc, EndLoc; + public: - DeclStmt(DeclGroupRef dg, SourceLocation startLoc, + DeclStmt(DeclGroupRef dg, SourceLocation startLoc, SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg), StartLoc(startLoc), EndLoc(endLoc) {} - + /// \brief Build an empty declaration statement. explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) { } - virtual void Destroy(ASTContext& Ctx); - /// isSingleDecl - This method returns true if this DeclStmt refers /// to a single Decl. bool isSingleDecl() const { return DG.isSingleDecl(); } - + const Decl *getSingleDecl() const { return DG.getSingleDecl(); } - Decl *getSingleDecl() { return DG.getSingleDecl(); } - + Decl *getSingleDecl() { return DG.getSingleDecl(); } + const DeclGroupRef getDeclGroup() const { return DG; } DeclGroupRef getDeclGroup() { return DG; } void setDeclGroup(DeclGroupRef DGR) { DG = DGR; } @@ -268,19 +314,19 @@ public: SourceRange getSourceRange() const { return SourceRange(StartLoc, EndLoc); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == DeclStmtClass; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == DeclStmtClass; } static bool classof(const DeclStmt *) { return true; } - + // Iterators over subexpressions. virtual child_iterator child_begin(); virtual child_iterator child_end(); - + typedef DeclGroupRef::iterator decl_iterator; typedef DeclGroupRef::const_iterator const_decl_iterator; - + decl_iterator decl_begin() { return DG.begin(); } decl_iterator decl_end() { return DG.end(); } const_decl_iterator decl_begin() const { return DG.begin(); } @@ -297,18 +343,16 @@ public: /// \brief Build an empty null statement. explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) { } - NullStmt* Clone(ASTContext &C) const; - SourceLocation getSemiLoc() const { return SemiLoc; } void setSemiLoc(SourceLocation L) { SemiLoc = L; } virtual SourceRange getSourceRange() const { return SourceRange(SemiLoc); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == NullStmtClass; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == NullStmtClass; } static bool classof(const NullStmt *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -321,24 +365,24 @@ class CompoundStmt : public Stmt { unsigned NumStmts; SourceLocation LBracLoc, RBracLoc; public: - CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned numStmts, + CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned numStmts, SourceLocation LB, SourceLocation RB) : Stmt(CompoundStmtClass), NumStmts(numStmts), LBracLoc(LB), RBracLoc(RB) { if (NumStmts == 0) { Body = 0; return; } - + Body = new (C) Stmt*[NumStmts]; memcpy(Body, StmtStart, numStmts * sizeof(*Body)); - } + } // \brief Build an empty compound statement. explicit CompoundStmt(EmptyShell Empty) : Stmt(CompoundStmtClass, Empty), Body(0), NumStmts(0) { } void setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts); - + bool body_empty() const { return NumStmts == 0; } unsigned size() const { return NumStmts; } @@ -366,25 +410,25 @@ public: const_reverse_body_iterator body_rbegin() const { return const_reverse_body_iterator(body_end()); } - + const_reverse_body_iterator body_rend() const { return const_reverse_body_iterator(body_begin()); } - - virtual SourceRange getSourceRange() const { - return SourceRange(LBracLoc, RBracLoc); + + virtual SourceRange getSourceRange() const { + return SourceRange(LBracLoc, RBracLoc); } - + SourceLocation getLBracLoc() const { return LBracLoc; } void setLBracLoc(SourceLocation L) { LBracLoc = L; } SourceLocation getRBracLoc() const { return RBracLoc; } void setRBracLoc(SourceLocation L) { RBracLoc = L; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CompoundStmtClass; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CompoundStmtClass; } static bool classof(const CompoundStmt *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -398,7 +442,7 @@ protected: SwitchCase *NextSwitchCase; SwitchCase(StmtClass SC) : Stmt(SC), NextSwitchCase(0) {} - + public: const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; } @@ -409,19 +453,19 @@ public: Stmt *getSubStmt() { return v_getSubStmt(); } virtual SourceRange getSourceRange() const { return SourceRange(); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CaseStmtClass || + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CaseStmtClass || T->getStmtClass() == DefaultStmtClass; } static bool classof(const SwitchCase *) { return true; } protected: - virtual Stmt* v_getSubStmt() = 0; + virtual Stmt* v_getSubStmt() = 0; }; class CaseStmt : public SwitchCase { enum { SUBSTMT, LHS, RHS, END_EXPR }; - Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for + Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for // GNU "case 1 ... 4" extension SourceLocation CaseLoc; SourceLocation EllipsisLoc; @@ -430,7 +474,7 @@ class CaseStmt : public SwitchCase { virtual Stmt* v_getSubStmt() { return getSubStmt(); } public: CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc, - SourceLocation ellipsisLoc, SourceLocation colonLoc) + SourceLocation ellipsisLoc, SourceLocation colonLoc) : SwitchCase(CaseStmtClass) { SubExprs[SUBSTMT] = 0; SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs); @@ -454,32 +498,32 @@ public: Expr *getRHS() { return reinterpret_cast<Expr*>(SubExprs[RHS]); } Stmt *getSubStmt() { return SubExprs[SUBSTMT]; } - const Expr *getLHS() const { - return reinterpret_cast<const Expr*>(SubExprs[LHS]); + const Expr *getLHS() const { + return reinterpret_cast<const Expr*>(SubExprs[LHS]); } - const Expr *getRHS() const { - return reinterpret_cast<const Expr*>(SubExprs[RHS]); + const Expr *getRHS() const { + return reinterpret_cast<const Expr*>(SubExprs[RHS]); } const Stmt *getSubStmt() const { return SubExprs[SUBSTMT]; } void setSubStmt(Stmt *S) { SubExprs[SUBSTMT] = S; } void setLHS(Expr *Val) { SubExprs[LHS] = reinterpret_cast<Stmt*>(Val); } void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); } - - + + virtual SourceRange getSourceRange() const { // Handle deeply nested case statements with iteration instead of recursion. const CaseStmt *CS = this; while (const CaseStmt *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt())) CS = CS2; - - return SourceRange(CaseLoc, CS->getSubStmt()->getLocEnd()); + + return SourceRange(CaseLoc, CS->getSubStmt()->getLocEnd()); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == CaseStmtClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == CaseStmtClass; } static bool classof(const CaseStmt *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -491,7 +535,7 @@ class DefaultStmt : public SwitchCase { SourceLocation ColonLoc; virtual Stmt* v_getSubStmt() { return getSubStmt(); } public: - DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) : + DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) : SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL), ColonLoc(CL) {} @@ -507,14 +551,14 @@ public: SourceLocation getColonLoc() const { return ColonLoc; } void setColonLoc(SourceLocation L) { ColonLoc = L; } - virtual SourceRange getSourceRange() const { - return SourceRange(DefaultLoc, SubStmt->getLocEnd()); + virtual SourceRange getSourceRange() const { + return SourceRange(DefaultLoc, SubStmt->getLocEnd()); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == DefaultStmtClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == DefaultStmtClass; } static bool classof(const DefaultStmt *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -525,13 +569,13 @@ class LabelStmt : public Stmt { Stmt *SubStmt; SourceLocation IdentLoc; public: - LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt) - : Stmt(LabelStmtClass), Label(label), + LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt) + : Stmt(LabelStmtClass), Label(label), SubStmt(substmt), IdentLoc(IL) {} // \brief Build an empty label statement. explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { } - + SourceLocation getIdentLoc() const { return IdentLoc; } IdentifierInfo *getID() const { return Label; } void setID(IdentifierInfo *II) { Label = II; } @@ -541,14 +585,14 @@ public: void setIdentLoc(SourceLocation L) { IdentLoc = L; } void setSubStmt(Stmt *SS) { SubStmt = SS; } - virtual SourceRange getSourceRange() const { - return SourceRange(IdentLoc, SubStmt->getLocEnd()); - } - static bool classof(const Stmt *T) { - return T->getStmtClass() == LabelStmtClass; + virtual SourceRange getSourceRange() const { + return SourceRange(IdentLoc, SubStmt->getLocEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == LabelStmtClass; } static bool classof(const LabelStmt *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -563,8 +607,8 @@ class IfStmt : public Stmt { SourceLocation IfLoc; SourceLocation ElseLoc; public: - IfStmt(SourceLocation IL, Expr *cond, Stmt *then, - SourceLocation EL = SourceLocation(), Stmt *elsev = 0) + IfStmt(SourceLocation IL, Expr *cond, Stmt *then, + SourceLocation EL = SourceLocation(), Stmt *elsev = 0) : Stmt(IfStmtClass) { SubExprs[COND] = reinterpret_cast<Stmt*>(cond); SubExprs[THEN] = then; @@ -572,14 +616,14 @@ public: IfLoc = IL; ElseLoc = EL; } - + /// \brief Build an empty if/then/else statement explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { } const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); } const Stmt *getThen() const { return SubExprs[THEN]; } - void setThen(Stmt *S) { SubExprs[THEN] = S; } + void setThen(Stmt *S) { SubExprs[THEN] = S; } const Stmt *getElse() const { return SubExprs[ELSE]; } void setElse(Stmt *S) { SubExprs[ELSE] = S; } @@ -592,18 +636,18 @@ public: SourceLocation getElseLoc() const { return ElseLoc; } void setElseLoc(SourceLocation L) { ElseLoc = L; } - virtual SourceRange getSourceRange() const { + virtual SourceRange getSourceRange() const { if (SubExprs[ELSE]) return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd()); else return SourceRange(IfLoc, SubExprs[THEN]->getLocEnd()); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == IfStmtClass; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == IfStmtClass; } static bool classof(const IfStmt *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -613,16 +657,20 @@ public: /// class SwitchStmt : public Stmt { enum { COND, BODY, END_EXPR }; - Stmt* SubExprs[END_EXPR]; + Stmt* SubExprs[END_EXPR]; // This points to a linked list of case and default statements. SwitchCase *FirstCase; SourceLocation SwitchLoc; + +protected: + virtual void DoDestroy(ASTContext &Ctx); + public: SwitchStmt(Expr *cond) : Stmt(SwitchStmtClass), FirstCase(0) { SubExprs[COND] = reinterpret_cast<Stmt*>(cond); SubExprs[BODY] = NULL; } - + /// \brief Build a empty switch statement. explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { } @@ -635,28 +683,34 @@ public: Stmt *getBody() { return SubExprs[BODY]; } void setBody(Stmt *S) { SubExprs[BODY] = S; } SwitchCase *getSwitchCaseList() { return FirstCase; } + + /// \brief Set the case list for this switch statement. + /// + /// The caller is responsible for incrementing the retain counts on + /// all of the SwitchCase statements in this list. void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; } SourceLocation getSwitchLoc() const { return SwitchLoc; } void setSwitchLoc(SourceLocation L) { SwitchLoc = L; } - void setBody(Stmt *S, SourceLocation SL) { - SubExprs[BODY] = S; + void setBody(Stmt *S, SourceLocation SL) { + SubExprs[BODY] = S; SwitchLoc = SL; - } + } void addSwitchCase(SwitchCase *SC) { assert(!SC->getNextSwitchCase() && "case/default already added to a switch"); + SC->Retain(); SC->setNextSwitchCase(FirstCase); FirstCase = SC; } - virtual SourceRange getSourceRange() const { - return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd()); + virtual SourceRange getSourceRange() const { + return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd()); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == SwitchStmtClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == SwitchStmtClass; } static bool classof(const SwitchStmt *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -675,7 +729,7 @@ public: SubExprs[BODY] = body; WhileLoc = WL; } - + /// \brief Build an empty while statement. explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) { } @@ -689,14 +743,14 @@ public: SourceLocation getWhileLoc() const { return WhileLoc; } void setWhileLoc(SourceLocation L) { WhileLoc = L; } - virtual SourceRange getSourceRange() const { - return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd()); + virtual SourceRange getSourceRange() const { + return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd()); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == WhileStmtClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == WhileStmtClass; } static bool classof(const WhileStmt *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -717,16 +771,16 @@ public: : Stmt(DoStmtClass), DoLoc(DL), WhileLoc(WL), RParenLoc(RP) { SubExprs[COND] = reinterpret_cast<Stmt*>(cond); SubExprs[BODY] = body; - } + } /// \brief Build an empty do-while statement. explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) { } - + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } Stmt *getBody() { return SubExprs[BODY]; } - const Stmt *getBody() const { return SubExprs[BODY]; } + const Stmt *getBody() const { return SubExprs[BODY]; } void setBody(Stmt *S) { SubExprs[BODY] = S; } SourceLocation getDoLoc() const { return DoLoc; } @@ -737,11 +791,11 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - virtual SourceRange getSourceRange() const { - return SourceRange(DoLoc, RParenLoc); + virtual SourceRange getSourceRange() const { + return SourceRange(DoLoc, RParenLoc); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == DoStmtClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == DoStmtClass; } static bool classof(const DoStmt *) { return true; } @@ -763,7 +817,7 @@ class ForStmt : public Stmt { public: ForStmt(Stmt *Init, Expr *Cond, Expr *Inc, Stmt *Body, SourceLocation FL, - SourceLocation LP, SourceLocation RP) + SourceLocation LP, SourceLocation RP) : Stmt(ForStmtClass) { SubExprs[INIT] = Init; SubExprs[COND] = reinterpret_cast<Stmt*>(Cond); @@ -773,7 +827,7 @@ public: LParenLoc = LP; RParenLoc = RP; } - + /// \brief Build an empty for statement. explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { } @@ -799,19 +853,19 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - virtual SourceRange getSourceRange() const { - return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); + virtual SourceRange getSourceRange() const { + return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ForStmtClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == ForStmtClass; } static bool classof(const ForStmt *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; - + /// GotoStmt - This represents a direct goto. /// class GotoStmt : public Stmt { @@ -819,9 +873,9 @@ class GotoStmt : public Stmt { SourceLocation GotoLoc; SourceLocation LabelLoc; public: - GotoStmt(LabelStmt *label, SourceLocation GL, SourceLocation LL) + GotoStmt(LabelStmt *label, SourceLocation GL, SourceLocation LL) : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {} - + /// \brief Build an empty goto statement. explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) { } @@ -833,14 +887,14 @@ public: SourceLocation getLabelLoc() const { return LabelLoc; } void setLabelLoc(SourceLocation L) { LabelLoc = L; } - virtual SourceRange getSourceRange() const { - return SourceRange(GotoLoc, LabelLoc); + virtual SourceRange getSourceRange() const { + return SourceRange(GotoLoc, LabelLoc); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == GotoStmtClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == GotoStmtClass; } static bool classof(const GotoStmt *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -853,20 +907,20 @@ class IndirectGotoStmt : public Stmt { SourceLocation StarLoc; Stmt *Target; public: - IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc, + IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc, Expr *target) : Stmt(IndirectGotoStmtClass), GotoLoc(gotoLoc), StarLoc(starLoc), Target((Stmt*)target) {} /// \brief Build an empty indirect goto statement. - explicit IndirectGotoStmt(EmptyShell Empty) + explicit IndirectGotoStmt(EmptyShell Empty) : Stmt(IndirectGotoStmtClass, Empty) { } - + void setGotoLoc(SourceLocation L) { GotoLoc = L; } SourceLocation getGotoLoc() const { return GotoLoc; } void setStarLoc(SourceLocation L) { StarLoc = L; } SourceLocation getStarLoc() const { return StarLoc; } - + Expr *getTarget(); const Expr *getTarget() const; void setTarget(Expr *E) { Target = reinterpret_cast<Stmt*>(E); } @@ -874,12 +928,12 @@ public: virtual SourceRange getSourceRange() const { return SourceRange(GotoLoc, Target->getLocEnd()); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == IndirectGotoStmtClass; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == IndirectGotoStmtClass; } static bool classof(const IndirectGotoStmt *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -892,24 +946,22 @@ class ContinueStmt : public Stmt { SourceLocation ContinueLoc; public: ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {} - + /// \brief Build an empty continue statement. explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) { } SourceLocation getContinueLoc() const { return ContinueLoc; } void setContinueLoc(SourceLocation L) { ContinueLoc = L; } - virtual SourceRange getSourceRange() const { - return SourceRange(ContinueLoc); + virtual SourceRange getSourceRange() const { + return SourceRange(ContinueLoc); } - ContinueStmt* Clone(ASTContext &C) const; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ContinueStmtClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == ContinueStmtClass; } static bool classof(const ContinueStmt *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -921,7 +973,7 @@ class BreakStmt : public Stmt { SourceLocation BreakLoc; public: BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {} - + /// \brief Build an empty break statement. explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) { } @@ -930,13 +982,11 @@ public: virtual SourceRange getSourceRange() const { return SourceRange(BreakLoc); } - BreakStmt* Clone(ASTContext &C) const; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == BreakStmtClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == BreakStmtClass; } static bool classof(const BreakStmt *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -956,7 +1006,7 @@ class ReturnStmt : public Stmt { Stmt *RetExpr; SourceLocation RetLoc; public: - ReturnStmt(SourceLocation RL, Expr *E = 0) : Stmt(ReturnStmtClass), + ReturnStmt(SourceLocation RL, Expr *E = 0) : Stmt(ReturnStmtClass), RetExpr((Stmt*) E), RetLoc(RL) {} /// \brief Build an empty return expression. @@ -970,12 +1020,12 @@ public: void setReturnLoc(SourceLocation L) { RetLoc = L; } virtual SourceRange getSourceRange() const; - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ReturnStmtClass; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ReturnStmtClass; } static bool classof(const ReturnStmt *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); @@ -989,18 +1039,18 @@ class AsmStmt : public Stmt { bool IsSimple; bool IsVolatile; - + unsigned NumOutputs; unsigned NumInputs; - + llvm::SmallVector<std::string, 4> Names; llvm::SmallVector<StringLiteral*, 4> Constraints; llvm::SmallVector<Stmt*, 4> Exprs; llvm::SmallVector<StringLiteral*, 4> Clobbers; public: - AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile, - unsigned numoutputs, unsigned numinputs, + AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile, + unsigned numoutputs, unsigned numinputs, std::string *names, StringLiteral **constraints, Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, StringLiteral **clobbers, SourceLocation rparenloc); @@ -1043,10 +1093,10 @@ public: : MyKind(Operand), Str(), OperandNo(OpNo) { Str += Modifier; } - + bool isString() const { return MyKind == String; } bool isOperand() const { return MyKind == Operand; } - + const std::string &getString() const { assert(isString()); return Str; @@ -1056,7 +1106,7 @@ public: assert(isOperand()); return OperandNo; } - + /// getModifier - Get the modifier for this operand, if present. This /// returns '\0' if there was no modifier. char getModifier() const { @@ -1064,16 +1114,16 @@ public: return Str[0]; } }; - + /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing /// it into pieces. If the asm string is erroneous, emit errors and return /// true, otherwise return false. This handles canonicalization and /// translation of strings from GCC syntax to LLVM IR syntax, and handles - //// flattening of named references like %[foo] to Operand AsmStringPiece's. + //// flattening of named references like %[foo] to Operand AsmStringPiece's. unsigned AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece> &Pieces, ASTContext &C, unsigned &DiagOffs) const; - - + + //===--- Output operands ---===// unsigned getNumOutputs() const { return NumOutputs; } @@ -1086,72 +1136,72 @@ public: /// output operand. All output constraints are known to be non-empty (either /// '=' or '+'). std::string getOutputConstraint(unsigned i) const; - + const StringLiteral *getOutputConstraintLiteral(unsigned i) const { return Constraints[i]; } StringLiteral *getOutputConstraintLiteral(unsigned i) { return Constraints[i]; } - - + + Expr *getOutputExpr(unsigned i); - + const Expr *getOutputExpr(unsigned i) const { return const_cast<AsmStmt*>(this)->getOutputExpr(i); } - + /// isOutputPlusConstraint - Return true if the specified output constraint /// is a "+" constraint (which is both an input and an output) or false if it /// is an "=" constraint (just an output). bool isOutputPlusConstraint(unsigned i) const { return getOutputConstraint(i)[0] == '+'; } - + /// getNumPlusOperands - Return the number of output operands that have a "+" /// constraint. unsigned getNumPlusOperands() const; - + //===--- Input operands ---===// - - unsigned getNumInputs() const { return NumInputs; } - + + unsigned getNumInputs() const { return NumInputs; } + const std::string &getInputName(unsigned i) const { return Names[i + NumOutputs]; } - + /// getInputConstraint - Return the specified input constraint. Unlike output /// constraints, these can be empty. std::string getInputConstraint(unsigned i) const; - + const StringLiteral *getInputConstraintLiteral(unsigned i) const { return Constraints[i + NumOutputs]; } StringLiteral *getInputConstraintLiteral(unsigned i) { return Constraints[i + NumOutputs]; } - - + + Expr *getInputExpr(unsigned i); - + const Expr *getInputExpr(unsigned i) const { return const_cast<AsmStmt*>(this)->getInputExpr(i); } void setOutputsAndInputs(unsigned NumOutputs, - unsigned NumInputs, + unsigned NumInputs, const std::string *Names, StringLiteral **Constraints, Stmt **Exprs); //===--- Other ---===// - + /// getNamedOperand - Given a symbolic operand reference like %[foo], /// translate this into a numeric value needed to reference the same operand. /// This returns -1 if the operand name is invalid. int getNamedOperand(const std::string &SymbolicName) const; - + unsigned getNumClobbers() const { return Clobbers.size(); } StringLiteral *getClobber(unsigned i) { return Clobbers[i]; } @@ -1161,62 +1211,62 @@ public: virtual SourceRange getSourceRange() const { return SourceRange(AsmLoc, RParenLoc); } - + static bool classof(const Stmt *T) {return T->getStmtClass() == AsmStmtClass;} static bool classof(const AsmStmt *) { return true; } - + // Input expr iterators. - + typedef ExprIterator inputs_iterator; typedef ConstExprIterator const_inputs_iterator; - + inputs_iterator begin_inputs() { return Exprs.data() + NumOutputs; } - + inputs_iterator end_inputs() { return Exprs.data() + NumOutputs + NumInputs; } - + const_inputs_iterator begin_inputs() const { return Exprs.data() + NumOutputs; } - + const_inputs_iterator end_inputs() const { return Exprs.data() + NumOutputs + NumInputs; } - + // Output expr iterators. - + typedef ExprIterator outputs_iterator; typedef ConstExprIterator const_outputs_iterator; - + outputs_iterator begin_outputs() { return Exprs.data(); } outputs_iterator end_outputs() { return Exprs.data() + NumOutputs; } - + const_outputs_iterator begin_outputs() const { return Exprs.data(); } const_outputs_iterator end_outputs() const { return Exprs.data() + NumOutputs; } - + // Input name iterator. - + const std::string *begin_output_names() const { return &Names[0]; } - + const std::string *end_output_names() const { return &Names[0] + NumOutputs; } - - // Child iterators - + + // Child iterators + virtual child_iterator child_begin(); virtual child_iterator child_end(); }; diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index 2338f1457a84..28fe348c4591 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -29,13 +29,14 @@ class CXXCatchStmt : public Stmt { /// The handler block. Stmt *HandlerBlock; +protected: + virtual void DoDestroy(ASTContext& Ctx); + public: CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock) : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl), HandlerBlock(handlerBlock) {} - virtual void Destroy(ASTContext& Ctx); - virtual SourceRange getSourceRange() const { return SourceRange(CatchLoc, HandlerBlock->getLocEnd()); } diff --git a/include/clang/AST/StmtGraphTraits.h b/include/clang/AST/StmtGraphTraits.h index 1bfac6a9587e..25d015287b75 100644 --- a/include/clang/AST/StmtGraphTraits.h +++ b/include/clang/AST/StmtGraphTraits.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines a template specialization of llvm::GraphTraits to +// This file defines a template specialization of llvm::GraphTraits to // treat ASTs (Stmt*) as graphs // //===----------------------------------------------------------------------===// @@ -20,7 +20,7 @@ #include "llvm/ADT/DepthFirstIterator.h" namespace llvm { - + //template <typename T> struct GraphTraits; @@ -28,23 +28,23 @@ template <> struct GraphTraits<clang::Stmt*> { typedef clang::Stmt NodeType; typedef clang::Stmt::child_iterator ChildIteratorType; typedef llvm::df_iterator<clang::Stmt*> nodes_iterator; - + static NodeType* getEntryNode(clang::Stmt* S) { return S; } - + static inline ChildIteratorType child_begin(NodeType* N) { if (N) return N->child_begin(); else return ChildIteratorType(); } - + static inline ChildIteratorType child_end(NodeType* N) { if (N) return N->child_end(); else return ChildIteratorType(); } - + static nodes_iterator nodes_begin(clang::Stmt* S) { return df_begin(S); } - + static nodes_iterator nodes_end(clang::Stmt* S) { return df_end(S); } @@ -55,29 +55,29 @@ template <> struct GraphTraits<const clang::Stmt*> { typedef const clang::Stmt NodeType; typedef clang::Stmt::const_child_iterator ChildIteratorType; typedef llvm::df_iterator<const clang::Stmt*> nodes_iterator; - + static NodeType* getEntryNode(const clang::Stmt* S) { return S; } - + static inline ChildIteratorType child_begin(NodeType* N) { if (N) return N->child_begin(); - else return ChildIteratorType(); + else return ChildIteratorType(); } - + static inline ChildIteratorType child_end(NodeType* N) { if (N) return N->child_end(); else return ChildIteratorType(); } - + static nodes_iterator nodes_begin(const clang::Stmt* S) { return df_begin(S); } - + static nodes_iterator nodes_end(const clang::Stmt* S) { return df_end(S); } }; - + } // end namespace llvm #endif diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h index 35bd5ada0256..2d523fffce74 100644 --- a/include/clang/AST/StmtIterator.h +++ b/include/clang/AST/StmtIterator.h @@ -14,54 +14,54 @@ #ifndef LLVM_CLANG_AST_STMT_ITR_H #define LLVM_CLANG_AST_STMT_ITR_H -#include "llvm/ADT/iterator.h" #include "llvm/Support/DataTypes.h" #include <cassert> +#include <iterator> namespace clang { class Stmt; class Decl; class VariableArrayType; - + class StmtIteratorBase { protected: enum { DeclMode = 0x1, SizeOfTypeVAMode = 0x2, DeclGroupMode = 0x3, Flags = 0x3 }; - + union { Stmt** stmt; Decl* decl; Decl** DGI; }; - uintptr_t RawVAPtr; + uintptr_t RawVAPtr; Decl** DGE; bool inDecl() const { return (RawVAPtr & Flags) == DeclMode; } - + bool inDeclGroup() const { return (RawVAPtr & Flags) == DeclGroupMode; } - - bool inSizeOfTypeVA() const { + + bool inSizeOfTypeVA() const { return (RawVAPtr & Flags) == SizeOfTypeVAMode; } - + bool inStmt() const { return (RawVAPtr & Flags) == 0; } - + VariableArrayType* getVAPtr() const { return reinterpret_cast<VariableArrayType*>(RawVAPtr & ~Flags); } - + void setVAPtr(VariableArrayType* P) { - assert (inDecl() || inDeclGroup() || inSizeOfTypeVA()); + assert (inDecl() || inDeclGroup() || inSizeOfTypeVA()); RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags); } - + void NextDecl(bool ImmediateAdvance = true); bool HandleDecl(Decl* D); void NextVA(); - + Stmt*& GetDeclExpr() const; StmtIteratorBase(Stmt** s) : stmt(s), RawVAPtr(0) {} @@ -70,22 +70,22 @@ protected: StmtIteratorBase(Decl** dgi, Decl** dge); StmtIteratorBase() : stmt(NULL), RawVAPtr(0) {} }; - - + + template <typename DERIVED, typename REFERENCE> -class StmtIteratorImpl : public StmtIteratorBase, +class StmtIteratorImpl : public StmtIteratorBase, public std::iterator<std::forward_iterator_tag, - REFERENCE, ptrdiff_t, - REFERENCE, REFERENCE> { + REFERENCE, ptrdiff_t, + REFERENCE, REFERENCE> { protected: StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {} public: - StmtIteratorImpl() {} + StmtIteratorImpl() {} StmtIteratorImpl(Stmt** s) : StmtIteratorBase(s) {} StmtIteratorImpl(Decl** dgi, Decl** dge) : StmtIteratorBase(dgi, dge) {} StmtIteratorImpl(Decl* d) : StmtIteratorBase(d) {} StmtIteratorImpl(VariableArrayType* t) : StmtIteratorBase(t) {} - + DERIVED& operator++() { if (inDecl() || inDeclGroup()) { if (getVAPtr()) NextVA(); @@ -95,36 +95,36 @@ public: NextVA(); else ++stmt; - + return static_cast<DERIVED&>(*this); } - + DERIVED operator++(int) { DERIVED tmp = static_cast<DERIVED&>(*this); operator++(); return tmp; } - + bool operator==(const DERIVED& RHS) const { return stmt == RHS.stmt && RawVAPtr == RHS.RawVAPtr; } - + bool operator!=(const DERIVED& RHS) const { return stmt != RHS.stmt || RawVAPtr != RHS.RawVAPtr; } - - REFERENCE operator*() const { + + REFERENCE operator*() const { return (REFERENCE) (inStmt() ? *stmt : GetDeclExpr()); } - - REFERENCE operator->() const { return operator*(); } + + REFERENCE operator->() const { return operator*(); } }; struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> { explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {} StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {} - StmtIterator(Decl** dgi, Decl** dge) + StmtIterator(Decl** dgi, Decl** dge) : StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {} StmtIterator(VariableArrayType* t):StmtIteratorImpl<StmtIterator,Stmt*&>(t) {} @@ -133,10 +133,10 @@ struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> { struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator, const Stmt*> { - explicit ConstStmtIterator() : + explicit ConstStmtIterator() : StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {} - - ConstStmtIterator(const StmtIterator& RHS) : + + ConstStmtIterator(const StmtIterator& RHS) : StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {} }; diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index a95a62731186..8d7e4b5fc0a3 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -25,6 +25,10 @@ # define EXPR(Type, Base) STMT(Type, Base) #endif +#ifndef ABSTRACT_EXPR +# define ABSTRACT_EXPR(Type, Base) EXPR(Type, Base) +#endif + // Normal Statements. STMT(NullStmt , Stmt) FIRST_STMT(NullStmt) @@ -64,7 +68,7 @@ STMT(CXXTryStmt , Stmt) LAST_STMT(CXXTryStmt) // Expressions. -EXPR(Expr , Stmt) +ABSTRACT_EXPR(Expr , Stmt) FIRST_EXPR(Expr) EXPR(PredefinedExpr , Expr) EXPR(DeclRefExpr , Expr) @@ -91,6 +95,7 @@ EXPR(ExtVectorElementExpr , Expr) EXPR(InitListExpr , Expr) EXPR(DesignatedInitExpr , Expr) EXPR(ImplicitValueInitExpr , Expr) +EXPR(ParenListExpr , Expr) EXPR(VAArgExpr , Expr) // GNU Extensions. @@ -119,6 +124,7 @@ EXPR(CXXZeroInitValueExpr , Expr) EXPR(CXXConditionDeclExpr , DeclRefExpr) EXPR(CXXNewExpr , Expr) EXPR(CXXDeleteExpr , Expr) +EXPR(CXXPseudoDestructorExpr, Expr) EXPR(UnresolvedFunctionNameExpr , Expr) EXPR(UnaryTypeTraitExpr , Expr) EXPR(QualifiedDeclRefExpr , DeclRefExpr) @@ -139,8 +145,9 @@ EXPR(ObjCSelectorExpr , Expr) EXPR(ObjCProtocolExpr , Expr) EXPR(ObjCIvarRefExpr , Expr) EXPR(ObjCPropertyRefExpr , Expr) -EXPR(ObjCKVCRefExpr , Expr) +EXPR(ObjCImplicitSetterGetterRefExpr , Expr) EXPR(ObjCSuperExpr , Expr) +EXPR(ObjCIsaExpr , Expr) // Clang Extensions. EXPR(ShuffleVectorExpr , Expr) @@ -149,8 +156,9 @@ EXPR(BlockDeclRefExpr , Expr) LAST_EXPR(BlockDeclRefExpr) -#undef STMT +#undef ABSTRACT_EXPR #undef EXPR +#undef STMT #undef FIRST_STMT #undef LAST_STMT #undef FIRST_EXPR diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h index 8ae707174403..3fd8f1672deb 100644 --- a/include/clang/AST/StmtObjC.h +++ b/include/clang/AST/StmtObjC.h @@ -27,47 +27,47 @@ class ObjCForCollectionStmt : public Stmt { SourceLocation ForLoc; SourceLocation RParenLoc; public: - ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body, + ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body, SourceLocation FCL, SourceLocation RPL); - explicit ObjCForCollectionStmt(EmptyShell Empty) : + explicit ObjCForCollectionStmt(EmptyShell Empty) : Stmt(ObjCForCollectionStmtClass, Empty) { } - + Stmt *getElement() { return SubExprs[ELEM]; } - Expr *getCollection() { - return reinterpret_cast<Expr*>(SubExprs[COLLECTION]); + Expr *getCollection() { + return reinterpret_cast<Expr*>(SubExprs[COLLECTION]); } Stmt *getBody() { return SubExprs[BODY]; } - + const Stmt *getElement() const { return SubExprs[ELEM]; } - const Expr *getCollection() const { + const Expr *getCollection() const { return reinterpret_cast<Expr*>(SubExprs[COLLECTION]); } const Stmt *getBody() const { return SubExprs[BODY]; } - + void setElement(Stmt *S) { SubExprs[ELEM] = S; } - void setCollection(Expr *E) { + void setCollection(Expr *E) { SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(E); } void setBody(Stmt *S) { SubExprs[BODY] = S; } - + SourceLocation getForLoc() const { return ForLoc; } void setForLoc(SourceLocation Loc) { ForLoc = Loc; } SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } - - virtual SourceRange getSourceRange() const { - return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); + + virtual SourceRange getSourceRange() const { + return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCForCollectionStmtClass; + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCForCollectionStmtClass; } static bool classof(const ObjCForCollectionStmt *) { return true; } - + // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); -}; - +}; + /// ObjCAtCatchStmt - This represents objective-c's @catch statement. class ObjCAtCatchStmt : public Stmt { private: @@ -78,95 +78,95 @@ private: public: ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc, - ParmVarDecl *catchVarDecl, + ParmVarDecl *catchVarDecl, Stmt *atCatchStmt, Stmt *atCatchList); - explicit ObjCAtCatchStmt(EmptyShell Empty) : + 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 ObjCAtCatchStmt *getNextCatchStmt() const { return static_cast<const ObjCAtCatchStmt*>(SubExprs[NEXT_CATCH]); } - ObjCAtCatchStmt *getNextCatchStmt() { + ObjCAtCatchStmt *getNextCatchStmt() { return static_cast<ObjCAtCatchStmt*>(SubExprs[NEXT_CATCH]); } void setNextCatchStmt(Stmt *S) { SubExprs[NEXT_CATCH] = S; } - - const ParmVarDecl *getCatchParamDecl() const { - return ExceptionDecl; + + const ParmVarDecl *getCatchParamDecl() const { + return ExceptionDecl; } - ParmVarDecl *getCatchParamDecl() { - return ExceptionDecl; + ParmVarDecl *getCatchParamDecl() { + return ExceptionDecl; } void setCatchParamDecl(ParmVarDecl *D) { ExceptionDecl = D; } - + SourceLocation getAtCatchLoc() const { return AtCatchLoc; } void setAtCatchLoc(SourceLocation Loc) { AtCatchLoc = Loc; } SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } - - virtual SourceRange getSourceRange() const { - return SourceRange(AtCatchLoc, SubExprs[BODY]->getLocEnd()); + + virtual SourceRange getSourceRange() const { + return SourceRange(AtCatchLoc, SubExprs[BODY]->getLocEnd()); } bool hasEllipsis() const { return getCatchParamDecl() == 0; } - + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtCatchStmtClass; } static bool classof(const ObjCAtCatchStmt *) { return true; } - + virtual child_iterator child_begin(); virtual child_iterator child_end(); }; - -/// ObjCAtFinallyStmt - This represent objective-c's @finally Statement + +/// ObjCAtFinallyStmt - This represent objective-c's @finally Statement class ObjCAtFinallyStmt : public Stmt { Stmt *AtFinallyStmt; - SourceLocation AtFinallyLoc; + SourceLocation AtFinallyLoc; public: ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt) - : Stmt(ObjCAtFinallyStmtClass), + : Stmt(ObjCAtFinallyStmtClass), AtFinallyStmt(atFinallyStmt), AtFinallyLoc(atFinallyLoc) {} - explicit ObjCAtFinallyStmt(EmptyShell Empty) : + explicit ObjCAtFinallyStmt(EmptyShell Empty) : Stmt(ObjCAtFinallyStmtClass, Empty) { } - + const Stmt *getFinallyBody() const { return AtFinallyStmt; } Stmt *getFinallyBody() { return AtFinallyStmt; } void setFinallyBody(Stmt *S) { AtFinallyStmt = S; } - - virtual SourceRange getSourceRange() const { - return SourceRange(AtFinallyLoc, AtFinallyStmt->getLocEnd()); + + virtual SourceRange getSourceRange() const { + return SourceRange(AtFinallyLoc, AtFinallyStmt->getLocEnd()); } - + SourceLocation getAtFinallyLoc() const { return AtFinallyLoc; } void setAtFinallyLoc(SourceLocation Loc) { AtFinallyLoc = Loc; } - + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtFinallyStmtClass; } static bool classof(const ObjCAtFinallyStmt *) { return true; } - + virtual child_iterator child_begin(); virtual child_iterator child_end(); }; - -/// ObjCAtTryStmt - This represent objective-c's over-all + +/// ObjCAtTryStmt - This represent objective-c's over-all /// @try ... @catch ... @finally statement. class ObjCAtTryStmt : public Stmt { private: enum { TRY, CATCH, FINALLY, END_EXPR }; - Stmt* SubStmts[END_EXPR]; - - SourceLocation AtTryLoc; + Stmt* SubStmts[END_EXPR]; + + SourceLocation AtTryLoc; public: - ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt, - Stmt *atCatchStmt, + ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt, + Stmt *atCatchStmt, Stmt *atFinallyStmt) : Stmt(ObjCAtTryStmtClass) { SubStmts[TRY] = atTryStmt; @@ -174,41 +174,41 @@ public: SubStmts[FINALLY] = atFinallyStmt; AtTryLoc = atTryLoc; } - explicit ObjCAtTryStmt(EmptyShell Empty) : + explicit ObjCAtTryStmt(EmptyShell Empty) : Stmt(ObjCAtTryStmtClass, Empty) { } - + 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]); + + const ObjCAtCatchStmt *getCatchStmts() const { + return dyn_cast_or_null<ObjCAtCatchStmt>(SubStmts[CATCH]); } - ObjCAtCatchStmt *getCatchStmts() { - return dyn_cast_or_null<ObjCAtCatchStmt>(SubStmts[CATCH]); + ObjCAtCatchStmt *getCatchStmts() { + return dyn_cast_or_null<ObjCAtCatchStmt>(SubStmts[CATCH]); } void setCatchStmts(Stmt *S) { SubStmts[CATCH] = S; } - - const ObjCAtFinallyStmt *getFinallyStmt() const { - return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]); + + const ObjCAtFinallyStmt *getFinallyStmt() const { + return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]); } - ObjCAtFinallyStmt *getFinallyStmt() { - return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]); + ObjCAtFinallyStmt *getFinallyStmt() { + return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]); } void setFinallyStmt(Stmt *S) { SubStmts[FINALLY] = S; } - virtual SourceRange getSourceRange() const { - return SourceRange(AtTryLoc, SubStmts[TRY]->getLocEnd()); + virtual SourceRange getSourceRange() const { + return SourceRange(AtTryLoc, SubStmts[TRY]->getLocEnd()); } - + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtTryStmtClass; } static bool classof(const ObjCAtTryStmt *) { return true; } - + virtual child_iterator child_begin(); virtual child_iterator child_end(); }; @@ -223,7 +223,7 @@ private: enum { SYNC_EXPR, SYNC_BODY, END_EXPR }; Stmt* SubStmts[END_EXPR]; SourceLocation AtSynchronizedLoc; - + public: ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr, Stmt *synchBody) @@ -232,41 +232,41 @@ public: SubStmts[SYNC_BODY] = synchBody; AtSynchronizedLoc = atSynchronizedLoc; } - explicit ObjCAtSynchronizedStmt(EmptyShell Empty) : + explicit ObjCAtSynchronizedStmt(EmptyShell Empty) : Stmt(ObjCAtSynchronizedStmtClass, Empty) { } - + SourceLocation getAtSynchronizedLoc() const { return AtSynchronizedLoc; } void setAtSynchronizedLoc(SourceLocation Loc) { AtSynchronizedLoc = Loc; } - + const CompoundStmt *getSynchBody() const { return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]); } - CompoundStmt *getSynchBody() { - return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]); + CompoundStmt *getSynchBody() { + return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]); } void setSynchBody(Stmt *S) { SubStmts[SYNC_BODY] = S; } - - const Expr *getSynchExpr() const { - return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]); + + const Expr *getSynchExpr() const { + return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]); } - Expr *getSynchExpr() { - return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]); + Expr *getSynchExpr() { + return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]); } void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; } - - virtual SourceRange getSourceRange() const { - return SourceRange(AtSynchronizedLoc, getSynchBody()->getLocEnd()); + + virtual SourceRange getSourceRange() const { + return SourceRange(AtSynchronizedLoc, getSynchBody()->getLocEnd()); } - + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtSynchronizedStmtClass; } static bool classof(const ObjCAtSynchronizedStmt *) { return true; } - + virtual child_iterator child_begin(); virtual child_iterator child_end(); }; - + /// ObjCAtThrowStmt - This represents objective-c's @throw statement. class ObjCAtThrowStmt : public Stmt { Stmt *Throw; @@ -276,28 +276,28 @@ public: : Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) { AtThrowLoc = atThrowLoc; } - explicit ObjCAtThrowStmt(EmptyShell Empty) : + explicit ObjCAtThrowStmt(EmptyShell Empty) : Stmt(ObjCAtThrowStmtClass, Empty) { } - + const Expr *getThrowExpr() const { return reinterpret_cast<Expr*>(Throw); } Expr *getThrowExpr() { return reinterpret_cast<Expr*>(Throw); } void setThrowExpr(Stmt *S) { Throw = S; } - + SourceLocation getThrowLoc() { return AtThrowLoc; } void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; } - + virtual SourceRange getSourceRange() const { if (Throw) - return SourceRange(AtThrowLoc, Throw->getLocEnd()); - else + return SourceRange(AtThrowLoc, Throw->getLocEnd()); + else return SourceRange(AtThrowLoc); } - + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtThrowStmtClass; } static bool classof(const ObjCAtThrowStmt *) { return true; } - + virtual child_iterator child_begin(); virtual child_iterator child_end(); }; diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h index 4f4066ab8602..3a525507dad3 100644 --- a/include/clang/AST/StmtVisitor.h +++ b/include/clang/AST/StmtVisitor.h @@ -20,17 +20,17 @@ #include "clang/AST/StmtObjC.h" namespace clang { - + #define DISPATCH(NAME, CLASS) \ return static_cast<ImplClass*>(this)->Visit ## NAME(static_cast<CLASS*>(S)) - + /// StmtVisitor - This class implements a simple visitor for Stmt subclasses. /// Since Expr derives from Stmt, this also includes support for visiting Exprs. template<typename ImplClass, typename RetTy=void> class StmtVisitor { public: RetTy Visit(Stmt *S) { - + // If we have a binary expr, dispatch to the subcode of the binop. A smart // optimizer (e.g. LLVM) will fold this comparison into the switch stmt // below. @@ -53,7 +53,7 @@ public: case BinaryOperator::GE: DISPATCH(BinGE, BinaryOperator); case BinaryOperator::EQ: DISPATCH(BinEQ, BinaryOperator); case BinaryOperator::NE: DISPATCH(BinNE, BinaryOperator); - + case BinaryOperator::And: DISPATCH(BinAnd, BinaryOperator); case BinaryOperator::Xor: DISPATCH(BinXor, BinaryOperator); case BinaryOperator::Or : DISPATCH(BinOr, BinaryOperator); @@ -101,7 +101,7 @@ public: case UnaryOperator::OffsetOf: DISPATCH(UnaryOffsetOf, UnaryOperator); } } - + // Top switch stmt: dispatch to VisitFooStmt for each FooStmt. switch (S->getStmtClass()) { default: assert(0 && "Unknown stmt kind!"); @@ -110,7 +110,7 @@ public: #include "clang/AST/StmtNodes.def" } } - + // If the implementation chooses not to implement a certain visit method, fall // back on VisitExpr or whatever else is the superclass. #define STMT(CLASS, PARENT) \ @@ -127,7 +127,7 @@ public: BINOP_FALLBACK(Mul) BINOP_FALLBACK(Div) BINOP_FALLBACK(Rem) BINOP_FALLBACK(Add) BINOP_FALLBACK(Sub) BINOP_FALLBACK(Shl) BINOP_FALLBACK(Shr) - + BINOP_FALLBACK(LT) BINOP_FALLBACK(GT) BINOP_FALLBACK(LE) BINOP_FALLBACK(GE) BINOP_FALLBACK(EQ) BINOP_FALLBACK(NE) BINOP_FALLBACK(And) BINOP_FALLBACK(Xor) BINOP_FALLBACK(Or) @@ -148,7 +148,7 @@ public: CAO_FALLBACK(ShrAssign) CAO_FALLBACK(AndAssign) CAO_FALLBACK(OrAssign) CAO_FALLBACK(XorAssign) #undef CAO_FALLBACK - + // If the implementation doesn't implement unary operator methods, fall back // on VisitUnaryOperator. #define UNARYOP_FALLBACK(NAME) \ @@ -158,13 +158,13 @@ public: UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec) UNARYOP_FALLBACK(PreInc) UNARYOP_FALLBACK(PreDec) UNARYOP_FALLBACK(AddrOf) UNARYOP_FALLBACK(Deref) - + UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus) UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot) UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag) UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf) #undef UNARYOP_FALLBACK - + // Base case, ignore it. :) RetTy VisitStmt(Stmt *Node) { return RetTy(); } }; diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index 511934c1dbf5..66ff34cf1e31 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -26,9 +26,11 @@ namespace clang { class DependentTemplateName; class IdentifierInfo; class NestedNameSpecifier; -class PrintingPolicy; +struct PrintingPolicy; class QualifiedTemplateName; +class NamedDecl; class TemplateDecl; +class OverloadedFunctionDecl; /// \brief Represents a C++ template name within the type system. /// @@ -58,7 +60,8 @@ class TemplateDecl; /// specifier in the typedef. "apply" is a nested template, and can /// only be understood in the context of class TemplateName { - typedef llvm::PointerUnion3<TemplateDecl *, QualifiedTemplateName *, + typedef llvm::PointerUnion4<TemplateDecl *, OverloadedFunctionDecl *, + QualifiedTemplateName *, DependentTemplateName *> StorageType; StorageType Storage; @@ -70,17 +73,32 @@ class TemplateName { public: TemplateName() : Storage() { } explicit TemplateName(TemplateDecl *Template) : Storage(Template) { } + explicit TemplateName(OverloadedFunctionDecl *FunctionTemplates) + : Storage(FunctionTemplates) { } explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { } explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { } + /// \brief Determine whether this template name is NULL. + bool isNull() const { return Storage.isNull(); } + /// \brief Retrieve the the underlying template declaration that /// this template name refers to, if known. /// /// \returns The template declaration that this template name refers /// to, if any. If the template name does not refer to a specific - /// declaration because it is a dependent name, returns NULL. + /// declaration because it is a dependent name, or if it refers to a + /// set of function templates, returns NULL. TemplateDecl *getAsTemplateDecl() const; + /// \brief Retrieve the the underlying, overloaded function template + // declarations that this template name refers to, if known. + /// + /// \returns The set of overloaded function templates that this template + /// name refers to, if known. If the template name does not refer to a + /// specific set of function templates because it is a dependent name or + /// refers to a single template, returns NULL. + OverloadedFunctionDecl *getAsOverloadedFunctionDecl() const; + /// \brief Retrieve the underlying qualified template name /// structure, if any. QualifiedTemplateName *getAsQualifiedTemplateName() const { @@ -119,8 +137,8 @@ public: void *getAsVoidPointer() const { return Storage.getOpaqueValue(); } /// \brief Build a template name from a void pointer. - static TemplateName getFromVoidPointer(void *Ptr) { - return TemplateName(Ptr); + static TemplateName getFromVoidPointer(void *Ptr) { + return TemplateName(Ptr); } }; @@ -145,15 +163,21 @@ class QualifiedTemplateName : public llvm::FoldingSetNode { /// this name with DependentTemplateName). llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier; - /// \brief The template declaration that this qualified name refers - /// to. - TemplateDecl *Template; + /// \brief The template declaration or set of overloaded function templates + /// that this qualified name refers to. + NamedDecl *Template; friend class ASTContext; QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, TemplateDecl *Template) - : Qualifier(NNS, TemplateKeyword? 1 : 0), Template(Template) { } + : Qualifier(NNS, TemplateKeyword? 1 : 0), + Template(reinterpret_cast<NamedDecl *>(Template)) { } + + QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, + OverloadedFunctionDecl *Template) + : Qualifier(NNS, TemplateKeyword? 1 : 0), + Template(reinterpret_cast<NamedDecl *>(Template)) { } public: /// \brief Return the nested name specifier that qualifies this name. @@ -163,16 +187,26 @@ public: /// keyword. bool hasTemplateKeyword() const { return Qualifier.getInt(); } + /// \brief The template declaration or set of overloaded functions that + /// that qualified name refers to. + NamedDecl *getDecl() const { return Template; } + /// \brief The template declaration to which this qualified name - /// refers. - TemplateDecl *getTemplateDecl() const { return Template; } + /// refers, or NULL if this qualified name refers to a set of overloaded + /// function templates. + TemplateDecl *getTemplateDecl() const; + + /// \brief The set of overloaded function tempaltes to which this qualified + /// name refers, or NULL if this qualified name refers to a single + /// template declaration. + OverloadedFunctionDecl *getOverloadedFunctionDecl() const; void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl()); + Profile(ID, getQualifier(), hasTemplateKeyword(), getDecl()); } - static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, - bool TemplateKeyword, TemplateDecl *Template) { + static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, + bool TemplateKeyword, NamedDecl *Template) { ID.AddPointer(NNS); ID.AddBoolean(TemplateKeyword); ID.AddPointer(Template); @@ -183,7 +217,7 @@ public: /// resolved prior to template instantiation. /// /// This kind of template name refers to a dependent template name, -/// including its nested name specifier. For example, +/// including its nested name specifier (if any). For example, /// DependentTemplateName can refer to "MetaFun::template apply", /// where "MetaFun::" is the nested name specifier and "apply" is the /// template name referenced. The "template" keyword is implied. @@ -205,11 +239,11 @@ class DependentTemplateName : public llvm::FoldingSetNode { friend class ASTContext; - DependentTemplateName(NestedNameSpecifier *Qualifier, + DependentTemplateName(NestedNameSpecifier *Qualifier, const IdentifierInfo *Name) : Qualifier(Qualifier), Name(Name), CanonicalTemplateName(this) { } - DependentTemplateName(NestedNameSpecifier *Qualifier, + DependentTemplateName(NestedNameSpecifier *Qualifier, const IdentifierInfo *Name, TemplateName Canon) : Qualifier(Qualifier), Name(Name), CanonicalTemplateName(Canon) { } @@ -226,7 +260,7 @@ public: Profile(ID, getQualifier(), getName()); } - static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, + static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, const IdentifierInfo *Name) { ID.AddPointer(NNS); ID.AddPointer(Name); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index a00c0c4ff1c4..89776b91fe4a 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -19,6 +19,7 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateName.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/type_traits.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" @@ -29,7 +30,13 @@ using llvm::cast; using llvm::cast_or_null; using llvm::dyn_cast; using llvm::dyn_cast_or_null; -namespace clang { class Type; } +namespace clang { + enum { + TypeAlignmentInBits = 3, + TypeAlignment = 1 << TypeAlignmentInBits + }; + class Type; class ExtQuals; +} namespace llvm { template <typename T> @@ -41,7 +48,16 @@ namespace llvm { static inline ::clang::Type *getFromVoidPointer(void *P) { return static_cast< ::clang::Type*>(P); } - enum { NumLowBitsAvailable = 3 }; + enum { NumLowBitsAvailable = clang::TypeAlignmentInBits }; + }; + template<> + class PointerLikeTypeTraits< ::clang::ExtQuals*> { + public: + static inline void *getAsVoidPointer(::clang::ExtQuals *P) { return P; } + static inline ::clang::ExtQuals *getFromVoidPointer(void *P) { + return static_cast< ::clang::ExtQuals*>(P); + } + enum { NumLowBitsAvailable = clang::TypeAlignmentInBits }; }; } @@ -66,54 +82,359 @@ namespace clang { class StmtIteratorBase; class TemplateArgument; class QualifiedNameType; - class PrintingPolicy; + struct PrintingPolicy; // Provide forward declarations for all of the *Type classes #define TYPE(Class, Base) class Class##Type; #include "clang/AST/TypeNodes.def" -/// QualType - For efficiency, we don't store CVR-qualified types as nodes on -/// their own: instead each reference to a type stores the qualifiers. This -/// greatly reduces the number of nodes we need to allocate for types (for -/// example we only need one for 'int', 'const int', 'volatile int', -/// 'const volatile int', etc). -/// -/// As an added efficiency bonus, instead of making this a pair, we just store -/// the three bits we care about in the low bits of the pointer. To handle the -/// packing/unpacking, we make QualType be a simple wrapper class that acts like -/// a smart pointer. -class QualType { - llvm::PointerIntPair<Type*, 3> Value; +/// Qualifiers - The collection of all-type qualifiers we support. +/// Clang supports five independent qualifiers: +/// * C99: const, volatile, and restrict +/// * Embedded C (TR18037): address spaces +/// * Objective C: the GC attributes (none, weak, or strong) +class Qualifiers { public: - enum TQ { // NOTE: These flags must be kept in sync with DeclSpec::TQ. + enum TQ { // NOTE: These flags must be kept in sync with DeclSpec::TQ. Const = 0x1, Restrict = 0x2, Volatile = 0x4, - CVRFlags = Const|Restrict|Volatile + CVRMask = Const | Volatile | Restrict }; - - enum GCAttrTypes { + + enum GC { GCNone = 0, Weak, Strong }; - + + enum { + /// The maximum supported address space number. + /// 24 bits should be enough for anyone. + MaxAddressSpace = 0xffffffu, + + /// The width of the "fast" qualifier mask. + FastWidth = 2, + + /// The fast qualifier mask. + FastMask = (1 << FastWidth) - 1 + }; + + Qualifiers() : Mask(0) {} + + static Qualifiers fromFastMask(unsigned Mask) { + Qualifiers Qs; + Qs.addFastQualifiers(Mask); + return Qs; + } + + static Qualifiers fromCVRMask(unsigned CVR) { + Qualifiers Qs; + Qs.addCVRQualifiers(CVR); + return Qs; + } + + // Deserialize qualifiers from an opaque representation. + static Qualifiers fromOpaqueValue(unsigned opaque) { + Qualifiers Qs; + Qs.Mask = opaque; + return Qs; + } + + // Serialize these qualifiers into an opaque representation. + unsigned getAsOpaqueValue() const { + return Mask; + } + + bool hasConst() const { return Mask & Const; } + void setConst(bool flag) { + Mask = (Mask & ~Const) | (flag ? Const : 0); + } + void removeConst() { Mask &= ~Const; } + void addConst() { Mask |= Const; } + + bool hasVolatile() const { return Mask & Volatile; } + void setVolatile(bool flag) { + Mask = (Mask & ~Volatile) | (flag ? Volatile : 0); + } + void removeVolatile() { Mask &= ~Volatile; } + void addVolatile() { Mask |= Volatile; } + + bool hasRestrict() const { return Mask & Restrict; } + void setRestrict(bool flag) { + Mask = (Mask & ~Restrict) | (flag ? Restrict : 0); + } + void removeRestrict() { Mask &= ~Restrict; } + void addRestrict() { Mask |= Restrict; } + + bool hasCVRQualifiers() const { return getCVRQualifiers(); } + unsigned getCVRQualifiers() const { return Mask & CVRMask; } + void setCVRQualifiers(unsigned mask) { + assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits"); + Mask = (Mask & ~CVRMask) | mask; + } + void removeCVRQualifiers(unsigned mask) { + assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits"); + Mask &= ~mask; + } + void removeCVRQualifiers() { + removeCVRQualifiers(CVRMask); + } + void addCVRQualifiers(unsigned mask) { + assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits"); + Mask |= mask; + } + + bool hasObjCGCAttr() const { return Mask & GCAttrMask; } + GC getObjCGCAttr() const { return GC((Mask & GCAttrMask) >> GCAttrShift); } + void setObjCGCAttr(GC type) { + Mask = (Mask & ~GCAttrMask) | (type << GCAttrShift); + } + void removeObjCGCAttr() { setObjCGCAttr(GCNone); } + void addObjCGCAttr(GC type) { + assert(type); + setObjCGCAttr(type); + } + + bool hasAddressSpace() const { return Mask & AddressSpaceMask; } + unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; } + void setAddressSpace(unsigned space) { + assert(space <= MaxAddressSpace); + Mask = (Mask & ~AddressSpaceMask) + | (((uint32_t) space) << AddressSpaceShift); + } + void removeAddressSpace() { setAddressSpace(0); } + void addAddressSpace(unsigned space) { + assert(space); + setAddressSpace(space); + } + + // Fast qualifiers are those that can be allocated directly + // on a QualType object. + bool hasFastQualifiers() const { return getFastQualifiers(); } + unsigned getFastQualifiers() const { return Mask & FastMask; } + void setFastQualifiers(unsigned mask) { + assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits"); + Mask = (Mask & ~FastMask) | mask; + } + void removeFastQualifiers(unsigned mask) { + assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits"); + Mask &= ~mask; + } + void removeFastQualifiers() { + removeFastQualifiers(FastMask); + } + void addFastQualifiers(unsigned mask) { + assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits"); + Mask |= mask; + } + + /// hasNonFastQualifiers - Return true if the set contains any + /// qualifiers which require an ExtQuals node to be allocated. + bool hasNonFastQualifiers() const { return Mask & ~FastMask; } + Qualifiers getNonFastQualifiers() const { + Qualifiers Quals = *this; + Quals.setFastQualifiers(0); + return Quals; + } + + /// hasQualifiers - Return true if the set contains any qualifiers. + bool hasQualifiers() const { return Mask; } + bool empty() const { return !Mask; } + + /// \brief Add the qualifiers from the given set to this set. + void addQualifiers(Qualifiers Q) { + // If the other set doesn't have any non-boolean qualifiers, just + // bit-or it in. + if (!(Q.Mask & ~CVRMask)) + Mask |= Q.Mask; + else { + Mask |= (Q.Mask & CVRMask); + if (Q.hasAddressSpace()) + addAddressSpace(Q.getAddressSpace()); + if (Q.hasObjCGCAttr()) + addObjCGCAttr(Q.getObjCGCAttr()); + } + } + + bool operator==(Qualifiers Other) const { return Mask == Other.Mask; } + bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; } + + operator bool() const { return hasQualifiers(); } + + Qualifiers &operator+=(Qualifiers R) { + addQualifiers(R); + return *this; + } + + // Union two qualifier sets. If an enumerated qualifier appears + // in both sets, use the one from the right. + friend Qualifiers operator+(Qualifiers L, Qualifiers R) { + L += R; + return L; + } + + std::string getAsString() const; + std::string getAsString(const PrintingPolicy &Policy) const { + std::string Buffer; + getAsStringInternal(Buffer, Policy); + return Buffer; + } + void getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddInteger(Mask); + } + +private: + + // bits: |0 1 2|3 .. 4|5 .. 31| + // |C R V|GCAttr|AddrSpace| + uint32_t Mask; + + static const uint32_t GCAttrMask = 0x18; + static const uint32_t GCAttrShift = 3; + static const uint32_t AddressSpaceMask = ~(CVRMask | GCAttrMask); + static const uint32_t AddressSpaceShift = 5; +}; + + +/// ExtQuals - We can encode up to three bits in the low bits of a +/// type pointer, but there are many more type qualifiers that we want +/// to be able to apply to an arbitrary type. Therefore we have this +/// struct, intended to be heap-allocated and used by QualType to +/// store qualifiers. +/// +/// The current design tags the 'const' and 'restrict' qualifiers in +/// two low bits on the QualType pointer; a third bit records whether +/// the pointer is an ExtQuals node. 'const' was chosen because it is +/// orders of magnitude more common than the other two qualifiers, in +/// both library and user code. It's relatively rare to see +/// 'restrict' in user code, but many standard C headers are saturated +/// with 'restrict' declarations, so that representing them efficiently +/// is a critical goal of this representation. +class ExtQuals : public llvm::FoldingSetNode { + // NOTE: changing the fast qualifiers should be straightforward as + // long as you don't make 'const' non-fast. + // 1. Qualifiers: + // a) Modify the bitmasks (Qualifiers::TQ and DeclSpec::TQ). + // Fast qualifiers must occupy the low-order bits. + // b) Update Qualifiers::FastWidth and FastMask. + // 2. QualType: + // a) Update is{Volatile,Restrict}Qualified(), defined inline. + // b) Update remove{Volatile,Restrict}, defined near the end of + // this header. + // 3. ASTContext: + // a) Update get{Volatile,Restrict}Type. + + /// Context - the context to which this set belongs. We save this + /// here so that QualifierCollector can use it to reapply extended + /// qualifiers to an arbitrary type without requiring a context to + /// be pushed through every single API dealing with qualifiers. + ASTContext& Context; + + /// BaseType - the underlying type that this qualifies + const Type *BaseType; + + /// Quals - the immutable set of qualifiers applied by this + /// node; always contains extended qualifiers. + Qualifiers Quals; + +public: + ExtQuals(ASTContext& Context, const Type *Base, Qualifiers Quals) + : Context(Context), BaseType(Base), Quals(Quals) + { + assert(Quals.hasNonFastQualifiers() + && "ExtQuals created with no fast qualifiers"); + assert(!Quals.hasFastQualifiers() + && "ExtQuals created with fast qualifiers"); + } + + Qualifiers getQualifiers() const { return Quals; } + + bool hasVolatile() const { return Quals.hasVolatile(); } + + bool hasObjCGCAttr() const { return Quals.hasObjCGCAttr(); } + Qualifiers::GC getObjCGCAttr() const { return Quals.getObjCGCAttr(); } + + bool hasAddressSpace() const { return Quals.hasAddressSpace(); } + unsigned getAddressSpace() const { return Quals.getAddressSpace(); } + + const Type *getBaseType() const { return BaseType; } + + ASTContext &getContext() const { return Context; } + +public: + void Profile(llvm::FoldingSetNodeID &ID) const { + Profile(ID, getBaseType(), Quals); + } + static void Profile(llvm::FoldingSetNodeID &ID, + const Type *BaseType, + Qualifiers Quals) { + assert(!Quals.hasFastQualifiers() && "fast qualifiers in ExtQuals hash!"); + ID.AddPointer(BaseType); + Quals.Profile(ID); + } +}; + + +/// QualType - For efficiency, we don't store CV-qualified types as nodes on +/// their own: instead each reference to a type stores the qualifiers. This +/// greatly reduces the number of nodes we need to allocate for types (for +/// example we only need one for 'int', 'const int', 'volatile int', +/// 'const volatile int', etc). +/// +/// As an added efficiency bonus, instead of making this a pair, we +/// just store the two bits we care about in the low bits of the +/// pointer. To handle the packing/unpacking, we make QualType be a +/// simple wrapper class that acts like a smart pointer. A third bit +/// indicates whether there are extended qualifiers present, in which +/// case the pointer points to a special structure. +class QualType { + // Thankfully, these are efficiently composable. + llvm::PointerIntPair<llvm::PointerUnion<const Type*,const ExtQuals*>, + Qualifiers::FastWidth> Value; + + bool hasExtQuals() const { + return Value.getPointer().is<const ExtQuals*>(); + } + + const ExtQuals *getExtQualsUnsafe() const { + return Value.getPointer().get<const ExtQuals*>(); + } + + const Type *getTypePtrUnsafe() const { + return Value.getPointer().get<const Type*>(); + } + + friend class QualifierCollector; +public: QualType() {} - + QualType(const Type *Ptr, unsigned Quals) - : Value(const_cast<Type*>(Ptr), Quals) {} + : Value(Ptr, Quals) {} + QualType(const ExtQuals *Ptr, unsigned Quals) + : Value(Ptr, Quals) {} + + unsigned getFastQualifiers() const { return Value.getInt(); } + void setFastQualifiers(unsigned Quals) { Value.setInt(Quals); } + + /// Retrieves a pointer to the underlying (unqualified) type. + /// This should really return a const Type, but it's not worth + /// changing all the users right now. + Type *getTypePtr() const { + if (hasNonFastQualifiers()) + return const_cast<Type*>(getExtQualsUnsafe()->getBaseType()); + return const_cast<Type*>(getTypePtrUnsafe()); + } - unsigned getCVRQualifiers() const { return Value.getInt(); } - void setCVRQualifiers(unsigned Quals) { Value.setInt(Quals); } - Type *getTypePtr() const { return Value.getPointer(); } - void *getAsOpaquePtr() const { return Value.getOpaqueValue(); } static QualType getFromOpaquePtr(void *Ptr) { QualType T; T.Value.setFromOpaqueValue(Ptr); return T; } - + Type &operator*() const { return *getTypePtr(); } @@ -121,65 +442,125 @@ public: Type *operator->() const { return getTypePtr(); } - + /// isNull - Return true if this QualType doesn't point to a type yet. bool isNull() const { - return getTypePtr() == 0; + return Value.getPointer().isNull(); } bool isConstQualified() const { - return (getCVRQualifiers() & Const) ? true : false; + return (getFastQualifiers() & Qualifiers::Const); + } + bool isRestrictQualified() const { + return (getFastQualifiers() & Qualifiers::Restrict); } bool isVolatileQualified() const { - return (getCVRQualifiers() & Volatile) ? true : false; + return (hasNonFastQualifiers() && getExtQualsUnsafe()->hasVolatile()); } - bool isRestrictQualified() const { - return (getCVRQualifiers() & Restrict) ? true : false; + + // Determines whether this type has any direct qualifiers. + bool hasQualifiers() const { + return getFastQualifiers() || hasNonFastQualifiers(); + } + + bool hasNonFastQualifiers() const { + return hasExtQuals(); + } + + // Retrieves the set of qualifiers belonging to this type. + Qualifiers getQualifiers() const { + Qualifiers Quals; + if (hasNonFastQualifiers()) + Quals = getExtQualsUnsafe()->getQualifiers(); + Quals.addFastQualifiers(getFastQualifiers()); + return Quals; } - bool isConstant(ASTContext& Ctx) const; - - /// addConst/addVolatile/addRestrict - add the specified type qual to this - /// QualType. - void addConst() { Value.setInt(Value.getInt() | Const); } - void addVolatile() { Value.setInt(Value.getInt() | Volatile); } - void addRestrict() { Value.setInt(Value.getInt() | Restrict); } + // Retrieves the CVR qualifiers of this type. + unsigned getCVRQualifiers() const { + unsigned CVR = getFastQualifiers(); + if (isVolatileQualified()) CVR |= Qualifiers::Volatile; + return CVR; + } - void removeConst() { Value.setInt(Value.getInt() & ~Const); } - void removeVolatile() { Value.setInt(Value.getInt() & ~Volatile); } - void removeRestrict() { Value.setInt(Value.getInt() & ~Restrict); } + bool isConstant(ASTContext& Ctx) const { + return QualType::isConstant(*this, Ctx); + } - QualType getQualifiedType(unsigned TQs) const { - return QualType(getTypePtr(), TQs); + // Don't promise in the API that anything besides 'const' can be + // easily added. + + /// addConst - add the specified type qualifier to this QualType. + void addConst() { + addFastQualifiers(Qualifiers::Const); + } + QualType withConst() const { + return withFastQualifiers(Qualifiers::Const); } - QualType getWithAdditionalQualifiers(unsigned TQs) const { - return QualType(getTypePtr(), TQs|getCVRQualifiers()); + + void addFastQualifiers(unsigned TQs) { + assert(!(TQs & ~Qualifiers::FastMask) + && "non-fast qualifier bits set in mask!"); + Value.setInt(Value.getInt() | TQs); + } + + void removeConst(); + void removeVolatile(); + void removeRestrict(); + void removeCVRQualifiers(unsigned Mask); + + void removeFastQualifiers() { Value.setInt(0); } + void removeFastQualifiers(unsigned Mask) { + assert(!(Mask & ~Qualifiers::FastMask) && "mask has non-fast qualifiers"); + Value.setInt(Value.getInt() & ~Mask); + } + + // Creates a type with the given qualifiers in addition to any + // qualifiers already on this type. + QualType withFastQualifiers(unsigned TQs) const { + QualType T = *this; + T.addFastQualifiers(TQs); + return T; + } + + // Creates a type with exactly the given fast qualifiers, removing + // any existing fast qualifiers. + QualType withExactFastQualifiers(unsigned TQs) const { + return withoutFastQualifiers().withFastQualifiers(TQs); + } + + // Removes fast qualifiers, but leaves any extended qualifiers in place. + QualType withoutFastQualifiers() const { + QualType T = *this; + T.removeFastQualifiers(); + return T; } - QualType withConst() const { return getWithAdditionalQualifiers(Const); } - QualType withVolatile() const { return getWithAdditionalQualifiers(Volatile);} - QualType withRestrict() const { return getWithAdditionalQualifiers(Restrict);} - - QualType getUnqualifiedType() const; + QualType getUnqualifiedType() const { return QualType(getTypePtr(), 0); } + bool isMoreQualifiedThan(QualType Other) const; bool isAtLeastAsQualifiedAs(QualType Other) const; QualType getNonReferenceType() const; - + /// getDesugaredType - Return the specified type with any "sugar" removed from /// the type. This takes off typedefs, typeof's etc. If the outer level of /// the type is already concrete, it returns it unmodified. This is similar /// to getting the canonical type, but it doesn't remove *all* typedefs. For /// example, it returns "T*" as "T*", (not as "int*"), because the pointer is /// concrete. - QualType getDesugaredType(bool ForDisplay = false) const; + /// + /// Qualifiers are left in place. + QualType getDesugaredType() const { + return QualType::getDesugaredType(*this); + } /// operator==/!= - Indicate whether the specified types and qualifiers are /// identical. - bool operator==(const QualType &RHS) const { - return Value == RHS.Value; + friend bool operator==(const QualType &LHS, const QualType &RHS) { + return LHS.Value == RHS.Value; } - bool operator!=(const QualType &RHS) const { - return Value != RHS.Value; + friend bool operator!=(const QualType &LHS, const QualType &RHS) { + return LHS.Value != RHS.Value; } std::string getAsString() const; @@ -190,31 +571,40 @@ public: } void getAsStringInternal(std::string &Str, const PrintingPolicy &Policy) const; - + void dump(const char *s) const; void dump() const; - + void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddPointer(getAsOpaquePtr()); } -public: - /// getAddressSpace - Return the address space of this type. inline unsigned getAddressSpace() const; - + /// GCAttrTypesAttr - Returns gc attribute of this type. - inline QualType::GCAttrTypes getObjCGCAttr() const; + inline Qualifiers::GC getObjCGCAttr() const; /// isObjCGCWeak true when Type is objc's weak. bool isObjCGCWeak() const { - return getObjCGCAttr() == Weak; + return getObjCGCAttr() == Qualifiers::Weak; } /// isObjCGCStrong true when Type is objc's strong. bool isObjCGCStrong() const { - return getObjCGCAttr() == Strong; + return getObjCGCAttr() == Qualifiers::Strong; } + + /// getNoReturnAttr - Returns true if the type has the noreturn attribute, + /// false otherwise. + bool getNoReturnAttr() const; + +private: + // These methods are implemented in a separate translation unit; + // "static"-ize them to avoid creating temporary QualTypes in the + // caller. + static bool isConstant(QualType T, ASTContext& Ctx); + static QualType getDesugaredType(QualType T); }; } // end clang. @@ -230,7 +620,7 @@ template<> struct simplify_type<const ::clang::QualType> { }; template<> struct simplify_type< ::clang::QualType> : public simplify_type<const ::clang::QualType> {}; - + // Teach SmallPtrSet that QualType is "basically a pointer". template<> class PointerLikeTypeTraits<clang::QualType> { @@ -241,9 +631,10 @@ public: static inline clang::QualType getFromVoidPointer(void *P) { return clang::QualType::getFromOpaquePtr(P); } - // CVR qualifiers go in low bits. + // Various qualifiers go in low bits. enum { NumLowBitsAvailable = 0 }; }; + } // end namespace llvm namespace clang { @@ -281,7 +672,10 @@ public: #include "clang/AST/TypeNodes.def" TagFirst = Record, TagLast = Enum }; - + +protected: + enum { TypeClassBitSize = 6 }; + private: QualType CanonicalType; @@ -291,7 +685,7 @@ private: /// TypeClass bitfield - Enum that specifies what subclass this belongs to. /// Note that this should stay at the end of the ivars for Type so that /// subclasses can pack their bitfields into the same word. - unsigned TC : 5; + unsigned TC : TypeClassBitSize; Type(const Type&); // DO NOT IMPLEMENT. void operator=(const Type&); // DO NOT IMPLEMENT. @@ -304,15 +698,15 @@ protected: virtual ~Type() {} virtual void Destroy(ASTContext& C); friend class ASTContext; - + public: TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); } - + bool isCanonical() const { return CanonicalType.getTypePtr() == this; } - /// Types are partitioned into 3 broad categories (C99 6.2.5p1): + /// Types are partitioned into 3 broad categories (C99 6.2.5p1): /// object types, function types, and incomplete types. - + /// \brief Determines whether the type describes an object in memory. /// /// Note that this definition of object type corresponds to the C++ @@ -324,7 +718,7 @@ public: /// isIncompleteType - Return true if this is an incomplete type. /// A type that can describe objects, but which lacks information needed to /// determine its size (e.g. void, or a fwd declared struct). Clients of this - /// routine will need to determine if the size is actually required. + /// routine will need to determine if the size is actually required. bool isIncompleteType() const; /// isIncompleteOrObjectType - Return true if this is an incomplete or object @@ -339,13 +733,13 @@ public: /// isVariablyModifiedType (C99 6.7.5.2p2) - Return true for variable array /// types that have a non-constant expression. This does not include "[]". bool isVariablyModifiedType() const; - + /// Helper methods to distinguish type categories. All type predicates /// operate on the canonical type, ignoring typedefs and qualifiers. /// isSpecificBuiltinType - Test for a particular builtin type. bool isSpecificBuiltinType(unsigned K) const; - + /// isIntegerType() does *not* include complex integers (a GCC extension). /// isComplexIntegerType() can be used to test for complex integers. bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum) @@ -354,7 +748,7 @@ public: bool isCharType() const; bool isWideCharType() const; bool isIntegralType() const; - + /// Floating point categories. bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double) /// isComplexType() does *not* include complex integers (a GCC extension). @@ -368,13 +762,14 @@ public: bool isDerivedType() const; // C99 6.2.5p20 bool isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers) bool isAggregateType() const; - + // Type Predicates: Check to see if this type is structurally the specified // type, ignoring typedefs and qualifiers. bool isFunctionType() const; - bool isFunctionNoProtoType() const { return getAsFunctionNoProtoType() != 0; } - bool isFunctionProtoType() const { return getAsFunctionProtoType() != 0; } + bool isFunctionNoProtoType() const { return getAs<FunctionNoProtoType>(); } + bool isFunctionProtoType() const { return getAs<FunctionProtoType>(); } bool isPointerType() const; + bool isAnyPointerType() const; // Any C pointer or ObjC object pointer bool isBlockPointerType() const; bool isVoidPointerType() const; bool isReferenceType() const; @@ -389,21 +784,27 @@ public: bool isVariableArrayType() const; bool isDependentSizedArrayType() const; bool isRecordType() const; - bool isClassType() const; - bool isStructureType() const; + bool isClassType() const; + bool isStructureType() const; bool isUnionType() const; bool isComplexIntegerType() const; // GCC _Complex integer type. bool isVectorType() const; // GCC vector type. bool isExtVectorType() const; // Extended vector type. bool isObjCObjectPointerType() const; // Pointer to *any* ObjC object. + // FIXME: change this to 'raw' interface type, so we can used 'interface' type + // for the common case. bool isObjCInterfaceType() const; // NSString or NSString<foo> bool isObjCQualifiedInterfaceType() const; // NSString<foo> bool isObjCQualifiedIdType() const; // id<foo> + bool isObjCQualifiedClassType() const; // Class<foo> + bool isObjCIdType() const; // id + bool isObjCClassType() const; // Class + bool isObjCBuiltinType() const; // 'id' or 'Class' bool isTemplateTypeParmType() const; // C++ template type parameter bool isNullPtrType() const; // C++0x nullptr_t /// isDependentType - Whether this type is a dependent type, meaning - /// that its definition somehow depends on a template parameter + /// that its definition somehow depends on a template parameter /// (C++ [temp.dep.type]). bool isDependentType() const { return Dependent; } bool isOverloadableType() const; @@ -416,41 +817,29 @@ public: /// hasObjCPointerRepresentation - Whether this type can represent /// an objective pointer type for the purpose of GC'ability - bool hasObjCPointerRepresentation() const; + bool hasObjCPointerRepresentation() const; // Type Checking Functions: Check to see if this type is structurally the // specified type, ignoring typedefs and qualifiers, and return a pointer to // the best type we can. - const BuiltinType *getAsBuiltinType() const; - const FunctionType *getAsFunctionType() const; - const FunctionNoProtoType *getAsFunctionNoProtoType() const; - const FunctionProtoType *getAsFunctionProtoType() const; - const PointerType *getAsPointerType() const; - const BlockPointerType *getAsBlockPointerType() const; - const ReferenceType *getAsReferenceType() const; - const LValueReferenceType *getAsLValueReferenceType() const; - const RValueReferenceType *getAsRValueReferenceType() const; - const MemberPointerType *getAsMemberPointerType() const; - const TagType *getAsTagType() const; - const RecordType *getAsRecordType() const; const RecordType *getAsStructureType() const; /// NOTE: getAs*ArrayType are methods on ASTContext. - const TypedefType *getAsTypedefType() const; const RecordType *getAsUnionType() const; - const EnumType *getAsEnumType() const; - const VectorType *getAsVectorType() const; // GCC vector type. - const ComplexType *getAsComplexType() const; const ComplexType *getAsComplexIntegerType() const; // GCC complex int type. - const ExtVectorType *getAsExtVectorType() const; // Extended vector type. - const ObjCObjectPointerType *getAsObjCObjectPointerType() const; - const ObjCInterfaceType *getAsObjCInterfaceType() const; - const ObjCQualifiedInterfaceType *getAsObjCQualifiedInterfaceType() const; + // The following is a convenience method that returns an ObjCObjectPointerType + // for object declared using an interface. + const ObjCObjectPointerType *getAsObjCInterfacePointerType() const; const ObjCObjectPointerType *getAsObjCQualifiedIdType() const; - const TemplateTypeParmType *getAsTemplateTypeParmType() const; + const ObjCInterfaceType *getAsObjCQualifiedInterfaceType() const; + const CXXRecordDecl *getCXXRecordDeclForPointerType() const; + + // Member-template getAs<specific type>'. This scheme will eventually + // replace the specific getAsXXXX methods above. + // + // There are some specializations of this member template listed + // immediately following this class. + template <typename T> const T *getAs() const; - const TemplateSpecializationType * - getAsTemplateSpecializationType() const; - /// getAsPointerToObjCInterfaceType - If this is a pointer to an ObjC /// interface, return the interface type, otherwise return null. const ObjCInterfaceType *getAsPointerToObjCInterfaceType() const; @@ -459,15 +848,16 @@ public: /// element type of the array, potentially with type qualifiers missing. /// This method should never be used when type qualifiers are meaningful. const Type *getArrayElementTypeNoTypeQual() const; - - /// getDesugaredType - Return the specified type with any "sugar" removed from - /// the type. This takes off typedefs, typeof's etc. If the outer level of - /// the type is already concrete, it returns it unmodified. This is similar - /// to getting the canonical type, but it doesn't remove *all* typedefs. For - /// example, it returns "T*" as "T*", (not as "int*"), because the pointer is - /// concrete. - QualType getDesugaredType(bool ForDisplay = false) const; - + + /// getPointeeType - If this is a pointer, ObjC object pointer, or block + /// pointer, this returns the respective pointee. |