diff options
author | Ed Schouten <ed@FreeBSD.org> | 2009-06-02 17:58:47 +0000 |
---|---|---|
committer | Ed Schouten <ed@FreeBSD.org> | 2009-06-02 17:58:47 +0000 |
commit | ec2b103c267a06a66e926f62cd96767b280f5cf5 (patch) | |
tree | ce7d964cbb5e39695b71481698f10cb099c23d4a /include/clang/AST | |
download | src-ec2b103c267a06a66e926f62cd96767b280f5cf5.tar.gz src-ec2b103c267a06a66e926f62cd96767b280f5cf5.zip |
Import Clang, at r72732.vendor/clang/clang-r72732
Notes
Notes:
svn path=/vendor/clang/dist/; revision=193326
svn path=/vendor/clang/clang-r72732/; revision=193327; tag=vendor/clang/clang-r72732
Diffstat (limited to 'include/clang/AST')
41 files changed, 18988 insertions, 0 deletions
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h new file mode 100644 index 000000000000..5d5abfe011d4 --- /dev/null +++ b/include/clang/AST/APValue.h @@ -0,0 +1,253 @@ +//===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- 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 APValue class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_APVALUE_H +#define LLVM_CLANG_AST_APVALUE_H + +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/APFloat.h" + +namespace clang { + class Expr; + +/// APValue - This class implements a discriminated union of [uninitialized] +/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset]. +class APValue { + typedef llvm::APSInt APSInt; + typedef llvm::APFloat APFloat; +public: + enum ValueKind { + Uninitialized, + Int, + Float, + ComplexInt, + ComplexFloat, + LValue, + Vector + }; +private: + ValueKind Kind; + + 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; + }; + struct Vec { + APValue *Elts; + unsigned NumElts; + Vec() : Elts(0), NumElts(0) {} + ~Vec() { delete[] Elts; } + }; + + enum { + 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*)]; + +public: + APValue() : Kind(Uninitialized) {} + explicit APValue(const APSInt &I) : Kind(Uninitialized) { + MakeInt(); setInt(I); + } + explicit APValue(const APFloat &F) : Kind(Uninitialized) { + MakeFloat(); setFloat(F); + } + explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) { + MakeVector(); setVector(E, N); + } + APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) { + MakeComplexInt(); setComplexInt(R, I); + } + APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) { + MakeComplexFloat(); setComplexFloat(R, I); + } + APValue(const APValue &RHS) : Kind(Uninitialized) { + *this = RHS; + } + APValue(Expr* B, uint64_t O) : Kind(Uninitialized) { + MakeLValue(); setLValue(B, O); + } + ~APValue() { + MakeUninit(); + } + + ValueKind getKind() const { return Kind; } + bool isUninit() const { return Kind == Uninitialized; } + bool isInt() const { return Kind == Int; } + bool isFloat() const { return Kind == Float; } + bool isComplexInt() const { return Kind == ComplexInt; } + 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; + } + const APSInt &getInt() const { + return const_cast<APValue*>(this)->getInt(); + } + + APFloat &getFloat() { + assert(isFloat() && "Invalid accessor"); + return *(APFloat*)(void*)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]; + } + unsigned getVectorLength() const { + assert(isVector() && "Invalid accessor"); + return ((Vec*)(void *)Data)->NumElts; + } + + APSInt &getComplexIntReal() { + assert(isComplexInt() && "Invalid accessor"); + return ((ComplexAPSInt*)(void*)Data)->Real; + } + const APSInt &getComplexIntReal() const { + return const_cast<APValue*>(this)->getComplexIntReal(); + } + + APSInt &getComplexIntImag() { + assert(isComplexInt() && "Invalid accessor"); + return ((ComplexAPSInt*)(void*)Data)->Imag; + } + const APSInt &getComplexIntImag() const { + return const_cast<APValue*>(this)->getComplexIntImag(); + } + + APFloat &getComplexFloatReal() { + assert(isComplexFloat() && "Invalid accessor"); + return ((ComplexAPFloat*)(void*)Data)->Real; + } + const APFloat &getComplexFloatReal() const { + return const_cast<APValue*>(this)->getComplexFloatReal(); + } + + APFloat &getComplexFloatImag() { + assert(isComplexFloat() && "Invalid accessor"); + return ((ComplexAPFloat*)(void*)Data)->Imag; + } + const APFloat &getComplexFloatImag() const { + return const_cast<APValue*>(this)->getComplexFloatImag(); + } + + Expr* getLValueBase() const { + assert(isLValue() && "Invalid accessor"); + return ((const LV*)(const void*)Data)->Base; + } + uint64_t getLValueOffset() const { + assert(isLValue() && "Invalid accessor"); + return ((const LV*)(const void*)Data)->Offset; + } + + void setInt(const APSInt &I) { + assert(isInt() && "Invalid accessor"); + *(APSInt*)(void*)Data = I; + } + void setFloat(const APFloat &F) { + assert(isFloat() && "Invalid accessor"); + *(APFloat*)(void*)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; + for (unsigned i = 0; i != N; ++i) + ((Vec*)(void*)Data)->Elts[i] = E[i]; + } + void setComplexInt(const APSInt &R, const APSInt &I) { + assert(R.getBitWidth() == I.getBitWidth() && + "Invalid complex int (type mismatch)."); + assert(isComplexInt() && "Invalid accessor"); + ((ComplexAPSInt*)(void*)Data)->Real = R; + ((ComplexAPSInt*)(void*)Data)->Imag = I; + } + void setComplexFloat(const APFloat &R, const APFloat &I) { + assert(&R.getSemantics() == &I.getSemantics() && + "Invalid complex float (type mismatch)."); + assert(isComplexFloat() && "Invalid accessor"); + ((ComplexAPFloat*)(void*)Data)->Real = R; + ((ComplexAPFloat*)(void*)Data)->Imag = I; + } + void setLValue(Expr *B, uint64_t O) { + assert(isLValue() && "Invalid accessor"); + ((LV*)(void*)Data)->Base = B; + ((LV*)(void*)Data)->Offset = O; + } + + const APValue &operator=(const APValue &RHS); + +private: + void MakeUninit(); + void MakeInt() { + assert(isUninit() && "Bad state change"); + new ((void*)Data) APSInt(1); + Kind = Int; + } + void MakeFloat() { + assert(isUninit() && "Bad state change"); + new ((APFloat*)(void*)Data) APFloat(0.0); + Kind = Float; + } + void MakeVector() { + assert(isUninit() && "Bad state change"); + new ((Vec*)(void*)Data) Vec(); + Kind = Vector; + } + void MakeComplexInt() { + assert(isUninit() && "Bad state change"); + new ((ComplexAPSInt*)(void*)Data) ComplexAPSInt(); + Kind = ComplexInt; + } + void MakeComplexFloat() { + assert(isUninit() && "Bad state change"); + new ((ComplexAPFloat*)(void*)Data) ComplexAPFloat(); + Kind = ComplexFloat; + } + void MakeLValue() { + assert(isUninit() && "Bad state change"); + new ((LV*)(void*)Data) LV(); + Kind = LValue; + } +}; + +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/AST.h b/include/clang/AST/AST.h new file mode 100644 index 000000000000..164c5fbbb6e2 --- /dev/null +++ b/include/clang/AST/AST.h @@ -0,0 +1,28 @@ +//===--- AST.h - "Umbrella" header for AST library --------------*- 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 interface to the AST classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_AST_H +#define LLVM_CLANG_AST_AST_H + +// This header exports all AST interfaces. +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/Type.h" +#include "clang/AST/StmtVisitor.h" + +#endif diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h new file mode 100644 index 000000000000..6dc7e13d8f70 --- /dev/null +++ b/include/clang/AST/ASTConsumer.h @@ -0,0 +1,81 @@ +//===--- ASTConsumer.h - Abstract interface for reading ASTs ----*- 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 ASTConsumer class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ASTCONSUMER_H +#define LLVM_CLANG_AST_ASTCONSUMER_H + +namespace clang { + class ASTContext; + class DeclGroupRef; + class TagDecl; + class HandleTagDeclDefinition; + class SemaConsumer; // layering violation required for safe SemaConsumer + class VarDecl; + +/// ASTConsumer - This is an abstract interface that should be implemented by +/// clients that read ASTs. This abstraction layer allows the client to be +/// independent of the AST producer (e.g. parser vs AST dump file reader, etc). +class ASTConsumer { + /// \brief Whether this AST consumer also requires information about + /// semantic analysis. + bool SemaConsumer; + + friend class SemaConsumer; + +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) {} + + /// 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. + /// + /// The variable declaration itself will be a tentative + /// definition. If it had an incomplete array type, its type will + /// have already been changed to an array of size 1. However, the + /// declaration remains a tentative definition and has not been + /// modified by the introduction of an implicit zero initializer. + virtual void CompleteTentativeDefinition(VarDecl *D) {} + + /// PrintStats - If desired, print any statistics. + virtual void PrintStats() { + } + + // Support isa/cast/dyn_cast + static bool classof(const ASTConsumer *) { return true; } +}; + +} // end namespace clang. + +#endif diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h new file mode 100644 index 000000000000..e99e9f2b18f3 --- /dev/null +++ b/include/clang/AST/ASTContext.h @@ -0,0 +1,857 @@ +//===--- ASTContext.h - Context to hold long-lived AST nodes ----*- 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 ASTContext interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ASTCONTEXT_H +#define LLVM_CLANG_AST_ASTCONTEXT_H + +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LangOptions.h" +#include "clang/AST/Attr.h" +#include "clang/AST/Builtins.h" +#include "clang/AST/Decl.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/PrettyPrinter.h" +#include "clang/AST/TemplateName.h" +#include "clang/AST/Type.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/Allocator.h" +#include <vector> + +namespace llvm { + struct fltSemantics; +} + +namespace clang { + class FileManager; + class ASTRecordLayout; + class Expr; + class ExternalASTSource; + class IdentifierTable; + class SelectorTable; + class SourceManager; + class TargetInfo; + // Decls + class Decl; + class ObjCPropertyDecl; + class RecordDecl; + class TagDecl; + class TranslationUnitDecl; + class TypeDecl; + class TypedefDecl; + class TemplateTypeParmDecl; + class FieldDecl; + class ObjCIvarRefExpr; + class ObjCIvarDecl; + +/// 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 { + std::vector<Type*> Types; + llvm::FoldingSet<ExtQualType> ExtQualTypes; + llvm::FoldingSet<ComplexType> ComplexTypes; + llvm::FoldingSet<PointerType> PointerTypes; + llvm::FoldingSet<BlockPointerType> BlockPointerTypes; + llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes; + llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes; + llvm::FoldingSet<MemberPointerType> MemberPointerTypes; + llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes; + llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes; + std::vector<VariableArrayType*> VariableArrayTypes; + std::vector<DependentSizedArrayType*> DependentSizedArrayTypes; + llvm::FoldingSet<VectorType> VectorTypes; + llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes; + llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes; + llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes; + llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes; + llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes; + llvm::FoldingSet<TypenameType> TypenameTypes; + llvm::FoldingSet<ObjCQualifiedInterfaceType> ObjCQualifiedInterfaceTypes; + llvm::FoldingSet<ObjCQualifiedIdType> ObjCQualifiedIdTypes; + + llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; + llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; + + /// \brief The set of nested name specifiers. + /// + /// This set is managed by the NestedNameSpecifier class. + llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers; + NestedNameSpecifier *GlobalNestedNameSpecifier; + friend class NestedNameSpecifier; + + /// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts. + /// This is lazily created. This is intentionally not serialized. + llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts; + llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*> ObjCLayouts; + + 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; + + /// 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 ObjCConstantStringType; + RecordDecl *CFConstantStringTypeDecl; + + RecordDecl *ObjCFastEnumerationStateTypeDecl; + + 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; + + /// MallocAlloc/BumpAlloc - The allocator objects used to create AST objects. + bool FreeMemory; + llvm::MallocAllocator MallocAlloc; + llvm::BumpPtrAllocator BumpAlloc; +public: + TargetInfo &Target; + IdentifierTable &Idents; + SelectorTable &Selectors; + DeclarationNameTable DeclarationNames; + llvm::OwningPtr<ExternalASTSource> ExternalSource; + clang::PrintingPolicy PrintingPolicy; + + 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) { + if (FreeMemory) + MallocAlloc.Deallocate(Ptr); + } + const LangOptions& getLangOptions() const { return LangOpts; } + + FullSourceLoc getFullLoc(SourceLocation Loc) const { + return FullSourceLoc(Loc,SourceMgr); + } + + TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } + + Builtin::Context BuiltinInfo; + + // Builtin Types. + QualType VoidTy; + QualType BoolTy; + QualType CharTy; + QualType WCharTy; // [C++ 3.9.1p5], integer type in C99. + QualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty; + QualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy; + QualType UnsignedLongLongTy, UnsignedInt128Ty; + QualType FloatTy, DoubleTy, LongDoubleTy; + QualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; + QualType VoidPtrTy, NullPtrTy; + QualType OverloadTy; + QualType DependentTy; + + ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t, + IdentifierTable &idents, SelectorTable &sels, + bool FreeMemory = true, unsigned size_reserve=0, + bool InitializeBuiltins = true); + + ~ASTContext(); + + /// \brief Initialize builtins. + /// + /// Typically, this routine will be called automatically by the + /// constructor. However, in certain cases (e.g., when there is a + /// PCH file to be loaded), the constructor does not perform + /// initialization for builtins. This routine can be called to + /// perform the initialization. + void InitializeBuiltins(IdentifierTable &idents); + + /// \brief Attach an external AST source to the AST context. + /// + /// The external AST source provides the ability to load parts of + /// the abstract syntax tree as needed from some external storage, + /// e.g., a precompiled header. + void setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source); + + /// \brief Retrieve a pointer to the external AST source associated + /// with this AST context, if any. + ExternalASTSource *getExternalSource() const { return ExternalSource.get(); } + + void PrintStats() const; + const std::vector<Type*>& getTypes() const { return Types; } + + //===--------------------------------------------------------------------===// + // 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 + /// 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); + + /// 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); + + /// getBlockPointerType - Return the uniqued reference to the type for a block + /// of the specified type. + QualType getBlockPointerType(QualType T); + + /// getLValueReferenceType - Return the uniqued reference to the type for an + /// lvalue reference to the specified type. + QualType getLValueReferenceType(QualType T); + + /// getRValueReferenceType - Return the uniqued reference to the type for an + /// rvalue reference to the specified type. + QualType getRValueReferenceType(QualType T); + + /// getMemberPointerType - Return the uniqued reference to the type for a + /// member pointer to the specified type in the specified class. The class + /// is a Type because it could be a dependent name. + QualType getMemberPointerType(QualType T, const Type *Cls); + + /// getVariableArrayType - Returns a non-unique reference to the type for a + /// variable array of the specified element type. + QualType getVariableArrayType(QualType EltTy, Expr *NumElts, + ArrayType::ArraySizeModifier ASM, + unsigned EltTypeQuals); + + /// 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); + + /// getIncompleteArrayType - Returns a unique reference to the type for a + /// incomplete array of the specified element type. + QualType getIncompleteArrayType(QualType EltTy, + ArrayType::ArraySizeModifier ASM, + unsigned EltTypeQuals); + + /// getConstantArrayType - Return the unique reference to the type for a + /// constant array of the specified element type. + QualType getConstantArrayType(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); + + /// getExtVectorType - Return the unique reference to an extended vector type + /// of the specified element type and size. VectorType must be a built-in + /// type. + QualType getExtVectorType(QualType VectorType, unsigned NumElts); + + /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'. + /// + QualType getFunctionNoProtoType(QualType ResultTy); + + /// getFunctionType - Return a normal function type with a typed argument + /// list. isVariadic indicates whether the argument list includes '...'. + QualType getFunctionType(QualType ResultTy, const QualType *ArgArray, + unsigned NumArgs, bool isVariadic, + unsigned TypeQuals, bool hasExceptionSpec = false, + bool hasAnyExceptionSpec = false, + unsigned NumExs = 0, const QualType *ExArray = 0); + + /// getTypeDeclType - Return the unique reference to the type for + /// the specified type declaration. + QualType getTypeDeclType(TypeDecl *Decl, TypeDecl* PrevDecl=0); + + /// 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, + IdentifierInfo *Name = 0); + + QualType getTemplateSpecializationType(TemplateName T, + const TemplateArgument *Args, + unsigned NumArgs, + QualType Canon = QualType()); + + QualType getQualifiedNameType(NestedNameSpecifier *NNS, + QualType NamedType); + QualType getTypenameType(NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + QualType Canon = QualType()); + QualType getTypenameType(NestedNameSpecifier *NNS, + const TemplateSpecializationType *TemplateId, + QualType Canon = QualType()); + + /// getObjCQualifiedInterfaceType - Return a + /// ObjCQualifiedInterfaceType type for the given interface decl and + /// the conforming protocol list. + QualType getObjCQualifiedInterfaceType(ObjCInterfaceDecl *Decl, + ObjCProtocolDecl **ProtocolList, + unsigned NumProtocols); + + /// getObjCQualifiedIdType - Return an ObjCQualifiedIdType for a + /// given 'id' and conforming protocol list. + QualType getObjCQualifiedIdType(ObjCProtocolDecl **ProtocolList, + unsigned NumProtocols); + + + /// getTypeOfType - GCC extension. + QualType getTypeOfExprType(Expr *e); + QualType getTypeOfType(QualType t); + + /// getTagDeclType - Return the unique reference to the type for the + /// specified TagDecl (struct/union/class/enum) decl. + QualType getTagDeclType(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; + + /// getWCharType - In C++, this returns the unique wchar_t type. In C99, this + /// returns a type compatible with the type defined in <stddef.h> as defined + /// by the target. + QualType getWCharType() const { return WCharTy; } + + /// getSignedWCharType - Return the type of "signed wchar_t". + /// Used when in C++, as a GCC extension. + QualType getSignedWCharType() const; + + /// 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(); + + /// Get the structure type used to representation CFStrings, or NULL + /// if it hasn't yet been built. + QualType getRawCFConstantStringType() { + if (CFConstantStringTypeDecl) + return getTagDeclType(CFConstantStringTypeDecl); + return QualType(); + } + void setCFConstantStringType(QualType T); + + // This setter/getter represents the ObjC type for an NSConstantString. + void setObjCConstantStringInterface(ObjCInterfaceDecl *Decl); + 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() { + if (ObjCFastEnumerationStateTypeDecl) + return getTagDeclType(ObjCFastEnumerationStateTypeDecl); + return QualType(); + } + + void setObjCFastEnumerationStateType(QualType T); + + /// 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, + const FieldDecl *Field=0); + + void getLegacyIntegralTypeEncoding(QualType &t) const; + + // Put the string version of type qualifiers into S. + 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, + const Decl *Container, + std::string &S); + + /// 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; } + 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; } + void setObjCClassType(QualType T); + + void setBuiltinVaListType(QualType T); + QualType getBuiltinVaListType() const { return BuiltinVaListType; } + + QualType getFixedWidthIntType(unsigned Width, bool Signed); + + TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, + bool TemplateKeyword, + TemplateDecl *Template); + + TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, + const IdentifierInfo *Name); + +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; + + /// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's + /// garbage collection attribute. + /// + QualType::GCAttrTypes 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) { + return getTypeInfo(T).first; + } + 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) { + return getTypeInfo(T).second; + } + 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); + + /// getASTObjCImplementationLayout - Get or compute information about + /// the layout of the specified Objective-C implementation. This may + /// differ from the interface if synthesized ivars are present. + const ASTRecordLayout & + getASTObjCImplementationLayout(const ObjCImplementationDecl *D); + + void CollectObjCIvars(const ObjCInterfaceDecl *OI, + llvm::SmallVectorImpl<FieldDecl*> &Fields); + + void CollectSynthesizedIvars(const ObjCInterfaceDecl *OI, + llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + void CollectProtocolSynthesizedIvars(const ObjCProtocolDecl *PD, + llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + + //===--------------------------------------------------------------------===// + // 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); + const Type *getCanonicalType(const Type *T) { + return T->getCanonicalTypeInternal().getTypePtr(); + } + + /// \brief Determine whether the given types are equivalent. + 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) { + T1 = getCanonicalType(T1); + T2 = getCanonicalType(T2); + 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" nested name specifier for a + /// given nested name specifier. + /// + /// The canonical nested name specifier is a nested name specifier + /// that uniquely identifies a type or namespace within the type + /// system. For example, given: + /// + /// \code + /// namespace N { + /// struct S { + /// template<typename T> struct X { typename T* type; }; + /// }; + /// } + /// + /// template<typename T> struct Y { + /// typename N::S::X<T>::type member; + /// }; + /// \endcode + /// + /// Here, the nested-name-specifier for N::S::X<T>:: will be + /// S::X<template-param-0-0>, since 'S' and 'X' are uniquely defined + /// by declarations in the type system and the canonical type for + /// the template type parameter 'T' is template-param-0-0. + NestedNameSpecifier * + getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS); + + /// \brief Retrieves the "canonical" template name that refers to a + /// given template. + /// + /// The canonical template name is the simplest expression that can + /// be used to refer to a given template. For most templates, this + /// expression is just the template declaration itself. For example, + /// the template std::vector can be referred to via a variety of + /// names---std::vector, ::std::vector, vector (if vector is in + /// scope), etc.---but all of these names map down to the same + /// TemplateDecl, which is used to form the canonical template name. + /// + /// Dependent template names are more interesting. Here, the + /// template name could be something like T::template apply or + /// std::allocator<T>::template rebind, where the nested name + /// specifier itself is dependent. In this case, the canonical + /// template name uses the shortest form of the dependent + /// nested-name-specifier, which itself contains all canonical + /// types, values, and templates. + TemplateName getCanonicalTemplateName(TemplateName Name); + + /// 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 + /// canonicalization, e.g. to move type qualifiers into the element type. + const ArrayType *getAsArrayType(QualType T); + const ConstantArrayType *getAsConstantArrayType(QualType T) { + return dyn_cast_or_null<ConstantArrayType>(getAsArrayType(T)); + } + const VariableArrayType *getAsVariableArrayType(QualType T) { + return dyn_cast_or_null<VariableArrayType>(getAsArrayType(T)); + } + const IncompleteArrayType *getAsIncompleteArrayType(QualType T) { + 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); + + /// 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, + /// this returns a pointer to a properly qualified element of the array. + /// + /// See C99 6.7.5.3p7 and C99 6.3.2.1p3. + QualType getArrayDecayedType(QualType T); + + /// 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. + 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. + int getFloatingTypeOrder(QualType LHS, QualType RHS); + + /// 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 typeDomain) const; + +private: + // Helper for integer ordering + unsigned getIntegerRank(Type* T); + +public: + + //===--------------------------------------------------------------------===// + // Type Compatibility Predicates + //===--------------------------------------------------------------------===// + + /// Compatibility predicates used to check assignment expressions. + bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1 + bool typesAreBlockCompatible(QualType lhs, QualType rhs); + + 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; + } + 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; + } + bool isObjCSelType(QualType T) const { + assert(SelStructType && "isObjCSelType used before 'SEL' type is built"); + return T->getAsStructureType() == SelStructType; + } + + // Check the safety of assignment from LHS to RHS + bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS, + const ObjCInterfaceType *RHS); + bool areComparableObjCPointerTypes(QualType LHS, QualType RHS); + + // Functions for calculating composite types + QualType mergeTypes(QualType, QualType); + QualType mergeFunctionTypes(QualType, QualType); + + //===--------------------------------------------------------------------===// + // Integer Predicates + //===--------------------------------------------------------------------===// + + // The width of an integer, as defined in C99 6.2.6.2. This is the number + // of bits in an integer type excluding any padding bits. + unsigned getIntWidth(QualType T); + + // Per C99 6.2.5p6, for every signed integer type, there is a corresponding + // unsigned integer type. This method takes a signed type, and returns the + // corresponding unsigned integer type. + QualType getCorrespondingUnsignedType(QualType T); + + //===--------------------------------------------------------------------===// + // 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(); } + + //===--------------------------------------------------------------------===// + // Integer Values + //===--------------------------------------------------------------------===// + + /// MakeIntValue - Make an APSInt of the appropriate width and + /// signedness for the given \arg Value and integer \arg Type. + llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) { + llvm::APSInt Res(getIntWidth(Type), !Type->isSignedIntegerType()); + Res = Value; + return Res; + } + +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, + bool ExpandPointedToStructures, + bool ExpandStructures, + const FieldDecl *Field, + bool OutermostType = false, + bool EncodingProperty = false); + + const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D, + const ObjCImplementationDecl *Impl); +}; + +} // end namespace clang + +// operator new and delete aren't allowed inside namespaces. +// The throw specifications are mandated by the standard. +/// @brief Placement new for using the ASTContext's allocator. +/// +/// This placement form of operator new uses the ASTContext's allocator for +/// obtaining memory. It is a non-throwing new, which means that it returns +/// null on error. (If that is what the allocator does. The current does, so if +/// this ever changes, this operator will have to be changed, too.) +/// Usage looks like this (assuming there's an ASTContext 'Context' in scope): +/// @code +/// // Default alignment (16) +/// IntegerLiteral *Ex = new (Context) IntegerLiteral(arguments); +/// // Specific alignment +/// IntegerLiteral *Ex2 = new (Context, 8) IntegerLiteral(arguments); +/// @endcode +/// Please note that you cannot use delete on the pointer; it must be +/// deallocated using an explicit destructor call followed by +/// @c Context.Deallocate(Ptr). +/// +/// @param Bytes The number of bytes to allocate. Calculated by the compiler. +/// @param C The ASTContext that provides the allocator. +/// @param Alignment The alignment of the allocated memory (if the underlying +/// allocator supports it). +/// @return The allocated memory. Could be NULL. +inline void *operator new(size_t Bytes, clang::ASTContext &C, + size_t Alignment) throw () { + return C.Allocate(Bytes, Alignment); +} +/// @brief Placement delete companion to the new above. +/// +/// This operator is just a companion to the new above. There is no way of +/// invoking it directly; see the new operator for more details. This operator +/// is called implicitly by the compiler if a placement new expression using +/// the ASTContext throws in the object constructor. +inline void operator delete(void *Ptr, clang::ASTContext &C, size_t) + throw () { + C.Deallocate(Ptr); +} + +/// This placement form of operator new[] uses the ASTContext's allocator for +/// obtaining memory. It is a non-throwing new[], which means that it returns +/// null on error. +/// Usage looks like this (assuming there's an ASTContext 'Context' in scope): +/// @code +/// // Default alignment (16) +/// char *data = new (Context) char[10]; +/// // Specific alignment +/// char *data = new (Context, 8) char[10]; +/// @endcode +/// Please note that you cannot use delete on the pointer; it must be +/// deallocated using an explicit destructor call followed by +/// @c Context.Deallocate(Ptr). +/// +/// @param Bytes The number of bytes to allocate. Calculated by the compiler. +/// @param C The ASTContext that provides the allocator. +/// @param Alignment The alignment of the allocated memory (if the underlying +/// allocator supports it). +/// @return The allocated memory. Could be NULL. +inline void *operator new[](size_t Bytes, clang::ASTContext& C, + size_t Alignment = 16) throw () { + return C.Allocate(Bytes, Alignment); +} + +/// @brief Placement delete[] companion to the new[] above. +/// +/// This operator is just a companion to the new[] above. There is no way of +/// invoking it directly; see the new[] operator for more details. This operator +/// is called implicitly by the compiler if a placement new[] expression using +/// the ASTContext throws in the object constructor. +inline void operator delete[](void *Ptr, clang::ASTContext &C) throw () { + C.Deallocate(Ptr); +} + +#endif diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h new file mode 100644 index 000000000000..244ca9e10f3a --- /dev/null +++ b/include/clang/AST/ASTDiagnostic.h @@ -0,0 +1,27 @@ +//===--- DiagnosticAST.h - Diagnostics for the AST library ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_DIAGNOSTICAST_H +#define LLVM_CLANG_DIAGNOSTICAST_H + +#include "clang/Basic/Diagnostic.h" + +namespace clang { + namespace diag { + enum { +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM, +#define ASTSTART +#include "clang/Basic/DiagnosticASTKinds.inc" +#undef DIAG + NUM_BUILTIN_AST_DIAGNOSTICS + }; + } // end namespace diag +} // end namespace clang + +#endif diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h new file mode 100644 index 000000000000..0427f0003a3a --- /dev/null +++ b/include/clang/AST/Attr.h @@ -0,0 +1,506 @@ +//===--- Attr.h - Classes for representing expressions ----------*- 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 Attr interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ATTR_H +#define LLVM_CLANG_AST_ATTR_H + +#include <cassert> +#include <cstring> +#include <string> +#include <algorithm> + +namespace clang { + class ASTContext; +} + + +// Defined in ASTContext.cpp +void *operator new(size_t Bytes, clang::ASTContext &C, + size_t Alignment = 16) throw (); + +namespace clang { + +/// Attr - This represents one attribute. +class Attr { +public: + enum Kind { + Alias, + Aligned, + AlwaysInline, + AnalyzerNoReturn, // Clang-specific. + Annotate, + AsmLabel, // Represent GCC asm label extension. + Blocks, + Cleanup, + Const, + Constructor, + DLLExport, + DLLImport, + Deprecated, + Destructor, + FastCall, + Format, + FormatArg, + GNUInline, + IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict with + NoReturn, + NoThrow, + Nodebug, + Noinline, + NonNull, + ObjCException, + ObjCNSObject, + CFReturnsRetained, // Clang/Checker-specific. + NSReturnsRetained, // Clang/Checker-specific. + Overloadable, // Clang-specific + Packed, + Pure, + Regparm, + Section, + Sentinel, + StdCall, + TransparentUnion, + Unavailable, + Unused, + Used, + Visibility, + WarnUnusedResult, + Weak, + WeakImport + }; + +private: + Attr *Next; + Kind AttrKind; + bool Inherited : 1; + +protected: + void* operator new(size_t bytes) throw() { + assert(0 && "Attrs cannot be allocated with regular 'new'."); + return 0; + } + 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; } + + Kind getKind() const { return AttrKind; } + + Attr *getNext() { return Next; } + const Attr *getNext() const { return Next; } + void setNext(Attr *next) { Next = next; } + + 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; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *) { return true; } +}; + +#define DEF_SIMPLE_ATTR(ATTR) \ +class ATTR##Attr : public Attr { \ +public: \ + ATTR##Attr() : Attr(ATTR) {} \ + virtual Attr *clone(ASTContext &C) const { return ::new (C) ATTR##Attr; }\ + static bool classof(const Attr *A) { return A->getKind() == ATTR; } \ + static bool classof(const ATTR##Attr *A) { return true; } \ +} + +class PackedAttr : public Attr { + unsigned Alignment; + +public: + PackedAttr(unsigned alignment) : Attr(Packed), Alignment(alignment) {} + + /// getAlignment - The specified alignment in bits. + unsigned getAlignment() const { return Alignment; } + + virtual Attr* clone(ASTContext &C) const { + return ::new (C) PackedAttr(Alignment); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == Packed; + } + static bool classof(const PackedAttr *A) { return true; } +}; + +class AlignedAttr : public Attr { + unsigned Alignment; +public: + AlignedAttr(unsigned alignment) : Attr(Aligned), Alignment(alignment) {} + + /// 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; + } + static bool classof(const AlignedAttr *A) { return true; } +}; + +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; + } + static bool classof(const AnnotateAttr *A) { return true; } +}; + +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; + } + static bool classof(const AsmLabelAttr *A) { return true; } +}; + +DEF_SIMPLE_ATTR(AlwaysInline); + +class AliasAttr : public Attr { + std::string Aliasee; +public: + AliasAttr(const std::string &aliasee) : Attr(Alias), Aliasee(aliasee) {} + + const std::string& getAliasee() const { return Aliasee; } + + virtual Attr *clone(ASTContext &C) const { return ::new (C) AliasAttr(Aliasee); } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Alias; } + static bool classof(const AliasAttr *A) { return true; } +}; + +class ConstructorAttr : public Attr { + int priority; +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 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 DestructorAttr *A) { return true; } +}; + +class GNUInlineAttr : public Attr { +public: + GNUInlineAttr() : Attr(GNUInline) {} + + virtual Attr *clone(ASTContext &C) const { return ::new (C) GNUInlineAttr; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == GNUInline; + } + static bool classof(const GNUInlineAttr *A) { return true; } +}; + +class IBOutletAttr : public Attr { +public: + IBOutletAttr() : Attr(IBOutletKind) {} + + virtual Attr *clone(ASTContext &C) const { return ::new (C) IBOutletAttr; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == IBOutletKind; + } + static bool classof(const IBOutletAttr *A) { return true; } +}; + +DEF_SIMPLE_ATTR(NoReturn); +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); } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == Section; + } + static bool classof(const SectionAttr *A) { return true; } +}; + +DEF_SIMPLE_ATTR(Unavailable); +DEF_SIMPLE_ATTR(Unused); +DEF_SIMPLE_ATTR(Used); +DEF_SIMPLE_ATTR(Weak); +DEF_SIMPLE_ATTR(WeakImport); +DEF_SIMPLE_ATTR(NoThrow); +DEF_SIMPLE_ATTR(Const); +DEF_SIMPLE_ATTR(Pure); + +class NonNullAttr : public Attr { + unsigned* ArgNums; + unsigned Size; +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; + } + + typedef const unsigned *iterator; + iterator begin() const { return ArgNums; } + iterator end() const { return ArgNums + Size; } + unsigned size() const { return Size; } + + bool isNonNull(unsigned arg) const { + return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true; + } + + virtual Attr *clone(ASTContext &C) const { return ::new (C) NonNullAttr(ArgNums, Size); } + + static bool classof(const Attr *A) { return A->getKind() == NonNull; } + static bool classof(const NonNullAttr *A) { return true; } +}; + +class FormatAttr : public Attr { + std::string Type; + int formatIdx, firstArg; +public: + FormatAttr(const std::string &type, int idx, int first) : Attr(Format), + Type(type), formatIdx(idx), firstArg(first) {} + + const std::string& getType() const { return Type; } + void setType(const std::string &type) { Type = type; } + int getFormatIdx() const { return formatIdx; } + int getFirstArg() const { return firstArg; } + + virtual Attr *clone(ASTContext &C) const { + return ::new (C) FormatAttr(Type, formatIdx, firstArg); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Format; } + static bool classof(const FormatAttr *A) { return true; } +}; + +class FormatArgAttr : public Attr { + int formatIdx; +public: + FormatArgAttr(int idx) : Attr(FormatArg), formatIdx(idx) {} + int getFormatIdx() const { return formatIdx; } + + virtual Attr *clone(ASTContext &C) const { + return ::new (C) FormatArgAttr(formatIdx); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == FormatArg; } + static bool classof(const FormatArgAttr *A) { return true; } +}; + +class SentinelAttr : public Attr { + int sentinel, NullPos; +public: + SentinelAttr(int sentinel_val, int nullPos) : Attr(Sentinel), + sentinel(sentinel_val), NullPos(nullPos) {} + int getSentinel() const { return sentinel; } + int getNullPos() const { return NullPos; } + + virtual Attr *clone(ASTContext &C) const { + return ::new (C) SentinelAttr(sentinel, NullPos); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Sentinel; } + static bool classof(const SentinelAttr *A) { return true; } +}; + +class VisibilityAttr : public Attr { +public: + /// @brief An enumeration for the kinds of visibility of symbols. + enum VisibilityTypes { + DefaultVisibility = 0, + HiddenVisibility, + ProtectedVisibility + }; +private: + VisibilityTypes VisibilityType; +public: + VisibilityAttr(VisibilityTypes v) : Attr(Visibility), + VisibilityType(v) {} + + VisibilityTypes getVisibility() const { return VisibilityType; } + + virtual Attr *clone(ASTContext &C) const { return ::new (C) VisibilityAttr(VisibilityType); } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Visibility; } + static bool classof(const VisibilityAttr *A) { return true; } +}; + +DEF_SIMPLE_ATTR(DLLImport); +DEF_SIMPLE_ATTR(DLLExport); +DEF_SIMPLE_ATTR(FastCall); +DEF_SIMPLE_ATTR(StdCall); +DEF_SIMPLE_ATTR(TransparentUnion); +DEF_SIMPLE_ATTR(ObjCNSObject); +DEF_SIMPLE_ATTR(ObjCException); + +class OverloadableAttr : public Attr { +public: + OverloadableAttr() : Attr(Overloadable) { } + + virtual bool isMerged() const { return false; } + + virtual Attr *clone(ASTContext &C) const { + return ::new (C) OverloadableAttr; + } + + static bool classof(const Attr *A) { return A->getKind() == Overloadable; } + static bool classof(const OverloadableAttr *) { return true; } +}; + +class BlocksAttr : public Attr { +public: + enum BlocksAttrTypes { + ByRef = 0 + }; +private: + BlocksAttrTypes BlocksAttrType; +public: + BlocksAttr(BlocksAttrTypes t) : Attr(Blocks), BlocksAttrType(t) {} + + BlocksAttrTypes getType() const { return BlocksAttrType; } + + virtual Attr *clone(ASTContext &C) const { return ::new (C) BlocksAttr(BlocksAttrType); } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Blocks; } + static bool classof(const BlocksAttr *A) { return true; } +}; + +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. + static bool classof(const Attr *A) { return A->getKind() == Cleanup; } + static bool classof(const CleanupAttr *A) { return true; } +}; + +DEF_SIMPLE_ATTR(Nodebug); +DEF_SIMPLE_ATTR(WarnUnusedResult); +DEF_SIMPLE_ATTR(Noinline); + +class RegparmAttr : public Attr { + unsigned NumParams; + +public: + RegparmAttr(unsigned np) : Attr(Regparm), NumParams(np) {} + + unsigned getNumParams() const { return NumParams; } + + virtual Attr *clone(ASTContext &C) const { + return ::new (C) RegparmAttr(NumParams); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Regparm; } + static bool classof(const RegparmAttr *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/Builtins.def b/include/clang/AST/Builtins.def new file mode 100644 index 000000000000..671c4bd6cd4a --- /dev/null +++ b/include/clang/AST/Builtins.def @@ -0,0 +1,389 @@ +//===--- Builtins.def - Builtin function info database ----------*- 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 standard builtin function database. Users of this file +// must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// FIXME: this needs to be the full list supported by GCC. Right now, I'm just +// adding stuff on demand. +// +// FIXME: This should really be a .td file, but that requires modifying tblgen. +// Perhaps tblgen should have plugins. + +// The first value provided to the macro specifies the function name of the +// builtin, and results in a clang::builtin::BIXX enum value for XX. + +// The second value provided to the macro specifies the type of the function +// (result value, then each argument) as follows: +// v -> void +// b -> boolean +// c -> char +// s -> short +// i -> int +// f -> float +// d -> double +// z -> size_t +// F -> constant CFString +// a -> __builtin_va_list +// A -> "reference" to __builtin_va_list +// V -> Vector, following num elements and a base type. +// P -> FILE +// . -> "...". This may only occur at the end of the function list. +// +// Types maybe prefixed with the following modifiers: +// L -> long (e.g. Li for 'long int') +// LL -> long long +// LLL -> __int128_t (e.g. LLLi) +// S -> signed +// U -> unsigned +// +// Types may be postfixed with the following modifiers: +// * -> pointer +// & -> reference +// C -> const + +// The third value provided to the macro specifies information about attributes +// of the function. These must be kept in sync with the predicates in the +// Builtin::Context class. Currently we have: +// n -> nothrow +// c -> const +// F -> this is a libc/libm function with a '__builtin_' prefix added. +// f -> this is a libc/libm function without the '__builtin_' prefix. It can +// be followed by ':headername:' to state which header this function +// comes from. +// p:N: -> this is a printf-like function whose Nth argument is the format +// string. +// P:N: -> similar to the p:N: attribute, but the function is like vprintf +// in that it accepts its arguments as a va_list rather than +// through an ellipsis +// e -> const, but only when -fmath-errno=0 +// FIXME: gcc has nonnull + +#if defined(BUILTIN) && !defined(LIBBUILTIN) +# define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) BUILTIN(ID, TYPE, ATTRS) +#endif + +// Standard libc/libm functions: +BUILTIN(__builtin_huge_val, "d", "nc") +BUILTIN(__builtin_huge_valf, "f", "nc") +BUILTIN(__builtin_huge_vall, "Ld", "nc") +BUILTIN(__builtin_inf , "d" , "nc") +BUILTIN(__builtin_inff , "f" , "nc") +BUILTIN(__builtin_infl , "Ld" , "nc") +BUILTIN(__builtin_nan, "dcC*" , "ncF") +BUILTIN(__builtin_nanf, "fcC*" , "ncF") +BUILTIN(__builtin_nanl, "LdcC*", "ncF") +BUILTIN(__builtin_nans, "dcC*" , "ncF") +BUILTIN(__builtin_nansf, "fcC*" , "ncF") +BUILTIN(__builtin_nansl, "LdcC*", "ncF") +BUILTIN(__builtin_abs , "ii" , "ncF") +BUILTIN(__builtin_fabs , "dd" , "ncF") +BUILTIN(__builtin_fabsf, "ff" , "ncF") +BUILTIN(__builtin_fabsl, "LdLd", "ncF") +BUILTIN(__builtin_copysign, "ddd", "ncF") +BUILTIN(__builtin_copysignf, "fff", "ncF") +BUILTIN(__builtin_copysignl, "LdLdLd", "ncF") +BUILTIN(__builtin_powi , "ddi" , "nc") +BUILTIN(__builtin_powif, "ffi" , "nc") +BUILTIN(__builtin_powil, "LdLdi", "nc") + +// FP Comparisons. +BUILTIN(__builtin_isgreater , "i.", "nc") +BUILTIN(__builtin_isgreaterequal, "i.", "nc") +BUILTIN(__builtin_isless , "i.", "nc") +BUILTIN(__builtin_islessequal , "i.", "nc") +BUILTIN(__builtin_islessgreater , "i.", "nc") +BUILTIN(__builtin_isunordered , "i.", "nc") + +// Builtins for arithmetic. +BUILTIN(__builtin_clz , "iUi" , "nc") +BUILTIN(__builtin_clzl , "iULi" , "nc") +BUILTIN(__builtin_clzll, "iULLi", "nc") +// TODO: int clzimax(uintmax_t) +BUILTIN(__builtin_ctz , "iUi" , "nc") +BUILTIN(__builtin_ctzl , "iULi" , "nc") +BUILTIN(__builtin_ctzll, "iULLi", "nc") +// TODO: int ctzimax(uintmax_t) +BUILTIN(__builtin_ffs , "iUi" , "nc") +BUILTIN(__builtin_ffsl , "iULi" , "nc") +BUILTIN(__builtin_ffsll, "iULLi", "nc") +BUILTIN(__builtin_parity , "iUi" , "nc") +BUILTIN(__builtin_parityl , "iULi" , "nc") +BUILTIN(__builtin_parityll, "iULLi", "nc") +BUILTIN(__builtin_popcount , "iUi" , "nc") +BUILTIN(__builtin_popcountl , "iULi" , "nc") +BUILTIN(__builtin_popcountll, "iULLi", "nc") + +// FIXME: These type signatures are not correct for targets with int != 32-bits +// or with ULL != 64-bits. +BUILTIN(__builtin_bswap32, "UiUi", "nc") +BUILTIN(__builtin_bswap64, "ULLiULLi", "nc") + +// Random GCC builtins +BUILTIN(__builtin_constant_p, "Us.", "nc") +BUILTIN(__builtin_classify_type, "i.", "nc") +BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc") +BUILTIN(__builtin_va_start, "vA.", "n") +BUILTIN(__builtin_va_end, "vA", "n") +BUILTIN(__builtin_va_copy, "vAA", "n") +BUILTIN(__builtin_stdarg_start, "vA.", "n") +BUILTIN(__builtin_bcmp, "iv*v*z", "n") +BUILTIN(__builtin_bcopy, "vv*v*z", "n") +BUILTIN(__builtin_bzero, "vv*z", "n") +BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF") +BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF") +BUILTIN(__builtin_memmove, "v*v*vC*z", "nF") +BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF") +BUILTIN(__builtin_memset, "v*v*iz", "nF") +BUILTIN(__builtin_stpcpy, "c*c*cC*", "nF") +BUILTIN(__builtin_stpncpy, "c*c*cC*z", "nF") +BUILTIN(__builtin_strcasecmp, "icC*cC*", "nF") +BUILTIN(__builtin_strcat, "c*c*cC*", "nF") +BUILTIN(__builtin_strchr, "c*cC*i", "nF") +BUILTIN(__builtin_strcmp, "icC*cC*", "nF") +BUILTIN(__builtin_strcpy, "c*c*cC*", "nF") +BUILTIN(__builtin_strcspn, "zcC*cC*", "nF") +BUILTIN(__builtin_strdup, "c*cC*", "nF") +BUILTIN(__builtin_strlen, "zcC*", "nF") +BUILTIN(__builtin_strncasecmp, "icC*cC*z", "nF") +BUILTIN(__builtin_strncat, "c*c*cC*z", "nF") +BUILTIN(__builtin_strncmp, "icC*cC*z", "nF") +BUILTIN(__builtin_strncpy, "c*c*cC*z", "nF") +BUILTIN(__builtin_strndup, "c*cC*z", "nF") +BUILTIN(__builtin_strpbrk, "c*cC*cC*", "nF") +BUILTIN(__builtin_strrchr, "c*cC*i", "nF") +BUILTIN(__builtin_strspn, "zcC*cC*", "nF") +BUILTIN(__builtin_strstr, "c*cC*cC*", "nF") +BUILTIN(__builtin_return_address, "v*Ui", "n") +BUILTIN(__builtin_extract_return_addr, "v*v*", "n") +BUILTIN(__builtin_frame_address, "v*Ui", "n") +BUILTIN(__builtin_flt_rounds, "i", "nc") +BUILTIN(__builtin_setjmp, "iv**", "") +BUILTIN(__builtin_longjmp, "vv**i", "") +BUILTIN(__builtin_unwind_init, "v", "") + +// GCC Object size checking builtins +BUILTIN(__builtin_object_size, "zv*i", "n") +BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "nF") +BUILTIN(__builtin___memmove_chk, "v*v*vC*zz", "nF") +BUILTIN(__builtin___mempcpy_chk, "v*v*vC*zz", "nF") +BUILTIN(__builtin___memset_chk, "v*v*izz", "nF") +BUILTIN(__builtin___stpcpy_chk, "c*c*cC*z", "nF") +BUILTIN(__builtin___strcat_chk, "c*c*cC*z", "nF") +BUILTIN(__builtin___strcpy_chk, "c*c*cC*z", "nF") +BUILTIN(__builtin___strncat_chk, "c*c*cC*zz", "nF") +BUILTIN(__builtin___strncpy_chk, "c*c*cC*zz", "nF") +BUILTIN(__builtin___snprintf_chk, "ic*zizcC*.", "Fp:4:") +BUILTIN(__builtin___sprintf_chk, "ic*izcC*.", "Fp:3:") +BUILTIN(__builtin___vsnprintf_chk, "ic*zizcC*a", "FP:4:") +BUILTIN(__builtin___vsprintf_chk, "ic*izcC*a", "FP:3:") +BUILTIN(__builtin___fprintf_chk, "iP*icC*.", "Fp:2:") +BUILTIN(__builtin___printf_chk, "iicC*.", "Fp:1:") +BUILTIN(__builtin___vfprintf_chk, "iP*icC*a", "FP:2:") +BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:") + +BUILTIN(__builtin_expect, "iii" , "nc") +BUILTIN(__builtin_prefetch, "vvC*.", "nc") +BUILTIN(__builtin_trap, "v", "n") + +BUILTIN(__builtin_shufflevector, "v." , "nc") + +BUILTIN(__builtin_alloca, "v*z" , "n") + +// "Overloaded" Atomic operator builtins. These are overloaded to support data +// types of i8, i16, i32, i64, and i128. The front-end sees calls to the +// non-suffixed version of these (which has a bogus type) and transforms them to +// the right overloaded version in Sema (plus casts). + +// FIXME: These assume that char -> i8, short -> i16, int -> i32, +// long long -> i64. + +BUILTIN(__sync_fetch_and_add, "v.", "") +BUILTIN(__sync_fetch_and_add_1, "cc*c.", "n") +BUILTIN(__sync_fetch_and_add_2, "ss*s.", "n") +BUILTIN(__sync_fetch_and_add_4, "ii*i.", "n") +BUILTIN(__sync_fetch_and_add_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_fetch_and_add_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_fetch_and_sub, "v.", "") +BUILTIN(__sync_fetch_and_sub_1, "cc*c.", "n") +BUILTIN(__sync_fetch_and_sub_2, "ss*s.", "n") +BUILTIN(__sync_fetch_and_sub_4, "ii*i.", "n") +BUILTIN(__sync_fetch_and_sub_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_fetch_and_or, "v.", "") +BUILTIN(__sync_fetch_and_or_1, "cc*c.", "n") +BUILTIN(__sync_fetch_and_or_2, "ss*s.", "n") +BUILTIN(__sync_fetch_and_or_4, "ii*i.", "n") +BUILTIN(__sync_fetch_and_or_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_fetch_and_or_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_fetch_and_and, "v.", "") +BUILTIN(__sync_fetch_and_and_1, "cc*c.", "n") +BUILTIN(__sync_fetch_and_and_2, "ss*s.", "n") +BUILTIN(__sync_fetch_and_and_4, "ii*i.", "n") +BUILTIN(__sync_fetch_and_and_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_fetch_and_and_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_fetch_and_xor, "v.", "") +BUILTIN(__sync_fetch_and_xor_1, "cc*c.", "n") +BUILTIN(__sync_fetch_and_xor_2, "ss*s.", "n") +BUILTIN(__sync_fetch_and_xor_4, "ii*i.", "n") +BUILTIN(__sync_fetch_and_xor_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_fetch_and_nand, "v.", "") +BUILTIN(__sync_fetch_and_nand_1, "cc*c.", "n") +BUILTIN(__sync_fetch_and_nand_2, "ss*s.", "n") +BUILTIN(__sync_fetch_and_nand_4, "ii*i.", "n") +BUILTIN(__sync_fetch_and_nand_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_fetch_and_nand_16, "LLLiLLLi*LLLi.", "n") + + +BUILTIN(__sync_add_and_fetch, "v.", "") +BUILTIN(__sync_add_and_fetch_1, "cc*c.", "n") +BUILTIN(__sync_add_and_fetch_2, "ss*s.", "n") +BUILTIN(__sync_add_and_fetch_4, "ii*i.", "n") +BUILTIN(__sync_add_and_fetch_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_add_and_fetch_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_sub_and_fetch, "v.", "") +BUILTIN(__sync_sub_and_fetch_1, "cc*c.", "n") +BUILTIN(__sync_sub_and_fetch_2, "ss*s.", "n") +BUILTIN(__sync_sub_and_fetch_4, "ii*i.", "n") +BUILTIN(__sync_sub_and_fetch_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_or_and_fetch, "v.", "") +BUILTIN(__sync_or_and_fetch_1, "cc*c.", "n") +BUILTIN(__sync_or_and_fetch_2, "ss*s.", "n") +BUILTIN(__sync_or_and_fetch_4, "ii*i.", "n") +BUILTIN(__sync_or_and_fetch_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_or_and_fetch_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_and_and_fetch, "v.", "") +BUILTIN(__sync_and_and_fetch_1, "cc*c.", "n") +BUILTIN(__sync_and_and_fetch_2, "ss*s.", "n") +BUILTIN(__sync_and_and_fetch_4, "ii*i.", "n") +BUILTIN(__sync_and_and_fetch_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_and_and_fetch_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_xor_and_fetch, "v.", "") +BUILTIN(__sync_xor_and_fetch_1, "cc*c.", "n") +BUILTIN(__sync_xor_and_fetch_2, "ss*s.", "n") +BUILTIN(__sync_xor_and_fetch_4, "ii*i.", "n") +BUILTIN(__sync_xor_and_fetch_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_nand_and_fetch, "v.", "") +BUILTIN(__sync_nand_and_fetch_1, "cc*c.", "n") +BUILTIN(__sync_nand_and_fetch_2, "ss*s.", "n") +BUILTIN(__sync_nand_and_fetch_4, "ii*i.", "n") +BUILTIN(__sync_nand_and_fetch_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_nand_and_fetch_16, "LLLiLLLi*LLLi.", "n") + + +BUILTIN(__sync_bool_compare_and_swap, "v.", "") +BUILTIN(__sync_bool_compare_and_swap_1, "bc*cc.", "n") +BUILTIN(__sync_bool_compare_and_swap_2, "bs*ss.", "n") +BUILTIN(__sync_bool_compare_and_swap_4, "bi*ii.", "n") +BUILTIN(__sync_bool_compare_and_swap_8, "bLLi*LLi.", "n") +BUILTIN(__sync_bool_compare_and_swap_16, "bLLLi*LLLiLLLi.", "n") + +BUILTIN(__sync_val_compare_and_swap, "v.", "") +BUILTIN(__sync_val_compare_and_swap_1, "cc*cc.", "n") +BUILTIN(__sync_val_compare_and_swap_2, "ss*ss.", "n") +BUILTIN(__sync_val_compare_and_swap_4, "ii*ii.", "n") +BUILTIN(__sync_val_compare_and_swap_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_val_compare_and_swap_16, "LLLiLLLi*LLLiLLLi.", "n") + +BUILTIN(__sync_lock_test_and_set, "v.", "") +BUILTIN(__sync_lock_test_and_set_1, "cc*c.", "n") +BUILTIN(__sync_lock_test_and_set_2, "ss*s.", "n") +BUILTIN(__sync_lock_test_and_set_4, "ii*i.", "n") +BUILTIN(__sync_lock_test_and_set_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_lock_release, "v.", "") +BUILTIN(__sync_lock_release_1, "vc*.", "n") +BUILTIN(__sync_lock_release_2, "vs*.", "n") +BUILTIN(__sync_lock_release_4, "vi*.", "n") +BUILTIN(__sync_lock_release_8, "vLLi*.", "n") +BUILTIN(__sync_lock_release_16, "vLLLi*.", "n") + + + +// Non-overloaded atomic builtins. +BUILTIN(__sync_synchronize, "v.", "n") +// LLVM instruction builtin [Clang extension]. +BUILTIN(__builtin_llvm_memory_barrier,"vbbbbb", "n") +// GCC does not support these, they are a Clang extension. +BUILTIN(__sync_fetch_and_min, "ii*i", "n") +BUILTIN(__sync_fetch_and_max, "ii*i", "n") +BUILTIN(__sync_fetch_and_umin, "UiUi*Ui", "n") +BUILTIN(__sync_fetch_and_umax, "UiUi*Ui", "n") + +// Builtin library functions +LIBBUILTIN(alloca, "v*z", "f", "stdlib.h") +LIBBUILTIN(calloc, "v*zz", "f", "stdlib.h") +LIBBUILTIN(malloc, "v*z", "f", "stdlib.h") +LIBBUILTIN(realloc, "v*v*z", "f", "stdlib.h") +LIBBUILTIN(memcpy, "v*v*vC*z", "f", "string.h") +LIBBUILTIN(memmove, "v*v*vC*z", "f", "string.h") +LIBBUILTIN(memset, "v*v*iz", "f", "string.h") +LIBBUILTIN(strcat, "c*c*cC*", "f", "string.h") +LIBBUILTIN(strchr, "c*cC*i", "f", "string.h") +LIBBUILTIN(strcpy, "c*c*cC*", "f", "string.h") +LIBBUILTIN(strcspn, "zcC*cC*", "f", "string.h") +LIBBUILTIN(strlen, "zcC*", "f", "string.h") +LIBBUILTIN(strncat, "c*c*cC*z", "f", "string.h") +LIBBUILTIN(strncpy, "c*c*cC*z", "f", "string.h") +LIBBUILTIN(strpbrk, "c*cC*cC*", "f", "string.h") +LIBBUILTIN(strrchr, "c*cC*i", "f", "string.h") +LIBBUILTIN(strspn, "zcC*cC*", "f", "string.h") +LIBBUILTIN(strstr, "c*cC*cC*", "f", "string.h") +LIBBUILTIN(printf, "icC*.", "fp:0:", "stdio.h") +LIBBUILTIN(fprintf, "iP*cC*.", "fp:1:", "stdio.h") +LIBBUILTIN(snprintf, "ic*zcC*.", "fp:2:", "stdio.h") +LIBBUILTIN(sprintf, "ic*cC*.", "fp:1:", "stdio.h") +LIBBUILTIN(vprintf, "icC*a", "fP:0:", "stdio.h") +LIBBUILTIN(vfprintf, "iP*cC*a", "fP:1:", "stdio.h") +LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h") +LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h") + +// FIXME: This type isn't very correct, it should be +// id objc_msgSend(id, SEL) +// but we need new type letters for that. +LIBBUILTIN(objc_msgSend, "v*.", "f", "objc/message.h") + +// FIXME: asprintf and vasprintf aren't C99 functions. Should they be +// target-specific builtins, perhaps? + +// Builtin math library functions +LIBBUILTIN(pow, "ddd", "fe", "math.h") +LIBBUILTIN(powl, "LdLdLd", "fe", "math.h") +LIBBUILTIN(powf, "fff", "fe", "math.h") + +LIBBUILTIN(sqrt, "dd", "fe", "math.h") +LIBBUILTIN(sqrtl, "LdLd", "fe", "math.h") +LIBBUILTIN(sqrtf, "ff", "fe", "math.h") + +LIBBUILTIN(sin, "dd", "fe", "math.h") +LIBBUILTIN(sinl, "LdLd", "fe", "math.h") +LIBBUILTIN(sinf, "ff", "fe", "math.h") + +LIBBUILTIN(cos, "dd", "fe", "math.h") +LIBBUILTIN(cosl, "LdLd", "fe", "math.h") +LIBBUILTIN(cosf, "ff", "fe", "math.h") + +#undef BUILTIN +#undef LIBBUILTIN diff --git a/include/clang/AST/Builtins.h b/include/clang/AST/Builtins.h new file mode 100644 index 000000000000..b16d3bf34139 --- /dev/null +++ b/include/clang/AST/Builtins.h @@ -0,0 +1,137 @@ +//===--- Builtins.h - Builtin function header -------------------*- 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 enum values for all the target-independent builtin +// functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_BUILTINS_H +#define LLVM_CLANG_AST_BUILTINS_H + +#include <cstring> +#include <string> +#include "llvm/ADT/SmallVector.h" + +namespace clang { + class TargetInfo; + class IdentifierTable; + class ASTContext; + class QualType; + +namespace Builtin { +enum ID { + NotBuiltin = 0, // This is not a builtin function. +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/AST/Builtins.def" + FirstTSBuiltin +}; + +struct Info { + const char *Name, *Type, *Attributes, *HeaderName; + bool Suppressed; + + bool operator==(const Info &RHS) const { + return !strcmp(Name, RHS.Name) && + !strcmp(Type, RHS.Type) && + !strcmp(Attributes, RHS.Attributes); + } + bool operator!=(const Info &RHS) const { return !(*this == RHS); } +}; + +/// Builtin::Context - This holds information about target-independent and +/// target-specific builtins, allowing easy queries by clients. +class Context { + const Info *TSRecords; + unsigned NumTSRecords; +public: + Context() : TSRecords(0), NumTSRecords(0) {} + + /// \brief Load all of the target builtins. This should be called + /// prior to initializing the builtin identifiers. + void InitializeTargetBuiltins(const TargetInfo &Target); + + /// InitializeBuiltins - Mark the identifiers for all the builtins with their + /// appropriate builtin ID # and mark any non-portable builtin identifiers as + /// such. + void InitializeBuiltins(IdentifierTable &Table, bool NoBuiltins = false); + + /// \brief Popular the vector with the names of all of the builtins. + void GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names, + bool NoBuiltins); + + /// Builtin::GetName - Return the identifier name for the specified builtin, + /// e.g. "__builtin_abs". + const char *GetName(unsigned ID) const { + return GetRecord(ID).Name; + } + + /// isConst - Return true if this function has no side effects and doesn't + /// read memory. + bool isConst(unsigned ID) const { + return strchr(GetRecord(ID).Attributes, 'c') != 0; + } + + /// isNoThrow - Return true if we know this builtin never throws an exception. + bool isNoThrow(unsigned ID) const { + return strchr(GetRecord(ID).Attributes, 'n') != 0; + } + + /// isLibFunction - Return true if this is a builtin for a libc/libm function, + /// with a "__builtin_" prefix (e.g. __builtin_abs). + bool isLibFunction(unsigned ID) const { + return strchr(GetRecord(ID).Attributes, 'F') != 0; + } + + /// \brief Determines whether this builtin is a predefined libc/libm + /// function, such as "malloc", where we know the signature a + /// priori. + bool isPredefinedLibFunction(unsigned ID) const { + return strchr(GetRecord(ID).Attributes, 'f') != 0; + } + + /// \brief If this is a library function that comes from a specific + /// header, retrieve that header name. + const char *getHeaderName(unsigned ID) const { + return GetRecord(ID).HeaderName; + } + + /// \brief Determine whether this builtin is like printf in its + /// formatting rules and, if so, set the index to the format string + /// argument and whether this function as a va_list argument. + bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg); + + /// hasVAListUse - Return true of the specified builtin uses __builtin_va_list + /// as an operand or return type. + bool hasVAListUse(unsigned ID) const { + return strpbrk(GetRecord(ID).Type, "Aa") != 0; + } + + /// isConstWithoutErrno - Return true if this function has no side + /// effects and doesn't read memory, except for possibly errno. Such + /// functions can be const when the MathErrno lang option is + /// disabled. + bool isConstWithoutErrno(unsigned ID) const { + return strchr(GetRecord(ID).Attributes, 'e') != 0; + } + + /// GetBuiltinType - Return the type for the specified builtin. + enum GetBuiltinTypeError { + GE_None, //< No error + GE_Missing_FILE //< Missing the FILE type from <stdio.h> + }; + QualType GetBuiltinType(unsigned ID, ASTContext &Context, + GetBuiltinTypeError &Error) const; +private: + const Info &GetRecord(unsigned ID) const; +}; + +} +} // end namespace clang +#endif diff --git a/include/clang/AST/CFG.h b/include/clang/AST/CFG.h new file mode 100644 index 000000000000..7a9ee01d4f62 --- /dev/null +++ b/include/clang/AST/CFG.h @@ -0,0 +1,405 @@ +//===--- CFG.h - Classes for representing and building CFGs------*- 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 CFG and CFGBuilder classes for representing and +// building Control-Flow Graphs (CFGs) from ASTs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CFG_H +#define LLVM_CLANG_CFG_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/raw_ostream.h" +#include <list> +#include <vector> +#include <cassert> + +namespace clang { + class Stmt; + class Expr; + class CFG; + class PrinterHelper; + class BlockEdge; + +/// CFGBlock - Represents a single basic block in a source-level CFG. +/// It consists of: +/// +/// (1) A set of statements/expressions (which may contain subexpressions). +/// (2) A "terminator" statement (not in the set of statements). +/// (3) A list of successors and predecessors. +/// +/// Terminator: The terminator represents the type of control-flow that occurs +/// at the end of the basic block. The terminator is a Stmt* referring to an +/// AST node that has control-flow: if-statements, breaks, loops, etc. +/// If the control-flow is conditional, the condition expression will appear +/// within the set of statements in the block (usually the last statement). +/// +/// Predecessors: the order in the set of predecessors is arbitrary. +/// +/// Successors: the order in the set of successors is NOT arbitrary. We +/// currently have the following orderings based on the terminator: +/// +/// Terminator Successor Ordering +/// ----------------------------------------------------- +/// if Then Block; Else Block +/// ? operator LHS expression; RHS expression +/// &&, || expression that uses result of && or ||, RHS +/// +class CFGBlock { + typedef std::vector<Stmt*> StatementListTy; + /// Stmts - The set of statements in the basic block. + StatementListTy Stmts; + + /// Label - An (optional) label that prefixes the executable + /// statements in the block. When this variable is non-NULL, it is + /// either an instance of LabelStmt or SwitchCase. + Stmt *Label; + + /// Terminator - The terminator for a basic block that + /// indicates the type of control-flow that occurs between a block + /// and its successors. + Stmt *Terminator; + + /// LoopTarget - Some blocks are used to represent the "loop edge" to + /// the start of a loop from within the loop body. This Stmt* will be + /// refer to the loop statement for such blocks (and be null otherwise). + const Stmt *LoopTarget; + + /// BlockID - A numerical ID assigned to a CFGBlock during construction + /// of the CFG. + unsigned BlockID; + + /// Predecessors/Successors - Keep track of the predecessor / successor + /// CFG blocks. + typedef std::vector<CFGBlock*> AdjacentBlocks; + AdjacentBlocks Preds; + AdjacentBlocks Succs; + +public: + explicit CFGBlock(unsigned blockid) : Label(NULL), Terminator(NULL), + LoopTarget(NULL), BlockID(blockid) {} + ~CFGBlock() {}; + + // Statement iterators + typedef StatementListTy::iterator iterator; + typedef StatementListTy::const_iterator const_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + + Stmt* front() const { return Stmts.front(); } + Stmt* back() const { return Stmts.back(); } + + iterator begin() { return Stmts.begin(); } + iterator end() { return Stmts.end(); } + const_iterator begin() const { return Stmts.begin(); } + const_iterator end() const { return Stmts.end(); } + + reverse_iterator rbegin() { return Stmts.rbegin(); } + reverse_iterator rend() { return Stmts.rend(); } + const_reverse_iterator rbegin() const { return Stmts.rbegin(); } + const_reverse_iterator rend() const { return Stmts.rend(); } + + unsigned size() const { return Stmts.size(); } + bool empty() const { return Stmts.empty(); } + + Stmt* operator[](size_t i) const { assert (i < size()); return Stmts[i]; } + + // CFG iterators + typedef AdjacentBlocks::iterator pred_iterator; + typedef AdjacentBlocks::const_iterator const_pred_iterator; + typedef AdjacentBlocks::reverse_iterator pred_reverse_iterator; + typedef AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator; + + typedef AdjacentBlocks::iterator succ_iterator; + typedef AdjacentBlocks::const_iterator const_succ_iterator; + typedef AdjacentBlocks::reverse_iterator succ_reverse_iterator; + typedef AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator; + + pred_iterator pred_begin() { return Preds.begin(); } + pred_iterator pred_end() { return Preds.end(); } + const_pred_iterator pred_begin() const { return Preds.begin(); } + const_pred_iterator pred_end() const { return Preds.end(); } + + pred_reverse_iterator pred_rbegin() { return Preds.rbegin(); } + pred_reverse_iterator pred_rend() { return Preds.rend(); } + const_pred_reverse_iterator pred_rbegin() const { return Preds.rbegin(); } + const_pred_reverse_iterator pred_rend() const { return Preds.rend(); } + + succ_iterator succ_begin() { return Succs.begin(); } + succ_iterator succ_end() { return Succs.end(); } + const_succ_iterator succ_begin() const { return Succs.begin(); } + const_succ_iterator succ_end() const { return Succs.end(); } + + succ_reverse_iterator succ_rbegin() { return Succs.rbegin(); } + succ_reverse_iterator succ_rend() { return Succs.rend(); } + const_succ_reverse_iterator succ_rbegin() const { return Succs.rbegin(); } + const_succ_reverse_iterator succ_rend() const { return Succs.rend(); } + + unsigned succ_size() const { return Succs.size(); } + bool succ_empty() const { return Succs.empty(); } + + unsigned pred_size() const { return Preds.size(); } + bool pred_empty() const { return Preds.empty(); } + + // Manipulation of block contents + + void appendStmt(Stmt* Statement) { Stmts.push_back(Statement); } + void setTerminator(Stmt* Statement) { Terminator = Statement; } + void setLabel(Stmt* Statement) { Label = Statement; } + void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; } + + Stmt* getTerminator() { return Terminator; } + const Stmt* getTerminator() const { return Terminator; } + + Stmt* getTerminatorCondition(); + + const Stmt* getTerminatorCondition() const { + return const_cast<CFGBlock*>(this)->getTerminatorCondition(); + } + + const Stmt *getLoopTarget() const { return LoopTarget; } + + bool hasBinaryBranchTerminator() const; + + Stmt* getLabel() { return Label; } + const Stmt* getLabel() const { return Label; } + + void reverseStmts(); + + void addSuccessor(CFGBlock* Block) { + Block->Preds.push_back(this); + Succs.push_back(Block); + } + + unsigned getBlockID() const { return BlockID; } + + void dump(const CFG* cfg) const; + void print(llvm::raw_ostream& OS, const CFG* cfg) const; + void printTerminator(llvm::raw_ostream& OS) const; +}; + + +/// CFG - Represents a source-level, intra-procedural CFG that represents the +/// control-flow of a Stmt. The Stmt can represent an entire function body, +/// or a single expression. A CFG will always contain one empty block that +/// represents the Exit point of the CFG. A CFG will also contain a designated +/// Entry block. The CFG solely represents control-flow; it consists of +/// CFGBlocks which are simply containers of Stmt*'s in the AST the CFG +/// was constructed from. +class CFG { +public: + //===--------------------------------------------------------------------===// + // CFG Construction & Manipulation. + //===--------------------------------------------------------------------===// + + /// buildCFG - Builds a CFG from an AST. The responsibility to free the + /// constructed CFG belongs to the caller. + static CFG* buildCFG(Stmt* AST); + + /// createBlock - Create a new block in the CFG. The CFG owns the block; + /// the caller should not directly free it. + CFGBlock* createBlock(); + + /// setEntry - Set the entry block of the CFG. This is typically used + /// only during CFG construction. Most CFG clients expect that the + /// entry block has no predecessors and contains no statements. + void setEntry(CFGBlock *B) { Entry = B; } + + /// setExit - Set the exit block of the CFG. This is typically used + /// only during CFG construction. Most CFG clients expect that the + /// exit block has no successors and contains no statements. + void setIndirectGotoBlock(CFGBlock* B) { IndirectGotoBlock = B; } + + //===--------------------------------------------------------------------===// + // Block Iterators + //===--------------------------------------------------------------------===// + + typedef std::list<CFGBlock> CFGBlockListTy; + + typedef CFGBlockListTy::iterator iterator; + typedef CFGBlockListTy::const_iterator const_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + CFGBlock& front() { return Blocks.front(); } + CFGBlock& back() { return Blocks.back(); } + + iterator begin() { return Blocks.begin(); } + iterator end() { return Blocks.end(); } + const_iterator begin() const { return Blocks.begin(); } + const_iterator end() const { return Blocks.end(); } + + reverse_iterator rbegin() { return Blocks.rbegin(); } + reverse_iterator rend() { return Blocks.rend(); } + const_reverse_iterator rbegin() const { return Blocks.rbegin(); } + const_reverse_iterator rend() const { return Blocks.rend(); } + + CFGBlock& getEntry() { return *Entry; } + const CFGBlock& getEntry() const { return *Entry; } + CFGBlock& getExit() { return *Exit; } + const CFGBlock& getExit() const { return *Exit; } + + CFGBlock* getIndirectGotoBlock() { return IndirectGotoBlock; } + const CFGBlock* getIndirectGotoBlock() const { return IndirectGotoBlock; } + + //===--------------------------------------------------------------------===// + // Member templates useful for various batch operations over CFGs. + //===--------------------------------------------------------------------===// + + template <typename CALLBACK> + void VisitBlockStmts(CALLBACK& O) const { + for (const_iterator I=begin(), E=end(); I != E; ++I) + for (CFGBlock::const_iterator BI=I->begin(), BE=I->end(); BI != BE; ++BI) + O(*BI); + } + + //===--------------------------------------------------------------------===// + // CFG Introspection. + //===--------------------------------------------------------------------===// + + struct BlkExprNumTy { + const signed Idx; + explicit BlkExprNumTy(signed idx) : Idx(idx) {} + explicit BlkExprNumTy() : Idx(-1) {} + operator bool() const { return Idx >= 0; } + operator unsigned() const { assert(Idx >=0); return (unsigned) Idx; } + }; + + bool isBlkExpr(const Stmt* S) { return getBlkExprNum(S); } + BlkExprNumTy getBlkExprNum(const Stmt* S); + unsigned getNumBlkExprs(); + + unsigned getNumBlockIDs() const { return NumBlockIDs; } + + //===--------------------------------------------------------------------===// + // CFG Debugging: Pretty-Printing and Visualization. + //===--------------------------------------------------------------------===// + + void viewCFG() const; + void print(llvm::raw_ostream& OS) const; + void dump() const; + + //===--------------------------------------------------------------------===// + // Internal: constructors and data. + //===--------------------------------------------------------------------===// + + CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0), + BlkExprMap(NULL) {}; + + ~CFG(); + + llvm::BumpPtrAllocator& getAllocator() { + return Alloc; + } + +private: + CFGBlock* Entry; + CFGBlock* Exit; + CFGBlock* IndirectGotoBlock; // Special block to contain collective dispatch + // for indirect gotos + CFGBlockListTy Blocks; + unsigned NumBlockIDs; + + // BlkExprMap - An opaque pointer to prevent inclusion of DenseMap.h. + // It represents a map from Expr* to integers to record the set of + // block-level expressions and their "statement number" in the CFG. + void* BlkExprMap; + + /// Alloc - An internal allocator. + llvm::BumpPtrAllocator Alloc; +}; +} // end namespace clang + +//===----------------------------------------------------------------------===// +// GraphTraits specializations for CFG basic block graphs (source-level CFGs) +//===----------------------------------------------------------------------===// + +namespace llvm { + +// Traits for: CFGBlock + +template <> struct GraphTraits<clang::CFGBlock* > { + typedef clang::CFGBlock NodeType; + typedef clang::CFGBlock::succ_iterator ChildIteratorType; + + static NodeType* getEntryNode(clang::CFGBlock* BB) + { return BB; } + + static inline ChildIteratorType child_begin(NodeType* N) + { return N->succ_begin(); } + + static inline ChildIteratorType child_end(NodeType* N) + { return N->succ_end(); } +}; + +template <> struct GraphTraits<const clang::CFGBlock* > { + typedef const clang::CFGBlock NodeType; + typedef clang::CFGBlock::const_succ_iterator ChildIteratorType; + + static NodeType* getEntryNode(const clang::CFGBlock* BB) + { return BB; } + + static inline ChildIteratorType child_begin(NodeType* N) + { return N->succ_begin(); } + + static inline ChildIteratorType child_end(NodeType* N) + { return N->succ_end(); } +}; + +template <> struct GraphTraits<Inverse<const clang::CFGBlock*> > { + typedef const clang::CFGBlock NodeType; + typedef clang::CFGBlock::const_pred_iterator ChildIteratorType; + + static NodeType *getEntryNode(Inverse<const clang::CFGBlock*> G) + { return G.Graph; } + + static inline ChildIteratorType child_begin(NodeType* N) + { return N->pred_begin(); } + + static inline ChildIteratorType child_end(NodeType* N) + { return N->pred_end(); } +}; + +// Traits for: CFG + +template <> struct GraphTraits<clang::CFG* > + : public GraphTraits<clang::CFGBlock* > { + + typedef clang::CFG::iterator nodes_iterator; + + static NodeType *getEntryNode(clang::CFG* F) { return &F->getEntry(); } + static nodes_iterator nodes_begin(clang::CFG* F) { return F->begin(); } + static nodes_iterator nodes_end(clang::CFG* F) { return F->end(); } +}; + +template <> struct GraphTraits< const clang::CFG* > + : public GraphTraits< const clang::CFGBlock* > { + + typedef clang::CFG::const_iterator nodes_iterator; + + static NodeType *getEntryNode( const clang::CFG* F) { return &F->getEntry(); } + static nodes_iterator nodes_begin( const clang::CFG* F) { return F->begin(); } + static nodes_iterator nodes_end( const clang::CFG* F) { return F->end(); } +}; + +template <> struct GraphTraits<Inverse<const clang::CFG*> > + : public GraphTraits<Inverse<const clang::CFGBlock*> > { + + typedef clang::CFG::const_iterator nodes_iterator; + + static NodeType *getEntryNode(const clang::CFG* F) { return &F->getExit(); } + static nodes_iterator nodes_begin(const clang::CFG* F) { return F->begin();} + static nodes_iterator nodes_end(const clang::CFG* F) { return F->end(); } +}; + +} // end llvm namespace + +#endif diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h new file mode 100644 index 000000000000..e134aed73d77 --- /dev/null +++ b/include/clang/AST/Decl.h @@ -0,0 +1,1409 @@ +//===--- Decl.h - Classes for representing declarations ---------*- 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 Decl subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECL_H +#define LLVM_CLANG_AST_DECL_H + +#include "clang/AST/APValue.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/ExternalASTSource.h" + +namespace clang { +class Expr; +class FunctionTemplateDecl; +class Stmt; +class CompoundStmt; +class StringLiteral; + +/// TranslationUnitDecl - The top declaration context. +class TranslationUnitDecl : public Decl, public DeclContext { + TranslationUnitDecl() + : Decl(TranslationUnit, 0, SourceLocation()), + DeclContext(TranslationUnit) {} +public: + 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 DeclContext *castToDeclContext(const TranslationUnitDecl *D) { + return static_cast<DeclContext *>(const_cast<TranslationUnitDecl*>(D)); + } + static TranslationUnitDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<TranslationUnitDecl *>(const_cast<DeclContext*>(DC)); + } +}; + +/// NamedDecl - This represents a decl with a name. Many decls have names such +/// as ObjCMethodDecl, but not @class, etc. +class NamedDecl : public Decl { + /// Name - The name of this declaration, which is typically a normal + /// identifier but may also be a special kind of name (C++ + /// constructor, Objective-C selector, etc.) + DeclarationName Name; + +protected: + NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N) + : Decl(DK, DC, L), Name(N) { } + +public: + /// getIdentifier - Get the identifier that names this declaration, + /// if there is one. This will return NULL if this declaration has + /// no name (e.g., for an unnamed class) or if the name is a special + /// name (C++ constructor, Objective-C selector, etc.). + IdentifierInfo *getIdentifier() const { return Name.getAsIdentifierInfo(); } + + /// getNameAsCString - Get the name of identifier for this declaration as a + /// C string (const char*). This requires that the declaration have a name + /// and that it be a simple identifier. + const char *getNameAsCString() const { + assert(getIdentifier() && "Name is not a simple identifier"); + return getIdentifier()->getName(); + } + + /// getDeclName - Get the actual, stored name of the declaration, + /// which may be a special name. + DeclarationName getDeclName() const { return Name; } + + /// \brief Set the name of this declaration. + void setDeclName(DeclarationName N) { Name = N; } + + /// getNameAsString - Get a human-readable name for the declaration, even if + /// it is one of the special kinds of names (C++ constructor, Objective-C + /// selector, etc). Creating this name requires expensive string + /// 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, + /// namespace), it will return same result as getNameAsString(). + /// Creating this name is expensive, so it should be called only when + /// performance doesn't matter. + std::string getQualifiedNameAsString() const; + + /// declarationReplaces - Determine whether this declaration, if + /// known to be well-formed within its context, will replace the + /// declaration OldD if introduced into scope. A declaration will + /// replace another declaration if, for example, it is a + /// redeclaration of the same variable or function, but not if it is + /// a declaration of a different kind (function vs. class) or an + /// overloaded function. + bool declarationReplaces(NamedDecl *OldD) const; + + /// \brief Determine whether this declaration has linkage. + bool hasLinkage() const; + + static bool classof(const Decl *D) { + return D->getKind() >= NamedFirst && D->getKind() <= NamedLast; + } + static bool classof(const NamedDecl *D) { return true; } +}; + +/// NamespaceDecl - Represent a C++ namespace. +class NamespaceDecl : public NamedDecl, public DeclContext { + SourceLocation LBracLoc, RBracLoc; + + // For extended namespace definitions: + // + // namespace A { int x; } + // namespace A { int y; } + // + // there will be one NamespaceDecl for each declaration. + // NextNamespace points to the next extended declaration. + // 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; + NextNamespace = 0; + } +public: + static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id); + + virtual void Destroy(ASTContext& C); + + NamespaceDecl *getNextNamespace() { return NextNamespace; } + const NamespaceDecl *getNextNamespace() const { return NextNamespace; } + void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; } + + NamespaceDecl *getOriginalNamespace() const { + return OrigNamespace; + } + void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; } + + SourceRange getSourceRange() const { + return SourceRange(LBracLoc, RBracLoc); + } + + SourceLocation getLBracLoc() const { return LBracLoc; } + 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; } + static DeclContext *castToDeclContext(const NamespaceDecl *D) { + return static_cast<DeclContext *>(const_cast<NamespaceDecl*>(D)); + } + static NamespaceDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC)); + } +}; + +/// 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. +class ValueDecl : public NamedDecl { + QualType DeclType; + +protected: + ValueDecl(Kind DK, DeclContext *DC, SourceLocation L, + 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; + } + static bool classof(const ValueDecl *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). +struct EvaluatedStmt { + EvaluatedStmt() : WasEvaluated(false), CheckedICE(false), IsICE(false) { } + + /// \brief Whether this statement was already evaluated. + bool WasEvaluated : 1; + + /// \brief Whether we already checked whether this statement was an + /// integral constant expression. + bool CheckedICE : 1; + + /// \brief Whether this statement is an integral constant + /// expression. Only valid if CheckedICE is true. + bool IsICE : 1; + + Stmt *Value; + APValue Evaluated; +}; + +/// VarDecl - An instance of this class is created to represent a variable +/// declaration or definition. +class VarDecl : public ValueDecl { +public: + enum StorageClass { + None, Auto, Register, Extern, Static, PrivateExtern + }; + + /// getStorageClassSpecifierString - Return the string used to + /// specify the storage class \arg SC. + /// + /// It is illegal to call this function with SC == None. + static const char *getStorageClassSpecifierString(StorageClass SC); + +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; + + /// 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(), + ThreadSpecified(false), HasCXXDirectInit(false), + DeclaredInCondition(false), PreviousDeclaration(0), + TypeSpecStartLoc(TSSL) { + SClass = SC; + } +public: + static VarDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + QualType T, StorageClass S, + SourceLocation TypeSpecStartLoc = SourceLocation()); + + virtual ~VarDecl(); + virtual void Destroy(ASTContext& C); + + StorageClass getStorageClass() const { return (StorageClass)SClass; } + void setStorageClass(StorageClass SC) { SClass = SC; } + + SourceLocation getTypeSpecStartLoc() const { return TypeSpecStartLoc; } + void setTypeSpecStartLoc(SourceLocation SL) { + TypeSpecStartLoc = SL; + } + + 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; + } + Expr *getInit() { + if (Init.isNull()) + return 0; + + Stmt *S = Init.dyn_cast<Stmt *>(); + if (!S) + S = Init.get<EvaluatedStmt *>()->Value; + + 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; + } + + 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 { + EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>(); + if (!Eval) { + Stmt *S = Init.get<Stmt *>(); + Eval = new (C) EvaluatedStmt; + Eval->Value = S; + Init = Eval; + } + + 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 { + if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) + if (Eval->WasEvaluated) + return &Eval->Evaluated; + + return 0; + } + + /// \brief Determines whether it is already known whether the + /// initializer is an integral constant expression or not. + bool isInitKnownICE() const { + if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) + return Eval->CheckedICE; + + return false; + } + + /// \brief Determines whether the initializer is an integral + /// constant expression. + /// + /// \pre isInitKnownICE() + bool isInitICE() const { + assert(isInitKnownICE() && + "Check whether we already know that the initializer is an ICE"); + return Init.get<EvaluatedStmt *>()->IsICE; + } + + /// \brief Note that we now know whether the initializer is an + /// integral constant expression. + void setInitKnownICE(ASTContext &C, bool IsICE) const { + EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>(); + if (!Eval) { + Stmt *S = Init.get<Stmt *>(); + Eval = new (C) EvaluatedStmt; + Eval->Value = S; + Init = Eval; + } + + Eval->CheckedICE = true; + Eval->IsICE = IsICE; + } + + /// \brief Retrieve the definition of this variable, which may come + /// from a previous declaration. Def will be set to the VarDecl that + /// contains the initializer, and the result will be that + /// initializer. + const Expr *getDefinition(const VarDecl *&Def) const; + + void setThreadSpecified(bool T) { ThreadSpecified = T; } + bool isThreadSpecified() const { + return ThreadSpecified; + } + + void setCXXDirectInitializer(bool T) { HasCXXDirectInit = T; } + + /// hasCXXDirectInitializer - If true, the initializer was a direct + /// initializer, e.g: "int x(1);". The Init expression will be the expression + /// inside the parens or a "ClassType(a,b,c)" class constructor expression for + /// class types. Clients can distinguish between "int x(1);" and "int x=1;" + /// by checking hasCXXDirectInitializer. + /// + 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 + /// if (int x = foo()) { ... } + /// @endcode + bool isDeclaredInCondition() const { + return DeclaredInCondition; + } + 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; + } + + /// 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; + } + + /// hasExternStorage - Returns true if a variable has extern or + /// __private_extern__ storage. + bool hasExternalStorage() const { + return getStorageClass() == Extern || getStorageClass() == PrivateExtern; + } + + /// hasGlobalStorage - Returns true for all variables that do not + /// have local storage. This includs all global variables as well + /// as static variables declared within a function. + bool hasGlobalStorage() const { return !hasLocalStorage(); } + + /// isBlockVarDecl - Returns true for local variable declarations. Note that + /// this includes static variables inside of functions. + /// + /// void foo() { int x; static int y; extern int z; } + /// + bool isBlockVarDecl() const { + if (getKind() != Decl::Var) + return false; + if (const DeclContext *DC = getDeclContext()) + 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 + /// variable 'x' in: + /// \code + /// struct S { + /// static int x; + /// }; + /// \endcode + bool isStaticDataMember() const { + return getDeclContext()->isRecord(); + } + + /// isFileVarDecl - Returns true for file scoped variable declaration. + bool isFileVarDecl() const { + if (getKind() != Decl::Var) + return false; + if (const DeclContext *Ctx = getDeclContext()) { + Ctx = Ctx->getLookupContext(); + if (isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx) ) + 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; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() >= VarFirst && D->getKind() <= VarLast; + } + static bool classof(const VarDecl *D) { return true; } +}; + +class ImplicitParamDecl : public VarDecl { +protected: + ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType Tw) + : VarDecl(DK, DC, L, Id, Tw, VarDecl::None) {} +public: + static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, + 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; } +}; + +/// ParmVarDecl - Represent a parameter to a function. +class ParmVarDecl : public VarDecl { + // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum + /// FIXME: Also can be paced into the bitfields in Decl. + /// in, inout, etc. + unsigned objcDeclQualifier : 6; + + /// Default argument, if any. [C++ Only] + Expr *DefaultArg; +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) {} + +public: + static ParmVarDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L,IdentifierInfo *Id, + QualType T, StorageClass S, Expr *DefArg); + + ObjCDeclQualifier getObjCDeclQualifier() const { + return ObjCDeclQualifier(objcDeclQualifier); + } + void setObjCDeclQualifier(ObjCDeclQualifier QTVal) { + objcDeclQualifier = QTVal; + } + + const Expr *getDefaultArg() const { return DefaultArg; } + Expr *getDefaultArg() { return DefaultArg; } + void setDefaultArg(Expr *defarg) { DefaultArg = defarg; } + + /// 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 + /// default arguments, e.g., + /// @code + /// class X { + /// public: + /// void f(int x = 17); // x has an unparsed default argument now + /// }; // x has a regular default argument now + /// @endcode + bool hasUnparsedDefaultArg() const { + return DefaultArg == reinterpret_cast<Expr *>(-1); + } + + /// setUnparsedDefaultArg - Specify that this parameter has an + /// unparsed default argument. The argument will be replaced with a + /// 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); } + + 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 + /// the DeclContext appropriately. + void setOwningFunction(DeclContext *FD) { setDeclContext(FD); } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return (D->getKind() == ParmVar || + D->getKind() == OriginalParmVar); + } + static bool classof(const ParmVarDecl *D) { return true; } +}; + +/// OriginalParmVarDecl - Represent a parameter to a function, when +/// the type of the parameter has been promoted. This node represents the +/// parameter to the function with its original type. +/// +class OriginalParmVarDecl : public ParmVarDecl { + friend class ParmVarDecl; +protected: + QualType OriginalType; +private: + OriginalParmVarDecl(DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType T, + QualType OT, StorageClass S, + Expr *DefArg) + : ParmVarDecl(OriginalParmVar, DC, L, Id, T, S, DefArg), OriginalType(OT) {} +public: + static OriginalParmVarDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L,IdentifierInfo *Id, + QualType T, QualType OT, + StorageClass S, Expr *DefArg); + + void setOriginalType(QualType T) { OriginalType = T; } + + // Implement isa/cast/dyncast/etc. + 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. +/// +/// Since a given function can be declared several times in a program, +/// there may be several FunctionDecls that correspond to that +/// function. Only one of those FunctionDecls will be found when +/// traversing the list of declarations in the context of the +/// 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 { +public: + enum StorageClass { + None, Extern, Static, PrivateExtern + }; +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. TODO: we could allocate this space immediately after the + /// FunctionDecl object to save an allocation like FunctionType does. + 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; + + // Move to DeclGroup when it is implemented. + SourceLocation TypeSpecStartLoc; + + /// \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. + llvm::PointerUnion<FunctionTemplateDecl*, FunctionDecl*> + TemplateOrInstantiation; + +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), + 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), + TemplateOrInstantiation() {} + + virtual ~FunctionDecl() {} + virtual void Destroy(ASTContext& C); + +public: + static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, + DeclarationName N, QualType T, + StorageClass S = None, bool isInline = false, + bool hasWrittenPrototype = true, + SourceLocation TSStartLoc = SourceLocation()); + + 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 + /// function. The variant that accepts a FunctionDecl pointer will + /// set that function declaration to the actual declaration + /// containing the body (if there is one). + Stmt *getBody(ASTContext &Context, const FunctionDecl *&Definition) const; + + virtual Stmt *getBody(ASTContext &Context) const { + const FunctionDecl* Definition; + return getBody(Context, 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 + /// previous definition); for that information, use getBody. + /// FIXME: Should return true if function is deleted or defaulted. However, + /// CodeGenModule.cpp uses it, and I don't know if this would break it. + bool isThisDeclarationADefinition() const { return Body; } + + void setBody(Stmt *B) { Body = B; } + void setLazyBody(uint64_t Offset) { Body = Offset; } + + /// Whether this function is marked as virtual explicitly. + bool isVirtualAsWritten() const { return IsVirtualAsWritten; } + void setVirtualAsWritten(bool V) { IsVirtualAsWritten = V; } + + /// Whether this virtual function is pure, i.e. makes the containing class + /// abstract. + bool isPure() const { return IsPure; } + void setPure(bool P = true) { IsPure = P; } + + /// \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 hasWrittenPrototype() const { return HasWrittenPrototype; } + void setHasWrittenPrototype(bool P) { HasWrittenPrototype = P; } + + /// \brief Whether this function inherited its prototype from a + /// previous declaration. + bool hasInheritedPrototype() const { return HasInheritedPrototype; } + void setHasInheritedPrototype(bool P = true) { HasInheritedPrototype = P; } + + /// \brief Whether this function has been deleted. + /// + /// A function that is "deleted" (via the C++0x "= delete" syntax) + /// acts like a normal function, except that it cannot actually be + /// called or have its address taken. Deleted functions are + /// typically used in C++ overload resolution to attract arguments + /// whose type or lvalue/rvalue-ness would permit the use of a + /// different overload that would behave incorrectly. For example, + /// one might use deleted functions to ban implicit conversion from + /// a floating-point number to an Integer type: + /// + /// @code + /// struct Integer { + /// Integer(long); // construct from a long + /// Integer(double) = delete; // no construction from float or double + /// Integer(long double) = delete; // no construction from long double + /// }; + /// @endcode + bool isDeleted() const { return IsDeleted; } + void setDeleted(bool D = true) { IsDeleted = D; } + + /// \brief Determines whether this is a function "main", which is + /// the entry point into an executable program. + bool isMain() const; + + /// \brief Determines whether this function is a function with + /// external, C linkage. + bool isExternC(ASTContext &Context) 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) { + PreviousDeclaration = PrevDecl; + } + + unsigned getBuiltinID(ASTContext &Context) 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]; + } + ParmVarDecl *getParamDecl(unsigned i) { + assert(i < getNumParams() && "Illegal param #"); + return ParamInfo[i]; + } + void setParams(ASTContext& C, ParmVarDecl **NewParamInfo, unsigned NumParams); + + /// getMinRequiredArguments - Returns the minimum number of arguments + /// needed to call this function. This may be fewer than the number of + /// function parameters, if some of the parameters have default + /// arguments (in C++). + unsigned getMinRequiredArguments() const; + + QualType getResultType() const { + return getType()->getAsFunctionType()->getResultType(); + } + StorageClass getStorageClass() const { return StorageClass(SClass); } + void setStorageClass(StorageClass SC) { SClass = SC; } + + 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() const; + + /// \brief Determines whether this function is a GNU "extern + /// inline", which is roughly the opposite of a C99 "extern inline" + /// function. + bool isExternGNUInline() const; + + /// isOverloadedOperator - Whether this function declaration + /// represents an C++ overloaded operator, e.g., "operator+". + bool isOverloadedOperator() const { + return getOverloadedOperator() != OO_None; + }; + + OverloadedOperatorKind getOverloadedOperator() const; + + /// \brief If this function is an instantiation of a member function + /// of a class template specialization, retrieves the function from + /// which it was instantiated. + /// + /// This routine will return non-NULL for (non-templated) member + /// functions of class templates and for instantiations of function + /// templates. For example, given: + /// + /// \code + /// template<typename T> + /// struct X { + /// void f(T); + /// }; + /// \endcode + /// + /// The declaration for X<int>::f is a (non-templated) FunctionDecl + /// whose parent is the class template specialization X<int>. For + /// this declaration, getInstantiatedFromFunction() will return + /// 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 TemplateOrInstantiation.dyn_cast<FunctionDecl*>(); + } + + /// \brief Specify that this record is an instantiation of the + /// member function RD. + void setInstantiationOfMemberFunction(FunctionDecl *RD) { + TemplateOrInstantiation = RD; + } + + /// \brief Retrieves the function template that is described by this + /// function declaration. + /// + /// Every function template is represented as a FunctionTemplateDecl + /// and a FunctionDecl (or something derived from FunctionDecl). The + /// former contains template properties (such as the template + /// parameter lists) while the latter contains the actual + /// description of the template's + /// contents. FunctionTemplateDecl::getTemplatedDecl() retrieves the + /// FunctionDecl that describes the function template, + /// getDescribedFunctionTemplate() retrieves the + /// FunctionTemplateDecl from a FunctionDecl. + FunctionTemplateDecl *getDescribedFunctionTemplate() const { + return TemplateOrInstantiation.dyn_cast<FunctionTemplateDecl*>(); + } + + void setDescribedFunctionTemplate(FunctionTemplateDecl *Template) { + TemplateOrInstantiation = Template; + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast; + } + static bool classof(const FunctionDecl *D) { return true; } + static DeclContext *castToDeclContext(const FunctionDecl *D) { + return static_cast<DeclContext *>(const_cast<FunctionDecl*>(D)); + } + static FunctionDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC)); + } +}; + + +/// FieldDecl - An instance of this class is created by Sema::ActOnField to +/// represent a member of a struct/union/class. +class FieldDecl : public ValueDecl { + // 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) + { } + +public: + static FieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType T, Expr *BW, + bool Mutable); + + /// isMutable - Determines whether this field is mutable (C++ only). + bool isMutable() const { return Mutable; } + + /// \brief Set whether this field is mutable (C++ only). + void setMutable(bool M) { Mutable = M; } + + /// isBitfield - Determines whether this field is a bitfield. + bool isBitField() const { return BitWidth != NULL; } + + /// @brief Determines whether this is an unnamed bitfield. + bool isUnnamedBitfield() const { return BitWidth != NULL && !getDeclName(); } + + /// isAnonymousStructOrUnion - Determines whether this field is a + /// representative for an anonymous struct or union. Such fields are + /// unnamed and are implicitly generated by the implementation to + /// store the data for the anonymous union or struct. + bool isAnonymousStructOrUnion() const; + + Expr *getBitWidth() const { return BitWidth; } + void setBitWidth(Expr *BW) { BitWidth = BW; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() >= FieldFirst && D->getKind() <= FieldLast; + } + static bool classof(const FieldDecl *D) { return true; } +}; + +/// EnumConstantDecl - An instance of this object exists for each enum constant +/// that is defined. For example, in "enum X {a,b}", each of a/b are +/// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a +/// TagType for the X EnumDecl. +class EnumConstantDecl : public ValueDecl { + Stmt *Init; // an integer constant expression + llvm::APSInt Val; // The value. +protected: + EnumConstantDecl(DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType T, Expr *E, + const llvm::APSInt &V) + : ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {} + + virtual ~EnumConstantDecl() {} +public: + + static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC, + 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; } + Expr *getInitExpr() { return (Expr*) Init; } + const llvm::APSInt &getInitVal() const { return Val; } + + 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; +}; + + +/// TypeDecl - Represents a declaration of a type. +/// +class TypeDecl : public NamedDecl { + /// TypeForDecl - This indicates the Type object that represents + /// this TypeDecl. It is a cache maintained by + /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and + /// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl. + mutable Type *TypeForDecl; + friend class ASTContext; + friend class DeclContext; + friend class TagDecl; + friend class TemplateTypeParmDecl; + friend class ClassTemplateSpecializationDecl; + friend class TagType; + +protected: + TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id) + : NamedDecl(DK, DC, L, Id), TypeForDecl(0) {} + +public: + // Low-level accessor + Type *getTypeForDecl() const { return TypeForDecl; } + void setTypeForDecl(Type *TD) { TypeForDecl = TD; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() >= TypeFirst && D->getKind() <= TypeLast; + } + static bool classof(const TypeDecl *D) { return true; } +}; + + +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) + : 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; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return D->getKind() == Typedef; } + static bool classof(const TypedefDecl *D) { return true; } +}; + +class TypedefDecl; + +/// TagDecl - Represents the declaration of a struct/union/class/enum. +class TagDecl : public TypeDecl, public DeclContext { +public: + enum TagKind { + TK_struct, + TK_union, + TK_class, + TK_enum + }; + +private: + // FIXME: This can be packed into the bitfields in Decl. + /// TagDeclKind - The TagKind enum. + unsigned TagDeclKind : 2; + + /// 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; + +protected: + TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id) + : TypeDecl(DK, DC, L, Id), DeclContext(DK), TypedefForAnonDecl(0) { + assert((DK != Enum || TK == TK_enum) &&"EnumDecl not matched with TK_enum"); + TagDeclKind = TK; + IsDefinition = false; + } +public: + + /// isDefinition - Return true if this decl has its body specified. + bool isDefinition() const { + return IsDefinition; + } + + /// \brief Whether this declaration declares a type that is + /// dependent, i.e., a type that somehow depends on template + /// parameters. + 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. + void startDefinition(); + + /// @brief Completes the definition of this tag declaration. + void completeDefinition(); + + /// 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 + /// specific TagDecl is defining declaration, not whether or not the + /// 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"; + } + } + + TagKind getTagKind() const { + return TagKind(TagDeclKind); + } + + void setTagKind(TagKind TK) { TagDeclKind = TK; } + + bool isStruct() const { return getTagKind() == TK_struct; } + 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; + } + static bool classof(const TagDecl *D) { return true; } + + static DeclContext *castToDeclContext(const TagDecl *D) { + return static_cast<DeclContext *>(const_cast<TagDecl*>(D)); + } + static TagDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<TagDecl *>(const_cast<DeclContext*>(DC)); + } + + void setDefinition(bool V) { IsDefinition = V; } +}; + +/// EnumDecl - Represents an enum. As an extension, we allow forward-declared +/// enums. +class EnumDecl : public TagDecl { + /// IntegerType - This represent the integer type that the enum corresponds + /// to for code generation purposes. Note that the enumerator constants may + /// have a different type than this does. + QualType IntegerType; + + /// \brief If the enumeration was instantiated from an enumeration + /// within a class or function template, this pointer refers to the + /// enumeration declared within the template. + EnumDecl *InstantiatedFrom; + + EnumDecl(DeclContext *DC, SourceLocation L, + IdentifierInfo *Id) + : TagDecl(Enum, TK_enum, DC, L, Id), InstantiatedFrom(0) { + IntegerType = QualType(); + } +public: + static EnumDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + EnumDecl *PrevDecl); + + virtual void Destroy(ASTContext& C); + + /// completeDefinition - When created, the EnumDecl corresponds to a + /// forward-declared enum. This method is used to mark the + /// declaration as being defined; it's enumerators have already been + /// added (via DeclContext::addDecl). NewType is the new underlying + /// type of the enumeration type. + void completeDefinition(ASTContext &C, QualType NewType); + + // enumerator_iterator - Iterates through the enumerators of this + // enumeration. + typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator; + + enumerator_iterator enumerator_begin(ASTContext &Context) const { + return enumerator_iterator(this->decls_begin(Context)); + } + + enumerator_iterator enumerator_end(ASTContext &Context) const { + return enumerator_iterator(this->decls_end(Context)); + } + + /// getIntegerType - Return the integer type this enum decl corresponds to. + /// This returns a null qualtype for an enum forward definition. + QualType getIntegerType() const { return IntegerType; } + + /// \brief Set the underlying integer type. + void setIntegerType(QualType T) { IntegerType = T; } + + /// \brief Returns the enumeration (declared within the template) + /// from which this enumeration type was instantiated, or NULL if + /// this enumeration was not instantiated from any template. + EnumDecl *getInstantiatedFromMemberEnum() const { + return InstantiatedFrom; + } + + void setInstantiationOfMemberEnum(EnumDecl *IF) { InstantiatedFrom = IF; } + + static bool classof(const Decl *D) { return D->getKind() == Enum; } + static bool classof(const EnumDecl *D) { return true; } +}; + + +/// RecordDecl - Represents a struct/union/class. For example: +/// struct X; // Forward declaration, no "body". +/// union Y { int A, B; }; // Has body with members A and B (FieldDecls). +/// This decl will be marked invalid if *any* members are invalid. +/// +class RecordDecl : public TagDecl { + // FIXME: This can be packed into the bitfields in Decl. + /// HasFlexibleArrayMember - This is true if this struct ends with a flexible + /// array member (e.g. int X[]) or if this union contains a struct that does. + /// If so, this cannot be contained in arrays or other structs as a member. + bool HasFlexibleArrayMember : 1; + + /// AnonymousStructOrUnion - Whether this is the type of an + /// anonymous struct or union. + bool AnonymousStructOrUnion : 1; + +protected: + RecordDecl(Kind DK, TagKind TK, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id); + virtual ~RecordDecl(); + +public: + static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + RecordDecl* PrevDecl = 0); + + virtual void Destroy(ASTContext& C); + + bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; } + void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; } + + /// isAnonymousStructOrUnion - Whether this is an anonymous struct + /// or union. To be an anonymous struct or union, it must have been + /// declared without a name and there must be no objects of this + /// type declared, e.g., + /// @code + /// union { int i; float f; }; + /// @endcode + /// is an anonymous union but neither of the following are: + /// @code + /// union X { int i; float f; }; + /// union { int i; float f; } obj; + /// @endcode + bool isAnonymousStructOrUnion() const { return AnonymousStructOrUnion; } + void setAnonymousStructOrUnion(bool Anon) { + AnonymousStructOrUnion = Anon; + } + + /// \brief Determines whether this declaration represents the + /// injected class name. + /// + /// The injected class name in C++ is the name of the class that + /// appears inside the class itself. For example: + /// + /// \code + /// struct C { + /// // C is implicitly declared here as a synonym for the class name. + /// }; + /// + /// C::C c; // same as "C c;" + /// \endcode + bool isInjectedClassName() const; + + /// 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 + /// RecordDecl is defining declaration, not whether or not the record + /// type is defined. This method returns NULL if there is no RecordDecl + /// that defines the struct/union/tag. + 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. + typedef specific_decl_iterator<FieldDecl> field_iterator; + + field_iterator field_begin(ASTContext &Context) const { + return field_iterator(decls_begin(Context)); + } + field_iterator field_end(ASTContext &Context) const { + return field_iterator(decls_end(Context)); + } + + // field_empty - Whether there are any fields (non-static data + // members) in this record. + bool field_empty(ASTContext &Context) const { + return field_begin(Context) == field_end(Context); + } + + /// completeDefinition - Notes that the definition of this type is + /// now complete. + void completeDefinition(ASTContext& C); + + static bool classof(const Decl *D) { + return D->getKind() >= RecordFirst && D->getKind() <= RecordLast; + } + static bool classof(const RecordDecl *D) { return true; } +}; + +class FileScopeAsmDecl : public Decl { + StringLiteral *AsmString; + FileScopeAsmDecl(DeclContext *DC, SourceLocation L, StringLiteral *asmstring) + : Decl(FileScopeAsm, DC, L), AsmString(asmstring) {} +public: + static FileScopeAsmDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, StringLiteral *Str); + + const StringLiteral *getAsmString() const { return AsmString; } + StringLiteral *getAsmString() { return AsmString; } + void setAsmString(StringLiteral *Asm) { AsmString = Asm; } + + static bool classof(const Decl *D) { + return D->getKind() == FileScopeAsm; + } + static bool classof(const FileScopeAsmDecl *D) { return true; } +}; + +/// BlockDecl - This represents a block literal declaration, which is like an +/// unnamed FunctionDecl. For example: +/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body } +/// +class BlockDecl : public Decl, public DeclContext { + // FIXME: This can be packed into the bitfields in Decl. + bool isVariadic : 1; + /// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal + /// parameters of this function. This is null if a prototype or if there are + /// no formals. + ParmVarDecl **ParamInfo; + unsigned NumParams; + + Stmt *Body; + +protected: + BlockDecl(DeclContext *DC, SourceLocation CaretLoc) + : Decl(Block, DC, CaretLoc), DeclContext(Block), + isVariadic(false), ParamInfo(0), NumParams(0), Body(0) {} + + virtual ~BlockDecl(); + virtual void Destroy(ASTContext& C); + +public: + static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); + + SourceLocation getCaretLocation() const { return getLocation(); } + + bool IsVariadic() const { return isVariadic; } + void setIsVariadic(bool value) { isVariadic = value; } + + CompoundStmt *getBody() const { return (CompoundStmt*) Body; } + Stmt *getBody(ASTContext &C) const { return (Stmt*) Body; } + void setBody(CompoundStmt *B) { Body = (Stmt*) B; } + + // Iterator access to formal parameters. + 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 #"); + return ParamInfo[i]; + } + ParmVarDecl *getParamDecl(unsigned i) { + assert(i < getNumParams() && "Illegal param #"); + 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 DeclContext *castToDeclContext(const BlockDecl *D) { + return static_cast<DeclContext *>(const_cast<BlockDecl*>(D)); + } + static BlockDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<BlockDecl *>(const_cast<DeclContext*>(DC)); + } +}; + +/// Insertion operator for diagnostics. This allows sending NamedDecl's +/// into a diagnostic with <<. +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + NamedDecl* ND) { + DB.AddTaggedVal(reinterpret_cast<intptr_t>(ND), Diagnostic::ak_nameddecl); + return DB; +} + +} // end namespace clang + +#endif diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h new file mode 100644 index 000000000000..c061b857063a --- /dev/null +++ b/include/clang/AST/DeclBase.h @@ -0,0 +1,900 @@ +//===-- DeclBase.h - Base Classes for representing declarations -*- 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 Decl and DeclContext interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLBASE_H +#define LLVM_CLANG_AST_DECLBASE_H + +#include "clang/AST/Attr.h" +#include "clang/AST/Type.h" +// FIXME: Layering violation +#include "clang/Parse/AccessSpecifier.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/ADT/PointerUnion.h" + +namespace clang { +class DeclContext; +class TranslationUnitDecl; +class NamespaceDecl; +class UsingDirectiveDecl; +class NamedDecl; +class FunctionDecl; +class CXXRecordDecl; +class EnumDecl; +class ObjCMethodDecl; +class ObjCContainerDecl; +class ObjCInterfaceDecl; +class ObjCCategoryDecl; +class ObjCProtocolDecl; +class ObjCImplementationDecl; +class ObjCCategoryImplDecl; +class LinkageSpecDecl; +class BlockDecl; +class DeclarationName; +class CompoundStmt; +} + +namespace llvm { +// DeclContext* is only 4-byte aligned on 32-bit systems. +template<> + class PointerLikeTypeTraits<clang::DeclContext*> { + typedef clang::DeclContext* PT; +public: + static inline void *getAsVoidPointer(PT P) { return P; } + static inline PT getFromVoidPointer(void *P) { + return static_cast<PT>(P); + } + enum { NumLowBitsAvailable = 2 }; +}; +} + +namespace clang { + +/// Decl - This represents one declaration (or definition), e.g. a variable, +/// typedef, function, struct, etc. +/// +class Decl { +public: + /// \brief Lists the kind of concrete classes of Decl. + enum Kind { +#define DECL(Derived, Base) Derived, +#define DECL_RANGE(CommonBase, Start, 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" + }; + + /// IdentifierNamespace - According to C99 6.2.3, there are four + /// namespaces, labels, tags, members and ordinary + /// identifiers. These are meant as bitmasks, so that searches in + /// C++ can look into the "tag" namespace during ordinary lookup. We + /// use additional namespaces for Objective-C entities. + enum IdentifierNamespace { + IDNS_Label = 0x1, + IDNS_Tag = 0x2, + IDNS_Member = 0x4, + IDNS_Ordinary = 0x8, + IDNS_ObjCProtocol = 0x10, + IDNS_ObjCImplementation = 0x20, + IDNS_ObjCCategoryImpl = 0x40 + }; + + /// 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). + enum ObjCDeclQualifier { + OBJC_TQ_None = 0x0, + OBJC_TQ_In = 0x1, + OBJC_TQ_Inout = 0x2, + OBJC_TQ_Out = 0x4, + OBJC_TQ_Bycopy = 0x8, + 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 + /// traversed via DeclContext's decls_begin()/decls_end(). + Decl *NextDeclInContext; + + friend class DeclContext; + + struct MultipleDC { + 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. + /// For declarations with C++ scope specifiers, it contains a MultipleDC* + /// with the context where it semantically belongs (SemanticDC) and the + /// context where it was lexically declared (LexicalDC). + /// e.g.: + /// + /// namespace A { + /// void f(); // SemanticDC == LexicalDC == 'namespace A' + /// } + /// void A::f(); // SemanticDC == namespace 'A' + /// // LexicalDC == global namespace + llvm::PointerUnion<DeclContext*, MultipleDC*> DeclCtx; + + inline bool isInSemaDC() const { return DeclCtx.is<DeclContext*>(); } + inline bool isOutOfSemaDC() const { return DeclCtx.is<MultipleDC*>(); } + inline MultipleDC *getMultipleDC() const { + return DeclCtx.get<MultipleDC*>(); + } + 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; + + /// Implicit - Whether this declaration was implicitly generated by + /// the implementation rather than explicitly written by the user. + bool Implicit : 1; + + /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. + unsigned IdentifierNamespace : 8; + +#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), + Loc(L), DeclKind(DK), InvalidDecl(0), + HasAttrs(false), Implicit(false), + IdentifierNamespace(getIdentifierNamespaceForKind(DK)), Access(AS_none) { + if (Decl::CollectingStats()) addDeclKind(DK); + } + + virtual ~Decl(); + +public: + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + + Kind getKind() const { return DeclKind; } + const char *getDeclKindName() const; + + Decl *getNextDeclInContext() { return NextDeclInContext; } + const Decl *getNextDeclInContext() const { return NextDeclInContext; } + + DeclContext *getDeclContext() { + if (isInSemaDC()) + return getSemanticDC(); + return getMultipleDC()->SemanticDC; + } + const DeclContext *getDeclContext() const { + return const_cast<Decl*>(this)->getDeclContext(); + } + + void setAccess(AccessSpecifier AS) { + Access = AS; + CheckAccessDeclContext(); + } + + AccessSpecifier getAccess() const { + CheckAccessDeclContext(); + return AccessSpecifier(Access); + } + + bool hasAttrs() const { return HasAttrs; } + void addAttr(Attr *attr); + const Attr *getAttrs() const { + if (!HasAttrs) return 0; // common case, no attributes. + return getAttrsImpl(); // Uncommon case, out of line hash lookup. + } + void swapAttrs(Decl *D); + void invalidateAttrs(); + + template<typename T> const T *getAttr() const { + for (const Attr *attr = getAttrs(); attr; attr = attr->getNext()) + if (const T *V = dyn_cast<T>(attr)) + return V; + return 0; + } + + 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; } + bool isInvalidDecl() const { return (bool) InvalidDecl; } + + /// isImplicit - Indicates whether the declaration was implicitly + /// generated by the implementation. If false, this declaration + /// was written explicitly in the source code. + bool isImplicit() const { return Implicit; } + void setImplicit(bool I = true) { Implicit = I; } + + unsigned getIdentifierNamespace() const { + return IdentifierNamespace; + } + bool isInIdentifierNamespace(unsigned NS) const { + return getIdentifierNamespace() & NS; + } + static unsigned getIdentifierNamespaceForKind(Kind DK); + + + /// getLexicalDeclContext - The declaration context where this Decl was + /// lexically declared (LexicalDC). May be different from + /// getDeclContext() (SemanticDC). + /// e.g.: + /// + /// namespace A { + /// void f(); // SemanticDC == LexicalDC == 'namespace A' + /// } + /// void A::f(); // SemanticDC == namespace 'A' + /// // LexicalDC == global namespace + DeclContext *getLexicalDeclContext() { + if (isInSemaDC()) + return getSemanticDC(); + return getMultipleDC()->LexicalDC; + } + const DeclContext *getLexicalDeclContext() const { + return const_cast<Decl*>(this)->getLexicalDeclContext(); + } + + /// setDeclContext - Set both the semantic and lexical DeclContext + /// to DC. + void setDeclContext(DeclContext *DC); + + void setLexicalDeclContext(DeclContext *DC); + + // isDefinedOutsideFunctionOrMethod - This predicate returns true if this + // scoped decl is defined outside the current function or method. This is + // roughly global variables and functions, but also handles enums (which could + // be defined inside or outside a function etc). + bool isDefinedOutsideFunctionOrMethod() const; + + /// 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. + virtual Stmt* getBody(ASTContext &Context) const { return 0; } + + /// getCompoundBody - Returns getBody(), dyn_casted to a CompoundStmt. + CompoundStmt* getCompoundBody(ASTContext &Context) const; + + /// getBodyRBrace - Gets the right brace of the body, if a body exists. + /// This works whether the body is a CompoundStmt or a CXXTryStmt. + SourceLocation getBodyRBrace(ASTContext &Context) const; + + // global temp stats (until we have a per-module visitor) + static void addDeclKind(Kind k); + static bool CollectingStats(bool Enable = false); + static void PrintStats(); + + /// isTemplateParameter - Determines whether this declartion is a + /// template parameter. + bool isTemplateParameter() const; + + // 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, ASTContext &Context, + unsigned Indentation = 0); + void print(llvm::raw_ostream &Out, ASTContext &Context, + const PrintingPolicy &Policy, unsigned Indentation = 0); + static void printGroup(Decl** Begin, unsigned NumDecls, + llvm::raw_ostream &Out, ASTContext &Context, + const PrintingPolicy &Policy, + unsigned Indentation = 0); + void dump(ASTContext &Context); + +private: + const Attr *getAttrsImpl() const; + +}; + +/// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when +/// doing something to a specific decl. +class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry { + Decl *TheDecl; + SourceLocation Loc; + SourceManager &SM; + const char *Message; +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 +/// that directly derive from DeclContext are mentioned, not their subclasses): +/// +/// TranslationUnitDecl +/// NamespaceDecl +/// FunctionDecl +/// TagDecl +/// ObjCMethodDecl +/// ObjCContainerDecl +/// ObjCCategoryImplDecl +/// ObjCImplementationDecl +/// LinkageSpecDecl +/// BlockDecl +/// +class DeclContext { + /// DeclKind - This indicates which class this is. + Decl::Kind DeclKind : 8; + + /// \brief Whether this declaration context also has some external + /// storage that contains additional declarations that are lexically + /// part of this context. + mutable bool ExternalLexicalStorage : 1; + + /// \brief Whether this declaration context also has some external + /// storage that contains additional declarations that are visible + /// in this context. + mutable bool ExternalVisibleStorage : 1; + + /// \brief Pointer to the data structure used to lookup declarations + /// within this context, which is a DenseMap<DeclarationName, + /// StoredDeclsList>. + mutable void* LookupPtr; + + /// FirstDecl - The first declaration stored within this declaration + /// context. + mutable Decl *FirstDecl; + + /// LastDecl - The last declaration stored within this declaration + /// context. FIXME: We could probably cache this value somewhere + /// outside of the DeclContext, to reduce the size of DeclContext by + /// another pointer. + mutable Decl *LastDecl; + +protected: + DeclContext(Decl::Kind K) + : DeclKind(K), ExternalLexicalStorage(false), + ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0), + LastDecl(0) { } + + void DestroyDecls(ASTContext &C); + +public: + ~DeclContext(); + + Decl::Kind getDeclKind() const { + return DeclKind; + } + const char *getDeclKindName() const; + + /// getParent - Returns the containing DeclContext. + DeclContext *getParent() { + return cast<Decl>(this)->getDeclContext(); + } + const DeclContext *getParent() const { + return const_cast<DeclContext*>(this)->getParent(); + } + + /// getLexicalParent - Returns the containing lexical DeclContext. May be + /// different from getParent, e.g.: + /// + /// namespace A { + /// struct S; + /// } + /// struct A::S {}; // getParent() == namespace 'A' + /// // getLexicalParent() == translation unit + /// + DeclContext *getLexicalParent() { + return cast<Decl>(this)->getLexicalDeclContext(); + } + const DeclContext *getLexicalParent() const { + return const_cast<DeclContext*>(this)->getLexicalParent(); + } + + bool isFunctionOrMethod() const { + switch (DeclKind) { + case Decl::Block: + case Decl::ObjCMethod: + return true; + default: + return DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast; + } + } + + bool isFileContext() const { + return DeclKind == Decl::TranslationUnit || DeclKind == Decl::Namespace; + } + + bool isTranslationUnit() const { + return DeclKind == Decl::TranslationUnit; + } + + bool isRecord() const { + return DeclKind >= Decl::RecordFirst && DeclKind <= Decl::RecordLast; + } + + bool isNamespace() const { + return DeclKind == Decl::Namespace; + } + + /// \brief Determines whether this context is dependent on a + /// template parameter. + bool isDependentContext() const; + + /// isTransparentContext - Determines whether this context is a + /// "transparent" context, meaning that the members declared in this + /// 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: + /// @code + /// enum E { + /// Val1 + /// }; + /// @endcode + /// Here, E is a transparent context, so its enumerator (Val1) will + /// appear (semantically) that it is in the same context of E. + /// Examples of transparent contexts include: enumerations (except for + /// C++0x scoped enums), C++ linkage specifications, and C++0x + /// inline namespaces. + bool isTransparentContext() const; + + bool Encloses(DeclContext *DC) const { + for (; DC; DC = DC->getParent()) + if (DC == this) + return true; + return false; + } + + /// getPrimaryContext - There may be many different + /// declarations of the same entity (including forward declarations + /// of classes, multiple definitions of namespaces, etc.), each with + /// a different set of declarations. This routine returns the + /// "primary" DeclContext structure, which will contain the + /// information needed to perform name lookup into this context. + DeclContext *getPrimaryContext(); + + /// getLookupContext - Retrieve the innermost non-transparent + /// context of this context, which corresponds to the innermost + /// location from which name lookup can find the entities in this + /// context. + DeclContext *getLookupContext(); + const DeclContext *getLookupContext() const { + return const_cast<DeclContext *>(this)->getLookupContext(); + } + + /// \brief Retrieve the nearest enclosing namespace context. + DeclContext *getEnclosingNamespaceContext(); + const DeclContext *getEnclosingNamespaceContext() const { + return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext(); + } + + /// getNextContext - If this is a DeclContext that may have other + /// DeclContexts that are semantically connected but syntactically + /// different, such as C++ namespaces, this routine retrieves the + /// next DeclContext in the link. Iteration through the chain of + /// DeclContexts should begin at the primary DeclContext and + /// continue until this function returns NULL. For example, given: + /// @code + /// namespace N { + /// int x; + /// } + /// namespace N { + /// int y; + /// } + /// @endcode + /// The first occurrence of namespace N will be the primary + /// DeclContext. Its getNextContext will return the second + /// occurrence of namespace N. + DeclContext *getNextContext(); + + /// decl_iterator - Iterates through the declarations stored + /// within this context. + class decl_iterator { + /// Current - The current declaration. + Decl *Current; + + public: + typedef Decl* value_type; + typedef Decl* reference; + typedef Decl* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + decl_iterator() : Current(0) { } + explicit decl_iterator(Decl *C) : Current(C) { } + + reference operator*() const { return Current; } + pointer operator->() const { return Current; } + + decl_iterator& operator++() { + Current = Current->getNextDeclInContext(); + return *this; + } + + decl_iterator operator++(int) { + decl_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(decl_iterator x, decl_iterator y) { + return x.Current == y.Current; + } + 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. + decl_iterator decls_begin(ASTContext &Context) const; + decl_iterator decls_end(ASTContext &Context) const; + bool decls_empty(ASTContext &Context) const; + + /// specific_decl_iterator - Iterates over a subrange of + /// declarations stored in a DeclContext, providing only those that + /// are of type SpecificDecl (or a class derived from it). This + /// iterator is used, for example, to provide iteration over just + /// the fields within a RecordDecl (with SpecificDecl = FieldDecl). + template<typename SpecificDecl> + class specific_decl_iterator { + /// Current - The current, underlying declaration iterator, which + /// 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. + void SkipToNextDecl() { + while (*Current && !isa<SpecificDecl>(*Current)) + ++Current; + } + + public: + typedef SpecificDecl* value_type; + typedef SpecificDecl* reference; + typedef SpecificDecl* pointer; + typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type + difference_type; + typedef std::forward_iterator_tag iterator_category; + + specific_decl_iterator() : Current() { } + + /// specific_decl_iterator - Construct a new iterator over a + /// subset of the declarations the range [C, + /// end-of-declarations). If A is non-NULL, it is a pointer to a + /// member function of SpecificDecl that should return true for + /// all of the SpecificDecl instances that will be in the subset + /// of iterators. For example, if you want Objective-C instance + /// methods, SpecificDecl will be ObjCMethodDecl and A will be + /// &ObjCMethodDecl::isInstanceMethod. + explicit specific_decl_iterator(DeclContext::decl_iterator C) : Current(C) { + SkipToNextDecl(); + } + + reference operator*() const { return cast<SpecificDecl>(*Current); } + pointer operator->() const { return cast<SpecificDecl>(*Current); } + + specific_decl_iterator& operator++() { + ++Current; + SkipToNextDecl(); + return *this; + } + + specific_decl_iterator operator++(int) { + specific_decl_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool + operator==(const specific_decl_iterator& x, const specific_decl_iterator& y) { + return x.Current == y.Current; + } + + friend bool + operator!=(const specific_decl_iterator& x, const specific_decl_iterator& y) { + return x.Current != y.Current; + } + }; + + /// \brief Iterates over a filtered subrange of declarations stored + /// in a DeclContext. + /// + /// This iterator visits only those declarations that are of type + /// SpecificDecl (or a class derived from it) and that meet some + /// additional run-time criteria. This iterator is used, for + /// example, to provide access to the instance methods within an + /// Objective-C interface (with SpecificDecl = ObjCMethodDecl and + /// Acceptable = ObjCMethodDecl::isInstanceMethod). + template<typename SpecificDecl, bool (SpecificDecl::*Acceptable)() const> + class filtered_decl_iterator { + /// Current - The current, underlying declaration iterator, which + /// 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. + void SkipToNextDecl() { + while (*Current && + (!isa<SpecificDecl>(*Current) || + (Acceptable && !(cast<SpecificDecl>(*Current)->*Acceptable)()))) + ++Current; + } + + public: + typedef SpecificDecl* value_type; + typedef SpecificDecl* reference; + typedef SpecificDecl* pointer; + typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type + difference_type; + typedef std::forward_iterator_tag iterator_category; + + filtered_decl_iterator() : Current() { } + + /// specific_decl_iterator - Construct a new iterator over a + /// subset of the declarations the range [C, + /// end-of-declarations). If A is non-NULL, it is a pointer to a + /// member function of SpecificDecl that should return true for + /// all of the SpecificDecl instances that will be in the subset + /// of iterators. For example, if you want Objective-C instance + /// methods, SpecificDecl will be ObjCMethodDecl and A will be + /// &ObjCMethodDecl::isInstanceMethod. + explicit filtered_decl_iterator(DeclContext::decl_iterator C) : Current(C) { + SkipToNextDecl(); + } + + reference operator*() const { return cast<SpecificDecl>(*Current); } + pointer operator->() const { return cast<SpecificDecl>(*Current); } + + filtered_decl_iterator& operator++() { + ++Current; + SkipToNextDecl(); + return *this; + } + + filtered_decl_iterator operator++(int) { + filtered_decl_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool + operator==(const filtered_decl_iterator& x, const filtered_decl_iterator& y) { + return x.Current == y.Current; + } + + friend bool + operator!=(const filtered_decl_iterator& x, const filtered_decl_iterator& y) { + return x.Current != y.Current; + } + }; + + /// @brief Add the declaration D into this context. + /// + /// This routine should be invoked when the declaration D has first + /// been declared, to place D into the context where it was + /// (lexically) defined. Every declaration must be added to one + /// (and only one!) context, where it can be visited via + /// [decls_begin(), decls_end()). Once a declaration has been added + /// to its lexical context, the corresponding DeclContext owns the + /// declaration. + /// + /// If D is also a NamedDecl, it will be made visible within its + /// semantic context via makeDeclVisibleInContext. + void addDecl(ASTContext &Context, Decl *D); + + /// lookup_iterator - An iterator that provides access to the results + /// of looking up a name within this context. + typedef NamedDecl **lookup_iterator; + + /// lookup_const_iterator - An iterator that provides non-mutable + /// access to the results of lookup up a name within this context. + typedef NamedDecl * const * lookup_const_iterator; + + typedef std::pair<lookup_iterator, lookup_iterator> lookup_result; + typedef std::pair<lookup_const_iterator, lookup_const_iterator> + lookup_const_result; + + /// lookup - Find the declarations (if any) with the given Name in + /// this context. Returns a range of iterators that contains all of + /// the declarations with this name, with object, function, member, + /// and enumerator names preceding any tag name. Note that this + /// routine will not look into parent contexts. + lookup_result lookup(ASTContext &Context, DeclarationName Name); + lookup_const_result lookup(ASTContext &Context, DeclarationName Name) const; + + /// @brief Makes a declaration visible within this context. + /// + /// This routine makes the declaration D visible to name lookup + /// within this context and, if this is a transparent context, + /// within its parent contexts up to the first enclosing + /// non-transparent context. Making a declaration visible within a + /// context does not transfer ownership of a declaration, and a + /// declaration can be visible in many contexts that aren't its + /// lexical context. + /// + /// If D is a redeclaration of an existing declaration that is + /// visible from this context, as determined by + /// NamedDecl::declarationReplaces, the previous declaration will be + /// replaced with D. + void makeDeclVisibleInContext(ASTContext &Context, NamedDecl *D); + + /// 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(ASTContext &Context) const; + + udir_iterator using_directives_begin(ASTContext &Context) const { + return getUsingDirectives(Context).first; + } + + udir_iterator using_directives_end(ASTContext &Context) const { + return getUsingDirectives(Context).second; + } + + // Low-level accessors + + /// \brief Retrieve the internal representation of the lookup structure. + void* getLookupPtr() const { return LookupPtr; } + + /// \brief Whether this DeclContext has external storage containing + /// additional declarations that are lexically in this context. + bool hasExternalLexicalStorage() const { return ExternalLexicalStorage; } + + /// \brief State whether this DeclContext has external storage for + /// declarations lexically in this context. + void setHasExternalLexicalStorage(bool ES = true) { + ExternalLexicalStorage = ES; + } + + /// \brief Whether this DeclContext has external storage containing + /// additional declarations that are visible in this context. + bool hasExternalVisibleStorage() const { return ExternalVisibleStorage; } + + /// \brief State whether this DeclContext has external storage for + /// declarations visible in this context. + void setHasExternalVisibleStorage(bool ES = true) { + ExternalVisibleStorage = ES; + } + + static bool classof(const Decl *D); + static bool classof(const DeclContext *D) { return true; } +#define DECL_CONTEXT(Name) \ + static bool classof(const Name##Decl *D) { return true; } +#include "clang/AST/DeclNodes.def" + +private: + void LoadLexicalDeclsFromExternalStorage(ASTContext &Context) const; + void LoadVisibleDeclsFromExternalStorage(ASTContext &Context) const; + + void buildLookup(ASTContext &Context, DeclContext *DCtx); + void makeDeclVisibleInContextImpl(ASTContext &Context, NamedDecl *D); +}; + +inline bool Decl::isTemplateParameter() const { + return getKind() == TemplateTypeParm || getKind() == NonTypeTemplateParm; +} + +inline bool Decl::isDefinedOutsideFunctionOrMethod() const { + if (getDeclContext()) + return !getDeclContext()->getLookupContext()->isFunctionOrMethod(); + return true; +} + +} // end clang. + +namespace llvm { + +/// Implement a isa_impl_wrap specialization to check whether a DeclContext is +/// a specific Decl. +template<class ToTy> +struct isa_impl_wrap<ToTy, + const ::clang::DeclContext,const ::clang::DeclContext> { + static bool doit(const ::clang::DeclContext &Val) { + return ToTy::classof(::clang::Decl::castFromDeclContext(&Val)); + } +}; +template<class ToTy> +struct isa_impl_wrap<ToTy, ::clang::DeclContext, ::clang::DeclContext> + : public isa_impl_wrap<ToTy, + const ::clang::DeclContext,const ::clang::DeclContext> {}; + +/// Implement cast_convert_val for Decl -> DeclContext conversions. +template<class FromTy> +struct cast_convert_val< ::clang::DeclContext, FromTy, FromTy> { + static ::clang::DeclContext &doit(const FromTy &Val) { + return *FromTy::castToDeclContext(&Val); + } +}; + +template<class FromTy> +struct cast_convert_val< ::clang::DeclContext, FromTy*, FromTy*> { + static ::clang::DeclContext *doit(const FromTy *Val) { + return FromTy::castToDeclContext(Val); + } +}; + +template<class FromTy> +struct cast_convert_val< const ::clang::DeclContext, FromTy, FromTy> { + static const ::clang::DeclContext &doit(const FromTy &Val) { + return *FromTy::castToDeclContext(&Val); + } +}; + +template<class FromTy> +struct cast_convert_val< const ::clang::DeclContext, FromTy*, FromTy*> { + static const ::clang::DeclContext *doit(const FromTy *Val) { + return FromTy::castToDeclContext(Val); + } +}; + +/// Implement cast_convert_val for DeclContext -> Decl conversions. +template<class ToTy> +struct cast_convert_val<ToTy, + const ::clang::DeclContext,const ::clang::DeclContext> { + static ToTy &doit(const ::clang::DeclContext &Val) { + return *reinterpret_cast<ToTy*>(ToTy::castFromDeclContext(&Val)); + } +}; +template<class ToTy> +struct cast_convert_val<ToTy, ::clang::DeclContext, ::clang::DeclContext> + : public cast_convert_val<ToTy, + const ::clang::DeclContext,const ::clang::DeclContext> {}; + +template<class ToTy> +struct cast_convert_val<ToTy, + const ::clang::DeclContext*, const ::clang::DeclContext*> { + static ToTy *doit(const ::clang::DeclContext *Val) { + return reinterpret_cast<ToTy*>(ToTy::castFromDeclContext(Val)); + } +}; +template<class ToTy> +struct cast_convert_val<ToTy, ::clang::DeclContext*, ::clang::DeclContext*> + : public cast_convert_val<ToTy, + const ::clang::DeclContext*,const ::clang::DeclContext*> {}; + +} // end namespace llvm + +#endif diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h new file mode 100644 index 000000000000..4a74a2c2cbc4 --- /dev/null +++ b/include/clang/AST/DeclCXX.h @@ -0,0 +1,1073 @@ +//===-- DeclCXX.h - Classes for representing C++ declarations -*- 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 C++ Decl subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLCXX_H +#define LLVM_CLANG_AST_DECLCXX_H + +#include "clang/AST/Decl.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + +class ClassTemplateDecl; +class CXXRecordDecl; +class CXXConstructorDecl; +class CXXDestructorDecl; +class CXXConversionDecl; +class CXXMethodDecl; +class ClassTemplateSpecializationDecl; + +/// 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. +/// +/// An OverloadedFunctionDecl has no ownership over the FunctionDecl +/// nodes it contains. Rather, the FunctionDecls are owned by the +/// enclosing scope (which also owns the OverloadedFunctionDecl +/// node). OverloadedFunctionDecl is used primarily to store a set of +/// overloaded functions for name lookup. +class OverloadedFunctionDecl : public NamedDecl { +protected: + OverloadedFunctionDecl(DeclContext *DC, DeclarationName N) + : NamedDecl(OverloadedFunction, DC, SourceLocation(), N) { } + + /// Functions - the set of overloaded functions contained in this + /// overload set. + llvm::SmallVector<FunctionDecl *, 4> Functions; + + // FIXME: This should go away when we stop using + // OverloadedFunctionDecl to store conversions in CXXRecordDecl. + friend class CXXRecordDecl; + +public: + typedef llvm::SmallVector<FunctionDecl *, 4>::iterator function_iterator; + typedef llvm::SmallVector<FunctionDecl *, 4>::const_iterator + function_const_iterator; + + static OverloadedFunctionDecl *Create(ASTContext &C, DeclContext *DC, + DeclarationName N); + + /// addOverload - Add an overloaded function FD to this set of + /// overloaded functions. + void addOverload(FunctionDecl *FD) { + assert((FD->getDeclName() == getDeclName() || + isa<CXXConversionDecl>(FD) || isa<CXXConstructorDecl>(FD)) && + "Overloaded functions must have the same name"); + Functions.push_back(FD); + + // An overloaded function declaration always has the location of + // the most-recently-added function declaration. + if (FD->getLocation().isValid()) + this->setLocation(FD->getLocation()); + } + + function_iterator function_begin() { return Functions.begin(); } + function_iterator function_end() { return Functions.end(); } + function_const_iterator function_begin() const { return Functions.begin(); } + function_const_iterator function_end() const { return Functions.end(); } + + /// getNumFunctions - the number of overloaded functions stored in + /// this set. + unsigned getNumFunctions() const { return Functions.size(); } + + /// getFunction - retrieve the ith function in the overload set. + const FunctionDecl *getFunction(unsigned i) const { + assert(i < getNumFunctions() && "Illegal function #"); + return Functions[i]; + } + FunctionDecl *getFunction(unsigned i) { + assert(i < getNumFunctions() && "Illegal function #"); + return Functions[i]; + } + + // getDeclContext - Get the context of these overloaded functions. + DeclContext *getDeclContext() { + assert(getNumFunctions() > 0 && "Context of an empty overload set"); + return getFunction(0)->getDeclContext(); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() == OverloadedFunction; + } + static bool classof(const OverloadedFunctionDecl *D) { return true; } +}; + +/// CXXBaseSpecifier - A base class of a C++ class. +/// +/// Each CXXBaseSpecifier represents a single, direct base class (or +/// struct) of a C++ class (or struct). It specifies the type of that +/// base class, whether it is a virtual or non-virtual base, and what +/// level of access (public, protected, private) is used for the +/// derivation. For example: +/// +/// @code +/// class A { }; +/// class B { }; +/// class C : public virtual A, protected B { }; +/// @endcode +/// +/// In this code, C will have two CXXBaseSpecifiers, one for "public +/// virtual A" and the other for "protected B". +class CXXBaseSpecifier { + /// Range - The source code range that covers the full base + /// specifier, including the "virtual" (if present) and access + /// specifier (if present). + SourceRange Range; + + /// Virtual - Whether this is a virtual base class or not. + bool Virtual : 1; + + /// BaseOfClass - Whether this is the base of a class (true) or of a + /// 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; + + /// Access - Access specifier as written in the source code (which + /// may be AS_none). The actual type of data stored here is an + /// AccessSpecifier, but we use "unsigned" here to work around a + /// VC++ bug. + unsigned Access : 2; + + /// BaseType - The type of the base class. This will be a class or + /// struct (or a typedef of such). + QualType BaseType; + +public: + CXXBaseSpecifier() { } + + CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, QualType T) + : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseType(T) { } + + /// 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; } + + /// getAccessSpecifier - Returns the access specifier for this base + /// specifier. This is the actual base specifier as used for + /// 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 { + if ((AccessSpecifier)Access == AS_none) + return BaseOfClass? AS_private : AS_public; + else + return (AccessSpecifier)Access; + } + + /// getAccessSpecifierAsWritten - Retrieves the access specifier as + /// written in the source code (which may mean that no access + /// specifier was explicitly written). Use getAccessSpecifier() to + /// retrieve the access specifier for use in semantic analysis. + AccessSpecifier getAccessSpecifierAsWritten() const { + return (AccessSpecifier)Access; + } + + /// getType - Retrieves the type of the base class. This type will + /// always be an unqualified class type. + QualType getType() const { return BaseType; } +}; + +/// CXXRecordDecl - Represents a C++ struct/union/class. +/// FIXME: This class will disappear once we've properly taught RecordDecl +/// to deal with C++-specific things. +class CXXRecordDecl : public RecordDecl { + /// UserDeclaredConstructor - True when this class has a + /// user-declared constructor. + bool UserDeclaredConstructor : 1; + + /// UserDeclaredCopyConstructor - True when this class has a + /// user-declared copy constructor. + bool UserDeclaredCopyConstructor : 1; + + /// UserDeclaredCopyAssignment - True when this class has a + /// user-declared copy assignment operator. + bool UserDeclaredCopyAssignment : 1; + + /// UserDeclaredDestructor - True when this class has a + /// user-declared destructor. + bool UserDeclaredDestructor : 1; + + /// Aggregate - True when this class is an aggregate. + bool Aggregate : 1; + + /// PlainOldData - True when this class is a POD-type. + bool PlainOldData : 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; + + /// 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 + bool HasTrivialConstructor : 1; + + /// HasTrivialDestructor - True when this class has a trivial destructor + bool HasTrivialDestructor : 1; + + /// Bases - Base classes of this class. + /// FIXME: This is wasted space for a union. + CXXBaseSpecifier *Bases; + + /// NumBases - The number of base class specifiers in Bases. + unsigned NumBases; + + /// 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. + OverloadedFunctionDecl Conversions; + + /// \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*> + TemplateOrInstantiation; + +protected: + CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id); + + ~CXXRecordDecl(); + +public: + /// base_class_iterator - Iterator that traverses the base classes + /// of a clas. + typedef CXXBaseSpecifier* base_class_iterator; + + /// base_class_const_iterator - Iterator that traverses the base + /// classes of a clas. + typedef const CXXBaseSpecifier* base_class_const_iterator; + + static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + CXXRecordDecl* PrevDecl=0, + bool DelayTypeCreation = false); + + /// setBases - Sets the base classes of this struct or class. + void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases); + + /// getNumBases - Retrieves the number of base classes of this + /// class. + unsigned getNumBases() const { return NumBases; } + + base_class_iterator bases_begin() { return Bases; } + 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; } + + /// hasConstCopyConstructor - Determines whether this class has a + /// copy constructor that accepts a const-qualified argument. + bool hasConstCopyConstructor(ASTContext &Context) const; + + /// hasConstCopyAssignment - Determines whether this class has a + /// copy assignment operator that accepts a const-qualified argument. + bool hasConstCopyAssignment(ASTContext &Context) const; + + /// addedConstructor - Notify the class that another constructor has + /// been added. This routine helps maintain information about the + /// class based on which constructors have been added. + void addedConstructor(ASTContext &Context, CXXConstructorDecl *ConDecl); + + /// hasUserDeclaredConstructor - Whether this class has any + /// user-declared constructors. When true, a default constructor + /// will not be implicitly declared. + bool hasUserDeclaredConstructor() const { return UserDeclaredConstructor; } + + /// hasUserDeclaredCopyConstructor - Whether this class has a + /// user-declared copy constructor. When false, a copy constructor + /// will be implicitly declared. + bool hasUserDeclaredCopyConstructor() const { + return UserDeclaredCopyConstructor; + } + + /// addedAssignmentOperator - Notify the class that another assignment + /// operator has been added. This routine helps maintain information about the + /// class based on which operators have been added. + void addedAssignmentOperator(ASTContext &Context, CXXMethodDecl *OpDecl); + + /// hasUserDeclaredCopyAssignment - Whether this class has a + /// user-declared copy assignment operator. When false, a copy + /// assigment operator will be implicitly declared. + bool hasUserDeclaredCopyAssignment() const { + return UserDeclaredCopyAssignment; + } + + /// hasUserDeclaredDestructor - Whether this class has a + /// user-declared destructor. When false, a destructor will be + /// implicitly declared. + bool hasUserDeclaredDestructor() const { return UserDeclaredDestructor; } + + /// 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; + } + + /// getConversions - Retrieve the overload set containing all of the + /// conversion functions in this class. + OverloadedFunctionDecl *getConversionFunctions() { + return &Conversions; + } + const OverloadedFunctionDecl *getConversionFunctions() const { + return &Conversions; + } + + /// addConversionFunction - Add a new conversion function to the + /// list of conversion functions. + void addConversionFunction(ASTContext &Context, CXXConversionDecl *ConvDecl); + + /// isAggregate - Whether this class is an aggregate (C++ + /// [dcl.init.aggr]), which is a class with no user-declared + /// constructors, no private or protected non-static data members, + /// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1). + bool isAggregate() const { return Aggregate; } + + /// setAggregate - Set whether this class is an aggregate (C++ + /// [dcl.init.aggr]). + void setAggregate(bool Agg) { Aggregate = Agg; } + + /// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class + /// that is an aggregate that has no non-static non-POD data members, no + /// reference data members, no user-defined copy assignment operator and no + /// user-defined destructor. + bool isPOD() const { return PlainOldData; } + + /// setPOD - Set whether this class is a POD-type (C++ [class]p4). + void setPOD(bool POD) { PlainOldData = POD; } + + /// 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; } + + /// setPolymorphic - Set whether this class is polymorphic (C++ + /// [class.virtual]). + void setPolymorphic(bool Poly) { Polymorphic = Poly; } + + /// 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; } + + // 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. + /// + /// This routine will return non-NULL for (non-templated) member + /// classes of class templates. For example, given: + /// + /// \code + /// template<typename T> + /// struct X { + /// struct A { }; + /// }; + /// \endcode + /// + /// The declaration for X<int>::A is a (non-templated) CXXRecordDecl + /// whose parent is the class template specialization X<int>. For + /// this declaration, getInstantiatedFromMemberClass() will return + /// 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*>(); + } + + /// \brief Specify that this record is an instantiation of the + /// member class RD. + void setInstantiationOfMemberClass(CXXRecordDecl *RD) { + TemplateOrInstantiation = RD; + } + + /// \brief Retrieves the class template that is described by this + /// class declaration. + /// + /// Every class template is represented as a ClassTemplateDecl and a + /// CXXRecordDecl. The former contains template properties (such as + /// the template parameter lists) while the latter contains the + /// actual description of the template's + /// contents. ClassTemplateDecl::getTemplatedDecl() retrieves the + /// CXXRecordDecl that from a ClassTemplateDecl, while + /// getDescribedClassTemplate() retrieves the ClassTemplateDecl from + /// a CXXRecordDecl. + ClassTemplateDecl *getDescribedClassTemplate() const { + return TemplateOrInstantiation.dyn_cast<ClassTemplateDecl*>(); + } + + void setDescribedClassTemplate(ClassTemplateDecl *Template) { + TemplateOrInstantiation = Template; + } + + /// getDestructor - Returns the destructor decl for this class. + const CXXDestructorDecl *getDestructor(ASTContext &Context); + + /// 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 || + D->getKind() == ClassTemplateSpecialization || + D->getKind() == ClassTemplatePartialSpecialization; + } + static bool classof(const CXXRecordDecl *D) { return true; } + static bool classof(const ClassTemplateSpecializationDecl *D) { + return true; + } +}; + +/// CXXMethodDecl - Represents a static or instance method of a +/// struct/union/class. +class CXXMethodDecl : public FunctionDecl { +protected: + CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L, + DeclarationName N, QualType T, + bool isStatic, bool isInline) + : FunctionDecl(DK, RD, L, N, T, (isStatic ? Static : None), + isInline) {} + +public: + static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation L, DeclarationName N, + QualType T, bool isStatic = false, + bool isInline = false); + + bool isStatic() const { return getStorageClass() == Static; } + bool isInstance() const { return !isStatic(); } + + bool isOutOfLineDefinition() const { + return getLexicalDeclContext() != getDeclContext(); + } + + bool isVirtual() const { + return isVirtualAsWritten() || + (begin_overridden_methods() != end_overridden_methods()); + } + + /// + 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()); + } + + /// getParent - Returns the parent of this method declaration, which + /// is the class in which this method is defined. + CXXRecordDecl *getParent() { + return const_cast<CXXRecordDecl *>( + cast<CXXRecordDecl>(FunctionDecl::getParent())); + } + + /// getThisType - Returns the type of 'this' pointer. + /// Should only be called for instance methods. + QualType getThisType(ASTContext &C) const; + + unsigned getTypeQualifiers() const { + return getType()->getAsFunctionProtoType()->getTypeQuals(); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() >= CXXMethod && D->getKind() <= CXXConversion; + } + static bool classof(const CXXMethodDecl *D) { return true; } +}; + +/// CXXBaseOrMemberInitializer - Represents a C++ base or member +/// initializer, which is part of a constructor initializer that +/// initializes one non-static member variable or one base class. For +/// example, in the following, both 'A(a)' and 'f(3.14159)' are member +/// initializers: +/// +/// @code +/// class A { }; +/// class B : public A { +/// float f; +/// public: +/// B(A& a) : A(a), f(3.14159) { } +/// }; +class CXXBaseOrMemberInitializer { + /// BaseOrMember - This points to the entity being initialized, + /// which is either a base class (a Type) or a non-static data + /// member. When the low bit is 1, it's a base + /// class; when the low bit is 0, it's a member. + uintptr_t BaseOrMember; + + /// Args - The arguments used to initialize the base or member. + Expr **Args; + unsigned NumArgs; + +public: + /// CXXBaseOrMemberInitializer - Creates a new base-class initializer. + explicit + CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs); + + /// CXXBaseOrMemberInitializer - Creates a new member initializer. + explicit + CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs); + + /// ~CXXBaseOrMemberInitializer - Destroy the base or member initializer. + ~CXXBaseOrMemberInitializer(); + + /// arg_iterator - Iterates through the member initialization + /// arguments. + typedef Expr **arg_iterator; + + /// arg_const_iterator - Iterates through the member initialization + /// arguments. + typedef Expr * const * arg_const_iterator; + + /// isBaseInitializer - Returns true when this initializer is + /// initializing a base class. + bool isBaseInitializer() const { return (BaseOrMember & 0x1) != 0; } + + /// isMemberInitializer - Returns true when this initializer is + /// initializing a non-static data member. + bool isMemberInitializer() const { return (BaseOrMember & 0x1) == 0; } + + /// getBaseClass - If this is a base class initializer, returns the + /// 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()) + return reinterpret_cast<Type*>(BaseOrMember & ~0x01); + else + return 0; + } + + /// getBaseClass - If this is a base class initializer, returns the + /// 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()) + return reinterpret_cast<const Type*>(BaseOrMember & ~0x01); + else + return 0; + } + + /// getMember - If this is a member initializer, returns the + /// declaration of the non-static data member being + /// initialized. Otherwise, returns NULL. + FieldDecl *getMember() { + if (isMemberInitializer()) + return reinterpret_cast<FieldDecl *>(BaseOrMember); + else + return 0; + } + + /// 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; } + + /// 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; } + + /// getNumArgs - Determine the number of arguments used to + /// initialize the member or base. + unsigned getNumArgs() const { return NumArgs; } +}; + +/// CXXConstructorDecl - Represents a C++ constructor within a +/// class. For example: +/// +/// @code +/// class X { +/// public: +/// explicit X(int); // represented by a CXXConstructorDecl. +/// }; +/// @endcode +class CXXConstructorDecl : public CXXMethodDecl { + /// Explicit - Whether this constructor is explicit. + bool Explicit : 1; + + /// ImplicitlyDefined - Whether this constructor was implicitly + /// defined by the compiler. When false, the constructor was defined + /// by the user. In C++03, this flag will have the same value as + /// Implicit. In C++0x, however, a constructor that is + /// explicitly defaulted (i.e., defined with " = default") will have + /// @c !Implicit && ImplicitlyDefined. + bool ImplicitlyDefined : 1; + + /// FIXME: Add support for base and member initializers. + + CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L, + DeclarationName N, QualType T, + bool isExplicit, bool isInline, bool isImplicitlyDeclared) + : CXXMethodDecl(CXXConstructor, RD, L, N, T, false, isInline), + Explicit(isExplicit), ImplicitlyDefined(false) { + setImplicit(isImplicitlyDeclared); + } + +public: + static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation L, DeclarationName N, + QualType T, bool isExplicit, + bool isInline, bool isImplicitlyDeclared); + + /// 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() && + "Can only get the implicit-definition flag once the constructor has been defined"); + return ImplicitlyDefined; + } + + /// setImplicitlyDefined - Set whether this constructor was + /// implicitly defined or not. + void setImplicitlyDefined(bool ID) { + assert(isThisDeclarationADefinition() && + "Can only set the implicit-definition flag once the constructor has been defined"); + ImplicitlyDefined = ID; + } + + /// isDefaultConstructor - Whether this constructor is a default + /// constructor (C++ [class.ctor]p5), which can be used to + /// default-initialize a class of this type. + bool isDefaultConstructor() const; + + /// isCopyConstructor - Whether this constructor is a copy + /// constructor (C++ [class.copy]p2, which can be used to copy the + /// class. @p TypeQuals will be set to the qualifiers on the + /// argument type. For example, @p TypeQuals would be set to @c + /// QualType::Const for the following copy constructor: + /// + /// @code + /// class X { + /// public: + /// X(const X&); + /// }; + /// @endcode + bool isCopyConstructor(ASTContext &Context, unsigned &TypeQuals) const; + + /// isCopyConstructor - Whether this constructor is a copy + /// constructor (C++ [class.copy]p2, which can be used to copy the + /// class. + bool isCopyConstructor(ASTContext &Context) const { + unsigned TypeQuals = 0; + return isCopyConstructor(Context, TypeQuals); + } + + /// isConvertingConstructor - Whether this constructor is a + /// converting constructor (C++ [class.conv.ctor]), which can be + /// used for user-defined conversions. + bool isConvertingConstructor() const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() == CXXConstructor; + } + static bool classof(const CXXConstructorDecl *D) { return true; } +}; + +/// CXXDestructorDecl - Represents a C++ destructor within a +/// class. For example: +/// +/// @code +/// class X { +/// public: +/// ~X(); // represented by a CXXDestructorDecl. +/// }; +/// @endcode +class CXXDestructorDecl : public CXXMethodDecl { + /// 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 + /// Implicit. In C++0x, however, a destructor that is + /// explicitly defaulted (i.e., defined with " = default") will have + /// @c !Implicit && ImplicitlyDefined. + bool ImplicitlyDefined : 1; + + CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L, + DeclarationName N, QualType T, + bool isInline, bool isImplicitlyDeclared) + : CXXMethodDecl(CXXDestructor, RD, L, N, T, false, isInline), + ImplicitlyDefined(false) { + setImplicit(isImplicitlyDeclared); + } + +public: + static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation L, DeclarationName N, + 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() && + "Can only get the implicit-definition flag once the destructor has been defined"); + return ImplicitlyDefined; + } + + /// setImplicitlyDefined - Set whether this destructor was + /// implicitly defined or not. + void setImplicitlyDefined(bool ID) { + assert(isThisDeclarationADefinition() && + "Can only set the implicit-definition flag once the destructor has been defined"); + ImplicitlyDefined = ID; + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() == CXXDestructor; + } + static bool classof(const CXXDestructorDecl *D) { return true; } +}; + +/// CXXConversionDecl - Represents a C++ conversion function within a +/// class. For example: +/// +/// @code +/// class X { +/// public: +/// operator bool(); +/// }; +/// @endcode +class CXXConversionDecl : public CXXMethodDecl { + /// Explicit - Whether this conversion function is marked + /// "explicit", meaning that it can only be applied when the user + /// explicitly wrote a cast. This is a C++0x feature. + bool Explicit : 1; + + CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L, + DeclarationName N, QualType T, + bool isInline, bool isExplicit) + : CXXMethodDecl(CXXConversion, RD, L, N, T, false, isInline), + Explicit(isExplicit) { } + +public: + static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation L, DeclarationName N, + QualType T, bool isInline, + bool isExplicit); + + /// isExplicit - Whether this is an explicit conversion operator + /// (C++0x only). Explicit conversion operators are only considered + /// when the user has explicitly written a cast. + bool isExplicit() const { return Explicit; } + + /// getConversionType - Returns the type that this conversion + /// function is converting to. + QualType getConversionType() const { + return getType()->getAsFunctionType()->getResultType(); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() == CXXConversion; + } + static bool classof(const CXXConversionDecl *D) { return true; } +}; + +/// LinkageSpecDecl - This represents a linkage specification. For example: +/// extern "C" void foo(); +/// +class LinkageSpecDecl : public Decl, public DeclContext { +public: + /// LanguageIDs - Used to represent the language in a linkage + /// specification. The values are part of the serialization abi for + /// ASTs and cannot be changed without altering that abi. To help + /// ensure a stable abi for this, we choose the DW_LANG_ encodings + /// from the dwarf standard. + enum LanguageIDs { lang_c = /* DW_LANG_C */ 0x0002, + lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004 }; +private: + /// Language - The language for this linkage specification. + LanguageIDs Language; + + /// HadBraces - Whether this linkage specification had curly braces or not. + bool HadBraces : 1; + + LinkageSpecDecl(DeclContext *DC, SourceLocation L, LanguageIDs lang, + bool Braces) + : Decl(LinkageSpec, DC, L), + DeclContext(LinkageSpec), Language(lang), HadBraces(Braces) { } + +public: + static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, LanguageIDs Lang, + bool Braces); + + LanguageIDs getLanguage() const { return Language; } + + /// hasBraces - Determines whether this linkage specification had + /// braces in its syntactic form. + bool hasBraces() const { return HadBraces; } + + static bool classof(const Decl *D) { + return D->getKind() == LinkageSpec; + } + static bool classof(const LinkageSpecDecl *D) { return true; } + static DeclContext *castToDeclContext(const LinkageSpecDecl *D) { + return static_cast<DeclContext *>(const_cast<LinkageSpecDecl*>(D)); + } + static LinkageSpecDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<LinkageSpecDecl *>(const_cast<DeclContext*>(DC)); + } +}; + +/// UsingDirectiveDecl - Represents C++ using-directive. For example: +/// +/// using namespace std; +/// +// NB: UsingDirectiveDecl should be Decl not NamedDecl, but we provide +// artificial name, for all using-directives in order to store +// them in DeclContext effectively. +class UsingDirectiveDecl : public NamedDecl { + + /// SourceLocation - Location of 'namespace' token. + SourceLocation NamespaceLoc; + + /// \brief The source range that covers the nested-name-specifier + /// preceding the namespace name. + SourceRange QualifierRange; + + /// \brief The nested-name-specifier that precedes the namespace + /// name, if any. + NestedNameSpecifier *Qualifier; + + /// IdentLoc - Location of nominated namespace-name identifier. + // FIXME: We don't store location of scope specifier. + SourceLocation IdentLoc; + + /// NominatedNamespace - Namespace nominated by using-directive. + NamespaceDecl *NominatedNamespace; + + /// Enclosing context containing both using-directive and nomintated + /// namespace. + DeclContext *CommonAncestor; + + /// getUsingDirectiveName - Returns special DeclarationName used by + /// using-directives. This is only used by DeclContext for storing + /// UsingDirectiveDecls in its lookup structure. + static DeclarationName getName() { + return DeclarationName::getUsingDirectiveName(); + } + + UsingDirectiveDecl(DeclContext *DC, SourceLocation L, + SourceLocation NamespcLoc, + SourceRange QualifierRange, + NestedNameSpecifier *Qualifier, + SourceLocation IdentLoc, + NamespaceDecl *Nominated, + DeclContext *CommonAncestor) + : NamedDecl(Decl::UsingDirective, DC, L, getName()), + NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange), + Qualifier(Qualifier), IdentLoc(IdentLoc), + NominatedNamespace(Nominated? Nominated->getOriginalNamespace() : 0), + CommonAncestor(CommonAncestor) { + } + +public: + /// \brief Retrieve the source range of the nested-name-specifier + /// that qualifiers the namespace name. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// \brief Retrieve the nested-name-specifier that qualifies the + /// name of the namespace. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + /// getNominatedNamespace - Returns namespace nominated by using-directive. + NamespaceDecl *getNominatedNamespace() { return NominatedNamespace; } + + const NamespaceDecl *getNominatedNamespace() const { + return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace(); + } + + /// getCommonAncestor - returns common ancestor context of using-directive, + /// and nominated by it namespace. + DeclContext *getCommonAncestor() { return CommonAncestor; } + const DeclContext *getCommonAncestor() const { return CommonAncestor; } + + /// getNamespaceKeyLocation - Returns location of namespace keyword. + SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; } + + /// getIdentLocation - Returns location of identifier. + SourceLocation getIdentLocation() const { return IdentLoc; } + + static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + SourceLocation NamespaceLoc, + SourceRange QualifierRange, + NestedNameSpecifier *Qualifier, + SourceLocation IdentLoc, + NamespaceDecl *Nominated, + DeclContext *CommonAncestor); + + static bool classof(const Decl *D) { + return D->getKind() == Decl::UsingDirective; + } + static bool classof(const UsingDirectiveDecl *D) { return true; } + + // Friend for getUsingDirectiveName. + friend class DeclContext; +}; + +/// NamespaceAliasDecl - Represents a C++ namespace alias. For example: +/// +/// @code +/// namespace Foo = Bar; +/// @endcode +class NamespaceAliasDecl : public NamedDecl { + SourceLocation AliasLoc; + + /// \brief The source range that covers the nested-name-specifier + /// preceding the namespace name. + SourceRange QualifierRange; + + /// \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 + /// NamespaceDecl or a NamespaceAliasDecl. + NamedDecl *Namespace; + + 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), + QualifierRange(QualifierRange), Qualifier(Qualifier), + IdentLoc(IdentLoc), Namespace(Namespace) { } + +public: + /// \brief Retrieve the source range of the nested-name-specifier + /// that qualifiers the namespace name. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// \brief Retrieve the nested-name-specifier that qualifies the + /// name of the namespace. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + NamespaceDecl *getNamespace() { + if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(Namespace)) + return AD->getNamespace(); + + return cast<NamespaceDecl>(Namespace); + } + + const NamespaceDecl *getNamespace() const { + return const_cast<NamespaceAliasDecl*>(this)->getNamespace(); + } + + /// \brief Retrieve the namespace that this alias refers to, which + /// 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, + SourceRange QualifierRange, + NestedNameSpecifier *Qualifier, + SourceLocation IdentLoc, + NamedDecl *Namespace); + + static bool classof(const Decl *D) { + return D->getKind() == Decl::NamespaceAlias; + } + static bool classof(const NamespaceAliasDecl *D) { return true; } +}; + +/// StaticAssertDecl - Represents a C++0x static_assert declaration. +class StaticAssertDecl : public Decl { + Expr *AssertExpr; + StringLiteral *Message; + + 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); + + static bool classof(const Decl *D) { + return D->getKind() == Decl::StaticAssert; + } + static bool classof(StaticAssertDecl *D) { return true; } +}; + +/// Insertion operator for diagnostics. This allows sending AccessSpecifier's +/// 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 new file mode 100644 index 000000000000..6c1231c0a73d --- /dev/null +++ b/include/clang/AST/DeclContextInternals.h @@ -0,0 +1,220 @@ +//===-- DeclContextInternals.h - DeclContext 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 data structures used in the implementation +// of DeclContext. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H +#define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H + +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclarationName.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/SmallVector.h" +#include <algorithm> + +namespace clang { + +/// StoredDeclsList - This is an array of decls optimized a common case of only +/// containing one entry. +struct StoredDeclsList { + /// The kind of data encoded in this list. + enum DataKind { + /// \brief The data is a NamedDecl*. + DK_Decl = 0, + /// \brief The data is a declaration ID (an unsigned value), + /// shifted left by 2 bits. + DK_DeclID = 1, + /// \brief The data is a pointer to a vector (of type VectorTy) + /// that contains declarations. + DK_Decl_Vector = 2, + /// \brief The data is a pointer to a vector (of type VectorTy) + /// that contains declaration ID. + DK_ID_Vector = 3 + }; + + /// VectorTy - When in vector form, this is what the Data pointer points to. + typedef llvm::SmallVector<uintptr_t, 4> VectorTy; + + /// \brief The stored data, which will be either a declaration ID, a + /// pointer to a NamedDecl, or a pointer to a vector. + uintptr_t Data; + +public: + StoredDeclsList() : Data(0) {} + + StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) { + if (VectorTy *RHSVec = RHS.getAsVector()) { + VectorTy *New = new VectorTy(*RHSVec); + 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; + Data = RHS.Data; + if (VectorTy *RHSVec = RHS.getAsVector()) { + VectorTy *New = new VectorTy(*RHSVec); + Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03); + } + return *this; + } + + bool isNull() const { return (Data & ~0x03) == 0; } + + NamedDecl *getAsDecl() const { + if ((Data & 0x03) != DK_Decl) + return 0; + + return reinterpret_cast<NamedDecl *>(Data & ~0x03); + } + + VectorTy *getAsVector() const { + if ((Data & 0x03) != DK_ID_Vector && (Data & 0x03) != DK_Decl_Vector) + return 0; + + return reinterpret_cast<VectorTy *>(Data & ~0x03); + } + + void setOnlyValue(NamedDecl *ND) { + assert(!getAsVector() && "Not inline"); + Data = reinterpret_cast<uintptr_t>(ND); + } + + void setFromDeclIDs(const llvm::SmallVectorImpl<unsigned> &Vec) { + if (Vec.size() > 1) { + VectorTy *Vector = getAsVector(); + if (!Vector) { + Vector = new VectorTy; + Data = reinterpret_cast<uintptr_t>(Vector) | DK_ID_Vector; + } + + Vector->resize(Vec.size()); + std::copy(Vec.begin(), Vec.end(), Vector->begin()); + return; + } + + if (VectorTy *Vector = getAsVector()) + delete Vector; + + if (Vec.empty()) + Data = 0; + else + Data = (Vec[0] << 2) | DK_DeclID; + } + + /// \brief Force the stored declarations list to contain actual + /// declarations. + /// + /// This routine will resolve any declaration IDs for declarations + /// that may not yet have been loaded from external storage. + void materializeDecls(ASTContext &Context); + + bool hasDeclarationIDs() const { + DataKind DK = (DataKind)(Data & 0x03); + return DK == DK_DeclID || DK == DK_ID_Vector; + } + + /// getLookupResult - Return an array of all the decls that this list + /// represents. + 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], + (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) { + if (hasDeclarationIDs()) + materializeDecls(Context); + + // Most decls only have one entry in their list, special case it. + if (NamedDecl *OldD = getAsDecl()) { + if (!D->declarationReplaces(OldD)) + return false; + setOnlyValue(D); + return true; + } + + // Determine if this declaration is actually a redeclaration. + VectorTy &Vec = *getAsVector(); + for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end(); + OD != ODEnd; ++OD) { + NamedDecl *OldD = reinterpret_cast<NamedDecl *>(*OD); + if (D->declarationReplaces(OldD)) { + *OD = reinterpret_cast<uintptr_t>(D); + return true; + } + } + + 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"); + + // If this is the second decl added to the list, convert this to vector + // form. + if (NamedDecl *OldD = getAsDecl()) { + VectorTy *VT = new VectorTy(); + 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) + Vec.push_back(reinterpret_cast<uintptr_t>(D)); + else if (reinterpret_cast<NamedDecl *>(Vec.back()) + ->getIdentifierNamespace() == Decl::IDNS_Tag) { + uintptr_t TagD = Vec.back(); + Vec.back() = reinterpret_cast<uintptr_t>(D); + Vec.push_back(TagD); + } else + Vec.push_back(reinterpret_cast<uintptr_t>(D)); + } +}; + +typedef llvm::DenseMap<DeclarationName, StoredDeclsList> StoredDeclsMap; + + +} // end namespace clang + +#endif diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h new file mode 100644 index 000000000000..15a8adef8e57 --- /dev/null +++ b/include/clang/AST/DeclGroup.h @@ -0,0 +1,152 @@ +//===--- DeclGroup.h - Classes for representing groups of Decls -*- 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 DeclGroup, DeclGroupRef, and OwningDeclGroup classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLGROUP_H +#define LLVM_CLANG_AST_DECLGROUP_H + +#include "llvm/Support/DataTypes.h" +#include <cassert> + +namespace clang { + +class ASTContext; +class Decl; +class DeclGroup; +class DeclGroupIterator; + +class DeclGroup { + // FIXME: Include a TypeSpecifier object. + unsigned NumDecls; + +private: + DeclGroup() : NumDecls(0) {} + DeclGroup(unsigned numdecls, Decl** decls); + +public: + static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls); + void Destroy(ASTContext& C); + + unsigned size() const { return NumDecls; } + + Decl*& operator[](unsigned i) { + assert (i < NumDecls && "Out-of-bounds access."); + return *((Decl**) (this+1)); + } + + 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 }; + Decl* D; + + Kind getKind() const { + return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask); + } + +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(); + if (NumDecls == 1) + 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; } + + Decl *getSingleDecl() { + assert(isSingleDecl() && "Isn't a declgroup"); + return D; + } + 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)); + } + const DeclGroup &getDeclGroup() const { + return const_cast<DeclGroupRef*>(this)->getDeclGroup(); + } + + iterator begin() { + if (isSingleDecl()) + return D ? &D : 0; + return &getDeclGroup()[0]; + } + + iterator end() { + if (isSingleDecl()) + return D ? &D+1 : 0; + 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; + const DeclGroup &G = getDeclGroup(); + return &G[0] + G.size(); + } + + void *getAsOpaquePtr() const { return D; } + static DeclGroupRef getFromOpaquePtr(void *Ptr) { + DeclGroupRef X; + X.D = static_cast<Decl*>(Ptr); + return X; + } +}; + +} // end clang namespace + +namespace llvm { + // DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits. + template <typename T> + class PointerLikeTypeTraits; + template <> + class PointerLikeTypeTraits<clang::DeclGroupRef> { + public: + static inline void *getAsVoidPointer(clang::DeclGroupRef P) { + return P.getAsOpaquePtr(); + } + static inline clang::DeclGroupRef getFromVoidPointer(void *P) { + return clang::DeclGroupRef::getFromOpaquePtr(P); + } + enum { NumLowBitsAvailable = 0 }; + }; +} +#endif diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def new file mode 100644 index 000000000000..d1b921a4cb65 --- /dev/null +++ b/include/clang/AST/DeclNodes.def @@ -0,0 +1,161 @@ +//===-- DeclNodes.def - Metadata about Decl AST nodes -----------*- 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 declaration nodes within the AST. The +// description of the declaration nodes uses six macros: +// +// DECL(Derived, Base) describes a normal declaration type Derived +// and specifies its base class. Note that Derived should not have +// the Decl suffix on it, while Base should. +// +// LAST_DECL(Derived, Base) is like DECL, but is used for the last +// declaration in the list. +// +// ABSTRACT_DECL(Derived, Base) describes an abstract class that is +// used to specify a classification of declarations. For example, +// TagDecl is an abstract class used to describe the various kinds of +// "tag" declarations (unions, structs, classes, enums). +// +// DECL_CONTEXT(Decl) specifies that Decl is a kind of declaration +// that is also a DeclContext. +// +// LAST_DECL_CONTEXT(Decl) is like DECL_CONTEXT, but is used for the +// last declaration context. +// +// DECL_RANGE(CommonBase, Start, End) specifies a range of +// declaration values that have a common (potentially indirect) base +// class. +// +// LAST_DECL_RANGE(CommonBase, Start, End) is like DECL_RANGE, but is +// used for the last declaration range. +// +// Note that, due to the use of ranges, the order of the these +// declarations is significant. A declaration should be listed under +// its base class. +// ===----------------------------------------------------------------------===// + +#ifndef DECL +# define DECL(Derived, Base) +#endif + +#ifndef LAST_DECL +# define LAST_DECL(Derived, Base) DECL(Derived, Base) +#endif + +#ifndef ABSTRACT_DECL +# define ABSTRACT_DECL(Derived, Base) +#endif + +#ifndef DECL_CONTEXT +# define DECL_CONTEXT(Decl) +#endif + +#ifndef DECL_CONTEXT_BASE +# define DECL_CONTEXT_BASE(Decl) DECL_CONTEXT(Decl) +#endif + +#ifndef LAST_DECL_CONTEXT +# define LAST_DECL_CONTEXT(Decl) DECL_CONTEXT(Decl) +#endif + +#ifndef DECL_RANGE +# define DECL_RANGE(CommonBase, Start, End) +#endif + +#ifndef LAST_DECL_RANGE +# define LAST_DECL_RANGE(CommonBase, Start, End) \ + DECL_RANGE(CommonBase, Start, End) +#endif + +DECL(TranslationUnit, Decl) +ABSTRACT_DECL(Named, Decl) + DECL(OverloadedFunction, NamedDecl) + DECL(Namespace, NamedDecl) + DECL(UsingDirective, NamedDecl) + DECL(NamespaceAlias, NamedDecl) + ABSTRACT_DECL(Type, NamedDecl) + DECL(Typedef, TypeDecl) + ABSTRACT_DECL(Tag, TypeDecl) + DECL(Enum, TagDecl) + DECL(Record, TagDecl) + DECL(CXXRecord, RecordDecl) + DECL(ClassTemplateSpecialization, CXXRecordDecl) + DECL(ClassTemplatePartialSpecialization, + ClassTemplateSpecializationDecl) + 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) + DECL(Template, NamedDecl) + DECL(FunctionTemplate, TemplateDecl) + DECL(ClassTemplate, TemplateDecl) + DECL(TemplateTemplateParm, TemplateDecl) + DECL(ObjCMethod, NamedDecl) + DECL(ObjCContainer, NamedDecl) + DECL(ObjCCategory, ObjCContainerDecl) + DECL(ObjCProtocol, ObjCContainerDecl) + DECL(ObjCInterface, ObjCContainerDecl) + 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(StaticAssert, Decl) +LAST_DECL(Block, Decl) + +// Declaration contexts. DECL_CONTEXT_BASE indicates that it has subclasses. +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(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(Function, Function, CXXConversion) +DECL_RANGE(Template, Template, TemplateTemplateParm) +DECL_RANGE(ObjCImpl, ObjCCategoryImpl, ObjCImplementation) +LAST_DECL_RANGE(Var, Var, NonTypeTemplateParm) + +#undef LAST_DECL_RANGE +#undef DECL_RANGE +#undef LAST_DECL_CONTEXT +#undef DECL_CONTEXT_BASE +#undef DECL_CONTEXT +#undef ABSTRACT_DECL +#undef LAST_DECL +#undef DECL diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h new file mode 100644 index 000000000000..6e89a7ae7bc9 --- /dev/null +++ b/include/clang/AST/DeclObjC.h @@ -0,0 +1,1224 @@ +//===--- DeclObjC.h - Classes for representing declarations -----*- 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 DeclObjC interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLOBJC_H +#define LLVM_CLANG_AST_DECLOBJC_H + +#include "clang/AST/Decl.h" +#include "llvm/ADT/STLExtras.h" + +namespace clang { +class Expr; +class Stmt; +class FunctionDecl; +class AttributeList; +class RecordDecl; +class ObjCIvarDecl; +class ObjCMethodDecl; +class ObjCProtocolDecl; +class ObjCCategoryDecl; +class ObjCPropertyDecl; +class ObjCPropertyImplDecl; + +class ObjCListBase { + void operator=(const ObjCListBase &); // DO NOT IMPLEMENT + ObjCListBase(const ObjCListBase&); // DO NOT IMPLEMENT +protected: + /// List is an array of pointers to objects that are not owned by this object. + void **List; + unsigned NumElts; + +public: + ObjCListBase() : List(0), NumElts(0) {} + ~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 +/// of it. +template <typename T> +class ObjCList : public ObjCListBase { +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). +/// Here are some brief examples: +/// +/// Setter/getter instance methods: +/// - (void)setMenu:(NSMenu *)menu; +/// - (NSMenu *)menu; +/// +/// Instance method that takes 2 NSView arguments: +/// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView; +/// +/// Getter class method: +/// + (NSMenu *)defaultMenu; +/// +/// A selector represents a unique name for a method. The selector names for +/// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu. +/// +class ObjCMethodDecl : public NamedDecl, public DeclContext { +public: + enum ImplementationControl { None, Required, Optional }; +private: + /// Bitfields must be first fields in this class so they pack with those + /// declared in class Decl. + /// 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 '{'. + + // The following are only used for method definitions, null otherwise. + // FIXME: space savings opportunity, consider a sub-class. + Stmt *Body; + + /// SelfDecl - Decl for the implicit self parameter. This is lazily + /// constructed by createImplicitParams. + ImplicitParamDecl *SelfDecl; + /// 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, + bool isInstance = true, + bool isVariadic = false, + bool isSynthesized = false, + ImplementationControl impControl = None) + : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), + DeclContext(ObjCMethod), + IsInstance(isInstance), IsVariadic(isVariadic), + IsSynthesized(isSynthesized), + DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), + MethodDeclType(T), + EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {} + + virtual ~ObjCMethodDecl() {} + +public: + + /// Destroy - Call destructors and release memory. + virtual void Destroy(ASTContext& C); + + static ObjCMethodDecl *Create(ASTContext &C, + SourceLocation beginLoc, + SourceLocation endLoc, Selector SelInfo, + QualType T, DeclContext *contextDecl, + bool isInstance = true, + bool isVariadic = false, + bool isSynthesized = false, + ImplementationControl impControl = None); + + 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); + } + + 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; + param_iterator param_begin() const { return ParamInfo.begin(); } + param_iterator param_end() const { return ParamInfo.end(); } + + void setMethodParams(ASTContext &C, ParmVarDecl *const *List, unsigned Num) { + ParamInfo.set(List, Num, C); + } + + // Iterator access to parameter types. + typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun; + typedef llvm::mapped_iterator<param_iterator, deref_fun> arg_type_iterator; + + arg_type_iterator arg_type_begin() const { + return llvm::map_iterator(param_begin(), deref_fun(&ParmVarDecl::getType)); + } + 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 + /// have already been created. + void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID); + + ImplicitParamDecl * getSelfDecl() const { return SelfDecl; } + 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; + } + ImplementationControl getImplementationControl() const { + return ImplementationControl(DeclImplementation); + } + + virtual Stmt *getBody(ASTContext &C) const { + return (Stmt*) Body; + } + CompoundStmt *getBody() { return (CompoundStmt*)Body; } + void setBody(Stmt *B) { Body = B; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return D->getKind() == ObjCMethod; } + static bool classof(const ObjCMethodDecl *D) { return true; } + static DeclContext *castToDeclContext(const ObjCMethodDecl *D) { + return static_cast<DeclContext *>(const_cast<ObjCMethodDecl*>(D)); + } + static ObjCMethodDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<ObjCMethodDecl *>(const_cast<DeclContext*>(DC)); + } +}; + +/// ObjCMethodList - a linked list of methods with different signatures. +struct ObjCMethodList { + ObjCMethodDecl *Method; + ObjCMethodList *Next; + + ObjCMethodList() { + Method = 0; + Next = 0; + } + ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) { + Method = M; + Next = C; + } +}; + +/// ObjCContainerDecl - Represents a container for method declarations. +/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl, and +/// ObjCProtocolDecl. +/// FIXME: Use for ObjC implementation decls. +/// +class ObjCContainerDecl : public NamedDecl, public DeclContext { + SourceLocation AtEndLoc; // marks the end of the method container. +public: + + ObjCContainerDecl(Kind DK, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id) + : NamedDecl(DK, DC, L, Id), DeclContext(DK) {} + + virtual ~ObjCContainerDecl() {} + + // Iterator access to properties. + typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator; + prop_iterator prop_begin(ASTContext &Context) const { + return prop_iterator(decls_begin(Context)); + } + prop_iterator prop_end(ASTContext &Context) const { + return prop_iterator(decls_end(Context)); + } + + // Iterator access to instance/class methods. + typedef specific_decl_iterator<ObjCMethodDecl> method_iterator; + method_iterator meth_begin(ASTContext &Context) const { + return method_iterator(decls_begin(Context)); + } + method_iterator meth_end(ASTContext &Context) const { + return method_iterator(decls_end(Context)); + } + + typedef filtered_decl_iterator<ObjCMethodDecl, + &ObjCMethodDecl::isInstanceMethod> + instmeth_iterator; + instmeth_iterator instmeth_begin(ASTContext &Context) const { + return instmeth_iterator(decls_begin(Context)); + } + instmeth_iterator instmeth_end(ASTContext &Context) const { + return instmeth_iterator(decls_end(Context)); + } + + typedef filtered_decl_iterator<ObjCMethodDecl, + &ObjCMethodDecl::isClassMethod> + classmeth_iterator; + classmeth_iterator classmeth_begin(ASTContext &Context) const { + return classmeth_iterator(decls_begin(Context)); + } + classmeth_iterator classmeth_end(ASTContext &Context) const { + return classmeth_iterator(decls_end(Context)); + } + + // Get the local instance/class method declared in this interface. + ObjCMethodDecl *getInstanceMethod(ASTContext &Context, Selector Sel) const; + ObjCMethodDecl *getClassMethod(ASTContext &Context, Selector Sel) const; + + ObjCMethodDecl * + getMethod(ASTContext &Context, Selector Sel, bool isInstance) const { + return isInstance ? getInstanceMethod(Context, Sel) + : getClassMethod(Context, Sel); + } + + ObjCPropertyDecl *FindPropertyDeclaration(ASTContext &Context, + IdentifierInfo *PropertyId) const; + + // Marks the end of the container. + SourceLocation getAtEndLoc() const { return AtEndLoc; } + void setAtEndLoc(SourceLocation L) { AtEndLoc = L; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() >= ObjCContainerFirst && + D->getKind() <= ObjCContainerLast; + } + static bool classof(const ObjCContainerDecl *D) { return true; } + + static DeclContext *castToDeclContext(const ObjCContainerDecl *D) { + return static_cast<DeclContext *>(const_cast<ObjCContainerDecl*>(D)); + } + static ObjCContainerDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<ObjCContainerDecl *>(const_cast<DeclContext*>(DC)); + } +}; + +/// ObjCInterfaceDecl - Represents an ObjC class declaration. For example: +/// +/// // MostPrimitive declares no super class (not particularly useful). +/// @interface MostPrimitive +/// // no instance variables or methods. +/// @end +/// +/// // NSResponder inherits from NSObject & implements NSCoding (a protocol). +/// @interface NSResponder : NSObject <NSCoding> +/// { // instance variables are represented by ObjCIvarDecl. +/// id nextResponder; // nextResponder instance variable. +/// } +/// - (NSResponder *)nextResponder; // return a pointer to NSResponder. +/// - (void)mouseMoved:(NSEvent *)theEvent; // return void, takes a pointer +/// @end // to an NSEvent. +/// +/// Unlike C/C++, forward class declarations are accomplished with @class. +/// Unlike C/C++, @class allows for a list of classes to be forward declared. +/// Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes +/// typically inherit from NSObject (an exception is NSProxy). +/// +class ObjCInterfaceDecl : public ObjCContainerDecl { + /// TypeForDecl - This indicates the Type object that represents this + /// 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. + virtual void Destroy(ASTContext& C); + + static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation atLoc, + IdentifierInfo *Id, + SourceLocation ClassLoc = SourceLocation(), + bool ForwardDecl = false, + bool isInternal = false); + const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const { + return ReferencedProtocols; + } + + ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const; + + 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(); } + + typedef ObjCList<ObjCIvarDecl>::iterator ivar_iterator; + ivar_iterator ivar_begin() const { return IVars.begin(); } + 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); + } + + 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) { + 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 { + // If RHS is derived from LHS it is OK; else it is not OK. + while (I != NULL) { + if (this == I) + return true; + I = I->getSuperClass(); + } + return false; + } + + ObjCIvarDecl *lookupInstanceVariable(ASTContext &Context, + IdentifierInfo *IVarName, + ObjCInterfaceDecl *&ClassDeclared); + ObjCIvarDecl *lookupInstanceVariable(ASTContext &Context, + IdentifierInfo *IVarName) { + ObjCInterfaceDecl *ClassDeclared; + return lookupInstanceVariable(Context, IVarName, ClassDeclared); + } + + // Lookup a method. First, we search locally. If a method isn't + // found, we search referenced protocols and class categories. + ObjCMethodDecl *lookupInstanceMethod(ASTContext &Context, Selector Sel); + ObjCMethodDecl *lookupClassMethod(ASTContext &Context, Selector Sel); + ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName); + + // 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; } + + // Low-level accessor + Type *getTypeForDecl() const { return TypeForDecl; } + void setTypeForDecl(Type *TD) const { TypeForDecl = TD; } + + static bool classof(const Decl *D) { return D->getKind() == ObjCInterface; } + static bool classof(const ObjCInterfaceDecl *D) { return true; } +}; + +/// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC +/// instance variables are identical to C. The only exception is Objective-C +/// supports C++ style access control. For example: +/// +/// @interface IvarExample : NSObject +/// { +/// id defaultToProtected; +/// @public: +/// id canBePublic; // same as C++. +/// @protected: +/// id canBeProtected; // same as C++. +/// @package: +/// id canBePackage; // framework visibility (not available in C++). +/// } +/// +class ObjCIvarDecl : public FieldDecl { +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), + DeclAccess(ac) {} + +public: + static ObjCIvarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType T, + AccessControl ac, Expr *BW = NULL); + + void setAccessControl(AccessControl ac) { DeclAccess = ac; } + + AccessControl getAccessControl() const { return AccessControl(DeclAccess); } + + 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; } +private: + // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum + 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) {} + +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. + static bool classof(const Decl *D) { return D->getKind() == ObjCAtDefsField; } + static bool classof(const ObjCAtDefsFieldDecl *D) { return true; } +}; + +/// 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++ +/// feature with nice semantics and lousy syntax:-). Here is an example: +/// +/// @protocol NSDraggingInfo <refproto1, refproto2> +/// - (NSWindow *)draggingDestinationWindow; +/// - (NSImage *)draggedImage; +/// @end +/// +/// This says that NSDraggingInfo requires two methods and requires everything +/// that the two "referenced protocols" 'refproto1' and 'refproto2' require as +/// well. +/// +/// @interface ImplementsNSDraggingInfo : NSObject <NSDraggingInfo> +/// @end +/// +/// 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, +/// protocols are referenced using angle brackets as follows: +/// +/// id <NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo; +/// +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), + isForwardProtoDecl(true) { + } + + virtual ~ObjCProtocolDecl() {} + +public: + 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 { + 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(ASTContext &Context, Selector Sel); + ObjCMethodDecl *lookupClassMethod(ASTContext &Context, Selector Sel); + + bool isForwardDecl() const { return isForwardProtoDecl; } + void setForwardDecl(bool val) { isForwardProtoDecl = val; } + + // 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, + 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, + unsigned nElts = 0); + + typedef ObjCList<ObjCInterfaceDecl>::iterator iterator; + iterator begin() const { return ForwardDecls.begin(); } + iterator end() const { return ForwardDecls.end(); } + unsigned size() const { return ForwardDecls.size(); } + + /// setClassList - Set the list of forward classes. + 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); + virtual ~ObjCForwardProtocolDecl() {} + +public: + static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC, + 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(); } + unsigned protocol_size() const { return ReferencedProtocols.size(); } + + /// setProtocolList - Set the list of forward protocols. + void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num, + ASTContext &C) { + ReferencedProtocols.set(List, Num, C); + } + static bool classof(const Decl *D) { + return D->getKind() == ObjCForwardProtocol; + } + static bool classof(const ObjCForwardProtocolDecl *D) { return true; } +}; + +/// 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 +/// you to add instance data. The following example adds "myMethod" to all +/// NSView's within a process: +/// +/// @interface NSView (MyViewMethods) +/// - myMethod; +/// @end +/// +/// Cateogries also allow you to split the implementation of a class across +/// 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) +/// 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; } + + /// 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 { + 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; + } + void insertNextClassCategory() { + NextClassCategory = ClassInterface->getCategoryList(); + ClassInterface->setCategoryList(this); + } + // 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 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) {} + +public: + virtual ~ObjCImplDecl() {} + + const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } + ObjCInterfaceDecl *getClassInterface() { return ClassInterface; } + void setClassInterface(ObjCInterfaceDecl *IFace) { ClassInterface = IFace; } + + void addInstanceMethod(ASTContext &Context, ObjCMethodDecl *method) { + // FIXME: Context should be set correctly before we get here. + method->setLexicalDeclContext(this); + addDecl(Context, method); + } + void addClassMethod(ASTContext &Context, ObjCMethodDecl *method) { + // FIXME: Context should be set correctly before we get here. + method->setLexicalDeclContext(this); + addDecl(Context, method); + } + + // Get the local instance/class method declared in this interface. + ObjCMethodDecl *getInstanceMethod(ASTContext &Context, Selector Sel) const; + ObjCMethodDecl *getClassMethod(ASTContext &Context, Selector Sel) const; + ObjCMethodDecl *getMethod(ASTContext &Context, Selector Sel, + bool isInstance) const { + return isInstance ? getInstanceMethod(Context, Sel) + : getClassMethod(Context, Sel); + } + + void addPropertyImplementation(ASTContext &Context, + ObjCPropertyImplDecl *property); + + ObjCPropertyImplDecl *FindPropertyImplDecl(ASTContext &Context, + IdentifierInfo *propertyId) const; + ObjCPropertyImplDecl *FindPropertyImplIvarDecl(ASTContext &Context, + IdentifierInfo *ivarId) const; + + // Iterator access to properties. + typedef specific_decl_iterator<ObjCPropertyImplDecl> propimpl_iterator; + propimpl_iterator propimpl_begin(ASTContext &Context) const { + return propimpl_iterator(decls_begin(Context)); + } + propimpl_iterator propimpl_end(ASTContext &Context) const { + return propimpl_iterator(decls_end(Context)); + } + + typedef filtered_decl_iterator<ObjCMethodDecl, + &ObjCMethodDecl::isInstanceMethod> + instmeth_iterator; + instmeth_iterator instmeth_begin(ASTContext &Context) const { + return instmeth_iterator(decls_begin(Context)); + } + instmeth_iterator instmeth_end(ASTContext &Context) const { + return instmeth_iterator(decls_end(Context)); + } + + typedef filtered_decl_iterator<ObjCMethodDecl, + &ObjCMethodDecl::isClassMethod> + classmeth_iterator; + classmeth_iterator classmeth_begin(ASTContext &Context) const { + return classmeth_iterator(decls_begin(Context)); + } + classmeth_iterator classmeth_end(ASTContext &Context) const { + return classmeth_iterator(decls_end(Context)); + } + + // Location information, modeled after the Stmt API. + SourceLocation getLocStart() const { return getLocation(); } + SourceLocation getLocEnd() const { return EndLoc; } + void setLocEnd(SourceLocation LE) { EndLoc = LE; }; +}; + +/// 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) +/// @property int p1, d1; +/// @end +/// @implementation I(CATEGORY) +/// @dynamic p1,d1; +/// @end +/// +/// ObjCCategoryImplDecl +class ObjCCategoryImplDecl : public ObjCImplDecl { + // Category name + IdentifierInfo *Id; + + ObjCCategoryImplDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + ObjCInterfaceDecl *classInterface) + : ObjCImplDecl(ObjCCategoryImpl, DC, L, classInterface), Id(Id) {} +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; + } + void setIdentifier(IdentifierInfo *II) { Id = II; } + + /// 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 +/// method definitions are specified. For example: +/// +/// @code +/// @implementation MyClass +/// - (void)myMethod { /* do something */ } +/// @end +/// @endcode +/// +/// 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 { + /// Implementation Class's super class. + ObjCInterfaceDecl *SuperClass; + + ObjCImplementationDecl(DeclContext *DC, SourceLocation L, + ObjCInterfaceDecl *classInterface, + ObjCInterfaceDecl *superDecl) + : ObjCImplDecl(ObjCImplementation, DC, L, classInterface), + SuperClass(superDecl){} +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(); + } + + /// getNameAsCString - Get the name of identifier for the class + /// interface associated with this implementation as a C string + /// (const char*). + const char *getNameAsCString() const { + assert(getIdentifier() && "Name is not a simple identifier"); + return getIdentifier()->getName(); + } + + /// @brief Get the name of the class associated with this interface. + std::string getNameAsString() const { + return getClassInterface()->getNameAsString(); + } + + 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(ASTContext &Context) const { + return ivar_iterator(decls_begin(Context)); + } + ivar_iterator ivar_end(ASTContext &Context) const { + return ivar_iterator(decls_end(Context)); + } + unsigned ivar_size(ASTContext &Context) const { + return std::distance(ivar_begin(Context), ivar_end(Context)); + } + bool ivar_empty(ASTContext &Context) const { + return ivar_begin(Context) == ivar_end(Context); + } + + 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 +/// 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) {} +public: + static ObjCCompatibleAliasDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + ObjCInterfaceDecl* aliasedClass); + + 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. +/// For example: +/// @property (assign, readwrite) int MyProperty; +/// +class ObjCPropertyDecl : public NamedDecl { +public: + enum PropertyAttributeKind { + OBJC_PR_noattr = 0x00, + OBJC_PR_readonly = 0x01, + OBJC_PR_getter = 0x02, + OBJC_PR_assign = 0x04, + OBJC_PR_readwrite = 0x08, + OBJC_PR_retain = 0x10, + OBJC_PR_copy = 0x20, + OBJC_PR_nonatomic = 0x40, + OBJC_PR_setter = 0x80 + }; + + enum SetterKind { Assign, Retain, Copy }; + enum PropertyControl { None, Required, Optional }; +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, + QualType T) + : NamedDecl(ObjCProperty, DC, L, Id), DeclType(T), + PropertyAttributes(OBJC_PR_noattr), PropertyImplementation(None), + GetterName(Selector()), + SetterName(Selector()), + GetterMethodDecl(0), SetterMethodDecl(0) , PropertyIvarDecl(0) {} +public: + static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + IdentifierInfo *Id, QualType T, + PropertyControl propControl = None); + QualType getType() const { return DeclType; } + void setType(QualType T) { DeclType = T; } + + PropertyAttributeKind getPropertyAttributes() const { + return PropertyAttributeKind(PropertyAttributes); + } + void setPropertyAttributes(PropertyAttributeKind PRVal) { + PropertyAttributes |= PRVal; + } + + void makeitReadWriteAttribute(void) { + PropertyAttributes &= ~OBJC_PR_readonly; + PropertyAttributes |= OBJC_PR_readwrite; + } + + // Helper methods for accessing attributes. + + /// isReadOnly - Return true iff the property has a setter. + bool isReadOnly() const { + return (PropertyAttributes & OBJC_PR_readonly); + } + + /// getSetterKind - Return the method used for doing assignment in + /// the property setter. This is only valid if the property has been + /// defined to have a setter. + SetterKind getSetterKind() const { + if (PropertyAttributes & OBJC_PR_retain) + return Retain; + if (PropertyAttributes & OBJC_PR_copy) + return Copy; + return Assign; + } + + 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 +/// in a class or category implementation block. For example: +/// @synthesize prop1 = ivar1; +/// +class ObjCPropertyImplDecl : public Decl { +public: + enum Kind { + Synthesize, + Dynamic + }; +private: + SourceLocation AtLoc; // location of @synthesize or @dynamic + /// Property declaration being implemented + ObjCPropertyDecl *PropertyDecl; + + /// Null for @dynamic. Required for @synthesize. + ObjCIvarDecl *PropertyIvarDecl; + + ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L, + ObjCPropertyDecl *property, + Kind PK, + ObjCIvarDecl *ivarDecl) + : 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, + ObjCIvarDecl *ivarDecl); + + SourceLocation getLocStart() const { return AtLoc; } + void setAtLoc(SourceLocation Loc) { AtLoc = Loc; } + + ObjCPropertyDecl *getPropertyDecl() const { + return PropertyDecl; + } + void setPropertyDecl(ObjCPropertyDecl *Prop) { PropertyDecl = Prop; } + + Kind getPropertyImplementation() const { + return PropertyIvarDecl ? Synthesize : Dynamic; + } + + ObjCIvarDecl *getPropertyIvarDecl() const { + return PropertyIvarDecl; + } + void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { PropertyIvarDecl = Ivar; } + + static bool classof(const Decl *D) { + return D->getKind() == ObjCPropertyImpl; + } + static bool classof(const ObjCPropertyImplDecl *D) { return true; } +}; + +} // end namespace clang +#endif diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h new file mode 100644 index 000000000000..226af3411d55 --- /dev/null +++ b/include/clang/AST/DeclTemplate.h @@ -0,0 +1,859 @@ +//===-- DeclTemplate.h - Classes for representing C++ templates -*- 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 C++ template declaration subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLTEMPLATE_H +#define LLVM_CLANG_AST_DECLTEMPLATE_H + +#include "clang/AST/DeclCXX.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/FoldingSet.h" + +namespace clang { + +class TemplateParameterList; +class TemplateDecl; +class FunctionTemplateDecl; +class ClassTemplateDecl; +class ClassTemplatePartialSpecializationDecl; +class TemplateTypeParmDecl; +class NonTypeTemplateParmDecl; +class TemplateTemplateParmDecl; + +/// TemplateParameterList - Stores a list of template parameters for a +/// TemplateDecl and its derived classes. +class TemplateParameterList { + /// The location of the 'template' keyword. + SourceLocation TemplateLoc; + + /// The locations of the '<' and '>' angle brackets. + SourceLocation LAngleLoc, RAngleLoc; + + /// The number of template parameters in this template + /// parameter list. + unsigned NumParams; + + TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, + Decl **Params, unsigned NumParams, + SourceLocation RAngleLoc); + +public: + static TemplateParameterList *Create(ASTContext &C, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + Decl **Params, + unsigned NumParams, + SourceLocation RAngleLoc); + + /// iterator - Iterates through the template parameters in this list. + typedef Decl** iterator; + + /// const_iterator - Iterates through the template parameters in this list. + typedef Decl* const* const_iterator; + + iterator begin() { return reinterpret_cast<Decl **>(this + 1); } + const_iterator begin() const { + return reinterpret_cast<Decl * const *>(this + 1); + } + iterator end() { return begin() + NumParams; } + const_iterator end() const { return begin() + NumParams; } + + unsigned size() const { return NumParams; } + + const Decl* getParam(unsigned Idx) const { + assert(Idx < size() && "Template parameter index out-of-range"); + return begin()[Idx]; + } + + /// \btief Returns the minimum number of arguments needed to form a + /// template specialization. This may be fewer than the number of + /// template parameters, if some of the parameters have default + /// arguments. + unsigned getMinRequiredArguments() const; + + SourceLocation getTemplateLoc() const { return TemplateLoc; } + SourceLocation getLAngleLoc() const { return LAngleLoc; } + SourceLocation getRAngleLoc() const { return RAngleLoc; } + + SourceRange getSourceRange() const { + return SourceRange(TemplateLoc, RAngleLoc); + } +}; + +//===----------------------------------------------------------------------===// +// Kinds of Templates +//===----------------------------------------------------------------------===// + +/// TemplateDecl - The base class of all kinds of template declarations (e.g., +/// class, function, etc.). The TemplateDecl class stores the list of template +/// parameters and a reference to the templated scoped declaration: the +/// underlying AST node. +class TemplateDecl : public NamedDecl { +protected: + // This is probably never used. + TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName Name) + : 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) + { } + + // Construct a template decl with name, parameters, and templated element. + TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName Name, TemplateParameterList *Params, + NamedDecl *Decl) + : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), + TemplateParams(Params) { } +public: + ~TemplateDecl(); + + /// Get the list of template parameters + TemplateParameterList *getTemplateParameters() const { + return TemplateParams; + } + + /// Get the underlying, templated declaration. + NamedDecl *getTemplatedDecl() const { return TemplatedDecl; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() >= TemplateFirst && D->getKind() <= TemplateLast; + } + static bool classof(const TemplateDecl *D) { return true; } + static bool classof(const FunctionTemplateDecl *D) { return true; } + static bool classof(const ClassTemplateDecl *D) { return true; } + static bool classof(const TemplateTemplateParmDecl *D) { return true; } + +protected: + NamedDecl *TemplatedDecl; + TemplateParameterList* TemplateParams; +}; + +/// Declaration of a template function. +class FunctionTemplateDecl : public TemplateDecl { +protected: + FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl) + : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { } +public: + /// Get the underling function declaration of the template. + FunctionDecl *getTemplatedDecl() const { + return static_cast<FunctionDecl*>(TemplatedDecl); + } + + /// Create a template function node. + static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl); + + // Implement isa/cast/dyncast support + static bool classof(const Decl *D) + { return D->getKind() == FunctionTemplate; } + static bool classof(const FunctionTemplateDecl *D) + { return true; } +}; + +//===----------------------------------------------------------------------===// +// Kinds of Template Parameters +//===----------------------------------------------------------------------===// + +/// The TemplateParmPosition class defines the position of a template parameter +/// within a template parameter list. Because template parameter can be listed +/// sequentially for out-of-line template members, each template parameter is +/// given a Depth - the nesting of template parameter scopes - and a Position - +/// 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 +{ +protected: + // FIXME: This should probably never be called, but it's here as + TemplateParmPosition() + : Depth(0), Position(0) + { /* assert(0 && "Cannot create positionless template parameter"); */ } + + TemplateParmPosition(unsigned D, unsigned P) + : Depth(D), Position(P) + { } + + // FIXME: These probably don't need to be ints. int:5 for depth, int:8 for + // position? Maybe? + unsigned Depth; + unsigned Position; + +public: + /// Get the nesting depth of the template parameter. + unsigned getDepth() const { return Depth; } + + /// Get the position of the template parameter within its parameter list. + unsigned getPosition() const { return Position; } +}; + +/// TemplateTypeParmDecl - Declaration of a template type parameter, +/// e.g., "T" in +/// @code +/// template<typename T> class vector; +/// @endcode +class TemplateTypeParmDecl : public TypeDecl { + /// \brief Whether this template type parameter was declaration with + /// the 'typename' keyword. If false, it was declared with the + /// 'class' keyword. + bool Typename : 1; + + /// \brief Whether this template type parameter inherited its + /// default argument. + bool InheritedDefault : 1; + + /// \brief The location of the default argument, if any. + SourceLocation DefaultArgumentLoc; + + /// \brief The default template argument, if any. + QualType DefaultArgument; + + TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + bool Typename, QualType Type) + : TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename), + InheritedDefault(false), DefaultArgument() { + TypeForDecl = Type.getTypePtr(); + } + +public: + static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, unsigned P, + IdentifierInfo *Id, bool Typename); + + /// \brief Whether this template type parameter was declared with + /// the 'typename' keyword. If not, it was declared with the 'class' + /// keyword. + bool wasDeclaredWithTypename() const { return Typename; } + + /// \brief Determine whether this template parameter has a default + /// argument. + bool hasDefaultArgument() const { return !DefaultArgument.isNull(); } + + /// \brief Retrieve the default argument, if any. + QualType getDefaultArgument() const { return DefaultArgument; } + + /// \brief Retrieve the location of the default argument, if any. + SourceLocation getDefaultArgumentLoc() const { return DefaultArgumentLoc; } + + /// \brief Determines whether the default argument was inherited + /// from a previous declaration of this template. + bool defaultArgumentWasInherited() const { return InheritedDefault; } + + /// \brief Set the default argument for this template parameter, and + /// whether that default argument was inherited from another + /// declaration. + void setDefaultArgument(QualType DefArg, SourceLocation DefArgLoc, + bool Inherited) { + DefaultArgument = DefArg; + DefaultArgumentLoc = DefArgLoc; + InheritedDefault = Inherited; + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() == TemplateTypeParm; + } + static bool classof(const TemplateTypeParmDecl *D) { return true; } +}; + +/// NonTypeTemplateParmDecl - Declares a non-type template parameter, +/// e.g., "Size" in +/// @code +/// template<int Size> class array { }; +/// @endcode +class NonTypeTemplateParmDecl + : public VarDecl, protected TemplateParmPosition { + /// \brief The default template argument, if any. + Expr *DefaultArgument; + + 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) + { } + +public: + static NonTypeTemplateParmDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, + unsigned P, IdentifierInfo *Id, QualType T, + SourceLocation TypeSpecStartLoc = SourceLocation()); + + using TemplateParmPosition::getDepth; + using TemplateParmPosition::getPosition; + + /// \brief Determine whether this template parameter has a default + /// argument. + bool hasDefaultArgument() const { return DefaultArgument; } + + /// \brief Retrieve the default argument, if any. + Expr *getDefaultArgument() const { return DefaultArgument; } + + /// \brief Retrieve the location of the default argument, if any. + SourceLocation getDefaultArgumentLoc() const; + + /// \brief Set the default argument for this template parameter. + void setDefaultArgument(Expr *DefArg) { + DefaultArgument = DefArg; + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() == NonTypeTemplateParm; + } + static bool classof(const NonTypeTemplateParmDecl *D) { return true; } +}; + +/// TemplateTemplateParmDecl - Declares a template template parameter, +/// e.g., "T" in +/// @code +/// template <template <typename> class T> class container { }; +/// @endcode +/// A template template parameter is a TemplateDecl because it defines the +/// name of a template and the template parameters allowable for substitution. +class TemplateTemplateParmDecl + : public TemplateDecl, protected TemplateParmPosition { + + /// \brief The default template argument, if any. + Expr *DefaultArgument; + + TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, + unsigned D, unsigned P, + IdentifierInfo *Id, TemplateParameterList *Params) + : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), + TemplateParmPosition(D, P), DefaultArgument(0) + { } + +public: + static TemplateTemplateParmDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, + unsigned P, IdentifierInfo *Id, + TemplateParameterList *Params); + + using TemplateParmPosition::getDepth; + using TemplateParmPosition::getPosition; + + /// \brief Determine whether this template parameter has a default + /// argument. + bool hasDefaultArgument() const { return DefaultArgument; } + + /// \brief Retrieve the default argument, if any. + Expr *getDefaultArgument() const { return DefaultArgument; } + + /// \brief Retrieve the location of the default argument, if any. + SourceLocation getDefaultArgumentLoc() const; + + /// \brief Set the default argument for this template parameter. + void setDefaultArgument(Expr *DefArg) { + DefaultArgument = DefArg; + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() == TemplateTemplateParm; + } + static bool classof(const TemplateTemplateParmDecl *D) { return true; } +}; + +/// \brief Represents a template argument within a class template +/// specialization. +class TemplateArgument { + union { + uintptr_t TypeOrValue; + struct { + char Value[sizeof(llvm::APSInt)]; + void *Type; + } Integer; + }; + + /// \brief Location of the beginning of this template argument. + SourceLocation StartLoc; + +public: + /// \brief The type of template argument we're storing. + enum ArgKind { + /// The template argument is a type. It's value is stored in the + /// TypeOrValue field. + Type = 0, + /// The template argument is a declaration + Declaration = 1, + /// The template argument is an integral value stored in an llvm::APSInt. + Integral = 2, + /// The template argument is a value- or type-dependent expression + /// stored in an Expr*. + Expression = 3 + } Kind; + + /// \brief Construct an empty, invalid template argument. + TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Type) { } + + /// \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. + TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) { + // FIXME: Need to be sure we have the "canonical" declaration! + TypeOrValue = reinterpret_cast<uintptr_t>(D); + StartLoc = Loc; + } + + /// \brief Construct an integral constant template argument. + TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value, + QualType Type) + : Kind(Integral) { + new (Integer.Value) llvm::APSInt(Value); + Integer.Type = Type.getAsOpaquePtr(); + StartLoc = Loc; + } + + /// \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) { + new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); + Integer.Type = Other.Integer.Type; + } + else + TypeOrValue = Other.TypeOrValue; + StartLoc = Other.StartLoc; + } + + TemplateArgument& operator=(const TemplateArgument& Other) { + // FIXME: Does not provide the strong guarantee for exception + // safety. + using llvm::APSInt; + + if (Kind == Other.Kind && Kind == Integral) { + // Copy integral values. + *this->getAsIntegral() = *Other.getAsIntegral(); + 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; + } else + TypeOrValue = Other.TypeOrValue; + } + StartLoc = Other.StartLoc; + + return *this; + } + + ~TemplateArgument() { + using llvm::APSInt; + + if (Kind == Integral) + getAsIntegral()->~APSInt(); + } + + /// \brief Return the kind of stored template argument. + ArgKind getKind() const { return Kind; } + + /// \brief Retrieve the template argument as a type. + QualType getAsType() const { + if (Kind != Type) + return QualType(); + + 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); + } + + /// \brief Retrieve the template argument as an expression. + Expr *getAsExpr() const { + if (Kind != Expression) + return 0; + + return reinterpret_cast<Expr *>(TypeOrValue); + } + + /// \brief Retrieve the location where the template argument starts. + SourceLocation getLocation() const { return StartLoc; } + + /// \brief Used to insert TemplateArguments into FoldingSets. + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddInteger(Kind); + switch (Kind) { + case Type: + getAsType().Profile(ID); + break; + + case Declaration: + ID.AddPointer(getAsDecl()); // FIXME: Must be canonical! + break; + + case Integral: + getAsIntegral()->Profile(ID); + getIntegralType().Profile(ID); + break; + + case Expression: + // FIXME: We need a canonical representation of expressions. + ID.AddPointer(getAsExpr()); + break; + } + } +}; + +/// \brief A template argument list. +/// +/// FIXME: In the future, this class will be extended to support +/// variadic templates and member templates, which will make some of +/// the function names below make more sense. +class TemplateArgumentList { + /// \brief The template argument list. + /// + /// The integer value will be non-zero to indicate that this + /// template argument list does not own the pointer. + llvm::PointerIntPair<TemplateArgument *, 1> Arguments; + + /// \brief The number of template arguments in this template + /// argument list. + unsigned NumArguments; + + +public: + TemplateArgumentList(ASTContext &Context, + TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + bool CopyArgs); + + ~TemplateArgumentList(); + + /// \brief Retrieve the template argument at a given index. + const TemplateArgument &get(unsigned Idx) const { + assert(Idx < NumArguments && "Invalid template argument index"); + return getFlatArgumentList()[Idx]; + } + + /// \brief Retrieve the template argument at a given index. + TemplateArgument &get(unsigned Idx) { + assert(Idx < NumArguments && "Invalid template argument index"); + return getFlatArgumentList()[Idx]; + } + + /// \brief Retrieve the template argument at a given index. + TemplateArgument &operator[](unsigned Idx) { return get(Idx); } + 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 NumArguments; } + + /// \brief Retrieve the number of template arguments in the + /// flattened template argument list. + unsigned flat_size() const { return NumArguments; } + + /// \brief Retrieve the flattened template argument list. + TemplateArgument *getFlatArgumentList() { + return Arguments.getPointer(); + } + const TemplateArgument *getFlatArgumentList() const { + return Arguments.getPointer(); + } +}; + +// \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. +/// +/// Class template specializations represent both explicit +/// specialization of class templates, as in the example below, and +/// implicit instantiations of class templates. +/// +/// \code +/// template<typename T> class array; +/// +/// template<> +/// class array<bool> { }; // class template specialization array<bool> +/// \endcode +class ClassTemplateSpecializationDecl + : public CXXRecordDecl, public llvm::FoldingSetNode { + /// \brief The template that this specialization specializes + ClassTemplateDecl *SpecializedTemplate; + + /// \brief The template arguments used to describe this specialization. + TemplateArgumentList TemplateArgs; + + /// \brief The kind of specialization this declaration refers to. + /// Really a value of type TemplateSpecializationKind. + unsigned SpecializationKind : 2; + +protected: + ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, + DeclContext *DC, SourceLocation L, + ClassTemplateDecl *SpecializedTemplate, + TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs); + +public: + static ClassTemplateSpecializationDecl * + Create(ASTContext &Context, DeclContext *DC, SourceLocation L, + ClassTemplateDecl *SpecializedTemplate, + TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, + ClassTemplateSpecializationDecl *PrevDecl); + + /// \brief Retrieve the template that this specialization specializes. + ClassTemplateDecl *getSpecializedTemplate() const { + return SpecializedTemplate; + } + + const TemplateArgumentList &getTemplateArgs() const { + return TemplateArgs; + } + + /// \brief Determine the kind of specialization that this + /// declaration represents. + TemplateSpecializationKind getSpecializationKind() const { + return static_cast<TemplateSpecializationKind>(SpecializationKind); + } + + void setSpecializationKind(TemplateSpecializationKind TSK) { + SpecializationKind = TSK; + } + + /// \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) { + TypeForDecl = T.getTypePtr(); + } + + void Profile(llvm::FoldingSetNodeID &ID) const { + Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size()); + } + + static void + Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs) { + for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg) + TemplateArgs[Arg].Profile(ID); + } + + static bool classof(const Decl *D) { + return D->getKind() == ClassTemplateSpecialization || + D->getKind() == ClassTemplatePartialSpecialization; + } + + static bool classof(const ClassTemplateSpecializationDecl *) { + return true; + } + + static bool classof(const ClassTemplatePartialSpecializationDecl *) { + return true; + } +}; + +class ClassTemplatePartialSpecializationDecl + : public ClassTemplateSpecializationDecl +{ + /// \brief The list of template parameters + TemplateParameterList* TemplateParams; + + ClassTemplatePartialSpecializationDecl(ASTContext &Context, + DeclContext *DC, SourceLocation L, + TemplateParameterList *Params, + ClassTemplateDecl *SpecializedTemplate, + TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs) + : ClassTemplateSpecializationDecl(Context, ClassTemplatePartialSpecialization, + DC, L, SpecializedTemplate, TemplateArgs, + NumTemplateArgs), + TemplateParams(Params) { } + +public: + static ClassTemplatePartialSpecializationDecl * + Create(ASTContext &Context, DeclContext *DC, SourceLocation L, + TemplateParameterList *Params, + ClassTemplateDecl *SpecializedTemplate, + TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, + ClassTemplatePartialSpecializationDecl *PrevDecl); + + /// Get the list of template parameters + TemplateParameterList *getTemplateParameters() const { + return TemplateParams; + } + + // FIXME: Add Profile support! + + static bool classof(const Decl *D) { + return D->getKind() == ClassTemplatePartialSpecialization; + } + + static bool classof(const ClassTemplatePartialSpecializationDecl *) { + return true; + } +}; + +/// Declaration of a class template. +class ClassTemplateDecl : public TemplateDecl { +protected: + /// \brief Data that is common to all of the declarations of a given + /// class template. + struct Common { + /// \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> + PartialSpecializations; + + /// \brief The injected-class-name type for this class template. + QualType InjectedClassNameType; + }; + + /// \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) + : TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl), + PreviousDeclaration(PrevDecl), CommonPtr(CommonPtr) { } + + ~ClassTemplateDecl(); + +public: + /// Get the underlying class declarations of the template. + CXXRecordDecl *getTemplatedDecl() const { + return static_cast<CXXRecordDecl *>(TemplatedDecl); + } + + /// \brief Retrieve the previous declaration of this template. + ClassTemplateDecl *getPreviousDeclaration() const { + return PreviousDeclaration; + } + + /// Create a class template node. + static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl, + ClassTemplateDecl *PrevDecl); + + /// \brief Retrieve the set of specializations of this class template. + llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() { + return CommonPtr->Specializations; + } + + /// \brief Retrieve the set of partial specializations of this class + /// template. + llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> & + getPartialSpecializations() { + return CommonPtr->PartialSpecializations; + } + + /// \brief Retrieve the type of the injected-class-name for this + /// class template. + /// + /// The injected-class-name for a class template \c X is \c + /// X<template-args>, where \c template-args is formed from the + /// template arguments that correspond to the template parameters of + /// \c X. For example: + /// + /// \code + /// template<typename T, int N> + /// struct array { + /// typedef array this_type; // "array" is equivalent to "array<T, N>" + /// }; + /// \endcode + QualType getInjectedClassNameType(ASTContext &Context); + + // Implement isa/cast/dyncast support + static bool classof(const Decl *D) + { return D->getKind() == ClassTemplate; } + static bool classof(const ClassTemplateDecl *D) + { return true; } + + virtual void Destroy(ASTContext& C); +}; + +} /* end of namespace clang */ + +#endif diff --git a/include/clang/AST/DeclVisitor.h b/include/clang/AST/DeclVisitor.h new file mode 100644 index 000000000000..9423c319c3e3 --- /dev/null +++ b/include/clang/AST/DeclVisitor.h @@ -0,0 +1,54 @@ +//===--- DeclVisitor.h - Visitor for Decl subclasses ------------*- 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 DeclVisitor interface. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_DECLVISITOR_H +#define LLVM_CLANG_AST_DECLVISITOR_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" + +namespace clang { + +#define DISPATCH(NAME, CLASS) \ + return static_cast<ImplClass*>(this)-> Visit##NAME(static_cast<CLASS*>(D)) + +/// \brief A simple visitor class that helps create declaration visitors. +template<typename ImplClass, typename RetTy=void> +class DeclVisitor { +public: + RetTy Visit(Decl *D) { + switch (D->getKind()) { + default: assert(false && "Decl that isn't part of DeclNodes.def!"); +#define DECL(Derived, Base) \ + case Decl::Derived: DISPATCH(Derived##Decl, Derived##Decl); +#define ABSTRACT_DECL(Derived, Base) +#include "clang/AST/DeclNodes.def" + } + } + + // If the implementation chooses not to implement a certain visit + // method, fall back to the parent. +#define DECL(Derived, Base) \ + RetTy Visit##Derived##Decl(Derived##Decl *D) { DISPATCH(Base, Base); } +#define ABSTRACT_DECL(Derived, Base) DECL(Derived, Base) +#include "clang/AST/DeclNodes.def" + + RetTy VisitDecl(Decl *D) { return RetTy(); } +}; + +#undef DISPATCH + +} // end namespace clang + +#endif // LLVM_CLANG_AST_DECLVISITOR_H diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h new file mode 100644 index 000000000000..db140999b045 --- /dev/null +++ b/include/clang/AST/DeclarationName.h @@ -0,0 +1,357 @@ +//===-- DeclarationName.h - Representation of declaration names -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the DeclarationName and DeclarationNameTable classes. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_DECLARATIONNAME_H +#define LLVM_CLANG_AST_DECLARATIONNAME_H + +#include "clang/Basic/IdentifierTable.h" +#include "clang/AST/Type.h" + +namespace llvm { + template <typename T> struct DenseMapInfo; +} + +namespace clang { + class CXXSpecialName; + class CXXOperatorIdName; + class DeclarationNameExtra; + class IdentifierInfo; + class MultiKeywordSelector; + class UsingDirectiveDecl; + +/// DeclarationName - The name of a declaration. In the common case, +/// this just stores an IdentifierInfo pointer to a normal +/// name. However, it also provides encodings for Objective-C +/// selectors (optimizing zero- and one-argument selectors, which make +/// up 78% percent of all selectors in Cocoa.h) and special C++ names +/// for constructors, destructors, and conversion functions. +class DeclarationName { +public: + /// NameKind - The kind of name this object contains. + enum NameKind { + Identifier, + ObjCZeroArgSelector, + ObjCOneArgSelector, + ObjCMultiArgSelector, + CXXConstructorName, + CXXDestructorName, + CXXConversionFunctionName, + CXXOperatorName, + CXXUsingDirective + }; + +private: + /// StoredNameKind - The kind of name that is actually stored in the + /// upper bits of the Ptr field. This is only used internally. + enum StoredNameKind { + StoredIdentifier = 0, + StoredObjCZeroArgSelector, + StoredObjCOneArgSelector, + StoredDeclarationNameExtra, + PtrMask = 0x03 + }; + + /// Ptr - The lowest two bits are used to express what kind of name + /// we're actually storing, using the values of NameKind. Depending + /// on the kind of name this is, the upper bits of Ptr may have one + /// of several different meanings: + /// + /// StoredIdentifier - The name is a normal identifier, and Ptr is + /// a normal IdentifierInfo pointer. + /// + /// StoredObjCZeroArgSelector - The name is an Objective-C + /// selector with zero arguments, and Ptr is an IdentifierInfo + /// pointer pointing to the selector name. + /// + /// StoredObjCOneArgSelector - The name is an Objective-C selector + /// with one argument, and Ptr is an IdentifierInfo pointer + /// pointing to the selector name. + /// + /// StoredDeclarationNameExtra - Ptr is actually a pointer to a + /// DeclarationNameExtra structure, whose first value will tell us + /// whether this is an Objective-C selector, C++ operator-id name, + /// or special C++ name. + uintptr_t Ptr; + + /// getStoredNameKind - Return the kind of object that is stored in + /// Ptr. + StoredNameKind getStoredNameKind() const { + return static_cast<StoredNameKind>(Ptr & PtrMask); + } + + /// getExtra - Get the "extra" information associated with this + /// multi-argument selector or C++ special name. + DeclarationNameExtra *getExtra() const { + assert(getStoredNameKind() == StoredDeclarationNameExtra && + "Declaration name does not store an Extra structure"); + return reinterpret_cast<DeclarationNameExtra *>(Ptr & ~PtrMask); + } + + /// getAsCXXSpecialName - If the stored pointer is actually a + /// CXXSpecialName, returns a pointer to it. Otherwise, returns + /// a NULL pointer. + CXXSpecialName *getAsCXXSpecialName() const { + if (getNameKind() >= CXXConstructorName && + getNameKind() <= CXXConversionFunctionName) + return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask); + return 0; + } + + /// getAsCXXOperatorIdName + CXXOperatorIdName *getAsCXXOperatorIdName() const { + if (getNameKind() == CXXOperatorName) + return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask); + return 0; + } + + // Construct a declaration name from the name of a C++ constructor, + // destructor, or conversion function. + 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)) { + assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXOperatorId"); + Ptr |= StoredDeclarationNameExtra; + } + + /// Construct a declaration name from a raw pointer. + DeclarationName(uintptr_t Ptr) : Ptr(Ptr) { } + + friend class DeclarationNameTable; + friend class NamedDecl; + + /// getFETokenInfoAsVoid - Retrieves the front end-specified pointer + /// for this name as a void pointer. + void *getFETokenInfoAsVoid() const; + +public: + /// DeclarationName - Used to create an empty selector. + DeclarationName() : Ptr(0) { } + + // Construct a declaration name from an IdentifierInfo *. + DeclarationName(const IdentifierInfo *II) + : Ptr(reinterpret_cast<uintptr_t>(II)) { + assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo"); + } + + // Construct a declaration name from an Objective-C selector. + DeclarationName(Selector Sel); + + /// getUsingDirectiveName - Return name for all using-directives. + static DeclarationName getUsingDirectiveName(); + + // operator bool() - Evaluates true when this declaration name is + // non-empty. + operator bool() const { + return ((Ptr & PtrMask) != 0) || + (reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask)); + } + + /// Predicate functions for querying what type of name this is. + bool isIdentifier() const { return getStoredNameKind() == StoredIdentifier; } + bool isObjCZeroArgSelector() const { + return getStoredNameKind() == StoredObjCZeroArgSelector; + } + 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; + + /// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in + /// this declaration name, or NULL if this declaration name isn't a + /// simple identifier. + IdentifierInfo *getAsIdentifierInfo() const { + if (isIdentifier()) + return reinterpret_cast<IdentifierInfo *>(Ptr); + return 0; + } + + /// getAsOpaqueInteger - Get the representation of this declaration + /// name as an opaque integer. + uintptr_t getAsOpaqueInteger() const { return Ptr; } + + /// getAsOpaquePtr - Get the representation of this declaration name as + /// an opaque pointer. + void *getAsOpaquePtr() const { return reinterpret_cast<void*>(Ptr); } + + static DeclarationName getFromOpaqueInteger(uintptr_t P) { + DeclarationName N; + N.Ptr = P; + 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. + QualType getCXXNameType() const; + + /// getCXXOverloadedOperator - If this name is the name of an + /// overloadable operator in C++ (e.g., @c operator+), retrieve the + /// kind of overloaded operator. + OverloadedOperatorKind getCXXOverloadedOperator() const; + + /// getObjCSelector - Get the Objective-C selector stored in this + /// declaration name. + Selector getObjCSelector() const; + + /// getFETokenInfo/setFETokenInfo - The language front-end is + /// allowed to associate arbitrary metadata with some kinds of + /// declaration names, including normal identifiers and C++ + /// constructors, destructors, and conversion functions. + template<typename T> + T *getFETokenInfo() const { return static_cast<T*>(getFETokenInfoAsVoid()); } + + void setFETokenInfo(void *T); + + /// operator== - Determine whether the specified names are identical.. + friend bool operator==(DeclarationName LHS, DeclarationName RHS) { + return LHS.Ptr == RHS.Ptr; + } + + /// operator!= - Determine whether the specified names are different. + friend bool operator!=(DeclarationName LHS, DeclarationName RHS) { + return LHS.Ptr != RHS.Ptr; + } + + static DeclarationName getEmptyMarker() { + return DeclarationName(uintptr_t(-1)); + } + + static DeclarationName getTombstoneMarker() { + return DeclarationName(uintptr_t(-2)); + } +}; + +/// Ordering on two declaration names. If both names are identifiers, +/// this provides a lexicographical ordering. +bool operator<(DeclarationName LHS, DeclarationName RHS); + +/// Ordering on two declaration names. If both names are identifiers, +/// this provides a lexicographical ordering. +inline bool operator>(DeclarationName LHS, DeclarationName RHS) { + return RHS < LHS; +} + +/// Ordering on two declaration names. If both names are identifiers, +/// this provides a lexicographical ordering. +inline bool operator<=(DeclarationName LHS, DeclarationName RHS) { + return !(RHS < LHS); +} + +/// Ordering on two declaration names. If both names are identifiers, +/// this provides a lexicographical ordering. +inline bool operator>=(DeclarationName LHS, DeclarationName RHS) { + return !(LHS < RHS); +} + +/// DeclarationNameTable - Used to store and retrieve DeclarationName +/// instances for the various kinds of declaration names, e.g., normal +/// identifiers, C++ constructor names, etc. This class contains +/// uniqued versions of each of the C++ special names, which can be +/// retrieved using its member functions (e.g., +/// getCXXConstructorName). +class DeclarationNameTable { + void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> * + CXXOperatorIdName *CXXOperatorNames; // Operator names + + DeclarationNameTable(const DeclarationNameTable&); // NONCOPYABLE + DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE + +public: + DeclarationNameTable(); + ~DeclarationNameTable(); + + /// getIdentifier - Create a declaration name that is a simple + /// identifier. + DeclarationName getIdentifier(IdentifierInfo *ID) { + return DeclarationName(ID); + } + + /// getCXXConstructorName - Returns the name of a C++ constructor + /// for the given Type. + DeclarationName getCXXConstructorName(QualType Ty) { + return getCXXSpecialName(DeclarationName::CXXConstructorName, Ty); + } + + /// getCXXDestructorName - Returns the name of a C++ destructor + /// for the given Type. + DeclarationName getCXXDestructorName(QualType Ty) { + return getCXXSpecialName(DeclarationName::CXXDestructorName, Ty); + } + + /// getCXXConversionFunctionName - Returns the name of a C++ + /// conversion function for the given Type. + DeclarationName getCXXConversionFunctionName(QualType 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); + + /// 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 <<. +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + DeclarationName N) { + DB.AddTaggedVal(N.getAsOpaqueInteger(), + Diagnostic::ak_declarationname); + return DB; +} + + +} // end namespace clang + +namespace llvm { +/// Define DenseMapInfo so that DeclarationNames can be used as keys +/// in DenseMap and DenseSets. +template<> +struct DenseMapInfo<clang::DeclarationName> { + static inline clang::DeclarationName getEmptyKey() { + return clang::DeclarationName::getEmptyMarker(); + } + + static inline clang::DeclarationName getTombstoneKey() { + return clang::DeclarationName::getTombstoneMarker(); + } + + static unsigned getHashValue(clang::DeclarationName); + + static inline bool + isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) { + return LHS == RHS; + } + + static inline bool isPod() { return true; } +}; + +} // end namespace llvm + +#endif diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h new file mode 100644 index 000000000000..98de5f9d382e --- /dev/null +++ b/include/clang/AST/Expr.h @@ -0,0 +1,2500 @@ +//===--- Expr.h - Classes for representing expressions ----------*- 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 Expr interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_EXPR_H +#define LLVM_CLANG_AST_EXPR_H + +#include "clang/AST/APValue.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/Type.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/SmallVector.h" +#include <vector> + +namespace clang { + class ASTContext; + class APValue; + class Decl; + class IdentifierInfo; + class ParmVarDecl; + class NamedDecl; + class ValueDecl; + class BlockDecl; + class CXXOperatorCallExpr; + class CXXMemberCallExpr; + +/// Expr - This represents one expression. Note that Expr's are subclasses of +/// Stmt. This allows an expression to be transparently used any place a Stmt +/// is required. +/// +class Expr : public Stmt { + QualType TR; + +protected: + /// TypeDependent - Whether this expression is type-dependent + /// (C++ [temp.dep.expr]). + bool TypeDependent : 1; + + /// 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) + : Stmt(SC), TypeDependent(false), ValueDependent(false) { + setType(T); + } + + Expr(StmtClass SC, QualType T, bool TD, bool VD) + : Stmt(SC), TypeDependent(TD), ValueDependent(VD) { + setType(T); + } + + /// \brief Construct an empty expression. + explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { } + +public: + QualType getType() const { return TR; } + 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 + // QualType::getNonReferenceType() to retrieve the non-reference + // 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()) && + "Expressions can't have reference type"); + + 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. + /// @code + /// template<int Size, char (&Chars)[Size]> struct meta_string; + /// @endcode + bool isValueDependent() const { return ValueDependent; } + + /// \brief Set whether this expression is value-dependent or not. + void setValueDependent(bool VD) { ValueDependent = VD; } + + /// isTypeDependent - Determines whether this expression is + /// type-dependent (C++ [temp.dep.expr]), which means that its type + /// could change from one template instantiation to the next. For + /// example, the expressions "x" and "x + y" are type-dependent in + /// the following code, but "y" is not type-dependent: + /// @code + /// template<typename T> + /// void add(T x, int y) { + /// x + y; + /// } + /// @endcode + bool isTypeDependent() const { return TypeDependent; } + + /// \brief Set whether this expression is type-dependent or not. + void setTypeDependent(bool TD) { TypeDependent = TD; } + + /// 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. + virtual SourceRange getSourceRange() const = 0; + + /// 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 + /// - e[i] + /// - (e), where e must be an lvalue + /// - e.name, where e must be an lvalue + /// - e->name + /// - *e, the type of e cannot be a function type + /// - string-constant + /// - reference type [C++ [expr]] + /// - b ? x : y, where x and y are lvalues of suitable types [C++] + /// + enum isLvalueResult { + LV_Valid, + LV_NotObjectType, + LV_IncompleteVoidType, + LV_DuplicateVectorComponents, + LV_InvalidExpression, + LV_MemberFunction + }; + isLvalueResult isLvalue(ASTContext &Ctx) const; + + // 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, + /// recursively, any member or element of all contained aggregates or unions) + /// with a const-qualified type. + /// + /// \param Loc [in] [out] - A source location which *may* be filled + /// in with the location of the expression making this a + /// non-modifiable lvalue, if specified. + enum isModifiableLvalueResult { + MLV_Valid, + MLV_NotObjectType, + MLV_IncompleteVoidType, + MLV_DuplicateVectorComponents, + MLV_InvalidExpression, + MLV_LValueCast, // Specialized form of MLV_InvalidExpression. + MLV_IncompleteType, + MLV_ConstQualified, + MLV_ArrayType, + MLV_NotBlockQualified, + MLV_ReadonlyProperty, + MLV_NoSetterProperty, + MLV_MemberFunction + }; + 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(); + + 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 + /// of the invalid expression. + bool isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, + SourceLocation *Loc = 0, + bool isEvaluated = true) const; + bool isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc = 0) const { + llvm::APSInt X; + return isIntegerConstantExpr(X, Ctx, Loc); + } + /// 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 + /// the error. + /// If the expression is foldable, but not an integer constant expression, + /// Diag contains a note diagnostic that describes why it isn't an integer + /// constant expression. If the expression *is* an integer constant + /// expression, then Diag will be zero. + unsigned Diag; + const Expr *DiagExpr; + SourceLocation DiagLoc; + + EvalResult() : HasSideEffects(false), Diag(0), DiagExpr(0) {} + }; + + /// Evaluate - Return true if this is a constant which we can fold using + /// any crazy technique (that has nothing to do with language standards) that + /// we want to. If this function returns true, it returns the folded constant + /// in Result. + bool Evaluate(EvalResult &Result, ASTContext &Ctx) const; + + /// isEvaluatable - Call Evaluate to see if this expression can be constant + /// folded, but discard the result. + bool isEvaluatable(ASTContext &Ctx) const; + + /// EvaluateAsInt - Call Evaluate and return the folded integer. This + /// 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. + bool EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const; + + /// 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; + + /// isOBJCGCCandidate - Return true if this expression may be used in a read/ + /// 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, + /// then this method recursively returns its subexpression, and so forth. + /// Otherwise, the method returns the current Expr. + Expr* IgnoreParens(); + + /// 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(); + } + const Expr *IgnoreParenCasts() const { + return const_cast<Expr*>(this)->IgnoreParenCasts(); + } + 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) { + return T->getStmtClass() >= firstExprConstant && + T->getStmtClass() <= lastExprConstant; + } + static bool classof(const Expr *) { return true; } +}; + + +//===----------------------------------------------------------------------===// +// Primary Expressions. +//===----------------------------------------------------------------------===// + +/// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function, +/// enum, etc. +class DeclRefExpr : public Expr { + NamedDecl *D; + SourceLocation Loc; + +protected: + // FIXME: Eventually, this constructor will go away and all subclasses + // will have to provide the type- and value-dependent flags. + DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l) : + Expr(SC, t), D(d), Loc(l) {} + + DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l, bool TD, + bool VD) : + Expr(SC, t, TD, VD), D(d), Loc(l) {} + +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) : + Expr(DeclRefExprClass, t), D(d), Loc(l) {} + + 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) + : Expr(DeclRefExprClass, Empty) { } + + NamedDecl *getDecl() { return D; } + const NamedDecl *getDecl() const { return D; } + void setDecl(NamedDecl *NewD) { D = NewD; } + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == DeclRefExprClass || + T->getStmtClass() == CXXConditionDeclExprClass || + T->getStmtClass() == QualifiedDeclRefExprClass; + } + static bool classof(const DeclRefExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__. +class PredefinedExpr : public Expr { +public: + enum IdentType { + Func, + Function, + PrettyFunction + }; + +private: + SourceLocation Loc; + IdentType Type; +public: + PredefinedExpr(SourceLocation l, QualType type, IdentType IT) + : Expr(PredefinedExprClass, type), Loc(l), Type(IT) {} + + /// \brief Construct an empty predefined expression. + 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. + + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + 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(); +}; + +class IntegerLiteral : public Expr { + llvm::APInt Value; + SourceLocation Loc; +public: + // 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) { + assert(type->isIntegerType() && "Illegal type in IntegerLiteral"); + } + + /// \brief Construct an empty integer literal. + 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); } + + /// \brief Retrieve the location of the literal. + SourceLocation getLocation() const { return Loc; } + + 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 IntegerLiteral *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +class CharacterLiteral : public Expr { + unsigned Value; + SourceLocation Loc; + bool IsWide; +public: + // type should be IntTy + CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l) + : Expr(CharacterLiteralClass, type), Value(value), Loc(l), IsWide(iswide) { + } + + /// \brief Construct an empty character literal. + CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { } + + CharacterLiteral* Clone(ASTContext &C) const; + + SourceLocation getLoc() 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 CharacterLiteral *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +class FloatingLiteral : public Expr { + llvm::APFloat Value; + bool IsExact : 1; + SourceLocation Loc; +public: + FloatingLiteral(const llvm::APFloat &V, bool* isexact, + QualType Type, SourceLocation L) + : Expr(FloatingLiteralClass, Type), Value(V), IsExact(*isexact), Loc(L) {} + + /// \brief Construct an empty floating-point literal. + 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; } + + bool isExact() const { return IsExact; } + void setExact(bool E) { IsExact = E; } + + /// getValueAsApproximateDouble - This returns the value as an inaccurate + /// 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; } + + // 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. + + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + 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(); +}; + +/// ImaginaryLiteral - We support imaginary integer and floating point literals, +/// like "1.0i". We represent these as a wrapper around FloatingLiteral and +/// IntegerLiteral classes. Instances of this class always have a Complex type +/// whose element type matches the subexpression. +/// +class ImaginaryLiteral : public Expr { + Stmt *Val; +public: + ImaginaryLiteral(Expr *val, QualType Ty) + : Expr(ImaginaryLiteralClass, Ty), Val(val) {} + + /// \brief Build an empty imaginary literal. + 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 ImaginaryLiteral *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// StringLiteral - This represents a string literal expression, e.g. "foo" +/// or L"bar" (wide strings). The actual string is returned by getStrData() +/// is NOT null-terminated, and the length of the string is determined by +/// calling getByteLength(). The C type for a string is always a +/// ConstantArrayType. In C++, the char type is const qualified, in C it is +/// not. +/// +/// Note that strings in C can be formed by concatenation of multiple string +/// literal pptokens in translation phase #6. This keeps track of the locations +/// of each of these pieces. +/// +/// Strings in C can also be truncated and extended by assigning into arrays, +/// e.g. with constructs like: +/// char X[2] = "foobar"; +/// In this case, getByteLength() will return 6, but the string literal will +/// have type "char[2]". +class StringLiteral : public Expr { + const char *StrData; + unsigned ByteLength; + bool IsWide; + unsigned NumConcatenated; + SourceLocation TokLocs[1]; + + StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty) {} +public: + /// This is the "fully general" constructor that allows representation of + /// strings formed from multiple concatenated tokens. + static StringLiteral *Create(ASTContext &C, const char *StrData, + unsigned ByteLength, bool Wide, QualType Ty, + const SourceLocation *Loc, unsigned NumStrs); + + /// Simple constructor for string literals made from one token. + 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); + } + + /// \brief Construct an empty string literal. + static StringLiteral *CreateEmpty(ASTContext &C, unsigned NumStrs); + + StringLiteral* Clone(ASTContext &C) const; + void Destroy(ASTContext &C); + + 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); + + 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]) + 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) { + assert(TokNum < NumConcatenated && "Invalid tok number"); + TokLocs[TokNum] = L; + } + + typedef const SourceLocation *tokloc_iterator; + 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]); + } + 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(); +}; + +/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This +/// AST node is only formed if full location information is requested. +class ParenExpr : public Expr { + SourceLocation L, R; + Stmt *Val; +public: + ParenExpr(SourceLocation l, SourceLocation r, Expr *val) + : Expr(ParenExprClass, val->getType(), + val->isTypeDependent(), val->isValueDependent()), + L(l), R(r), Val(val) {} + + /// \brief Construct an empty parenthesized expression. + explicit ParenExpr(EmptyShell Empty) + : Expr(ParenExprClass, Empty) { } + + const Expr *getSubExpr() const { return cast<Expr>(Val); } + Expr *getSubExpr() { return cast<Expr>(Val); } + void setSubExpr(Expr *E) { Val = E; } + + virtual SourceRange getSourceRange() const { return SourceRange(L, R); } + + /// \brief Get the location of the left parentheses '('. + SourceLocation getLParen() const { return L; } + void setLParen(SourceLocation Loc) { L = Loc; } + + /// \brief Get the location of the right parentheses ')'. + 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 ParenExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +/// UnaryOperator - This represents the unary-expression's (except sizeof and +/// alignof), the postinc/postdec operators from postfix-expression, and various +/// extensions. +/// +/// Notes on various nodes: +/// +/// Real/Imag - These return the real/imag part of a complex operand. If +/// applied to a non-complex value, the former returns its operand and the +/// 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 +/// ArraySubscriptExpr's applied to it. +/// +class UnaryOperator : public Expr { +public: + // Note that additions to this should also update the StmtVisitor class. + enum Opcode { + PostInc, PostDec, // [C99 6.5.2.4] Postfix increment and decrement operators + PreInc, PreDec, // [C99 6.5.3.1] Prefix increment and decrement operators. + AddrOf, Deref, // [C99 6.5.3.2] Address and indirection operators. + Plus, Minus, // [C99 6.5.3.3] Unary arithmetic operators. + Not, LNot, // [C99 6.5.3.3] Unary arithmetic operators. + Real, Imag, // "__real expr"/"__imag expr" Extension. + Extension, // __extension__ marker. + OffsetOf // __builtin_offsetof + }; +private: + Stmt *Val; + Opcode Opc; + SourceLocation Loc; +public: + + UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l) + : Expr(UnaryOperatorClass, type, + input->isTypeDependent() && opc != OffsetOf, + input->isValueDependent()), + Val(input), Opc(opc), Loc(l) {} + + /// \brief Build an empty unary operator. + explicit UnaryOperator(EmptyShell Empty) + : Expr(UnaryOperatorClass, Empty), Opc(AddrOf) { } + + Opcode getOpcode() const { return Opc; } + void setOpcode(Opcode O) { Opc = O; } + + Expr *getSubExpr() const { return cast<Expr>(Val); } + void setSubExpr(Expr *E) { Val = E; } + + /// getOperatorLoc - Return the location of the operator. + SourceLocation getOperatorLoc() const { return Loc; } + void setOperatorLoc(SourceLocation L) { Loc = L; } + + /// isPostfix - Return true if this is a postfix operation, like x++. + static bool isPostfix(Opcode Op) { + return Op == PostInc || Op == PostDec; + } + + /// isPostfix - Return true if this is a prefix operation, like --x. + static bool isPrefix(Opcode Op) { + return Op == PreInc || Op == PreDec; + } + + bool isPrefix() const { return isPrefix(Opc); } + bool isPostfix() const { return isPostfix(Opc); } + bool isIncrementOp() const {return Opc==PreInc || Opc==PostInc; } + bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; } + bool isOffsetOfOp() const { return Opc == OffsetOf; } + static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; } + + /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it + /// corresponds to, e.g. "sizeof" or "[pre]++" + static const char *getOpcodeStr(Opcode Op); + + /// \brief Retrieve the unary opcode that corresponds to the given + /// overloaded operator. + static Opcode getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix); + + /// \brief Retrieve the overloaded operator kind that corresponds to + /// the given unary opcode. + static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); + + virtual SourceRange getSourceRange() const { + if (isPostfix()) + return SourceRange(Val->getLocStart(), Loc); + else + 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 UnaryOperator *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// SizeOfAlignOfExpr - [C99 6.5.3.4] - This is for sizeof/alignof, both of +/// types and expressions. +class SizeOfAlignOfExpr : public Expr { + bool isSizeof : 1; // true if sizeof, false if alignof. + bool isType : 1; // true if operand is a type, false if an expression + union { + void *Ty; + Stmt *Ex; + } Argument; + SourceLocation OpLoc, RParenLoc; +public: + SizeOfAlignOfExpr(bool issizeof, QualType T, + QualType resultType, SourceLocation op, + SourceLocation rp) : + Expr(SizeOfAlignOfExprClass, resultType, + false, // Never type-dependent (C++ [temp.dep.expr]p3). + // Value-dependent if the argument is type-dependent. + T->isDependentType()), + isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) { + Argument.Ty = T.getAsOpaquePtr(); + } + + SizeOfAlignOfExpr(bool issizeof, Expr *E, + QualType resultType, SourceLocation op, + SourceLocation rp) : + Expr(SizeOfAlignOfExprClass, resultType, + false, // Never type-dependent (C++ [temp.dep.expr]p3). + // Value-dependent if the argument is type-dependent. + E->isTypeDependent()), + isSizeof(issizeof), isType(false), OpLoc(op), RParenLoc(rp) { + Argument.Ex = E; + } + + /// \brief Construct an empty sizeof/alignof expression. + explicit SizeOfAlignOfExpr(EmptyShell Empty) + : Expr(SizeOfAlignOfExprClass, Empty) { } + + virtual void Destroy(ASTContext& C); + + bool isSizeOf() const { return isSizeof; } + void setSizeof(bool S) { isSizeof = S; } + + bool isArgumentType() const { return isType; } + QualType getArgumentType() const { + assert(isArgumentType() && "calling getArgumentType() when arg is expr"); + return QualType::getFromOpaquePtr(Argument.Ty); + } + Expr *getArgumentExpr() { + assert(!isArgumentType() && "calling getArgumentExpr() when arg is type"); + return static_cast<Expr*>(Argument.Ex); + } + const Expr *getArgumentExpr() const { + return const_cast<SizeOfAlignOfExpr*>(this)->getArgumentExpr(); + } + + void setArgument(Expr *E) { Argument.Ex = E; isType = false; } + void setArgument(QualType T) { + Argument.Ty = T.getAsOpaquePtr(); + isType = true; + } + + /// Gets the argument type, or the type of the argument expression, whichever + /// is appropriate. + QualType getTypeOfArgument() const { + return isArgumentType() ? getArgumentType() : getArgumentExpr()->getType(); + } + + SourceLocation getOperatorLoc() const { return OpLoc; } + void setOperatorLoc(SourceLocation L) { OpLoc = L; } + + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(OpLoc, RParenLoc); + } + + 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(); +}; + +//===----------------------------------------------------------------------===// +// Postfix Operators. +//===----------------------------------------------------------------------===// + +/// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting. +class ArraySubscriptExpr : public Expr { + enum { LHS, RHS, END_EXPR=2 }; + Stmt* SubExprs[END_EXPR]; + SourceLocation RBracketLoc; +public: + ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t, + SourceLocation rbracketloc) + : Expr(ArraySubscriptExprClass, t, + lhs->isTypeDependent() || rhs->isTypeDependent(), + lhs->isValueDependent() || rhs->isValueDependent()), + RBracketLoc(rbracketloc) { + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + } + + /// \brief Create an empty array subscript expression. + explicit ArraySubscriptExpr(EmptyShell Shell) + : Expr(ArraySubscriptExprClass, Shell) { } + + /// An array access can be written A[4] or 4[A] (both are equivalent). + /// - getBase() and getIdx() always present the normalized view: A[4]. + /// In this case getBase() returns "A" and getIdx() returns "4". + /// - getLHS() and getRHS() present the syntactic view. e.g. for + /// 4[A] getLHS() returns "4". + /// Note: Because vector element access is also written A[4] we must + /// predicate the format conversion in getBase and getIdx only on the + /// the type of the RHS, as it is possible for the LHS to be a vector of + /// integer type + Expr *getLHS() { return cast<Expr>(SubExprs[LHS]); } + const Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } + void setLHS(Expr *E) { SubExprs[LHS] = E; } + + 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() { + return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS()); + } + + const Expr *getBase() const { + return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS()); + } + + 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 { + 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 ArraySubscriptExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +/// 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)", +/// while its subclasses may represent alternative syntax that (semantically) +/// 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 { + enum { FN=0, ARGS_START=1 }; + 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); + +public: + 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() {} + + 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; } + + /// 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!"); + return cast<Expr>(SubExprs[Arg+ARGS_START]); + } + const Expr *getArg(unsigned Arg) const { + 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; } + + /// 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 + /// type. + QualType getCallReturnType() const; + + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(getCallee()->getLocStart(), RParenLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CallExprClass || + T->getStmtClass() == CXXOperatorCallExprClass || + T->getStmtClass() == CXXMemberCallExprClass; + } + static bool classof(const CallExpr *) { return true; } + static bool classof(const CXXOperatorCallExpr *) { return true; } + static bool classof(const CXXMemberCallExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// 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; +public: + MemberExpr(Expr *base, bool isarrow, NamedDecl *memberdecl, SourceLocation l, + QualType ty) + : Expr(MemberExprClass, ty, + base->isTypeDependent(), base->isValueDependent()), + Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow) {} + + /// \brief Build an empty member reference expression. + explicit MemberExpr(EmptyShell Empty) : Expr(MemberExprClass, Empty) { } + + void setBase(Expr *E) { Base = E; } + Expr *getBase() const { return cast<Expr>(Base); } + + /// \brief Retrieve the member declaration to which this expression refers. + /// + /// The returned declaration will either be a FieldDecl or (in C++) + /// a CXXMethodDecl. + NamedDecl *getMemberDecl() const { return MemberDecl; } + void setMemberDecl(NamedDecl *D) { MemberDecl = D; } + + 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 getMemberLoc() const { return MemberLoc; } + void setMemberLoc(SourceLocation L) { MemberLoc = L; } + + virtual SourceRange getSourceRange() const { + // If we have an implicit base (like a C++ implicit this), + // make sure not to return its location + SourceLocation BaseLoc = getBase()->getLocStart(); + if (BaseLoc.isInvalid()) + return SourceRange(MemberLoc, MemberLoc); + return SourceRange(BaseLoc, MemberLoc); + } + + virtual SourceLocation getExprLoc() const { return MemberLoc; } + + 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] +/// +class CompoundLiteralExpr : public Expr { + /// LParenLoc - If non-null, this is the location of the left paren in a + /// compound literal like "(int){4}". This can be null if this is a + /// synthesized compound expression. + SourceLocation LParenLoc; + Stmt *Init; + bool FileScope; +public: + CompoundLiteralExpr(SourceLocation lparenloc, QualType ty, Expr *init, + bool fileScope) + : Expr(CompoundLiteralExprClass, ty), LParenLoc(lparenloc), Init(init), + FileScope(fileScope) {} + + /// \brief Construct an empty compound literal. + explicit CompoundLiteralExpr(EmptyShell Empty) + : Expr(CompoundLiteralExprClass, Empty) { } + + const Expr *getInitializer() const { return cast<Expr>(Init); } + Expr *getInitializer() { return cast<Expr>(Init); } + void setInitializer(Expr *E) { Init = E; } + + bool isFileScope() const { return FileScope; } + void setFileScope(bool FS) { FileScope = FS; } + + SourceLocation getLParenLoc() const { return LParenLoc; } + void setLParenLoc(SourceLocation L) { LParenLoc = L; } + + virtual SourceRange getSourceRange() const { + // FIXME: Init should never be null. + if (!Init) + return SourceRange(); + if (LParenLoc.isInvalid()) + return Init->getSourceRange(); + return SourceRange(LParenLoc, Init->getLocEnd()); + } + + 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(); +}; + +/// CastExpr - Base class for type casts, including both implicit +/// casts (ImplicitCastExpr) and explicit casts that have some +/// representation in the source code (ExplicitCastExpr's derived +/// classes). +class CastExpr : public Expr { + Stmt *Op; +protected: + CastExpr(StmtClass SC, QualType ty, 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) {} + + /// \brief Construct an empty cast. + CastExpr(StmtClass SC, EmptyShell Empty) + : Expr(SC, Empty) { } + +public: + 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) { + StmtClass SC = T->getStmtClass(); + if (SC >= CXXNamedCastExprClass && SC <= CXXFunctionalCastExprClass) + return true; + + if (SC >= ImplicitCastExprClass && SC <= CStyleCastExprClass) + return true; + + return false; + } + static bool classof(const CastExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ImplicitCastExpr - Allows us to explicitly represent implicit type +/// conversions, which have no direct representation in the original +/// source code. For example: converting T[]->T*, void f()->void +/// (*f)(), float->double, short->int, etc. +/// +/// In C, implicit casts always produce rvalues. However, in C++, an +/// implicit cast whose result is being bound to a reference will be +/// an lvalue. For example: +/// +/// @code +/// class Base { }; +/// class Derived : public Base { }; +/// void f(Derived d) { +/// Base& b = d; // initializer is an ImplicitCastExpr to an lvalue of type Base +/// } +/// @endcode +class ImplicitCastExpr : public CastExpr { + /// LvalueCast - Whether this cast produces an lvalue. + bool LvalueCast; + +public: + ImplicitCastExpr(QualType ty, Expr *op, bool Lvalue) : + CastExpr(ImplicitCastExprClass, ty, op), LvalueCast(Lvalue) { } + + /// \brief Construct an empty implicit cast. + explicit ImplicitCastExpr(EmptyShell Shell) + : CastExpr(ImplicitCastExprClass, Shell) { } + + + virtual SourceRange getSourceRange() const { + return getSubExpr()->getSourceRange(); + } + + /// isLvalueCast - Whether this cast produces an lvalue. + bool isLvalueCast() const { return LvalueCast; } + + /// 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 ImplicitCastExpr *) { return true; } +}; + +/// ExplicitCastExpr - An explicit cast written in the source +/// code. +/// +/// This class is effectively an abstract class, because it provides +/// the basic representation of an explicitly-written cast without +/// specifying which kind of cast (C cast, functional cast, static +/// cast, etc.) was written; specific derived classes represent the +/// particular style of cast and its location information. +/// +/// Unlike implicit casts, explicit cast nodes have two different +/// types: the type that was written into the source code, and the +/// actual type of the expression as determined by semantic +/// analysis. These types may differ slightly. For example, in C++ one +/// can cast to a reference type, which indicates that the resulting +/// expression will be an lvalue. The reference type, however, will +/// not be used as the type of the expression. +class ExplicitCastExpr : public CastExpr { + /// TypeAsWritten - The type that this expression is casting to, as + /// written in the source code. + QualType TypeAsWritten; + +protected: + ExplicitCastExpr(StmtClass SC, QualType exprTy, Expr *op, QualType writtenTy) + : CastExpr(SC, exprTy, op), TypeAsWritten(writtenTy) {} + + /// \brief Construct an empty explicit cast. + ExplicitCastExpr(StmtClass SC, EmptyShell Shell) + : CastExpr(SC, Shell) { } + +public: + /// getTypeAsWritten - Returns the type that this expression is + /// casting to, as written in the source code. + QualType getTypeAsWritten() const { return TypeAsWritten; } + void setTypeAsWritten(QualType T) { TypeAsWritten = T; } + + static bool classof(const Stmt *T) { + StmtClass SC = T->getStmtClass(); + if (SC >= ExplicitCastExprClass && SC <= CStyleCastExprClass) + return true; + if (SC >= CXXNamedCastExprClass && SC <= CXXFunctionalCastExprClass) + return true; + + return false; + } + static bool classof(const ExplicitCastExpr *) { return true; } +}; + +/// CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style +/// cast in C++ (C++ [expr.cast]), which uses the syntax +/// (Type)expr. For example: @c (int)f. +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), + LPLoc(l), RPLoc(r) {} + + /// \brief Construct an empty C-style explicit cast. + explicit CStyleCastExpr(EmptyShell Shell) + : ExplicitCastExpr(CStyleCastExprClass, Shell) { } + + SourceLocation getLParenLoc() const { return LPLoc; } + void setLParenLoc(SourceLocation L) { LPLoc = L; } + + SourceLocation getRParenLoc() const { return RPLoc; } + void setRParenLoc(SourceLocation L) { RPLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(LPLoc, getSubExpr()->getSourceRange().getEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == CStyleCastExprClass; + } + static bool classof(const CStyleCastExpr *) { return true; } +}; + +/// \brief A builtin binary operation expression such as "x + y" or "x <= y". +/// +/// This expression node kind describes a builtin binary operation, +/// such as "x + y" for integer values "x" and "y". The operands will +/// already have been converted to appropriate types (e.g., by +/// performing promotions or conversions). +/// +/// In C++, where operators may be overloaded, a different kind of +/// expression node (CXXOperatorCallExpr) is used to express the +/// invocation of an overloaded operator with operator syntax. Within +/// a C++ template, whether BinaryOperator or CXXOperatorCallExpr is +/// used to store an expression "x + y" depends on the subexpressions +/// for x and y. If neither x or y is type-dependent, and the "+" +/// operator resolves to a built-in operation, BinaryOperator will be +/// used to express the computation (x and y may still be +/// value-dependent). If either x or y is type-dependent, or if the +/// "+" resolves to an overloaded operator, CXXOperatorCallExpr will +/// be used to express the computation. +class BinaryOperator : public Expr { +public: + enum Opcode { + // Operators listed in order of precedence. + // Note that additions to this should also update the StmtVisitor class. + PtrMemD, PtrMemI, // [C++ 5.5] Pointer-to-member operators. + Mul, Div, Rem, // [C99 6.5.5] Multiplicative operators. + Add, Sub, // [C99 6.5.6] Additive operators. + Shl, Shr, // [C99 6.5.7] Bitwise shift operators. + LT, GT, LE, GE, // [C99 6.5.8] Relational operators. + EQ, NE, // [C99 6.5.9] Equality operators. + And, // [C99 6.5.10] Bitwise AND operator. + Xor, // [C99 6.5.11] Bitwise XOR operator. + Or, // [C99 6.5.12] Bitwise OR operator. + LAnd, // [C99 6.5.13] Logical AND operator. + LOr, // [C99 6.5.14] Logical OR operator. + Assign, MulAssign,// [C99 6.5.16] Assignment operators. + DivAssign, RemAssign, + AddAssign, SubAssign, + ShlAssign, ShrAssign, + AndAssign, XorAssign, + OrAssign, + Comma // [C99 6.5.17] Comma operator. + }; +private: + enum { LHS, RHS, END_EXPR }; + Stmt* SubExprs[END_EXPR]; + Opcode Opc; + SourceLocation OpLoc; +public: + + BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, + SourceLocation opLoc) + : Expr(BinaryOperatorClass, ResTy, + lhs->isTypeDependent() || rhs->isTypeDependent(), + lhs->isValueDependent() || rhs->isValueDependent()), + Opc(opc), OpLoc(opLoc) { + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + assert(!isCompoundAssignmentOp() && + "Use ArithAssignBinaryOperator for compound assignments"); + } + + /// \brief Construct an empty binary operator. + explicit BinaryOperator(EmptyShell Empty) + : Expr(BinaryOperatorClass, Empty), Opc(Comma) { } + + SourceLocation getOperatorLoc() const { return OpLoc; } + void setOperatorLoc(SourceLocation L) { OpLoc = L; } + + Opcode getOpcode() const { return Opc; } + void setOpcode(Opcode O) { Opc = O; } + + Expr *getLHS() const { return cast<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; } + + 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); + + /// \brief Retrieve the binary opcode that corresponds to the given + /// overloaded operator. + static Opcode getOverloadedOpcode(OverloadedOperatorKind OO); + + /// \brief Retrieve the overloaded operator kind that corresponds to + /// the given binary opcode. + static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); + + /// predicates to categorize the respective opcodes. + bool isMultiplicativeOp() const { return Opc >= Mul && Opc <= Rem; } + bool isAdditiveOp() const { return Opc == Add || Opc == Sub; } + bool isShiftOp() const { return Opc == Shl || Opc == Shr; } + bool isBitwiseOp() const { return Opc >= And && Opc <= Or; } + + 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; } + 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) { + return S->getStmtClass() == BinaryOperatorClass || + S->getStmtClass() == CompoundAssignOperatorClass; + } + static bool classof(const BinaryOperator *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); + +protected: + BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, + SourceLocation oploc, bool dead) + : Expr(CompoundAssignOperatorClass, ResTy), Opc(opc), OpLoc(oploc) { + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + } + + BinaryOperator(StmtClass SC, EmptyShell Empty) + : Expr(SC, Empty), Opc(MulAssign) { } +}; + +/// CompoundAssignOperator - For compound assignments (e.g. +=), we keep +/// track of the type the operation is performed in. Due to the semantics of +/// these operators, the operands are promoted, the aritmetic performed, an +/// implicit conversion back to the result type done, then the assignment takes +/// place. This captures the intermediate type which the computation is done +/// in. +class CompoundAssignOperator : public BinaryOperator { + QualType ComputationLHSType; + QualType ComputationResultType; +public: + CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, + QualType ResType, QualType CompLHSType, + QualType CompResultType, + SourceLocation OpLoc) + : BinaryOperator(lhs, rhs, opc, ResType, OpLoc, true), + ComputationLHSType(CompLHSType), + ComputationResultType(CompResultType) { + assert(isCompoundAssignmentOp() && + "Only should be used for compound assignments"); + } + + /// \brief Build an empty compound assignment operator expression. + explicit CompoundAssignOperator(EmptyShell Empty) + : BinaryOperator(CompoundAssignOperatorClass, Empty) { } + + // The two computation types are the type the LHS is converted + // to for the computation and the type of the result; the two are + // distinct in a few cases (specifically, int+=ptr and ptr-=ptr). + QualType getComputationLHSType() const { return ComputationLHSType; } + void setComputationLHSType(QualType T) { ComputationLHSType = T; } + + QualType getComputationResultType() const { return ComputationResultType; } + void setComputationResultType(QualType T) { ComputationResultType = T; } + + static bool classof(const CompoundAssignOperator *) { return true; } + static bool classof(const Stmt *S) { + return S->getStmtClass() == CompoundAssignOperatorClass; + } +}; + +/// ConditionalOperator - The ?: operator. Note that LHS may be null when the +/// GNU "missing LHS" extension is in use. +/// +class ConditionalOperator : public Expr { + enum { COND, LHS, RHS, END_EXPR }; + Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides. +public: + ConditionalOperator(Expr *cond, Expr *lhs, 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() || + (lhs && lhs->isValueDependent()) || + (rhs && rhs->isValueDependent()))) { + SubExprs[COND] = cond; + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + } + + /// \brief Build an empty conditional operator. + explicit ConditionalOperator(EmptyShell Empty) + : Expr(ConditionalOperatorClass, Empty) { } + + // getCond - Return the expression representing the condition for + // the ?: operator. + Expr *getCond() const { return cast<Expr>(SubExprs[COND]); } + void setCond(Expr *E) { SubExprs[COND] = E; } + + // getTrueExpr - Return the subexpression representing the value of the ?: + // expression if the condition evaluates to true. In most cases this value + // 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. + 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; } + + virtual SourceRange getSourceRange() const { + return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd()); + } + 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(); +}; + +/// AddrLabelExpr - The GNU address of label extension, representing &&label. +class AddrLabelExpr : public Expr { + SourceLocation AmpAmpLoc, LabelLoc; + LabelStmt *Label; +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) + : Expr(AddrLabelExprClass, Empty) { } + + SourceLocation getAmpAmpLoc() const { return AmpAmpLoc; } + void setAmpAmpLoc(SourceLocation L) { AmpAmpLoc = L; } + SourceLocation getLabelLoc() const { return LabelLoc; } + void setLabelLoc(SourceLocation L) { LabelLoc = L; } + + 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; + } + static bool classof(const AddrLabelExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}). +/// The StmtExpr contains a single CompoundStmt node, which it evaluates and +/// takes the value of the last subexpression. +class StmtExpr : public Expr { + Stmt *SubStmt; + SourceLocation LParenLoc, RParenLoc; +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) { } + + CompoundStmt *getSubStmt() { return cast<CompoundStmt>(SubStmt); } + const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); } + void setSubStmt(CompoundStmt *S) { SubStmt = S; } + + 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; + } + static bool classof(const StmtExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// TypesCompatibleExpr - GNU builtin-in function __builtin_types_compatible_p. +/// This AST node represents a function that returns 1 if two *types* (not +/// expressions) are compatible. The result of this built-in function can be +/// used in integer constant expressions. +class TypesCompatibleExpr : public Expr { + QualType Type1; + QualType Type2; + SourceLocation BuiltinLoc, RParenLoc; +public: + TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc, + QualType t1, QualType t2, SourceLocation RP) : + Expr(TypesCompatibleExprClass, ReturnType), Type1(t1), Type2(t2), + BuiltinLoc(BLoc), RParenLoc(RP) {} + + /// \brief Build an empty __builtin_type_compatible_p expression. + explicit TypesCompatibleExpr(EmptyShell Empty) + : Expr(TypesCompatibleExprClass, Empty) { } + + QualType getArgType1() const { return Type1; } + 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; + } + static bool classof(const TypesCompatibleExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ShuffleVectorExpr - clang-specific builtin-in function +/// __builtin_shufflevector. +/// This AST node represents a operator that does a constant +/// shuffle, similar to LLVM's shufflevector instruction. It takes +/// two vectors and a variable number of constant indices, +/// and returns the appropriately shuffled vector. +class ShuffleVectorExpr : public Expr { + SourceLocation BuiltinLoc, RParenLoc; + + // SubExprs - the list of values passed to the __builtin_shufflevector + // function. The first two are vectors, and the rest are constant + // indices. The number of values in this list is always + // 2+the number of indices in the vector type. + Stmt **SubExprs; + unsigned NumExprs; + +public: + ShuffleVectorExpr(Expr **args, unsigned nexpr, + QualType Type, SourceLocation BLoc, + SourceLocation RP) : + Expr(ShuffleVectorExprClass, Type), BuiltinLoc(BLoc), + RParenLoc(RP), NumExprs(nexpr) { + + SubExprs = new Stmt*[nexpr]; + for (unsigned i = 0; i < nexpr; i++) + SubExprs[i] = args[i]; + } + + /// \brief Build an empty vector-shuffle expression. + 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; } + + virtual SourceRange getSourceRange() const { + return SourceRange(BuiltinLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == ShuffleVectorExprClass; + } + static bool classof(const ShuffleVectorExpr *) { return true; } + + ~ShuffleVectorExpr() { + delete [] SubExprs; + } + + /// 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!"); + return cast<Expr>(SubExprs[Index]); + } + const Expr *getExpr(unsigned Index) const { + assert((Index < NumExprs) && "Arg access out of range!"); + return cast<Expr>(SubExprs[Index]); + } + + void setExprs(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 +/// the following exceptions: +/// - the test expression must be a integer constant expression. +/// - the expression returned acts like the chosen subexpression in every +/// visible way: the type is the same as that of the chosen subexpression, +/// and all predicates (whether it's an l-value, whether it's an integer +/// constant expression, etc.) return the same result as for the chosen +/// sub-expression. +class ChooseExpr : public Expr { + enum { COND, LHS, RHS, END_EXPR }; + Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides. + SourceLocation BuiltinLoc, RParenLoc; +public: + ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, QualType t, + SourceLocation RP) + : Expr(ChooseExprClass, t), + 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) { } + + /// isConditionTrue - Return whether the condition is true (i.e. not + /// equal to zero). + bool isConditionTrue(ASTContext &C) const; + + /// getChosenSubExpr - Return the subexpression chosen according to the + /// condition. + Expr *getChosenSubExpr(ASTContext &C) const { + return isConditionTrue(C) ? getLHS() : getRHS(); + } + + Expr *getCond() const { return cast<Expr>(SubExprs[COND]); } + void setCond(Expr *E) { SubExprs[COND] = E; } + Expr *getLHS() const { return cast<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 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() == ChooseExprClass; + } + static bool classof(const ChooseExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// GNUNullExpr - Implements the GNU __null extension, which is a name +/// for a null pointer constant that has integral type (e.g., int or +/// long) and is the same size and alignment as a pointer. The __null +/// extension is typically only used by system headers, which define +/// NULL as __null in C++ rather than using 0 (which is an integer +/// that may not match the size of a pointer). +class GNUNullExpr : public Expr { + /// TokenLoc - The location of the __null keyword. + SourceLocation TokenLoc; + +public: + 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; } + + virtual SourceRange getSourceRange() const { + return SourceRange(TokenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == GNUNullExprClass; + } + static bool classof(const GNUNullExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// VAArgExpr, used for the builtin function __builtin_va_start. +class VAArgExpr : public Expr { + Stmt *Val; + SourceLocation BuiltinLoc, RParenLoc; +public: + VAArgExpr(SourceLocation BLoc, Expr* e, QualType t, SourceLocation RPLoc) + : Expr(VAArgExprClass, t), + Val(e), + BuiltinLoc(BLoc), + RParenLoc(RPLoc) { } + + /// \brief Create an empty __builtin_va_start expression. + explicit VAArgExpr(EmptyShell Empty) : Expr(VAArgExprClass, Empty) { } + + const Expr *getSubExpr() const { return cast<Expr>(Val); } + Expr *getSubExpr() { return cast<Expr>(Val); } + void setSubExpr(Expr *E) { Val = E; } + + 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(); +}; + +/// @brief Describes an C or C++ initializer list. +/// +/// InitListExpr describes an initializer list, which can be used to +/// initialize objects of different types, including +/// struct/class/union types, arrays, and vectors. For example: +/// +/// @code +/// struct foo x = { 1, { 2, 3 } }; +/// @endcode +/// +/// Prior to semantic analysis, an initializer list will represent the +/// initializer list as written by the user, but will have the +/// placeholder type "void". This initializer list is called the +/// syntactic form of the initializer, and may contain C99 designated +/// initializers (represented as DesignatedInitExprs), initializations +/// of subobject members without explicit braces, and so on. Clients +/// interested in the original syntax of the initializer list should +/// use the syntactic form of the initializer list. +/// +/// After semantic analysis, the initializer list will represent the +/// semantic form of the initializer, where the initializations of all +/// subobjects are made explicit with nested InitListExpr nodes and +/// C99 designators have been eliminated by placing the designated +/// initializations into the subobject they initialize. Additionally, +/// any "holes" in the initialization, where no initializer has been +/// specified for a particular subobject, will be replaced with +/// implicitly-generated ImplicitValueInitExpr expressions that +/// value-initialize the subobjects. Note, however, that the +/// initializer lists may still have fewer initializers than there are +/// elements to initialize within the object. +/// +/// Given the semantic form of the initializer list, one can retrieve +/// the original syntactic form of that initializer list (if it +/// exists) using getSyntacticForm(). Since many initializer lists +/// have the same syntactic and semantic forms, getSyntacticForm() may +/// return NULL, indicating that the current initializer list also +/// serves as its syntactic form. +class InitListExpr : public Expr { + std::vector<Stmt *> InitExprs; + SourceLocation LBraceLoc, RBraceLoc; + + /// Contains the initializer list that describes the syntactic form + /// written in the source code. + InitListExpr *SyntacticForm; + + /// If this initializer list initializes a union, specifies which + /// field within the union will be initialized. + FieldDecl *UnionFieldInit; + + /// Whether this initializer list originally had a GNU array-range + /// designator in it. This is a temporary marker used by CodeGen. + bool HadArrayRangeDesignator; + +public: + InitListExpr(SourceLocation lbraceloc, Expr **initexprs, unsigned numinits, + SourceLocation rbraceloc); + + /// \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 { + assert(Init < getNumInits() && "Initializer access out of range!"); + return cast_or_null<Expr>(InitExprs[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) { + 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 + /// initializers will be destroyed. If there are fewer than @p + /// NumInits initializers, NULL expressions will be added for the + /// unknown initializers. + void resizeInits(ASTContext &Context, unsigned NumInits); + + /// @brief Updates the initializer at index @p Init with the new + /// expression @p expr, and returns the old expression at that + /// location. + /// + /// When @p Init is out of range for this initializer list, the + /// initializer list will be extended with NULL expressions to + /// accomodate the new entry. + Expr *updateInit(unsigned Init, Expr *expr); + + /// \brief If this initializes a union, specifies which field in the + /// union to initialize. + /// + /// Typically, this field is the first named field within the + /// union. However, a designated initializer can specify the + /// initialization of a different field within the union. + FieldDecl *getInitializedFieldInUnion() { return UnionFieldInit; } + void setInitializedFieldInUnion(FieldDecl *FD) { UnionFieldInit = FD; } + + // Explicit InitListExpr's originate from source code (and have valid source + // locations). Implicit InitListExpr's are created by the semantic analyzer. + bool isExplicit() { + return LBraceLoc.isValid() && RBraceLoc.isValid(); + } + + SourceLocation getLBraceLoc() const { return LBraceLoc; } + void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; } + SourceLocation getRBraceLoc() const { return RBraceLoc; } + void setRBraceLoc(SourceLocation Loc) { RBraceLoc = Loc; } + + /// @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) { + HadArrayRangeDesignator = ARD; + } + + virtual SourceRange getSourceRange() const { + return SourceRange(LBraceLoc, RBraceLoc); + } + static bool classof(const Stmt *T) { + 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(); } + reverse_iterator rend() { return InitExprs.rend(); } +}; + +/// @brief Represents a C99 designated initializer expression. +/// +/// A designated initializer expression (C99 6.7.8) contains one or +/// more designators (which can be field designators, array +/// 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; +/// double y; +/// }; +/// struct point ptarray[10] = { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; +/// @endcode +/// +/// The InitListExpr contains three DesignatedInitExprs, the first of +/// which covers @c [2].y=1.0. This DesignatedInitExpr will have two +/// designators, one array designator for @c [2] followed by one field +/// designator for @c .y. The initalization expression will be 1.0. +class DesignatedInitExpr : public Expr { +public: + /// \brief Forward declaration of the Designator class. + class Designator; + +private: + /// The location of the '=' or ':' prior to the actual initializer + /// expression. + SourceLocation EqualOrColonLoc; + + /// Whether this designated initializer used the GNU deprecated + /// syntax rather than the C99 '=' syntax. + bool GNUSyntax : 1; + + /// The number of designators in this initializer expression. + unsigned NumDesignators : 15; + + /// \brief The designators in this designated initialization + /// expression. + Designator *Designators; + + /// The number of subexpressions of this initializer expression, + /// which contains both the initializer and any additional + /// expressions used by array and array-range designators. + unsigned NumSubExprs : 16; + + + DesignatedInitExpr(QualType Ty, unsigned NumDesignators, + const Designator *Designators, + SourceLocation EqualOrColonLoc, bool GNUSyntax, + Expr **IndexExprs, unsigned NumIndexExprs, + Expr *Init); + + explicit DesignatedInitExpr(unsigned NumSubExprs) + : Expr(DesignatedInitExprClass, EmptyShell()), + NumDesignators(0), Designators(0), NumSubExprs(NumSubExprs) { } + +public: + /// A field designator, e.g., ".x". + struct FieldDesignator { + /// Refers to the field that is being initialized. The low bit + /// of this field determines whether this is actually a pointer + /// to an IdentifierInfo (if 1) or a FieldDecl (if 0). When + /// initially constructed, a field designator will store an + /// 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; + }; + + /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]". + struct ArrayOrRangeDesignator { + /// Location of the first index expression within the designated + /// initializer expression's list of subexpressions. + unsigned Index; + /// The location of the '[' starting the array range designator. + unsigned LBracketLoc; + /// The location of the ellipsis separating the start and end + /// indices. Only valid for GNU array-range designators. + unsigned EllipsisLoc; + /// The location of the ']' terminating the array range designator. + unsigned RBracketLoc; + }; + + /// @brief Represents a single C99 designator. + /// + /// @todo This class is infuriatingly similar to clang::Designator, + /// but minor differences (storing indices vs. storing pointers) + /// keep us from reusing it. Try harder, later, to rectify these + /// differences. + class Designator { + /// @brief The kind of designator this describes. + enum { + FieldDesignator, + ArrayDesignator, + ArrayRangeDesignator + } Kind; + + union { + /// A field designator, e.g., ".x". + struct FieldDesignator Field; + /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]". + struct ArrayOrRangeDesignator ArrayOrRange; + }; + friend class DesignatedInitExpr; + + public: + Designator() {} + + /// @brief Initializes a field designator. + Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc, + SourceLocation FieldLoc) + : Kind(FieldDesignator) { + Field.NameOrField = reinterpret_cast<uintptr_t>(FieldName) | 0x01; + Field.DotLoc = DotLoc.getRawEncoding(); + Field.FieldLoc = FieldLoc.getRawEncoding(); + } + + /// @brief Initializes an array designator. + Designator(unsigned Index, SourceLocation LBracketLoc, + SourceLocation RBracketLoc) + : Kind(ArrayDesignator) { + ArrayOrRange.Index = Index; + ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding(); + ArrayOrRange.EllipsisLoc = SourceLocation().getRawEncoding(); + ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding(); + } + + /// @brief Initializes a GNU array-range designator. + Designator(unsigned Index, SourceLocation LBracketLoc, + SourceLocation EllipsisLoc, SourceLocation RBracketLoc) + : Kind(ArrayRangeDesignator) { + ArrayOrRange.Index = Index; + ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding(); + ArrayOrRange.EllipsisLoc = EllipsisLoc.getRawEncoding(); + ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding(); + } + + bool isFieldDesignator() const { return Kind == FieldDesignator; } + bool isArrayDesignator() const { return Kind == ArrayDesignator; } + bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; } + + IdentifierInfo * getFieldName(); + + FieldDecl *getField() { + assert(Kind == FieldDesignator && "Only valid on a field designator"); + if (Field.NameOrField & 0x01) + return 0; + else + return reinterpret_cast<FieldDecl *>(Field.NameOrField); + } + + void setField(FieldDecl *FD) { + assert(Kind == FieldDesignator && "Only valid on a field designator"); + Field.NameOrField = reinterpret_cast<uintptr_t>(FD); + } + + SourceLocation getDotLoc() const { + assert(Kind == FieldDesignator && "Only valid on a field designator"); + return SourceLocation::getFromRawEncoding(Field.DotLoc); + } + + SourceLocation getFieldLoc() const { + assert(Kind == FieldDesignator && "Only valid on a field designator"); + return SourceLocation::getFromRawEncoding(Field.FieldLoc); + } + + SourceLocation getLBracketLoc() const { + assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && + "Only valid on an array or array-range designator"); + return SourceLocation::getFromRawEncoding(ArrayOrRange.LBracketLoc); + } + + SourceLocation getRBracketLoc() const { + assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && + "Only valid on an array or array-range designator"); + return SourceLocation::getFromRawEncoding(ArrayOrRange.RBracketLoc); + } + + SourceLocation getEllipsisLoc() const { + assert(Kind == ArrayRangeDesignator && + "Only valid on an array-range designator"); + return SourceLocation::getFromRawEncoding(ArrayOrRange.EllipsisLoc); + } + + unsigned getFirstExprIndex() const { + assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && + "Only valid on an array or array-range designator"); + return ArrayOrRange.Index; + } + + SourceLocation getStartLocation() const { + if (Kind == FieldDesignator) + return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc(); + else + return getLBracketLoc(); + } + }; + + static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators, + unsigned NumDesignators, + Expr **IndexExprs, unsigned NumIndexExprs, + SourceLocation EqualOrColonLoc, + bool GNUSyntax, Expr *Init); + + static DesignatedInitExpr *CreateEmpty(ASTContext &C, unsigned NumIndexExprs); + + /// @brief Returns the number of designators in this initializer. + unsigned size() const { return NumDesignators; } + + // Iterator access to the designators. + typedef Designator* designators_iterator; + designators_iterator designators_begin() { return Designators; } + designators_iterator designators_end() { + return Designators + NumDesignators; + } + + Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; } + + void setDesignators(const Designator *Desigs, unsigned NumDesigs); + + Expr *getArrayIndex(const Designator& D); + Expr *getArrayRangeStart(const Designator& D); + Expr *getArrayRangeEnd(const Designator& D); + + /// @brief Retrieve the location of the '=' that precedes the + /// initializer value itself, if present. + SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; } + void setEqualOrColonLoc(SourceLocation L) { EqualOrColonLoc = L; } + + /// @brief Determines whether this designated initializer used the + /// deprecated GNU syntax for designated initializers. + bool usesGNUSyntax() const { return GNUSyntax; } + void setGNUSyntax(bool GNU) { GNUSyntax = GNU; } + + /// @brief Retrieve the initializer value. + Expr *getInit() const { + return cast<Expr>(*const_cast<DesignatedInitExpr*>(this)->child_begin()); + } + + void setInit(Expr *init) { + *child_begin() = init; + } + + /// \brief Retrieve the total number of subexpressions in this + /// designated initializer expression, including the actual + /// initialized value and any expressions that occur within array + /// and array-range designators. + unsigned getNumSubExprs() const { return NumSubExprs; } + + Expr *getSubExpr(unsigned Idx) { + assert(Idx < NumSubExprs && "Subscript out of range"); + char* Ptr = static_cast<char*>(static_cast<void *>(this)); + Ptr += sizeof(DesignatedInitExpr); + return reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx]; + } + + void setSubExpr(unsigned Idx, Expr *E) { + assert(Idx < NumSubExprs && "Subscript out of range"); + char* Ptr = static_cast<char*>(static_cast<void *>(this)); + Ptr += sizeof(DesignatedInitExpr); + reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx] = E; + } + + /// \brief Replaces the designator at index @p Idx with the series + /// of designators in [First, Last). + 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; + } + static bool classof(const DesignatedInitExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// \brief Represents an implicitly-generated value initialization of +/// an object of a given type. +/// +/// Implicit value initializations occur within semantic initializer +/// list expressions (InitListExpr) as placeholders for subobject +/// initializations not explicitly specified by the user. +/// +/// \see InitListExpr +class ImplicitValueInitExpr : public Expr { +public: + 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) { + return T->getStmtClass() == ImplicitValueInitExprClass; + } + static bool classof(const ImplicitValueInitExpr *) { return true; } + + virtual SourceRange getSourceRange() const { + return SourceRange(); + } + + ImplicitValueInitExpr *Clone(ASTContext &C) const; + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +//===----------------------------------------------------------------------===// +// Clang Extensions +//===----------------------------------------------------------------------===// + + +/// ExtVectorElementExpr - This represents access to specific elements of a +/// vector, and may occur on the left hand side or right hand side. For example +/// the following is legal: "V.xy = V.zw" if V is a 4 element extended vector. +/// +/// Note that the base may have either vector or pointer to vector type, just +/// like a struct field reference. +/// +class ExtVectorElementExpr : public Expr { + Stmt *Base; + IdentifierInfo *Accessor; + SourceLocation AccessorLoc; +public: + ExtVectorElementExpr(QualType ty, Expr *base, IdentifierInfo &accessor, + SourceLocation loc) + : Expr(ExtVectorElementExprClass, ty), + Base(base), Accessor(&accessor), AccessorLoc(loc) {} + + /// \brief Build an empty vector element expression. + explicit ExtVectorElementExpr(EmptyShell Empty) + : Expr(ExtVectorElementExprClass, Empty) { } + + const Expr *getBase() const { return cast<Expr>(Base); } + Expr *getBase() { return cast<Expr>(Base); } + void setBase(Expr *E) { Base = E; } + + IdentifierInfo &getAccessor() const { return *Accessor; } + void setAccessor(IdentifierInfo *II) { Accessor = II; } + + SourceLocation getAccessorLoc() const { return AccessorLoc; } + void setAccessorLoc(SourceLocation L) { AccessorLoc = L; } + + /// 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 ExtVectorElementExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +/// BlockExpr - Adaptor class for mixing a BlockDecl with expressions. +/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body } +class BlockExpr : public Expr { +protected: + BlockDecl *TheBlock; + bool HasBlockDeclRefExprs; +public: + BlockExpr(BlockDecl *BD, QualType ty, bool hasBlockDeclRefExprs) + : Expr(BlockExprClass, ty), + TheBlock(BD), HasBlockDeclRefExprs(hasBlockDeclRefExprs) {} + + /// \brief Build an empty block expression. + explicit BlockExpr(EmptyShell Empty) : Expr(BlockExprClass, Empty) { } + + const BlockDecl *getBlockDecl() const { return TheBlock; } + BlockDecl *getBlockDecl() { return TheBlock; } + void setBlockDecl(BlockDecl *BD) { TheBlock = BD; } + + // Convenience functions for probing the underlying BlockDecl. + SourceLocation getCaretLocation() const; + const Stmt *getBody() const; + Stmt *getBody(); + + const Stmt *getBody(ASTContext &C) const { return getBody(); } + Stmt *getBody(ASTContext &C) { return getBody(); } + + virtual SourceRange getSourceRange() const { + return SourceRange(getCaretLocation(), getBody()->getLocEnd()); + } + + /// getFunctionType - Return the underlying function type for this block. + const FunctionType *getFunctionType() const; + + /// hasBlockDeclRefExprs - Return true iff the block has BlockDeclRefExpr + /// inside of the block that reference values outside the block. + bool hasBlockDeclRefExprs() const { return HasBlockDeclRefExprs; } + void setHasBlockDeclRefExprs(bool BDRE) { HasBlockDeclRefExprs = BDRE; } + + 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; + SourceLocation Loc; + bool IsByRef; +public: + BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef) : + Expr(BlockDeclRefExprClass, t), D(d), Loc(l), IsByRef(ByRef) {} + + // \brief Build an empty reference to a declared variable in a + // block. + explicit BlockDeclRefExpr(EmptyShell Empty) + : Expr(BlockDeclRefExprClass, Empty) { } + + ValueDecl *getDecl() { return D; } + const ValueDecl *getDecl() const { return D; } + void setDecl(ValueDecl *VD) { D = VD; } + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + bool isByRef() const { return IsByRef; } + void setByRef(bool BR) { IsByRef = BR; } + + 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(); +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h new file mode 100644 index 000000000000..53386231a03f --- /dev/null +++ b/include/clang/AST/ExprCXX.h @@ -0,0 +1,1234 @@ +//===--- ExprCXX.h - Classes for representing expressions -------*- 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 Expr interface and subclasses for C++ expressions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_EXPRCXX_H +#define LLVM_CLANG_AST_EXPRCXX_H + +#include "clang/Basic/TypeTraits.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Decl.h" + +namespace clang { + + class CXXConstructorDecl; + class CXXDestructorDecl; + class CXXTemporary; + +//===--------------------------------------------------------------------===// +// C++ Expressions. +//===--------------------------------------------------------------------===// + +/// \brief A call to an overloaded operator written using operator +/// syntax. +/// +/// Represents a call to an overloaded operator written using operator +/// syntax, e.g., "x + y" or "*p". While semantically equivalent to a +/// normal call, this AST node provides better information about the +/// syntactic representation of the call. +/// +/// In a C++ template, this expression node kind will be used whenever +/// any of the arguments are type-dependent. In this case, the +/// function itself will be a (possibly empty) set of functions and +/// function templates that were found by name lookup at template +/// definition time. +class CXXOperatorCallExpr : public CallExpr { + /// \brief The overloaded operator. + OverloadedOperatorKind Operator; + +public: + 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) {} + + /// getOperator - Returns the kind of overloaded operator that this + /// expression refers to. + OverloadedOperatorKind getOperator() const { return Operator; } + + /// getOperatorLoc - Returns the location of the operator symbol in + /// the expression. When @c getOperator()==OO_Call, this is the + /// location of the right parentheses; when @c + /// getOperator()==OO_Subscript, this is the location of the right + /// bracket. + SourceLocation getOperatorLoc() const { return getRParenLoc(); } + + virtual SourceRange getSourceRange() const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXOperatorCallExprClass; + } + static bool classof(const CXXOperatorCallExpr *) { return true; } +}; + +/// CXXMemberCallExpr - Represents a call to a member function that +/// may be written either with member call syntax (e.g., "obj.func()" +/// or "objptr->func()") or with normal function-call syntax +/// ("func()") within a member function that ends up calling a member +/// function. The callee in either case is a MemberExpr that contains +/// both the object argument and the member function, while the +/// arguments are the arguments within the parentheses (not including +/// the object argument). +class CXXMemberCallExpr : public CallExpr { +public: + CXXMemberCallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, + QualType t, SourceLocation rparenloc) + : CallExpr(C, CXXMemberCallExprClass, fn, args, numargs, t, rparenloc) {} + + /// getImplicitObjectArgument - Retrieves the implicit object + /// argument for the member call. For example, in "x.f(5)", this + /// operation would return "x". + Expr *getImplicitObjectArgument(); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXMemberCallExprClass; + } + static bool classof(const CXXMemberCallExpr *) { return true; } +}; + +/// CXXNamedCastExpr - Abstract class common to all of the C++ "named" +/// casts, @c static_cast, @c dynamic_cast, @c reinterpret_cast, or @c +/// const_cast. +/// +/// This abstract class is inherited by all of the classes +/// representing "named" casts, e.g., CXXStaticCastExpr, +/// CXXDynamicCastExpr, CXXReinterpretCastExpr, and CXXConstCastExpr. +class CXXNamedCastExpr : public ExplicitCastExpr { +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) {} + +public: + const char *getCastName() const; + + /// \brief Retrieve the location of the cast operator keyword, e.g., + /// "static_cast". + SourceLocation getOperatorLoc() const { return Loc; } + void setOperatorLoc(SourceLocation L) { Loc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(Loc, getSubExpr()->getSourceRange().getEnd()); + } + static bool classof(const Stmt *T) { + switch (T->getStmtClass()) { + case CXXNamedCastExprClass: + case CXXStaticCastExprClass: + case CXXDynamicCastExprClass: + case CXXReinterpretCastExprClass: + case CXXConstCastExprClass: + return true; + default: + return false; + } + } + static bool classof(const CXXNamedCastExpr *) { return true; } +}; + +/// 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) {} + + 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 +/// 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) {} + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXDynamicCastExprClass; + } + static bool classof(const CXXDynamicCastExpr *) { return true; } +}; + +/// 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) {} + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXReinterpretCastExprClass; + } + static bool classof(const CXXReinterpretCastExpr *) { return true; } +}; + +/// 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, + SourceLocation l) + : CXXNamedCastExpr(CXXConstCastExprClass, ty, op, writtenTy, l) {} + + 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) : + 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) { + return T->getStmtClass() == CXXBoolLiteralExprClass; + } + static bool classof(const CXXBoolLiteralExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXNullPtrLiteralExpr - [C++0x 2.14.7] C++ Pointer Literal +class CXXNullPtrLiteralExpr : public Expr { + SourceLocation Loc; +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) { + return T->getStmtClass() == CXXNullPtrLiteralExprClass; + } + static bool classof(const CXXNullPtrLiteralExpr *) { return true; } + + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXTypeidExpr - A C++ @c typeid expression (C++ [expr.typeid]), which gets +/// the type_info that corresponds to the supplied type, or the (possibly +/// dynamic) type of the supplied expression. +/// +/// This represents code like @c typeid(int) or @c typeid(*objPtr) +class CXXTypeidExpr : public Expr { +private: + bool isTypeOp : 1; + union { + void *Ty; + Stmt *Ex; + } Operand; + SourceRange Range; + +public: + CXXTypeidExpr(bool isTypeOp, void *op, QualType Ty, const SourceRange r) : + Expr(CXXTypeidExprClass, Ty, + // typeid is never type-dependent (C++ [temp.dep.expr]p4) + false, + // typeid is value-dependent if the type or expression are dependent + (isTypeOp ? QualType::getFromOpaquePtr(op)->isDependentType() + : static_cast<Expr*>(op)->isValueDependent())), + isTypeOp(isTypeOp), Range(r) { + if (isTypeOp) + Operand.Ty = op; + else + // op was an Expr*, so cast it back to that to be safe + Operand.Ex = static_cast<Expr*>(op); + } + + bool isTypeOperand() const { return isTypeOp; } + QualType getTypeOperand() const { + assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); + return QualType::getFromOpaquePtr(Operand.Ty); + } + Expr* getExprOperand() const { + assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); + return static_cast<Expr*>(Operand.Ex); + } + + virtual SourceRange getSourceRange() const { + return Range; + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXTypeidExprClass; + } + static bool classof(const CXXTypeidExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXThisExpr - Represents the "this" expression in C++, which is a +/// pointer to the object on which the current member function is +/// executing (C++ [expr.prim]p3). Example: +/// +/// @code +/// class Foo { +/// public: +/// void bar(); +/// void test() { this->bar(); } +/// }; +/// @endcode +class CXXThisExpr : public Expr { + SourceLocation Loc; + +public: + 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) + Type->isDependentType(), Type->isDependentType()), + Loc(L) { } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXThisExprClass; + } + static bool classof(const CXXThisExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXThrowExpr - [C++ 15] C++ Throw Expression. This handles +/// 'throw' and 'throw' assignment-expression. When +/// assignment-expression isn't present, Op will be null. +/// +class CXXThrowExpr : public Expr { + Stmt *Op; + SourceLocation ThrowLoc; +public: + // Ty is the void type which is used as the result type of the + // exepression. The l is the location of the throw keyword. expr + // can by null, if the optional expression to throw isn't present. + CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l) : + Expr(CXXThrowExprClass, Ty, false, false), Op(expr), ThrowLoc(l) {} + const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); } + Expr *getSubExpr() { return cast_or_null<Expr>(Op); } + void setSubExpr(Expr *E) { Op = E; } + + SourceLocation getThrowLoc() const { return ThrowLoc; } + void setThrowLoc(SourceLocation L) { ThrowLoc = L; } + + virtual SourceRange getSourceRange() const { + if (getSubExpr() == 0) + return SourceRange(ThrowLoc, ThrowLoc); + return SourceRange(ThrowLoc, getSubExpr()->getSourceRange().getEnd()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXThrowExprClass; + } + static bool classof(const CXXThrowExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXDefaultArgExpr - C++ [dcl.fct.default]. This wraps up a +/// function call argument that was created from the corresponding +/// parameter's default argument, when the call did not explicitly +/// supply arguments for all of the parameters. +class CXXDefaultArgExpr : public Expr { + ParmVarDecl *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) { } + + // Retrieve the parameter that the argument was created from. + const ParmVarDecl *getParam() const { return Param; } + ParmVarDecl *getParam() { return Param; } + + // Retrieve the actual argument to the function call. + const Expr *getExpr() const { return Param->getDefaultArg(); } + Expr *getExpr() { return Param->getDefaultArg(); } + + virtual SourceRange getSourceRange() const { + // Default argument expressions have no representation in the + // source, so they have an empty source range. + return SourceRange(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXDefaultArgExprClass; + } + static bool classof(const CXXDefaultArgExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXTemporary - Represents a C++ temporary. +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, + const CXXDestructorDecl *Destructor); + void Destroy(ASTContext &C); + + const CXXDestructorDecl *getDestructor() const { return Destructor; } +}; + +/// 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) + : Expr(CXXBindTemporaryExprClass, + subexpr->getType()), Temp(temp), SubExpr(subexpr) { } + ~CXXBindTemporaryExpr() { } + +public: + static CXXBindTemporaryExpr *Create(ASTContext &C, CXXTemporary *Temp, + Expr* SubExpr); + void Destroy(ASTContext &C); + + CXXTemporary *getTemporary() { return Temp; } + const CXXTemporary *getTemporary() const { return Temp; } + + const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } + Expr *getSubExpr() { return cast<Expr>(SubExpr); } + void setSubExpr(Expr *E) { SubExpr = E; } + + virtual SourceRange getSourceRange() const { return SourceRange(); } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXBindTemporaryExprClass; + } + static bool classof(const CXXBindTemporaryExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXConstructExpr - Represents a call to a C++ constructor. +class CXXConstructExpr : public Expr { + CXXConstructorDecl *Constructor; + + bool Elidable; + + Stmt **Args; + unsigned NumArgs; + + +protected: + CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, + CXXConstructorDecl *d, bool elidable, + Expr **args, unsigned numargs); + ~CXXConstructExpr() { } + +public: + static CXXConstructExpr *Create(ASTContext &C, QualType T, + CXXConstructorDecl *D, bool Elidable, + Expr **Args, unsigned NumArgs); + + void Destroy(ASTContext &C); + + CXXConstructorDecl* getConstructor() const { return Constructor; } + + /// \brief Whether this construction is elidable. + bool isElidable() const { return Elidable; } + + 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; } + const_arg_iterator arg_end() const { return Args + NumArgs; } + + unsigned getNumArgs() const { return NumArgs; } + + virtual SourceRange getSourceRange() const { return SourceRange(); } + + 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(); +}; + +/// CXXFunctionalCastExpr - Represents an explicit C++ type conversion +/// that uses "functional" notion (C++ [expr.type.conv]). Example: @c +/// x = int(0.5); +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) {} + + 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 CXXFunctionalCastExpr *) { return true; } +}; + +/// @brief Represents a C++ functional cast expression that builds a +/// temporary object. +/// +/// 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 +/// performing a value-initialized an object whose class type has no +/// user-declared constructors), CXXZeroInitValueExpr will represent +/// the functional cast. Finally, with N == 1 arguments the functional +/// cast expression will be represented by CXXFunctionalCastExpr. +/// Example: +/// @code +/// struct X { X(int, float); } +/// +/// X create_X() { +/// return X(1, 3.14f); // creates a CXXTemporaryObjectExpr +/// }; +/// @endcode +class CXXTemporaryObjectExpr : public CXXConstructExpr { + SourceLocation TyBeginLoc; + SourceLocation RParenLoc; + +public: + CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons, + QualType writtenTy, SourceLocation tyBeginLoc, + Expr **Args,unsigned NumArgs, + SourceLocation rParenLoc); + + ~CXXTemporaryObjectExpr() { } + + 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() == CXXTemporaryObjectExprClass; + } + static bool classof(const CXXTemporaryObjectExpr *) { return true; } +}; + +/// CXXZeroInitValueExpr - [C++ 5.2.3p2] +/// Expression "T()" which creates a value-initialized rvalue of type +/// T, which is either a non-class type or a class type without any +/// user-defined constructors. +/// +class CXXZeroInitValueExpr : public Expr { + SourceLocation TyBeginLoc; + SourceLocation RParenLoc; + +public: + CXXZeroInitValueExpr(QualType ty, SourceLocation tyBeginLoc, + 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(); + } + + virtual SourceRange getSourceRange() const { + return SourceRange(TyBeginLoc, RParenLoc); + } + + CXXZeroInitValueExpr* Clone(ASTContext &C) const; + + 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(); +}; + +/// CXXConditionDeclExpr - Condition declaration of a if/switch/while/for +/// statement, e.g: "if (int x = f()) {...}". +/// The main difference with DeclRefExpr is that CXXConditionDeclExpr owns the +/// decl that it references. +/// +class CXXConditionDeclExpr : public DeclRefExpr { +public: + CXXConditionDeclExpr(SourceLocation startLoc, + SourceLocation eqLoc, VarDecl *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) { + return T->getStmtClass() == CXXConditionDeclExprClass; + } + static bool classof(const CXXConditionDeclExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXNewExpr - A new expression for memory allocation and constructor calls, +/// e.g: "new CXXNewExpr(foo)". +class CXXNewExpr : public Expr { + // Was the usage ::new, i.e. is the global new to be used? + bool GlobalNew : 1; + // Was the form (type-id) used? Otherwise, it was new-type-id. + bool ParenTypeId : 1; + // Is there an initializer? If not, built-ins are uninitialized, else they're + // value-initialized. + bool Initializer : 1; + // Do we allocate an array? If so, the first SubExpr is the size expression. + bool Array : 1; + // The number of placement new arguments. + unsigned NumPlacementArgs : 14; + // The number of constructor arguments. This may be 1 even for non-class + // types; use the pseudo copy constructor. + unsigned NumConstructorArgs : 14; + // Contains an optional array size expression, any number of optional + // placement arguments, and any number of optional constructor arguments, + // in that order. + Stmt **SubExprs; + // Points to the allocation function used. + FunctionDecl *OperatorNew; + // Points to the deallocation function used in case of error. May be null. + FunctionDecl *OperatorDelete; + // Points to the constructor used. Cannot be null if AllocType is a record; + // it would still point at the default constructor (even an implicit one). + // Must be null for all other types. + CXXConstructorDecl *Constructor; + + SourceLocation StartLoc; + SourceLocation EndLoc; + +public: + CXXNewExpr(bool globalNew, FunctionDecl *operatorNew, Expr **placementArgs, + unsigned numPlaceArgs, bool ParenTypeId, Expr *arraySize, + CXXConstructorDecl *constructor, bool initializer, + Expr **constructorArgs, unsigned numConsArgs, + FunctionDecl *operatorDelete, QualType ty, + SourceLocation startLoc, SourceLocation endLoc); + ~CXXNewExpr() { + delete[] SubExprs; + } + + QualType getAllocatedType() const { + assert(getType()->isPointerType()); + return getType()->getAsPointerType()->getPointeeType(); + } + + FunctionDecl *getOperatorNew() const { return OperatorNew; } + FunctionDecl *getOperatorDelete() const { return OperatorDelete; } + CXXConstructorDecl *getConstructor() const { return Constructor; } + + bool isArray() const { return Array; } + Expr *getArraySize() { + return Array ? cast<Expr>(SubExprs[0]) : 0; + } + const Expr *getArraySize() const { + return Array ? cast<Expr>(SubExprs[0]) : 0; + } + + unsigned getNumPlacementArgs() const { return NumPlacementArgs; } + Expr *getPlacementArg(unsigned i) { + assert(i < NumPlacementArgs && "Index out of range"); + return cast<Expr>(SubExprs[Array + i]); + } + const Expr *getPlacementArg(unsigned i) const { + assert(i < NumPlacementArgs && "Index out of range"); + return cast<Expr>(SubExprs[Array + i]); + } + + bool isGlobalNew() const { return GlobalNew; } + bool isParenTypeId() const { return ParenTypeId; } + bool hasInitializer() const { return Initializer; } + + unsigned getNumConstructorArgs() const { return NumConstructorArgs; } + Expr *getConstructorArg(unsigned i) { + assert(i < NumConstructorArgs && "Index out of range"); + return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]); + } + const Expr *getConstructorArg(unsigned i) const { + assert(i < NumConstructorArgs && "Index out of range"); + return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]); + } + + typedef ExprIterator arg_iterator; + typedef ConstExprIterator const_arg_iterator; + + arg_iterator placement_arg_begin() { + return SubExprs + Array; + } + arg_iterator placement_arg_end() { + return SubExprs + Array + getNumPlacementArgs(); + } + const_arg_iterator placement_arg_begin() const { + return SubExprs + Array; + } + const_arg_iterator placement_arg_end() const { + return SubExprs + Array + getNumPlacementArgs(); + } + + arg_iterator constructor_arg_begin() { + return SubExprs + Array + getNumPlacementArgs(); + } + arg_iterator constructor_arg_end() { + return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); + } + const_arg_iterator constructor_arg_begin() const { + return SubExprs + Array + getNumPlacementArgs(); + } + const_arg_iterator constructor_arg_end() const { + return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); + } + + virtual SourceRange getSourceRange() const { + return SourceRange(StartLoc, EndLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXNewExprClass; + } + static bool classof(const CXXNewExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXDeleteExpr - A delete expression for memory deallocation and destructor +/// calls, e.g. "delete[] pArray". +class CXXDeleteExpr : public Expr { + // Is this a forced global delete, i.e. "::delete"? + bool GlobalDelete : 1; + // Is this the array form of delete, i.e. "delete[]"? + bool ArrayForm : 1; + // Points to the operator delete overload that is used. Could be a member. + FunctionDecl *OperatorDelete; + // The pointer expression to be deleted. + Stmt *Argument; + // Location of the expression. + SourceLocation Loc; +public: + CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm, + FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc) + : Expr(CXXDeleteExprClass, ty, false, false), GlobalDelete(globalDelete), + ArrayForm(arrayForm), OperatorDelete(operatorDelete), Argument(arg), + Loc(loc) { } + + bool isGlobalDelete() const { return GlobalDelete; } + bool isArrayForm() const { return ArrayForm; } + + FunctionDecl *getOperatorDelete() const { return OperatorDelete; } + + Expr *getArgument() { return cast<Expr>(Argument); } + const Expr *getArgument() const { return cast<Expr>(Argument); } + + virtual SourceRange getSourceRange() const { + return SourceRange(Loc, Argument->getLocEnd()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXDeleteExprClass; + } + static bool classof(const CXXDeleteExpr *) { 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. +/// +/// Unresolved function names occur when a function name is +/// encountered prior to an open parentheses ('(') in a C++ function +/// call, and the function name itself did not resolve to a +/// declaration. These function names can only be resolved when they +/// form the postfix-expression of a function call, so that +/// argument-dependent lookup finds declarations corresponding to +/// these functions. + +/// @code +/// template<typename T> void f(T x) { +/// g(x); // g is an unresolved function name (that is also a dependent name) +/// } +/// @endcode +class UnresolvedFunctionNameExpr : public Expr { + /// The name that was present in the source + DeclarationName Name; + + /// The location of this name in the source code + SourceLocation Loc; + +public: + UnresolvedFunctionNameExpr(DeclarationName N, QualType T, SourceLocation L) + : Expr(UnresolvedFunctionNameExprClass, T, false, false), Name(N), Loc(L) { } + + /// \brief Retrieves the name that occurred in the source code. + DeclarationName getName() const { return Name; } + + /// getLocation - Retrieves the location in the source code where + /// the name occurred. + SourceLocation getLocation() const { return Loc; } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + UnresolvedFunctionNameExpr* Clone(ASTContext &C) const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnresolvedFunctionNameExprClass; + } + static bool classof(const UnresolvedFunctionNameExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the +/// implementation of TR1/C++0x type trait templates. +/// Example: +/// __is_pod(int) == true +/// __is_enum(std::string) == false +class UnaryTypeTraitExpr : public Expr { + /// UTT - The trait. + UnaryTypeTrait UTT; + + /// Loc - The location of the type trait keyword. + SourceLocation Loc; + + /// RParen - The location of the closing paren. + SourceLocation RParen; + + /// QueriedType - The type we're testing. + QualType QueriedType; + +public: + UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt, QualType queried, + SourceLocation rparen, QualType ty) + : Expr(UnaryTypeTraitExprClass, ty, false, queried->isDependentType()), + UTT(utt), Loc(loc), RParen(rparen), QueriedType(queried) { } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen);} + + UnaryTypeTrait getTrait() const { return UTT; } + + QualType getQueriedType() const { return QueriedType; } + + bool EvaluateTrait() const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnaryTypeTraitExprClass; + } + static bool classof(const UnaryTypeTraitExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// QualifiedDeclRefExpr - A reference to a declared variable, +/// function, enum, etc., that includes a qualification, e.g., +/// "N::foo". +class QualifiedDeclRefExpr : public DeclRefExpr { + /// QualifierRange - The source range that covers the + /// nested-name-specifier. + SourceRange QualifierRange; + + /// \brief The nested-name-specifier that qualifies this declaration + /// name. + NestedNameSpecifier *NNS; + +public: + QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, + bool VD, SourceRange R, NestedNameSpecifier *NNS) + : DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD), + QualifierRange(R), NNS(NNS) { } + + /// \brief Retrieve the source range of the nested-name-specifier. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// \brief Retrieve the nested-name-specifier that qualifies this + /// declaration. + NestedNameSpecifier *getQualifier() const { return NNS; } + + virtual SourceRange getSourceRange() const { + return SourceRange(QualifierRange.getBegin(), getLocation()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == QualifiedDeclRefExprClass; + } + static bool classof(const QualifiedDeclRefExpr *) { return true; } +}; + +/// \brief A qualified reference to a name whose declaration cannot +/// yet be resolved. +/// +/// UnresolvedDeclRefExpr is similar to QualifiedDeclRefExpr in that +/// it expresses a qualified reference to a declaration such as +/// X<T>::value. The difference, however, is that an +/// UnresolvedDeclRefExpr node is used only within C++ templates when +/// the qualification (e.g., X<T>::) refers to a dependent type. In +/// this case, X<T>::value cannot resolve to a declaration because the +/// declaration will differ from on instantiation of X<T> to the +/// next. Therefore, UnresolvedDeclRefExpr keeps track of the +/// qualifier (X<T>::) and the name of the entity being referenced +/// ("value"). Such expressions will instantiate to +/// QualifiedDeclRefExprs. +class UnresolvedDeclRefExpr : public Expr { + /// The name of the entity we will be referencing. + DeclarationName Name; + + /// Location of the name of the declaration we're referencing. + SourceLocation Loc; + + /// QualifierRange - The source range that covers the + /// nested-name-specifier. + SourceRange QualifierRange; + + /// \brief The nested-name-specifier that qualifies this unresolved + /// declaration name. + NestedNameSpecifier *NNS; + +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) { } + + /// \brief Retrieve the name that this expression refers to. + DeclarationName getDeclName() const { return Name; } + + /// \brief Retrieve the location of the name within the expression. + SourceLocation getLocation() const { return Loc; } + + /// \brief Retrieve the source range of the nested-name-specifier. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// \brief Retrieve the nested-name-specifier that qualifies this + /// declaration. + NestedNameSpecifier *getQualifier() const { return NNS; } + + virtual SourceRange getSourceRange() const { + return SourceRange(QualifierRange.getBegin(), getLocation()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnresolvedDeclRefExprClass; + } + static bool classof(const UnresolvedDeclRefExpr *) { return true; } + + virtual StmtIterator child_begin(); + virtual StmtIterator child_end(); +}; + +class CXXExprWithTemporaries : public Expr { + Stmt *SubExpr; + + CXXTemporary **Temps; + unsigned NumTemps; + + CXXExprWithTemporaries(Expr *subexpr, CXXTemporary **temps, + unsigned numtemps); + ~CXXExprWithTemporaries(); + +public: + static CXXExprWithTemporaries *Create(ASTContext &C, Expr *SubExpr, + CXXTemporary **Temps, + unsigned NumTemps); + void Destroy(ASTContext &C); + + unsigned getNumTemporaries() const { return NumTemps; } + CXXTemporary *getTemporary(unsigned i) { + assert(i < NumTemps && "Index out of range"); + return Temps[i]; + } + const CXXTemporary *getTemporary(unsigned i) const { + assert(i < NumTemps && "Index out of range"); + return Temps[i]; + } + + 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(); } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXExprWithTemporariesClass; + } + static bool classof(const CXXExprWithTemporaries *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// \brief Describes an explicit type conversion that uses functional +/// notion but could not be resolved because one or more arguments are +/// type-dependent. +/// +/// The explicit type conversions expressed by +/// CXXUnresolvedConstructExpr have the form \c T(a1, a2, ..., aN), +/// where \c T is some type and \c a1, a2, ..., aN are values, and +/// either \C T is a dependent type or one or more of the \c a's is +/// type-dependent. For example, this would occur in a template such +/// as: +/// +/// \code +/// template<typename T, typename A1> +/// inline T make_a(const A1& a1) { +/// return T(a1); +/// } +/// \endcode +/// +/// When the returned expression is instantiated, it may resolve to a +/// constructor call, conversion function call, or some kind of type +/// conversion. +class CXXUnresolvedConstructExpr : public Expr { + /// \brief The starting location of the type + SourceLocation TyBeginLoc; + + /// \brief The type being constructed. + QualType Type; + + /// \brief The location of the left parentheses ('('). + SourceLocation LParenLoc; + + /// \brief The location of the right parentheses (')'). + SourceLocation RParenLoc; + + /// \brief The number of arguments used to construct the type. + unsigned NumArgs; + + CXXUnresolvedConstructExpr(SourceLocation TyBegin, + QualType T, + SourceLocation LParenLoc, + Expr **Args, + unsigned NumArgs, + SourceLocation RParenLoc); + +public: + static CXXUnresolvedConstructExpr *Create(ASTContext &C, + SourceLocation TyBegin, + QualType T, + SourceLocation LParenLoc, + Expr **Args, + unsigned NumArgs, + SourceLocation RParenLoc); + + /// \brief Retrieve the source location where the type begins. + SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } + void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; } + + /// \brief Retrieve the type that is being constructed, as specified + /// in the source code. + QualType getTypeAsWritten() const { return Type; } + void setTypeAsWritten(QualType T) { Type = T; } + + /// \brief Retrieve the location of the left parentheses ('(') that + /// precedes the argument list. + SourceLocation getLParenLoc() const { return LParenLoc; } + void setLParenLoc(SourceLocation L) { LParenLoc = L; } + + /// \brief Retrieve the location of the right parentheses (')') that + /// follows the argument list. + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + /// \brief Retrieve the number of arguments. + unsigned arg_size() const { return NumArgs; } + + typedef Expr** arg_iterator; + arg_iterator arg_begin() { return reinterpret_cast<Expr**>(this + 1); } + arg_iterator arg_end() { return arg_begin() + NumArgs; } + + Expr *getArg(unsigned I) { + assert(I < NumArgs && "Argument index out-of-range"); + return *(arg_begin() + I); + } + + virtual SourceRange getSourceRange() const { + return SourceRange(TyBeginLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXUnresolvedConstructExprClass; + } + static bool classof(const CXXUnresolvedConstructExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// \brief +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; + + /// \brief The location of the '->' or '.' operator. + SourceLocation OperatorLoc; + + /// \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. + DeclarationName Member; + + /// \brief The location of the member name. + SourceLocation MemberLoc; + +public: + CXXUnresolvedMemberExpr(ASTContext &C, + Expr *Base, bool IsArrow, + SourceLocation OperatorLoc, + DeclarationName Member, + SourceLocation MemberLoc) + : Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true), + Base(Base), IsArrow(IsArrow), OperatorLoc(OperatorLoc), + Member(Member), MemberLoc(MemberLoc) { } + + /// \brief Retrieve the base object of this member expressions, + /// e.g., the \c x in \c x.m. + Expr *getBase() { return cast<Expr>(Base); } + void setBase(Expr *E) { Base = E; } + + /// \brief Determine whether this member expression used the '->' + /// operator; otherwise, it used the '.' operator. + bool isArrow() const { return IsArrow; } + void setArrow(bool A) { IsArrow = A; } + + /// \brief Retrieve the location of the '->' or '.' operator. + SourceLocation getOperatorLoc() const { return OperatorLoc; } + void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } + + /// \brief Retrieve the name of the member that this expression + /// refers to. + DeclarationName getMember() const { return Member; } + void setMember(DeclarationName N) { Member = N; } + + // \brief Retrieve the location of the name of the member that this + // expression refers to. + SourceLocation getMemberLoc() const { return MemberLoc; } + void setMemberLoc(SourceLocation L) { MemberLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(Base->getSourceRange().getBegin(), + MemberLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXUnresolvedMemberExprClass; + } + static bool classof(const CXXUnresolvedMemberExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h new file mode 100644 index 000000000000..51b99610cd9d --- /dev/null +++ b/include/clang/AST/ExprObjC.h @@ -0,0 +1,494 @@ +//===--- ExprObjC.h - Classes for representing ObjC expressions -*- 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 ExprObjC interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_EXPROBJC_H +#define LLVM_CLANG_AST_EXPROBJC_H + +#include "clang/AST/Expr.h" +#include "clang/Basic/IdentifierTable.h" + +namespace clang { + class IdentifierInfo; + class ASTContext; + class ObjCMethodDecl; + class ObjCPropertyDecl; + +/// ObjCStringLiteral, used for Objective-C string literals +/// i.e. @"foo". +class ObjCStringLiteral : public Expr { + Stmt *String; + SourceLocation AtLoc; +public: + ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L) + : Expr(ObjCStringLiteralClass, T), String(SL), AtLoc(L) {} + explicit ObjCStringLiteral(EmptyShell Empty) + : Expr(ObjCStringLiteralClass, Empty) {} + + StringLiteral *getString() { return cast<StringLiteral>(String); } + const StringLiteral *getString() const { return cast<StringLiteral>(String); } + void setString(StringLiteral *S) { String = S; } + + SourceLocation getAtLoc() const { return AtLoc; } + void setAtLoc(SourceLocation L) { AtLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(AtLoc, String->getLocEnd()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCStringLiteralClass; + } + 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. +class ObjCEncodeExpr : public Expr { + QualType EncType; + SourceLocation AtLoc, RParenLoc; +public: + ObjCEncodeExpr(QualType T, QualType ET, + SourceLocation at, SourceLocation rp) + : Expr(ObjCEncodeExprClass, T), 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(); +}; + +/// ObjCSelectorExpr used for @selector in Objective-C. +class ObjCSelectorExpr : public Expr { + Selector SelName; + SourceLocation AtLoc, RParenLoc; +public: + ObjCSelectorExpr(QualType T, Selector selInfo, + SourceLocation at, SourceLocation rp) + : Expr(ObjCSelectorExprClass, T), SelName(selInfo), AtLoc(at), RParenLoc(rp){} + explicit ObjCSelectorExpr(EmptyShell Empty) + : Expr(ObjCSelectorExprClass, Empty) {} + + 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; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + 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 *Protocol; + SourceLocation AtLoc, RParenLoc; +public: + ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, + SourceLocation at, SourceLocation rp) + : Expr(ObjCProtocolExprClass, T), Protocol(protocol), + AtLoc(at), RParenLoc(rp) {} + explicit ObjCProtocolExpr(EmptyShell Empty) + : Expr(ObjCProtocolExprClass, Empty) {} + + ObjCProtocolDecl *getProtocol() const { return Protocol; } + void setProtocol(ObjCProtocolDecl *P) { Protocol = P; } + + SourceLocation getAtLoc() const { return AtLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setAtLoc(SourceLocation L) { AtLoc = L; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + 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(); +}; + +/// ObjCIvarRefExpr - A reference to an ObjC instance variable. +class ObjCIvarRefExpr : public Expr { + class ObjCIvarDecl *D; + SourceLocation Loc; + 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) : + 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 { + return isFreeIvar() ? SourceRange(Loc) + : SourceRange(getBase()->getLocStart(), Loc); + } + + 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(); +}; + +/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC +/// property. +/// +class ObjCPropertyRefExpr : public Expr { +private: + ObjCPropertyDecl *AsProperty; + SourceLocation IdLoc; + Stmt *Base; +public: + 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 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 { + ObjCMethodDecl *Setter; + ObjCMethodDecl *Getter; + SourceLocation Loc; + // FIXME: Swizzle these into a single pointer. + Stmt *Base; + ObjCInterfaceDecl *ClassProp; + SourceLocation ClassLoc; + +public: + ObjCKVCRefExpr(ObjCMethodDecl *getter, + QualType t, + ObjCMethodDecl *setter, + SourceLocation l, Expr *base) + : Expr(ObjCKVCRefExprClass, t), Setter(setter), + Getter(getter), Loc(l), Base(base), ClassProp(0), + ClassLoc(SourceLocation()) { + } + ObjCKVCRefExpr(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) { + } + explicit ObjCKVCRefExpr(EmptyShell Empty) : Expr(ObjCKVCRefExprClass, Empty){} + + ObjCMethodDecl *getGetterMethod() const { return Getter; } + ObjCMethodDecl *getSetterMethod() const { return Setter; } + ObjCInterfaceDecl *getClassProp() const { return ClassProp; } + void setGetterMethod(ObjCMethodDecl *D) { Getter = D; } + void setSetterMethod(ObjCMethodDecl *D) { Setter = D; } + void setClassProp(ObjCInterfaceDecl *D) { ClassProp = D; } + + virtual SourceRange getSourceRange() const { + if (Base) + return SourceRange(getBase()->getLocStart(), Loc); + return SourceRange(ClassLoc, Loc); + } + 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 getClassLoc() const { return ClassLoc; } + void setClassLoc(SourceLocation L) { ClassLoc = L; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCKVCRefExprClass; + } + static bool classof(const ObjCKVCRefExpr *) { 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). + // FIXME: Since method decls contain the selector, and most messages have a + // prototype, consider devising a scheme for unifying SelName/MethodProto. + ObjCMethodDecl *MethodProto; + + SourceLocation LBracloc, RBracloc; + + // Constants for indexing into SubExprs. + enum { RECEIVER=0, ARGS_START=1 }; + + // 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. + ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo, + QualType retType, ObjCMethodDecl *methDecl, + SourceLocation LBrac, SourceLocation RBrac, + Expr **ArgExprs, unsigned NumArgs); + + /// This constructor is used to represent class messages where the + /// ObjCInterfaceDecl* of the receiver is known. + // FIXME: clsName should be typed to ObjCInterfaceType + ObjCMessageExpr(ObjCInterfaceDecl *cls, Selector selInfo, + 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() { + uintptr_t x = (uintptr_t) SubExprs[RECEIVER]; + return (x & Flags) == IsInstMeth ? (Expr*) x : 0; + } + const Expr *getReceiver() const { + return const_cast<ObjCMessageExpr*>(this)->getReceiver(); + } + // FIXME: need setters for different receiver types. + void setReceiver(Expr *rec) { SubExprs[RECEIVER] = rec; } + Selector getSelector() const { return SelName; } + void setSelector(Selector S) { SelName = S; } + + 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; + void setClassInfo(const ClassInfo &C); + + /// getClassName - For class methods, this returns the invoked class, + /// 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; + // 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!"); + return cast<Expr>(SubExprs[Arg+ARGS_START]); + } + const Expr *getArg(unsigned Arg) const { + 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; + } + + 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(); + } + virtual SourceRange getSourceRange() const { + return SourceRange(LBracloc, RBracloc); + } + + static bool classof(const Stmt *T) { + 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]; } + const_arg_iterator arg_end() const { return &SubExprs[ARGS_START] + NumArgs; } +}; + +/// ObjCSuperExpr - Represents the "super" expression in Objective-C, +/// which refers to the object on which the current method is executing. +class ObjCSuperExpr : public Expr { + SourceLocation Loc; +public: + 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) { + return T->getStmtClass() == ObjCSuperExprClass; + } + static bool classof(const ObjCSuperExpr *) { 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 new file mode 100644 index 000000000000..4219bd507a90 --- /dev/null +++ b/include/clang/AST/ExternalASTSource.h @@ -0,0 +1,184 @@ +//===--- ExternalASTSource.h - Abstract External AST Interface --*- 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 ExternalASTSource interface, which enables +// construction of AST nodes from some external source.x +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H +#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H + +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Type.h" +#include "llvm/ADT/SmallVector.h" +#include <cassert> +namespace clang { + +class ASTConsumer; +class Decl; +class DeclContext; +class ExternalSemaSource; // layering violation required for downcasting +class Stmt; + +/// \brief The deserialized representation of a set of declarations +/// with the same name that are visible in a given context. +struct VisibleDeclaration { + /// \brief The name of the declarations. + DeclarationName 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; +}; + +/// \brief Abstract interface for external sources of AST nodes. +/// +/// External AST sources provide AST nodes constructed from some +/// external source, such as a precompiled header. External AST +/// sources can resolve types and declarations from abstract IDs into +/// actual type and declaration nodes, and read parts of declaration +/// contexts. +class ExternalASTSource { + /// \brief Whether this AST source also provides information for + /// semantic analysis. + bool SemaSource; + + friend class ExternalSemaSource; + +public: + ExternalASTSource() : SemaSource(false) { } + + virtual ~ExternalASTSource(); + + /// \brief Resolve a type ID into a type, potentially building a new + /// type. + virtual QualType GetType(uint32_t ID) = 0; + + /// \brief Resolve a declaration ID into a declaration, potentially + /// building a new declaration. + virtual Decl *GetDecl(uint32_t ID) = 0; + + /// \brief Resolve the offset of a statement in the decl stream into a + /// statement. + /// + /// This operation will read a new statement from the external + /// source each time it is called, and is meant to be used via a + /// LazyOffsetPtr. + virtual Stmt *GetDeclStmt(uint64_t Offset) = 0; + + /// \brief Read all of the declarations lexically stored in a + /// declaration context. + /// + /// \param DC The declaration context whose declarations will be + /// read. + /// + /// \param Decls Vector that will contain the declarations loaded + /// from the external source. The caller is responsible for merging + /// these declarations with any declarations already stored in the + /// declaration context. + /// + /// \returns true if there was an error while reading the + /// declarations for this declaration context. + virtual bool ReadDeclsLexicallyInContext(DeclContext *DC, + llvm::SmallVectorImpl<uint32_t> &Decls) = 0; + + /// \brief Read all of the declarations visible from a declaration + /// context. + /// + /// \param DC The declaration context whose visible declarations + /// will be read. + /// + /// \param Decls A vector of visible declaration structures, + /// providing the mapping from each name visible in the declaration + /// context to the declaration IDs of declarations with that name. + /// + /// \returns true if there was an error while reading the + /// declarations for this declaration context. + virtual bool ReadDeclsVisibleInContext(DeclContext *DC, + llvm::SmallVectorImpl<VisibleDeclaration> & Decls) = 0; + + /// \brief Function that will be invoked when we begin parsing a new + /// translation unit involving this external AST source. + virtual void StartTranslationUnit(ASTConsumer *Consumer) { } + + /// \brief Print any statistics that have been gathered regarding + /// the external AST source. + virtual void PrintStats(); +}; + +/// \brief A lazy pointer to an AST node (of base type T) that resides +/// within an external AST source. +/// +/// The AST node is identified within the external AST source by a +/// 63-bit offset, and can be retrieved via an operation on the +/// external AST source itself. +template<typename T, T* (ExternalASTSource::*Get)(uint64_t Offset)> +struct LazyOffsetPtr { + /// \brief Either a pointer to an AST node or the offset within the + /// external AST source where the AST node can be found. + /// + /// If the low bit is clear, a pointer to the AST node. If the low + /// bit is set, the upper 63 bits are the offset. + mutable uint64_t Ptr; + +public: + LazyOffsetPtr() : Ptr(0) { } + + explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { } + explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) { + assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); + if (Offset == 0) + Ptr = 0; + } + + LazyOffsetPtr &operator=(T *Ptr) { + 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) + Ptr = 0; + else + Ptr = (Offset << 1) | 0x01; + + return *this; + } + + /// \brief Whether this pointer is non-NULL. + /// + /// This operation does not require the AST node to be deserialized. + operator bool() const { return Ptr != 0; } + + /// \brief Whether this pointer is currently stored as an offset. + bool isOffset() const { return Ptr & 0x01; } + + /// \brief Retrieve the pointer to the AST node that this lazy pointer + /// + /// \param Source the external AST source. + /// + /// \returns a pointer to the AST node. + T* get(ExternalASTSource *Source) const { + if (isOffset()) { + assert(Source && + "Cannot deserialize a lazy pointer without an AST source"); + Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1)); + } + return reinterpret_cast<T*>(Ptr); + } +}; + +/// \brief A lazy pointer to a statement. +typedef LazyOffsetPtr<Stmt, &ExternalASTSource::GetDeclStmt> LazyDeclStmtPtr; + +} // end namespace clang + +#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h new file mode 100644 index 000000000000..4eea1031f063 --- /dev/null +++ b/include/clang/AST/NestedNameSpecifier.h @@ -0,0 +1,183 @@ +//===--- NestedNameSpecifier.h - C++ nested name specifiers -----*- 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 NestedNameSpecifier class, which represents +// a C++ nested-name-specifier. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H +#define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerIntPair.h" + +namespace llvm { + class raw_ostream; +} + +namespace clang { + +class ASTContext; +class NamespaceDecl; +class IdentifierInfo; +class PrintingPolicy; +class Type; + +/// \brief Represents a C++ nested name specifier, such as +/// "::std::vector<int>::". +/// +/// C++ nested name specifiers are the prefixes to qualified +/// namespaces. For example, "foo::" in "foo::x" is a nested name +/// specifier. Nested name specifiers are made up of a sequence of +/// specifiers, each of which can be a namespace, type, identifier +/// (for dependent names), or the global specifier ('::', must be the +/// first specifier). +class NestedNameSpecifier : public llvm::FoldingSetNode { + /// \brief The nested name specifier that precedes this nested name + /// specifier. + /// + /// The pointer is the nested-name-specifier that precedes this + /// one. The integer stores one of the first four values of type + /// SpecifierKind. + llvm::PointerIntPair<NestedNameSpecifier *, 2> Prefix; + + /// \brief The last component in the nested name specifier, which + /// can be an identifier, a declaration, or a type. + /// + /// When the pointer is NULL, this specifier represents the global + /// specifier '::'. Otherwise, the pointer is one of + /// IdentifierInfo*, Namespace*, or Type*, depending on the kind of + /// specifier as encoded within the prefix. + void* Specifier; + +public: + /// \brief The kind of specifier that completes this nested name + /// specifier. + enum SpecifierKind { + /// \brief An identifier, stored as an IdentifierInfo*. + Identifier = 0, + /// \brief A namespace, stored as a Namespace*. + Namespace = 1, + /// \brief A type, stored as a Type*. + TypeSpec = 2, + /// \brief A type that was preceded by the 'template' keyword, + /// stored as a Type*. + TypeSpecWithTemplate = 3, + /// \brief The global specifier '::'. There is no stored value. + Global = 4 + }; + +private: + /// \brief Builds the global specifier. + NestedNameSpecifier() : Prefix(0, 0), Specifier(0) { } + + /// \brief Copy constructor used internally to clone nested name + /// specifiers. + NestedNameSpecifier(const NestedNameSpecifier &Other) + : llvm::FoldingSetNode(Other), Prefix(Other.Prefix), + Specifier(Other.Specifier) { + } + + NestedNameSpecifier &operator=(const NestedNameSpecifier &); // do not implement + + /// \brief Either find or insert the given nested name specifier + /// mockup in the given context. + static NestedNameSpecifier *FindOrInsert(ASTContext &Context, + const NestedNameSpecifier &Mockup); + +public: + /// \brief Builds a specifier combining a prefix and an identifier. + /// + /// 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, + IdentifierInfo *II); + + /// \brief Builds a nested name specifier that names a namespace. + 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, + bool Template, Type *T); + + /// \brief Returns the nested name specifier representing the global + /// scope. + static NestedNameSpecifier *GlobalSpecifier(ASTContext &Context); + + /// \brief Return the prefix of this nested name specifier. + /// + /// The prefix contains all of the parts of the nested name + /// specifier that preced this current specifier. For example, for a + /// nested name specifier that represents "foo::bar::", the current + /// specifier will contain "bar::" and the prefix will contain + /// "foo::". + NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); } + + /// \brief Determine what kind of nested name specifier is stored. + SpecifierKind getKind() const { + if (Specifier == 0) + return Global; + return (SpecifierKind)Prefix.getInt(); + } + + /// \brief Retrieve the identifier stored in this nested name + /// specifier. + IdentifierInfo *getAsIdentifier() const { + if (Prefix.getInt() == Identifier) + return (IdentifierInfo *)Specifier; + + return 0; + } + + /// \brief Retrieve the namespace stored in this nested name + /// specifier. + NamespaceDecl *getAsNamespace() const { + if (Prefix.getInt() == Namespace) + return (NamespaceDecl *)Specifier; + + return 0; + } + + /// \brief Retrieve the type stored in this nested name specifier. + Type *getAsType() const { + if (Prefix.getInt() == TypeSpec || + Prefix.getInt() == TypeSpecWithTemplate) + return (Type *)Specifier; + + return 0; + } + + /// \brief Whether this nested name specifier refers to a dependent + /// type or not. + bool isDependent() const; + + /// \brief Print this nested name specifier to the given output + /// stream. + void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddPointer(Prefix.getOpaqueValue()); + ID.AddPointer(Specifier); + } + + void Destroy(ASTContext &Context); + + /// \brief Dump the nested name specifier to standard output to aid + /// in debugging. + void dump(); +}; + +} + +#endif diff --git a/include/clang/AST/PPCBuiltins.def b/include/clang/AST/PPCBuiltins.def new file mode 100644 index 000000000000..b8c791286e55 --- /dev/null +++ b/include/clang/AST/PPCBuiltins.def @@ -0,0 +1,24 @@ +//===--- PPCBuiltins.def - PowerPC Builtin function database ----*- 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 PowerPC-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// FIXME: this needs to be the full list supported by GCC. Right now, I'm just +// adding stuff on demand. + +// The format of this database matches clang/AST/Builtins.def. + +// This is just a placeholder, the types and attributes are wrong. +BUILTIN(__builtin_altivec_abs_v4sf , "ii" , "nc") +// FIXME: Obviously incomplete. + +#undef BUILTIN diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h new file mode 100644 index 000000000000..c669991ccc08 --- /dev/null +++ b/include/clang/AST/ParentMap.h @@ -0,0 +1,50 @@ +//===--- ParentMap.h - Mappings from Stmts to their Parents -----*- 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 ParentMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARENTMAP_H +#define LLVM_CLANG_PARENTMAP_H + +namespace clang { +class Stmt; +class Expr; + +class ParentMap { + void* Impl; +public: + ParentMap(Stmt* ASTRoot); + ~ParentMap(); + + Stmt *getParent(Stmt*) const; + Stmt *getParentIgnoreParens(Stmt *) const; + + 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)); + } + + 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 new file mode 100644 index 000000000000..385602b1fb9c --- /dev/null +++ b/include/clang/AST/PrettyPrinter.h @@ -0,0 +1,86 @@ +//===--- PrettyPrinter.h - Classes for aiding with AST printing -*- 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 PrinterHelper interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_PRETTY_PRINTER_H +#define LLVM_CLANG_AST_PRETTY_PRINTER_H + +namespace llvm { + class raw_ostream; +} + +namespace clang { + +class Stmt; +class TagDecl; + +class PrinterHelper { +public: + virtual ~PrinterHelper(); + virtual bool handledStmt(Stmt* E, llvm::raw_ostream& OS) = 0; +}; + +/// \brief Describes how types, statements, expressions, and +/// declarations should be printed. +struct PrintingPolicy { + /// \brief Create a default printing policy for C. + PrintingPolicy() + : Indentation(2), CPlusPlus(false), SuppressSpecifiers(false), + SuppressTag(false), SuppressTagKind(false), Dump(false) { } + + /// \brief The number of spaces to use to indent each line. + unsigned Indentation : 8; + + /// \brief Whether we're printing C++ code (otherwise, we're + /// printing C code). + bool CPlusPlus : 1; + + /// \brief Whether we should suppress printing of the actual specifiers for + /// the given type or declaration. + /// + /// This flag is only used when we are printing declarators beyond + /// the first declarator within a declaration group. For example, given: + /// + /// \code + /// const int *x, *y; + /// \endcode + /// + /// SuppressSpecifiers will be false when printing the + /// declaration for "x", so that we will print "int *x"; it will be + /// \c true when we print "y", so that we suppress printing the + /// "const int" type specifier and instead only print the "*y". + bool SuppressSpecifiers : 1; + + /// \brief Whether type printing should skip printing the actual tag type. + /// + /// This is used when the caller needs to print a tag definition in front + /// of the type, as in constructs like the following: + /// + /// \code + /// typedef struct { int x, y; } Point; + /// \endcode + bool SuppressTag : 1; + + /// \brief If we are printing a tag type, suppresses printing of the + /// kind of tag, e.g., "struct", "union", "enum". + bool SuppressTagKind : 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; +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h new file mode 100644 index 000000000000..ab184563da23 --- /dev/null +++ b/include/clang/AST/RecordLayout.h @@ -0,0 +1,103 @@ +//===--- RecordLayout.h - Layout information for a struct/union -*- 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 RecordLayout interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_LAYOUTINFO_H +#define LLVM_CLANG_AST_LAYOUTINFO_H + +#include "llvm/Support/DataTypes.h" + +namespace clang { + class ASTContext; + class RecordDecl; + +/// 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 +/// 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 + uint64_t *FieldOffsets; + unsigned Alignment; // Alignment of record in bits. + unsigned FieldCount; // Number of fields + friend class ASTContext; + + ASTRecordLayout(uint64_t S = 0, unsigned A = 8) + : Size(S), NextOffset(S), Alignment(A), FieldCount(0) {} + ~ASTRecordLayout() { + delete [] FieldOffsets; + } + + /// Initialize record layout. N is the number of fields in this record. + void InitializeLayout(unsigned N) { + FieldCount = N; + FieldOffsets = new uint64_t[N]; + } + + /// 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); + } + + void SetFieldOffset(unsigned FieldNo, uint64_t Offset) { + assert (FieldNo < FieldCount && "Invalid Field No"); + FieldOffsets[FieldNo] = Offset; + } + + 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; + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h new file mode 100644 index 000000000000..3656333d7423 --- /dev/null +++ b/include/clang/AST/Stmt.h @@ -0,0 +1,1223 @@ +//===--- Stmt.h - Classes for representing statements -----------*- 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 Stmt interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_STMT_H +#define LLVM_CLANG_AST_STMT_H + +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/AST/PrettyPrinter.h" +#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 clang { + class ASTContext; + class Expr; + class Decl; + class ParmVarDecl; + class QualType; + class IdentifierInfo; + 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& operator++() { ++I; return *this; } + ExprIterator operator-(size_t i) { return I-i; } + ExprIterator operator+(size_t i) { return I+i; } + Expr* operator[](size_t idx); + // FIXME: Verify that this will correctly return a signed distance. + signed operator-(const ExprIterator& R) const { return I - R.I; } + Expr* operator*() const; + Expr* operator->() const; + bool operator==(const ExprIterator& R) const { return I == R.I; } + bool operator!=(const ExprIterator& R) const { return I != R.I; } + 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& operator++() { ++I; return *this; } + ConstExprIterator operator+(size_t i) { return I+i; } + ConstExprIterator operator-(size_t i) { return I-i; } + const Expr * operator[](size_t idx) const; + signed operator-(const ConstExprIterator& R) const { return I - R.I; } + const Expr * operator*() const; + const Expr * operator->() const; + 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; } + bool operator>=(const ConstExprIterator& R) const { return I >= R.I; } + }; + +//===----------------------------------------------------------------------===// +// AST classes for statements. +//===----------------------------------------------------------------------===// + +/// Stmt - This represents one statement. +/// +class Stmt { +public: + enum StmtClass { + NoStmtClass = 0, +#define STMT(CLASS, PARENT) CLASS##Class, +#define FIRST_STMT(CLASS) firstStmtConstant = CLASS##Class, +#define LAST_STMT(CLASS) lastStmtConstant = CLASS##Class, +#define FIRST_EXPR(CLASS) firstExprConstant = CLASS##Class, +#define LAST_EXPR(CLASS) lastExprConstant = CLASS##Class +#include "clang/AST/StmtNodes.def" +}; +private: + const StmtClass sClass; + + // Make vanilla 'new' and 'delete' illegal for Stmts. +protected: + void* operator new(size_t bytes) throw() { + assert(0 && "Stmts cannot be allocated with regular 'new'."); + return 0; + } + 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. + 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; + } + + void operator delete(void*, ASTContext&, unsigned) throw() { } + void operator delete(void*, ASTContext*, unsigned) throw() { } + void operator delete(void*, std::size_t) throw() { } + void operator delete(void*, void*) throw() { } + +public: + /// \brief A placeholder type used to construct an empty shell of a + /// type, that will be filled in later (e.g., by some + /// de-serialization). + struct EmptyShell { }; + +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) { + if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); + } + +public: + Stmt(StmtClass SC) : sClass(SC) { + if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); + } + virtual ~Stmt() {} + + virtual void Destroy(ASTContext &Ctx); + + StmtClass getStmtClass() const { return 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. + virtual SourceRange getSourceRange() const = 0; + SourceLocation getLocStart() const { return getSourceRange().getBegin(); } + SourceLocation getLocEnd() const { return getSourceRange().getEnd(); } + + // global temp stats (until we have a per-module visitor) + static void addStmtClass(const StmtClass s); + static bool CollectingStats(bool enable=false); + static void PrintStats(); + + /// dump - This does a local dump of the specified AST fragment. It dumps the + /// specified node and a few nodes underneath it, but not the whole subtree. + /// This is useful in a debugger. + void dump() const; + void dump(SourceManager &SM) const; + + /// dumpAll - This does a dump of the specified AST fragment and all subtrees. + void dumpAll() const; + void dumpAll(SourceManager &SM) const; + + /// 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 = 0, + const PrintingPolicy &Policy = PrintingPolicy(), + unsigned Indentation = 0) const { + printPretty(OS, *(ASTContext*)0, Helper, Policy, Indentation); + } + void printPretty(llvm::raw_ostream &OS, ASTContext& Context, + PrinterHelper *Helper = 0, + const PrintingPolicy &Policy = PrintingPolicy(), + 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; } + + /// 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 + /// such implicit control-flow. Such statements are also specially handled + /// within CFGs. + bool hasImplicitControlFlow() const; + + /// Child Iterators: All subclasses must implement child_begin and child_end + /// to permit easy iteration over the substatements/subexpessions of an + /// 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()); + } +}; + +/// 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 +/// 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, + 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(); } + + const DeclGroupRef getDeclGroup() const { return DG; } + DeclGroupRef getDeclGroup() { return DG; } + void setDeclGroup(DeclGroupRef DGR) { DG = DGR; } + + SourceLocation getStartLoc() const { return StartLoc; } + void setStartLoc(SourceLocation L) { StartLoc = L; } + SourceLocation getEndLoc() const { return EndLoc; } + void setEndLoc(SourceLocation L) { EndLoc = L; } + + SourceRange getSourceRange() const { + return SourceRange(StartLoc, EndLoc); + } + + 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(); } + const_decl_iterator decl_end() const { return DG.end(); } +}; + +/// NullStmt - This is the null statement ";": C99 6.8.3p3. +/// +class NullStmt : public Stmt { + SourceLocation SemiLoc; +public: + NullStmt(SourceLocation L) : Stmt(NullStmtClass), SemiLoc(L) {} + + /// \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 NullStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CompoundStmt - This represents a group of statements like { stmt stmt }. +/// +class CompoundStmt : public Stmt { + Stmt** Body; + unsigned NumStmts; + SourceLocation LBracLoc, RBracLoc; +public: + 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; } + + typedef Stmt** body_iterator; + body_iterator body_begin() { return Body; } + body_iterator body_end() { return Body + NumStmts; } + Stmt *body_back() { return NumStmts ? Body[NumStmts-1] : 0; } + + typedef Stmt* const * const_body_iterator; + const_body_iterator body_begin() const { return Body; } + const_body_iterator body_end() const { return Body + NumStmts; } + const Stmt *body_back() const { return NumStmts ? Body[NumStmts-1] : 0; } + + typedef std::reverse_iterator<body_iterator> reverse_body_iterator; + reverse_body_iterator body_rbegin() { + return reverse_body_iterator(body_end()); + } + reverse_body_iterator body_rend() { + return reverse_body_iterator(body_begin()); + } + + typedef std::reverse_iterator<const_body_iterator> + const_reverse_body_iterator; + + 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); + } + + 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 CompoundStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +// SwitchCase is the base class for CaseStmt and DefaultStmt, +class SwitchCase : public Stmt { +protected: + // A pointer to the following CaseStmt or DefaultStmt class, + // used by SwitchStmt. + SwitchCase *NextSwitchCase; + + SwitchCase(StmtClass SC) : Stmt(SC), NextSwitchCase(0) {} + +public: + const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; } + + SwitchCase *getNextSwitchCase() { return NextSwitchCase; } + + void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; } + + Stmt *getSubStmt() { return v_getSubStmt(); } + + virtual SourceRange getSourceRange() const { return SourceRange(); } + + 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; +}; + +class CaseStmt : public SwitchCase { + enum { SUBSTMT, LHS, RHS, END_EXPR }; + Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for + // GNU "case 1 ... 4" extension + SourceLocation CaseLoc; + SourceLocation EllipsisLoc; + SourceLocation ColonLoc; + + virtual Stmt* v_getSubStmt() { return getSubStmt(); } +public: + CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc, + SourceLocation ellipsisLoc, SourceLocation colonLoc) + : SwitchCase(CaseStmtClass) { + SubExprs[SUBSTMT] = 0; + SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs); + SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs); + CaseLoc = caseLoc; + EllipsisLoc = ellipsisLoc; + ColonLoc = colonLoc; + } + + /// \brief Build an empty switch case statement. + explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass) { } + + SourceLocation getCaseLoc() const { return CaseLoc; } + void setCaseLoc(SourceLocation L) { CaseLoc = L; } + SourceLocation getEllipsisLoc() const { return EllipsisLoc; } + void setEllipsisLoc(SourceLocation L) { EllipsisLoc = L; } + SourceLocation getColonLoc() const { return ColonLoc; } + void setColonLoc(SourceLocation L) { ColonLoc = L; } + + Expr *getLHS() { return reinterpret_cast<Expr*>(SubExprs[LHS]); } + 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 *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()); + } + 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(); +}; + +class DefaultStmt : public SwitchCase { + Stmt* SubStmt; + SourceLocation DefaultLoc; + SourceLocation ColonLoc; + virtual Stmt* v_getSubStmt() { return getSubStmt(); } +public: + DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) : + SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL), + ColonLoc(CL) {} + + /// \brief Build an empty default statement. + explicit DefaultStmt(EmptyShell) : SwitchCase(DefaultStmtClass) { } + + Stmt *getSubStmt() { return SubStmt; } + const Stmt *getSubStmt() const { return SubStmt; } + void setSubStmt(Stmt *S) { SubStmt = S; } + + SourceLocation getDefaultLoc() const { return DefaultLoc; } + void setDefaultLoc(SourceLocation L) { DefaultLoc = L; } + SourceLocation getColonLoc() const { return ColonLoc; } + void setColonLoc(SourceLocation L) { ColonLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(DefaultLoc, SubStmt->getLocEnd()); + } + 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(); +}; + +class LabelStmt : public Stmt { + IdentifierInfo *Label; + Stmt *SubStmt; + SourceLocation IdentLoc; +public: + 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; } + const char *getName() const; + Stmt *getSubStmt() { return SubStmt; } + const Stmt *getSubStmt() const { return SubStmt; } + 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; + } + static bool classof(const LabelStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +/// IfStmt - This represents an if/then/else. +/// +class IfStmt : public Stmt { + enum { COND, THEN, ELSE, END_EXPR }; + Stmt* SubExprs[END_EXPR]; + SourceLocation IfLoc; + SourceLocation ElseLoc; +public: + IfStmt(SourceLocation IL, Expr *cond, Stmt *then, + SourceLocation EL = SourceLocation(), Stmt *elsev = 0) + : Stmt(IfStmtClass) { + SubExprs[COND] = reinterpret_cast<Stmt*>(cond); + SubExprs[THEN] = then; + SubExprs[ELSE] = elsev; + 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; } + const Stmt *getElse() const { return SubExprs[ELSE]; } + void setElse(Stmt *S) { SubExprs[ELSE] = S; } + + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } + Stmt *getThen() { return SubExprs[THEN]; } + Stmt *getElse() { return SubExprs[ELSE]; } + + SourceLocation getIfLoc() const { return IfLoc; } + void setIfLoc(SourceLocation L) { IfLoc = L; } + SourceLocation getElseLoc() const { return ElseLoc; } + void setElseLoc(SourceLocation L) { ElseLoc = L; } + + 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 IfStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// SwitchStmt - This represents a 'switch' stmt. +/// +class SwitchStmt : public Stmt { + enum { COND, BODY, END_EXPR }; + Stmt* SubExprs[END_EXPR]; + // This points to a linked list of case and default statements. + SwitchCase *FirstCase; + SourceLocation SwitchLoc; +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) { } + + const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} + const Stmt *getBody() const { return SubExprs[BODY]; } + const SwitchCase *getSwitchCaseList() const { return FirstCase; } + + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]);} + void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); } + Stmt *getBody() { return SubExprs[BODY]; } + void setBody(Stmt *S) { SubExprs[BODY] = S; } + SwitchCase *getSwitchCaseList() { return FirstCase; } + 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; + SwitchLoc = SL; + } + void addSwitchCase(SwitchCase *SC) { + assert(!SC->getNextSwitchCase() && "case/default already added to a switch"); + SC->setNextSwitchCase(FirstCase); + FirstCase = SC; + } + virtual SourceRange getSourceRange() const { + return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd()); + } + 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(); +}; + + +/// WhileStmt - This represents a 'while' stmt. +/// +class WhileStmt : public Stmt { + enum { COND, BODY, END_EXPR }; + Stmt* SubExprs[END_EXPR]; + SourceLocation WhileLoc; +public: + WhileStmt(Expr *cond, Stmt *body, SourceLocation WL) : Stmt(WhileStmtClass) { + SubExprs[COND] = reinterpret_cast<Stmt*>(cond); + SubExprs[BODY] = body; + WhileLoc = WL; + } + + /// \brief Build an empty while statement. + explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, 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]; } + void setBody(Stmt *S) { SubExprs[BODY] = S; } + + SourceLocation getWhileLoc() const { return WhileLoc; } + void setWhileLoc(SourceLocation L) { WhileLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd()); + } + 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(); +}; + +/// DoStmt - This represents a 'do/while' stmt. +/// +class DoStmt : public Stmt { + enum { COND, BODY, END_EXPR }; + Stmt* SubExprs[END_EXPR]; + SourceLocation DoLoc; + SourceLocation WhileLoc; + +public: + DoStmt(Stmt *body, Expr *cond, SourceLocation DL, SourceLocation WL) + : Stmt(DoStmtClass), DoLoc(DL), WhileLoc(WL) { + SubExprs[COND] = reinterpret_cast<Stmt*>(cond); + SubExprs[BODY] = body; + DoLoc = DL; + WhileLoc = WL; + } + + /// \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]; } + void setBody(Stmt *S) { SubExprs[BODY] = S; } + + SourceLocation getDoLoc() const { return DoLoc; } + void setDoLoc(SourceLocation L) { DoLoc = L; } + SourceLocation getWhileLoc() const { return WhileLoc; } + void setWhileLoc(SourceLocation L) { WhileLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(DoLoc, SubExprs[BODY]->getLocEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == DoStmtClass; + } + static bool classof(const DoStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +/// ForStmt - This represents a 'for (init;cond;inc)' stmt. Note that any of +/// the init/cond/inc parts of the ForStmt will be null if they were not +/// specified in the source. +/// +class ForStmt : public Stmt { + enum { INIT, COND, INC, BODY, END_EXPR }; + Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt. + SourceLocation ForLoc; + SourceLocation LParenLoc, RParenLoc; + +public: + ForStmt(Stmt *Init, Expr *Cond, Expr *Inc, Stmt *Body, SourceLocation FL, + SourceLocation LP, SourceLocation RP) + : Stmt(ForStmtClass) { + SubExprs[INIT] = Init; + SubExprs[COND] = reinterpret_cast<Stmt*>(Cond); + SubExprs[INC] = reinterpret_cast<Stmt*>(Inc); + SubExprs[BODY] = Body; + ForLoc = FL; + LParenLoc = LP; + RParenLoc = RP; + } + + /// \brief Build an empty for statement. + explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { } + + Stmt *getInit() { return SubExprs[INIT]; } + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } + Expr *getInc() { return reinterpret_cast<Expr*>(SubExprs[INC]); } + Stmt *getBody() { return SubExprs[BODY]; } + + const Stmt *getInit() const { return SubExprs[INIT]; } + const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} + const Expr *getInc() const { return reinterpret_cast<Expr*>(SubExprs[INC]); } + const Stmt *getBody() const { return SubExprs[BODY]; } + + void setInit(Stmt *S) { SubExprs[INIT] = S; } + void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } + void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); } + void setBody(Stmt *S) { SubExprs[BODY] = S; } + + SourceLocation getForLoc() const { return ForLoc; } + void setForLoc(SourceLocation L) { ForLoc = L; } + SourceLocation getLParenLoc() const { return LParenLoc; } + void setLParenLoc(SourceLocation L) { LParenLoc = L; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); + } + 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 { + LabelStmt *Label; + SourceLocation GotoLoc; + SourceLocation LabelLoc; +public: + 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) { } + + LabelStmt *getLabel() const { return Label; } + void setLabel(LabelStmt *S) { Label = S; } + + SourceLocation getGotoLoc() const { return GotoLoc; } + void setGotoLoc(SourceLocation L) { GotoLoc = L; } + SourceLocation getLabelLoc() const { return LabelLoc; } + void setLabelLoc(SourceLocation L) { LabelLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(GotoLoc, LabelLoc); + } + 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(); +}; + +/// IndirectGotoStmt - This represents an indirect goto. +/// +class IndirectGotoStmt : public Stmt { + SourceLocation GotoLoc; + SourceLocation StarLoc; + Stmt *Target; +public: + 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) + : 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); } + + virtual SourceRange getSourceRange() const { + return SourceRange(GotoLoc, Target->getLocEnd()); + } + + 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(); +}; + + +/// ContinueStmt - This represents a continue. +/// +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); + } + + ContinueStmt* Clone(ASTContext &C) const; + + 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(); +}; + +/// BreakStmt - This represents a break. +/// +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) { } + + SourceLocation getBreakLoc() const { return BreakLoc; } + void setBreakLoc(SourceLocation L) { BreakLoc = L; } + + 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 BreakStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +/// ReturnStmt - This represents a return, optionally of an expression: +/// return; +/// return 4; +/// +/// Note that GCC allows return with no argument in a function declared to +/// return a value, and it allows returning a value in functions declared to +/// return void. We explicitly model this in the AST, which means you can't +/// depend on the return type of the function and the presence of an argument. +/// +class ReturnStmt : public Stmt { + Stmt *RetExpr; + SourceLocation RetLoc; +public: + ReturnStmt(SourceLocation RL, Expr *E = 0) : Stmt(ReturnStmtClass), + RetExpr((Stmt*) E), RetLoc(RL) {} + + /// \brief Build an empty return expression. + explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { } + + const Expr *getRetValue() const; + Expr *getRetValue(); + void setRetValue(Expr *E) { RetExpr = reinterpret_cast<Stmt*>(E); } + + SourceLocation getReturnLoc() const { return RetLoc; } + void setReturnLoc(SourceLocation L) { RetLoc = L; } + + virtual SourceRange getSourceRange() const; + + 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(); +}; + +/// AsmStmt - This represents a GNU inline-assembly statement extension. +/// +class AsmStmt : public Stmt { + SourceLocation AsmLoc, RParenLoc; + StringLiteral *AsmStr; + + 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, + std::string *names, StringLiteral **constraints, + Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, + StringLiteral **clobbers, SourceLocation rparenloc); + + /// \brief Build an empty inline-assembly statement. + explicit AsmStmt(EmptyShell Empty) : Stmt(AsmStmtClass, Empty) { } + + SourceLocation getAsmLoc() const { return AsmLoc; } + void setAsmLoc(SourceLocation L) { AsmLoc = L; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + bool isVolatile() const { return IsVolatile; } + void setVolatile(bool V) { IsVolatile = V; } + bool isSimple() const { return IsSimple; } + void setSimple(bool V) { IsSimple = false; } + + //===--- Asm String Analysis ---===// + + const StringLiteral *getAsmString() const { return AsmStr; } + StringLiteral *getAsmString() { return AsmStr; } + void setAsmString(StringLiteral *E) { AsmStr = E; } + + /// AsmStringPiece - this is part of a decomposed asm string specification + /// (for use with the AnalyzeAsmString function below). An asm string is + /// considered to be a concatenation of these parts. + class AsmStringPiece { + public: + enum Kind { + String, // String in .ll asm string form, "$" -> "$$" and "%%" -> "%". + Operand // Operand reference, with optional modifier %c4. + }; + private: + Kind MyKind; + std::string Str; + unsigned OperandNo; + public: + AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {} + AsmStringPiece(unsigned OpNo, char Modifier) + : 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; + } + + unsigned getOperandNo() const { + assert(isOperand()); + return OperandNo; + } + + /// getModifier - Get the modifier for this operand, if present. This + /// returns '\0' if there was no modifier. + char getModifier() const { + assert(isOperand()); + 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. + unsigned AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece> &Pieces, + ASTContext &C, unsigned &DiagOffs) const; + + + //===--- Output operands ---===// + + unsigned getNumOutputs() const { return NumOutputs; } + + const std::string &getOutputName(unsigned i) const { + return Names[i]; + } + + /// getOutputConstraint - Return the constraint string for the specified + /// 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; } + + 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, + 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]; } + const StringLiteral *getClobber(unsigned i) const { return Clobbers[i]; } + void setClobbers(StringLiteral **Clobbers, unsigned NumClobbers); + + 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 + + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h new file mode 100644 index 000000000000..2338f1457a84 --- /dev/null +++ b/include/clang/AST/StmtCXX.h @@ -0,0 +1,100 @@ +//===--- StmtCXX.h - Classes for representing C++ statements ----*- 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 C++ statement AST node classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_STMTCXX_H +#define LLVM_CLANG_AST_STMTCXX_H + +#include "clang/AST/Stmt.h" + +namespace clang { + +class VarDecl; + +/// CXXCatchStmt - This represents a C++ catch block. +/// +class CXXCatchStmt : public Stmt { + SourceLocation CatchLoc; + /// The exception-declaration of the type. + VarDecl *ExceptionDecl; + /// The handler block. + Stmt *HandlerBlock; + +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()); + } + + SourceLocation getCatchLoc() const { return CatchLoc; } + VarDecl *getExceptionDecl() { return ExceptionDecl; } + QualType getCaughtType(); + Stmt *getHandlerBlock() { return HandlerBlock; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXCatchStmtClass; + } + static bool classof(const CXXCatchStmt *) { return true; } + + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXTryStmt - A C++ try block, including all handlers. +/// +class CXXTryStmt : public Stmt { + SourceLocation TryLoc; + // First place is the guarded CompoundStatement. Subsequent are the handlers. + // More than three handlers should be rare. + llvm::SmallVector<Stmt*, 4> Stmts; + +public: + CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, + Stmt **handlers, unsigned numHandlers); + + virtual SourceRange getSourceRange() const { + return SourceRange(TryLoc, Stmts.back()->getLocEnd()); + } + + SourceLocation getTryLoc() const { return TryLoc; } + + CompoundStmt *getTryBlock() { return llvm::cast<CompoundStmt>(Stmts[0]); } + const CompoundStmt *getTryBlock() const { + return llvm::cast<CompoundStmt>(Stmts[0]); + } + + unsigned getNumHandlers() const { return Stmts.size() - 1; } + CXXCatchStmt *getHandler(unsigned i) { + return llvm::cast<CXXCatchStmt>(Stmts[i + 1]); + } + const CXXCatchStmt *getHandler(unsigned i) const { + return llvm::cast<CXXCatchStmt>(Stmts[i + 1]); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXTryStmtClass; + } + static bool classof(const CXXTryStmt *) { return true; } + + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +} // end namespace clang + +#endif diff --git a/include/clang/AST/StmtGraphTraits.h b/include/clang/AST/StmtGraphTraits.h new file mode 100644 index 000000000000..1bfac6a9587e --- /dev/null +++ b/include/clang/AST/StmtGraphTraits.h @@ -0,0 +1,83 @@ +//===--- StmtGraphTraits.h - Graph Traits for the class Stmt ----*- 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 a template specialization of llvm::GraphTraits to +// treat ASTs (Stmt*) as graphs +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_STMT_GRAPHTRAITS_H +#define LLVM_CLANG_AST_STMT_GRAPHTRAITS_H + +#include "clang/AST/Stmt.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/DepthFirstIterator.h" + +namespace llvm { + +//template <typename T> struct GraphTraits; + + +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); + } +}; + + +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(); + } + + 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 new file mode 100644 index 000000000000..35bd5ada0256 --- /dev/null +++ b/include/clang/AST/StmtIterator.h @@ -0,0 +1,145 @@ +//===--- StmtIterator.h - Iterators for Statements ------------------------===// +// +// 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 StmtIterator and ConstStmtIterator classes. +// +//===----------------------------------------------------------------------===// + +#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> + +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; + Decl** DGE; + + bool inDecl() const { + return (RawVAPtr & Flags) == DeclMode; + } + + bool inDeclGroup() const { + return (RawVAPtr & Flags) == DeclGroupMode; + } + + 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()); + 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) {} + StmtIteratorBase(Decl* d); + StmtIteratorBase(VariableArrayType* t); + StmtIteratorBase(Decl** dgi, Decl** dge); + StmtIteratorBase() : stmt(NULL), RawVAPtr(0) {} +}; + + +template <typename DERIVED, typename REFERENCE> +class StmtIteratorImpl : public StmtIteratorBase, + public std::iterator<std::forward_iterator_tag, + REFERENCE, ptrdiff_t, + REFERENCE, REFERENCE> { +protected: + StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {} +public: + 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(); + else NextDecl(); + } + else if (inSizeOfTypeVA()) + 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 { + return (REFERENCE) (inStmt() ? *stmt : GetDeclExpr()); + } + + 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) + : StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {} + + StmtIterator(VariableArrayType* t):StmtIteratorImpl<StmtIterator,Stmt*&>(t) {} + StmtIterator(Decl* D) : StmtIteratorImpl<StmtIterator,Stmt*&>(D) {} +}; + +struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator, + const Stmt*> { + explicit ConstStmtIterator() : + StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {} + + ConstStmtIterator(const StmtIterator& RHS) : + StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {} +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def new file mode 100644 index 000000000000..ab6524663d63 --- /dev/null +++ b/include/clang/AST/StmtNodes.def @@ -0,0 +1,156 @@ +//===-- StmtNodes.def - Metadata about Stmt AST nodes -----------*- 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 AST Node info database. +// +//===----------------------------------------------------------------------===// + +#ifndef FIRST_STMT +#define FIRST_STMT(CLASS) +#define LAST_STMT(CLASS) +#endif + +#ifndef FIRST_EXPR +#define FIRST_EXPR(CLASS) +#define LAST_EXPR(CLASS) +#endif + +#ifndef EXPR +# define EXPR(Type, Base) STMT(Type, Base) +#endif + +// Normal Statements. +STMT(NullStmt , Stmt) +FIRST_STMT(NullStmt) +STMT(CompoundStmt , Stmt) +STMT(CaseStmt , SwitchCase) +STMT(DefaultStmt , SwitchCase) +STMT(LabelStmt , Stmt) +STMT(IfStmt , Stmt) +STMT(SwitchStmt , Stmt) +STMT(WhileStmt , Stmt) +STMT(DoStmt , Stmt) +STMT(ForStmt , Stmt) +STMT(GotoStmt , Stmt) +STMT(IndirectGotoStmt, Stmt) +STMT(ContinueStmt , Stmt) +STMT(BreakStmt , Stmt) +STMT(ReturnStmt , Stmt) +STMT(DeclStmt , Stmt) +STMT(SwitchCase , Stmt) + +// GNU Stmt Extensions +STMT(AsmStmt , Stmt) + +// Obj-C statements +STMT(ObjCAtTryStmt , Stmt) +STMT(ObjCAtCatchStmt , Stmt) +STMT(ObjCAtFinallyStmt , Stmt) +STMT(ObjCAtThrowStmt , Stmt) +STMT(ObjCAtSynchronizedStmt , Stmt) +// Obj-C2 statements +STMT(ObjCForCollectionStmt, Stmt) + +// C++ statements +STMT(CXXCatchStmt, Stmt) +STMT(CXXTryStmt , Stmt) + +LAST_STMT(CXXTryStmt) + +// Expressions. +EXPR(Expr , Stmt) +FIRST_EXPR(Expr) +EXPR(PredefinedExpr , Expr) +EXPR(DeclRefExpr , Expr) +EXPR(IntegerLiteral , Expr) +EXPR(FloatingLiteral , Expr) +EXPR(ImaginaryLiteral , Expr) +EXPR(StringLiteral , Expr) +EXPR(CharacterLiteral , Expr) +EXPR(ParenExpr , Expr) +EXPR(UnaryOperator , Expr) +EXPR(SizeOfAlignOfExpr , Expr) +EXPR(ArraySubscriptExpr , Expr) +EXPR(CallExpr , Expr) +EXPR(MemberExpr , Expr) +EXPR(CastExpr , Expr) +EXPR(BinaryOperator , Expr) +EXPR(CompoundAssignOperator, BinaryOperator) +EXPR(ConditionalOperator , Expr) +EXPR(ImplicitCastExpr , CastExpr) +EXPR(ExplicitCastExpr , CastExpr) +EXPR(CStyleCastExpr , ExplicitCastExpr) +EXPR(CompoundLiteralExpr , Expr) +EXPR(ExtVectorElementExpr , Expr) +EXPR(InitListExpr , Expr) +EXPR(DesignatedInitExpr , Expr) +EXPR(ImplicitValueInitExpr , Expr) +EXPR(VAArgExpr , Expr) + +// GNU Extensions. +EXPR(AddrLabelExpr , Expr) +EXPR(StmtExpr , Expr) +EXPR(TypesCompatibleExpr , Expr) +EXPR(ChooseExpr , Expr) +EXPR(GNUNullExpr , Expr) + +// C++ Expressions. +EXPR(CXXOperatorCallExpr , CallExpr) +EXPR(CXXMemberCallExpr , CallExpr) +EXPR(CXXNamedCastExpr , ExplicitCastExpr) +EXPR(CXXStaticCastExpr , CXXNamedCastExpr) +EXPR(CXXDynamicCastExpr , CXXNamedCastExpr) +EXPR(CXXReinterpretCastExpr , CXXNamedCastExpr) +EXPR(CXXConstCastExpr , CXXNamedCastExpr) +EXPR(CXXFunctionalCastExpr , ExplicitCastExpr) +EXPR(CXXTypeidExpr , Expr) +EXPR(CXXBoolLiteralExpr , Expr) +EXPR(CXXNullPtrLiteralExpr , Expr) +EXPR(CXXThisExpr , Expr) +EXPR(CXXThrowExpr , Expr) +EXPR(CXXDefaultArgExpr , Expr) +EXPR(CXXZeroInitValueExpr , Expr) +EXPR(CXXConditionDeclExpr , DeclRefExpr) +EXPR(CXXNewExpr , Expr) +EXPR(CXXDeleteExpr , Expr) +EXPR(UnresolvedFunctionNameExpr , Expr) +EXPR(UnaryTypeTraitExpr , Expr) +EXPR(QualifiedDeclRefExpr , DeclRefExpr) +EXPR(UnresolvedDeclRefExpr , Expr) +EXPR(CXXConstructExpr , Expr) +EXPR(CXXBindTemporaryExpr , Expr) +EXPR(CXXExprWithTemporaries , Expr) +EXPR(CXXTemporaryObjectExpr , CXXConstructExpr) +EXPR(CXXUnresolvedConstructExpr, Expr) +EXPR(CXXUnresolvedMemberExpr, Expr) + +// Obj-C Expressions. +EXPR(ObjCStringLiteral , Expr) +EXPR(ObjCEncodeExpr , Expr) +EXPR(ObjCMessageExpr , Expr) +EXPR(ObjCSelectorExpr , Expr) +EXPR(ObjCProtocolExpr , Expr) +EXPR(ObjCIvarRefExpr , Expr) +EXPR(ObjCPropertyRefExpr , Expr) +EXPR(ObjCKVCRefExpr , Expr) +EXPR(ObjCSuperExpr , Expr) + +// Clang Extensions. +EXPR(ShuffleVectorExpr , Expr) +EXPR(BlockExpr , Expr) +EXPR(BlockDeclRefExpr , Expr) + +LAST_EXPR(BlockDeclRefExpr) + +#undef STMT +#undef EXPR +#undef FIRST_STMT +#undef LAST_STMT +#undef FIRST_EXPR +#undef LAST_EXPR diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h new file mode 100644 index 000000000000..8ae707174403 --- /dev/null +++ b/include/clang/AST/StmtObjC.h @@ -0,0 +1,307 @@ +//===--- StmtObjC.h - Classes for representing ObjC statements --*- 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 Objective-C statement AST node classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_STMTOBJC_H +#define LLVM_CLANG_AST_STMTOBJC_H + +#include "clang/AST/Stmt.h" + +namespace clang { + +/// ObjCForCollectionStmt - This represents Objective-c's collection statement; +/// represented as 'for (element 'in' collection-expression)' stmt. +/// +class ObjCForCollectionStmt : public Stmt { + enum { ELEM, COLLECTION, BODY, END_EXPR }; + Stmt* SubExprs[END_EXPR]; // SubExprs[ELEM] is an expression or declstmt. + SourceLocation ForLoc; + SourceLocation RParenLoc; +public: + ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body, + SourceLocation FCL, SourceLocation RPL); + explicit ObjCForCollectionStmt(EmptyShell Empty) : + Stmt(ObjCForCollectionStmtClass, Empty) { } + + Stmt *getElement() { return SubExprs[ELEM]; } + Expr *getCollection() { + return reinterpret_cast<Expr*>(SubExprs[COLLECTION]); + } + Stmt *getBody() { return SubExprs[BODY]; } + + const Stmt *getElement() const { return SubExprs[ELEM]; } + 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) { + 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()); + } + 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: + enum { BODY, NEXT_CATCH, END_EXPR }; + ParmVarDecl *ExceptionDecl; + Stmt *SubExprs[END_EXPR]; + SourceLocation AtCatchLoc, RParenLoc; + +public: + ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc, + ParmVarDecl *catchVarDecl, + Stmt *atCatchStmt, Stmt *atCatchList); + + 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() { + return static_cast<ObjCAtCatchStmt*>(SubExprs[NEXT_CATCH]); + } + void setNextCatchStmt(Stmt *S) { SubExprs[NEXT_CATCH] = S; } + + const ParmVarDecl *getCatchParamDecl() const { + 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()); + } + + 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 +class ObjCAtFinallyStmt : public Stmt { + Stmt *AtFinallyStmt; + SourceLocation AtFinallyLoc; +public: + ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt) + : Stmt(ObjCAtFinallyStmtClass), + AtFinallyStmt(atFinallyStmt), AtFinallyLoc(atFinallyLoc) {} + + 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()); + } + + 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 +/// @try ... @catch ... @finally statement. +class ObjCAtTryStmt : public Stmt { +private: + enum { TRY, CATCH, FINALLY, END_EXPR }; + Stmt* SubStmts[END_EXPR]; + + SourceLocation AtTryLoc; +public: + ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt, + Stmt *atCatchStmt, + Stmt *atFinallyStmt) + : Stmt(ObjCAtTryStmtClass) { + SubStmts[TRY] = atTryStmt; + SubStmts[CATCH] = atCatchStmt; + SubStmts[FINALLY] = atFinallyStmt; + AtTryLoc = atTryLoc; + } + explicit ObjCAtTryStmt(EmptyShell Empty) : + Stmt(ObjCAtTryStmtClass, Empty) { } + + 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]); + } + 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]); + } + 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()); + } + + 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(); +}; + +/// ObjCAtSynchronizedStmt - This is for objective-c's @synchronized statement. +/// Example: @synchronized (sem) { +/// do-something; +/// } +/// +class ObjCAtSynchronizedStmt : public Stmt { +private: + enum { SYNC_EXPR, SYNC_BODY, END_EXPR }; + Stmt* SubStmts[END_EXPR]; + SourceLocation AtSynchronizedLoc; + +public: + ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr, + Stmt *synchBody) + : Stmt(ObjCAtSynchronizedStmtClass) { + SubStmts[SYNC_EXPR] = synchExpr; + SubStmts[SYNC_BODY] = synchBody; + AtSynchronizedLoc = atSynchronizedLoc; + } + 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]); + } + void setSynchBody(Stmt *S) { SubStmts[SYNC_BODY] = S; } + + const Expr *getSynchExpr() const { + 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()); + } + + 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; + SourceLocation AtThrowLoc; +public: + ObjCAtThrowStmt(SourceLocation atThrowLoc, Stmt *throwExpr) + : Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) { + AtThrowLoc = atThrowLoc; + } + 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); + } + + 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(); +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h new file mode 100644 index 000000000000..4f4066ab8602 --- /dev/null +++ b/include/clang/AST/StmtVisitor.h @@ -0,0 +1,176 @@ +//===--- StmtVisitor.h - Visitor for Stmt subclasses ------------*- 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 StmtVisitor interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_STMTVISITOR_H +#define LLVM_CLANG_AST_STMTVISITOR_H + +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/StmtCXX.h" +#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. + if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { + switch (BinOp->getOpcode()) { + default: assert(0 && "Unknown binary operator!"); + case BinaryOperator::PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator); + case BinaryOperator::PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator); + case BinaryOperator::Mul: DISPATCH(BinMul, BinaryOperator); + case BinaryOperator::Div: DISPATCH(BinDiv, BinaryOperator); + case BinaryOperator::Rem: DISPATCH(BinRem, BinaryOperator); + case BinaryOperator::Add: DISPATCH(BinAdd, BinaryOperator); + case BinaryOperator::Sub: DISPATCH(BinSub, BinaryOperator); + case BinaryOperator::Shl: DISPATCH(BinShl, BinaryOperator); + case BinaryOperator::Shr: DISPATCH(BinShr, BinaryOperator); + + case BinaryOperator::LT: DISPATCH(BinLT, BinaryOperator); + case BinaryOperator::GT: DISPATCH(BinGT, BinaryOperator); + case BinaryOperator::LE: DISPATCH(BinLE, BinaryOperator); + 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); + case BinaryOperator::LAnd: DISPATCH(BinLAnd, BinaryOperator); + case BinaryOperator::LOr : DISPATCH(BinLOr, BinaryOperator); + case BinaryOperator::Assign: DISPATCH(BinAssign, BinaryOperator); + case BinaryOperator::MulAssign: + DISPATCH(BinMulAssign, CompoundAssignOperator); + case BinaryOperator::DivAssign: + DISPATCH(BinDivAssign, CompoundAssignOperator); + case BinaryOperator::RemAssign: + DISPATCH(BinRemAssign, CompoundAssignOperator); + case BinaryOperator::AddAssign: + DISPATCH(BinAddAssign, CompoundAssignOperator); + case BinaryOperator::SubAssign: + DISPATCH(BinSubAssign, CompoundAssignOperator); + case BinaryOperator::ShlAssign: + DISPATCH(BinShlAssign, CompoundAssignOperator); + case BinaryOperator::ShrAssign: + DISPATCH(BinShrAssign, CompoundAssignOperator); + case BinaryOperator::AndAssign: + DISPATCH(BinAndAssign, CompoundAssignOperator); + case BinaryOperator::OrAssign: + DISPATCH(BinOrAssign, CompoundAssignOperator); + case BinaryOperator::XorAssign: + DISPATCH(BinXorAssign, CompoundAssignOperator); + case BinaryOperator::Comma: DISPATCH(BinComma, BinaryOperator); + } + } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { + switch (UnOp->getOpcode()) { + default: assert(0 && "Unknown unary operator!"); + case UnaryOperator::PostInc: DISPATCH(UnaryPostInc, UnaryOperator); + case UnaryOperator::PostDec: DISPATCH(UnaryPostDec, UnaryOperator); + case UnaryOperator::PreInc: DISPATCH(UnaryPreInc, UnaryOperator); + case UnaryOperator::PreDec: DISPATCH(UnaryPreDec, UnaryOperator); + case UnaryOperator::AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator); + case UnaryOperator::Deref: DISPATCH(UnaryDeref, UnaryOperator); + case UnaryOperator::Plus: DISPATCH(UnaryPlus, UnaryOperator); + case UnaryOperator::Minus: DISPATCH(UnaryMinus, UnaryOperator); + case UnaryOperator::Not: DISPATCH(UnaryNot, UnaryOperator); + case UnaryOperator::LNot: DISPATCH(UnaryLNot, UnaryOperator); + case UnaryOperator::Real: DISPATCH(UnaryReal, UnaryOperator); + case UnaryOperator::Imag: DISPATCH(UnaryImag, UnaryOperator); + case UnaryOperator::Extension: DISPATCH(UnaryExtension, UnaryOperator); + case UnaryOperator::OffsetOf: DISPATCH(UnaryOffsetOf, UnaryOperator); + } + } + + // Top switch stmt: dispatch to VisitFooStmt for each FooStmt. + switch (S->getStmtClass()) { + default: assert(0 && "Unknown stmt kind!"); +#define STMT(CLASS, PARENT) \ + case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS); +#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) \ + RetTy Visit ## CLASS(CLASS *S) { DISPATCH(PARENT, PARENT); } +#include "clang/AST/StmtNodes.def" + + // If the implementation doesn't implement binary operator methods, fall back + // on VisitBinaryOperator. +#define BINOP_FALLBACK(NAME) \ + RetTy VisitBin ## NAME(BinaryOperator *S) { \ + DISPATCH(BinaryOperator, BinaryOperator); \ + } + BINOP_FALLBACK(PtrMemD) BINOP_FALLBACK(PtrMemI) + 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) + BINOP_FALLBACK(LAnd) BINOP_FALLBACK(LOr) + + BINOP_FALLBACK(Assign) + BINOP_FALLBACK(Comma) +#undef BINOP_FALLBACK + + // If the implementation doesn't implement compound assignment operator + // methods, fall back on VisitCompoundAssignOperator. +#define CAO_FALLBACK(NAME) \ + RetTy VisitBin ## NAME(CompoundAssignOperator *S) { \ + DISPATCH(CompoundAssignOperator, CompoundAssignOperator); \ + } + CAO_FALLBACK(MulAssign) CAO_FALLBACK(DivAssign) CAO_FALLBACK(RemAssign) + CAO_FALLBACK(AddAssign) CAO_FALLBACK(SubAssign) CAO_FALLBACK(ShlAssign) + 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) \ + RetTy VisitUnary ## NAME(UnaryOperator *S) { \ + DISPATCH(UnaryOperator, UnaryOperator); \ + } + 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(); } +}; + +#undef DISPATCH + +} // end namespace clang + +#endif diff --git a/include/clang/AST/TargetBuiltins.h b/include/clang/AST/TargetBuiltins.h new file mode 100644 index 000000000000..d425a9b8ecad --- /dev/null +++ b/include/clang/AST/TargetBuiltins.h @@ -0,0 +1,38 @@ +//===--- TargetBuiltins.h - Target specific builtin IDs -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_TARGET_BUILTINS_H +#define LLVM_CLANG_AST_TARGET_BUILTINS_H + +#include "clang/AST/Builtins.h" +#undef PPC + +namespace clang { + /// X86 builtins + namespace X86 { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "X86Builtins.def" + LastTSBuiltin + }; + } + + /// PPC builtins + namespace PPC { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "PPCBuiltins.def" + LastTSBuiltin + }; + } +} // end namespace clang. + +#endif diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h new file mode 100644 index 000000000000..511934c1dbf5 --- /dev/null +++ b/include/clang/AST/TemplateName.h @@ -0,0 +1,258 @@ +//===--- TemplateName.h - C++ Template Name 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 TemplateName interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_TEMPLATENAME_H +#define LLVM_CLANG_AST_TEMPLATENAME_H + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerUnion.h" + +namespace llvm { + class raw_ostream; +} + +namespace clang { + +class DependentTemplateName; +class IdentifierInfo; +class NestedNameSpecifier; +class PrintingPolicy; +class QualifiedTemplateName; +class TemplateDecl; + +/// \brief Represents a C++ template name within the type system. +/// +/// A C++ template name refers to a template within the C++ type +/// system. In most cases, a template name is simply a reference to a +/// class template, e.g. +/// +/// \code +/// template<typename T> class X { }; +/// +/// X<int> xi; +/// \endcode +/// +/// Here, the 'X' in \c X<int> is a template name that refers to the +/// declaration of the class template X, above. Template names can +/// also refer to function templates, C++0x template aliases, etc. +/// +/// Some template names are dependent. For example, consider: +/// +/// \code +/// template<typename MetaFun, typename T1, typename T2> struct apply2 { +/// typedef typename MetaFun::template apply<T1, T2>::type type; +/// }; +/// \endcode +/// +/// Here, "apply" is treated as a template name within the typename +/// 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 *, + DependentTemplateName *> StorageType; + + StorageType Storage; + + explicit TemplateName(void *Ptr) { + Storage = StorageType::getFromOpaqueValue(Ptr); + } + +public: + TemplateName() : Storage() { } + explicit TemplateName(TemplateDecl *Template) : Storage(Template) { } + explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { } + explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { } + + /// \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. + TemplateDecl *getAsTemplateDecl() const; + + /// \brief Retrieve the underlying qualified template name + /// structure, if any. + QualifiedTemplateName *getAsQualifiedTemplateName() const { + return Storage.dyn_cast<QualifiedTemplateName *>(); + } + + /// \brief Retrieve the underlying dependent template name + /// structure, if any. + DependentTemplateName *getAsDependentTemplateName() const { + return Storage.dyn_cast<DependentTemplateName *>(); + } + + /// \brief Determines whether this is a dependent template name. + bool isDependent() const; + + /// \brief Print the template name. + /// + /// \param OS the output stream to which the template name will be + /// printed. + /// + /// \param SuppressNNS if true, don't print the + /// nested-name-specifier that precedes the template name (if it has + /// one). + void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy, + bool SuppressNNS = false) const; + + /// \brief Debugging aid that dumps the template name to standard + /// error. + void dump() const; + + void Profile(llvm::FoldingSetNodeID &ID) { + ID.AddPointer(Storage.getOpaqueValue()); + } + + /// \brief Retrieve the template name as a void pointer. + void *getAsVoidPointer() const { return Storage.getOpaqueValue(); } + + /// \brief Build a template name from a void pointer. + static TemplateName getFromVoidPointer(void *Ptr) { + return TemplateName(Ptr); + } +}; + +/// \brief Represents a template name that was expressed as a +/// qualified name. +/// +/// This kind of template name refers to a template name that was +/// preceded by a nested name specifier, e.g., \c std::vector. Here, +/// the nested name specifier is "std::" and the template name is the +/// declaration for "vector". The QualifiedTemplateName class is only +/// used to provide "sugar" for template names that were expressed +/// with a qualified name, and has no semantic meaning. In this +/// manner, it is to TemplateName what QualifiedNameType is to Type, +/// providing extra syntactic sugar for downstream clients. +class QualifiedTemplateName : public llvm::FoldingSetNode { + /// \brief The nested name specifier that qualifies the template name. + /// + /// The bit is used to indicate whether the "template" keyword was + /// present before the template name itself. Note that the + /// "template" keyword is always redundant in this case (otherwise, + /// the template name would be a dependent name and we would express + /// this name with DependentTemplateName). + llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier; + + /// \brief The template declaration that this qualified name refers + /// to. + TemplateDecl *Template; + + friend class ASTContext; + + QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, + TemplateDecl *Template) + : Qualifier(NNS, TemplateKeyword? 1 : 0), Template(Template) { } + +public: + /// \brief Return the nested name specifier that qualifies this name. + NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); } + + /// \brief Whether the template name was prefixed by the "template" + /// keyword. + bool hasTemplateKeyword() const { return Qualifier.getInt(); } + + /// \brief The template declaration to which this qualified name + /// refers. + TemplateDecl *getTemplateDecl() const { return Template; } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, + bool TemplateKeyword, TemplateDecl *Template) { + ID.AddPointer(NNS); + ID.AddBoolean(TemplateKeyword); + ID.AddPointer(Template); + } +}; + +/// \brief Represents a dependent template name that cannot be +/// resolved prior to template instantiation. +/// +/// This kind of template name refers to a dependent template name, +/// including its nested name specifier. 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. +class DependentTemplateName : public llvm::FoldingSetNode { + /// \brief The nested name specifier that qualifies the template + /// name. + NestedNameSpecifier *Qualifier; + + /// \brief The dependent template name. + const IdentifierInfo *Name; + + /// \brief The canonical template name to which this dependent + /// template name refers. + /// + /// The canonical template name for a dependent template name is + /// another dependent template name whose nested name specifier is + /// canonical. + TemplateName CanonicalTemplateName; + + friend class ASTContext; + + DependentTemplateName(NestedNameSpecifier *Qualifier, + const IdentifierInfo *Name) + : Qualifier(Qualifier), Name(Name), CanonicalTemplateName(this) { } + + DependentTemplateName(NestedNameSpecifier *Qualifier, + const IdentifierInfo *Name, + TemplateName Canon) + : Qualifier(Qualifier), Name(Name), CanonicalTemplateName(Canon) { } + +public: + /// \brief Return the nested name specifier that qualifies this name. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + /// \brief Return the name to which this dependent template name + /// refers. + const IdentifierInfo *getName() const { return Name; } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getQualifier(), getName()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, + const IdentifierInfo *Name) { + ID.AddPointer(NNS); + ID.AddPointer(Name); + } +}; + +} // end namespace clang. + +namespace llvm { + +/// \brief The clang::TemplateName class is effectively a pointer. +template<> +class PointerLikeTypeTraits<clang::TemplateName> { +public: + static inline void *getAsVoidPointer(clang::TemplateName TN) { + return TN.getAsVoidPointer(); + } + + static inline clang::TemplateName getFromVoidPointer(void *Ptr) { + return clang::TemplateName::getFromVoidPointer(Ptr); + } + + // No bits are available! + enum { NumLowBitsAvailable = 0 }; +}; + +} // end namespace llvm. + +#endif diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h new file mode 100644 index 000000000000..1b012385c9f2 --- /dev/null +++ b/include/clang/AST/Type.h @@ -0,0 +1,1977 @@ +//===--- Type.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 Type interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_TYPE_H +#define LLVM_CLANG_AST_TYPE_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/TemplateName.h" +#include "llvm/Support/Casting.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" + +using llvm::isa; +using llvm::cast; +using llvm::cast_or_null; +using llvm::dyn_cast; +using llvm::dyn_cast_or_null; +namespace clang { class Type; } + +namespace llvm { + template <typename T> + class PointerLikeTypeTraits; + template<> + class PointerLikeTypeTraits< ::clang::Type*> { + public: + static inline void *getAsVoidPointer(::clang::Type *P) { return P; } + static inline ::clang::Type *getFromVoidPointer(void *P) { + return static_cast< ::clang::Type*>(P); + } + enum { NumLowBitsAvailable = 3 }; + }; +} + +namespace clang { + class ASTContext; + class TypedefDecl; + class TemplateDecl; + class TemplateTypeParmDecl; + class NonTypeTemplateParmDecl; + class TemplateTemplateParmDecl; + class TagDecl; + class RecordDecl; + class CXXRecordDecl; + class EnumDecl; + class FieldDecl; + class ObjCInterfaceDecl; + class ObjCProtocolDecl; + class ObjCMethodDecl; + class Expr; + class Stmt; + class SourceLocation; + class StmtIteratorBase; + class TemplateArgument; + class QualifiedNameType; + class 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; +public: + enum TQ { // NOTE: These flags must be kept in sync with DeclSpec::TQ. + Const = 0x1, + Restrict = 0x2, + Volatile = 0x4, + CVRFlags = Const|Restrict|Volatile + }; + + enum GCAttrTypes { + GCNone = 0, + Weak, + Strong + }; + + QualType() {} + + QualType(const Type *Ptr, unsigned Quals) + : Value(const_cast<Type*>(Ptr), Quals) {} + + 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(); + } + + Type *operator->() const { + return getTypePtr(); + } + + /// isNull - Return true if this QualType doesn't point to a type yet. + bool isNull() const { + return getTypePtr() == 0; + } + + bool isConstQualified() const { + return (getCVRQualifiers() & Const) ? true : false; + } + bool isVolatileQualified() const { + return (getCVRQualifiers() & Volatile) ? true : false; + } + bool isRestrictQualified() const { + return (getCVRQualifiers() & Restrict) ? true : false; + } + + 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); } + + void removeConst() { Value.setInt(Value.getInt() & ~Const); } + void removeVolatile() { Value.setInt(Value.getInt() & ~Volatile); } + void removeRestrict() { Value.setInt(Value.getInt() & ~Restrict); } + + QualType getQualifiedType(unsigned TQs) const { + return QualType(getTypePtr(), TQs); + } + QualType getWithAdditionalQualifiers(unsigned TQs) const { + return QualType(getTypePtr(), TQs|getCVRQualifiers()); + } + + QualType withConst() const { return getWithAdditionalQualifiers(Const); } + QualType withVolatile() const { return getWithAdditionalQualifiers(Volatile);} + QualType withRestrict() const { return getWithAdditionalQualifiers(Restrict);} + + QualType getUnqualifiedType() const; + 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; + + /// operator==/!= - Indicate whether the specified types and qualifiers are + /// identical. + bool operator==(const QualType &RHS) const { + return Value == RHS.Value; + } + bool operator!=(const QualType &RHS) const { + return Value != RHS.Value; + } + std::string getAsString() const; + + std::string getAsString(const PrintingPolicy &Policy) const { + std::string S; + getAsStringInternal(S, Policy); + return S; + } + 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; + + /// isObjCGCWeak true when Type is objc's weak. + bool isObjCGCWeak() const { + return getObjCGCAttr() == Weak; + } + + /// isObjCGCStrong true when Type is objc's strong. + bool isObjCGCStrong() const { + return getObjCGCAttr() == Strong; + } +}; + +} // end clang. + +namespace llvm { +/// Implement simplify_type for QualType, so that we can dyn_cast from QualType +/// to a specific Type class. +template<> struct simplify_type<const ::clang::QualType> { + typedef ::clang::Type* SimpleType; + static SimpleType getSimplifiedValue(const ::clang::QualType &Val) { + return Val.getTypePtr(); + } +}; +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> { +public: + static inline void *getAsVoidPointer(clang::QualType P) { + return P.getAsOpaquePtr(); + } + static inline clang::QualType getFromVoidPointer(void *P) { + return clang::QualType::getFromOpaquePtr(P); + } + // CVR qualifiers go in low bits. + enum { NumLowBitsAvailable = 0 }; +}; +} // end namespace llvm + +namespace clang { + +/// Type - This is the base class of the type hierarchy. A central concept +/// with types is that each type always has a canonical type. A canonical type +/// is the type with any typedef names stripped out of it or the types it +/// references. For example, consider: +/// +/// typedef int foo; +/// typedef foo* bar; +/// 'int *' 'foo *' 'bar' +/// +/// There will be a Type object created for 'int'. Since int is canonical, its +/// canonicaltype pointer points to itself. There is also a Type for 'foo' (a +/// TypedefType). Its CanonicalType pointer points to the 'int' Type. Next +/// there is a PointerType that represents 'int*', which, like 'int', is +/// canonical. Finally, there is a PointerType type for 'foo*' whose canonical +/// type is 'int*', and there is a TypedefType for 'bar', whose canonical type +/// is also 'int*'. +/// +/// Non-canonical types are useful for emitting diagnostics, without losing +/// information about typedefs being used. Canonical types are useful for type +/// comparisons (they allow by-pointer equality tests) and useful for reasoning +/// about whether something has a particular form (e.g. is a function type), +/// because they implicitly, recursively, strip all typedefs out of a type. +/// +/// Types, once created, are immutable. +/// +class Type { +public: + enum TypeClass { +#define TYPE(Class, Base) Class, +#define ABSTRACT_TYPE(Class, Base) +#include "clang/AST/TypeNodes.def" + TagFirst = Record, TagLast = Enum + }; + +private: + QualType CanonicalType; + + /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]). + bool Dependent : 1; + + /// 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; + + Type(const Type&); // DO NOT IMPLEMENT. + void operator=(const Type&); // DO NOT IMPLEMENT. +protected: + // silence VC++ warning C4355: 'this' : used in base member initializer list + Type *this_() { return this; } + Type(TypeClass tc, QualType Canonical, bool dependent) + : CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical), + Dependent(dependent), TC(tc) {} + 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): + /// 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++ + /// definition of object type, which includes incomplete types, as + /// opposed to the C definition (which does not include incomplete + /// types). + bool isObjectType() const; + + /// 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. + bool isIncompleteType() const; + + /// isIncompleteOrObjectType - Return true if this is an incomplete or object + /// type, in other words, not a function type. + bool isIncompleteOrObjectType() const { + return !isFunctionType(); + } + + /// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10). + bool isPODType() const; + + /// 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) + bool isEnumeralType() const; + bool isBooleanType() const; + 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). + /// isComplexIntegerType() can be used to test for complex integers. + bool isComplexType() const; // C99 6.2.5p11 (complex) + bool isAnyComplexType() const; // C99 6.2.5p11 (complex) + Complex Int. + bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex) + bool isRealType() const; // C99 6.2.5p17 (real floating + integer) + bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating) + bool isVoidType() const; // C99 6.2.5p19 + 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 isPointerType() const; + bool isBlockPointerType() const; + bool isReferenceType() const; + bool isLValueReferenceType() const; + bool isRValueReferenceType() const; + bool isFunctionPointerType() const; + bool isMemberPointerType() const; + bool isMemberFunctionPointerType() const; + bool isArrayType() const; + bool isConstantArrayType() const; + bool isIncompleteArrayType() const; + bool isVariableArrayType() const; + bool isDependentSizedArrayType() const; + bool isRecordType() 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 isObjCInterfaceType() const; // NSString or NSString<foo> + bool isObjCQualifiedInterfaceType() const; // NSString<foo> + bool isObjCQualifiedIdType() const; // id<foo> + 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 + /// (C++ [temp.dep.type]). + bool isDependentType() const { return Dependent; } + bool isOverloadableType() const; + + /// hasPointerRepresentation - Whether this type is represented + /// natively as a pointer; this includes pointers, references, block + /// pointers, and Objective-C interface, qualified id, and qualified + /// interface types, as well as nullptr_t. + bool hasPointerRepresentation() const; + + /// hasObjCPointerRepresentation - Whether this type can represent + /// an objective pointer type for the purpose of GC'ability + 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 ObjCInterfaceType *getAsObjCInterfaceType() const; + const ObjCQualifiedInterfaceType *getAsObjCQualifiedInterfaceType() const; + const ObjCQualifiedIdType *getAsObjCQualifiedIdType() const; + const TemplateTypeParmType *getAsTemplateTypeParmType() 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; + + /// getArrayElementTypeNoTypeQual - If this is an array type, return the + /// 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; + + /// More type predicates useful for type checking/promotion + bool isPromotableIntegerType() const; // C99 6.3.1.1p2 + + /// isSignedIntegerType - Return true if this is an integer type that is + /// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..], + /// an enum decl which has a signed representation, or a vector of signed + /// integer element type. + bool isSignedIntegerType() const; + + /// isUnsignedIntegerType - Return true if this is an integer type that is + /// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], an enum + /// decl which has an unsigned representation, or a vector of unsigned integer + /// element type. + bool isUnsignedIntegerType() const; + + /// isConstantSizeType - Return true if this is not a variable sized type, + /// according to the rules of C99 6.7.5p3. It is not legal to call this on + /// incomplete types. + bool isConstantSizeType() const; + + /// isSpecifierType - Returns true if this type can be represented by some + /// set of type specifiers. + bool isSpecifierType() const; + + QualType getCanonicalTypeInternal() const { return CanonicalType; } + void dump() const; + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const = 0; + static bool classof(const Type *) { return true; } +}; + +/// ExtQualType - TR18037 (C embedded extensions) 6.2.5p26 +/// This supports all kinds of type attributes; including, +/// address space qualified types, objective-c's __weak and +/// __strong attributes. +/// +class ExtQualType : public Type, public llvm::FoldingSetNode { + /// BaseType - This is the underlying type that this qualifies. All CVR + /// qualifiers are stored on the QualType that references this type, so we + /// can't have any here. + Type *BaseType; + + /// Address Space ID - The address space ID this type is qualified with. + unsigned AddressSpace; + /// GC __weak/__strong attributes + QualType::GCAttrTypes GCAttrType; + + ExtQualType(Type *Base, QualType CanonicalPtr, unsigned AddrSpace, + QualType::GCAttrTypes gcAttr) : + Type(ExtQual, CanonicalPtr, Base->isDependentType()), BaseType(Base), + AddressSpace(AddrSpace), GCAttrType(gcAttr) { + assert(!isa<ExtQualType>(BaseType) && + "Cannot have ExtQualType of ExtQualType"); + } + friend class ASTContext; // ASTContext creates these. +public: + Type *getBaseType() const { return BaseType; } + QualType::GCAttrTypes getObjCGCAttr() const { return GCAttrType; } + unsigned getAddressSpace() const { return AddressSpace; } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getBaseType(), AddressSpace, GCAttrType); + } + static void Profile(llvm::FoldingSetNodeID &ID, Type *Base, + unsigned AddrSpace, QualType::GCAttrTypes gcAttr) { + ID.AddPointer(Base); + ID.AddInteger(AddrSpace); + ID.AddInteger(gcAttr); + } + + static bool classof(const Type *T) { return T->getTypeClass() == ExtQual; } + static bool classof(const ExtQualType *) { return true; } +}; + + +/// BuiltinType - This class is used for builtin types like 'int'. Builtin +/// types are always canonical and have a literal name field. +class BuiltinType : public Type { +public: + enum Kind { + Void, + + Bool, // This is bool and/or _Bool. + Char_U, // This is 'char' for targets where char is unsigned. + UChar, // This is explicitly qualified unsigned char. + UShort, + UInt, + ULong, + ULongLong, + UInt128, // __uint128_t + + Char_S, // This is 'char' for targets where char is signed. + SChar, // This is explicitly qualified signed char. + WChar, // This is 'wchar_t' for C++. + Short, + Int, + Long, + LongLong, + Int128, // __int128_t + + Float, Double, LongDouble, + + NullPtr, // This is the type of C++0x 'nullptr'. + + Overload, // This represents the type of an overloaded function declaration. + Dependent // This represents the type of a type-dependent expression. + }; +private: + Kind TypeKind; +public: + BuiltinType(Kind K) + : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent)), + TypeKind(K) {} + + Kind getKind() const { return TypeKind; } + const char *getName(bool CPlusPlus) const; + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { return T->getTypeClass() == Builtin; } + static bool classof(const BuiltinType *) { return true; } +}; + +/// FixedWidthIntType - Used for arbitrary width types that we either don't +/// want to or can't map to named integer types. These always have a lower +/// integer rank than builtin types of the same width. +class FixedWidthIntType : public Type { +private: + unsigned Width; + bool Signed; +public: + FixedWidthIntType(unsigned W, bool S) : Type(FixedWidthInt, QualType(), false), + Width(W), Signed(S) {} + + unsigned getWidth() const { return Width; } + bool isSigned() const { return Signed; } + const char *getName() const; + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { return T->getTypeClass() == FixedWidthInt; } + static bool classof(const FixedWidthIntType *) { return true; } +}; + +/// ComplexType - C99 6.2.5p11 - Complex values. This supports the C99 complex +/// types (_Complex float etc) as well as the GCC integer complex extensions. +/// +class ComplexType : public Type, public llvm::FoldingSetNode { + QualType ElementType; + ComplexType(QualType Element, QualType CanonicalPtr) : + Type(Complex, CanonicalPtr, Element->isDependentType()), + ElementType(Element) { + } + friend class ASTContext; // ASTContext creates these. +public: + QualType getElementType() const { return ElementType; } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getElementType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Element) { + ID.AddPointer(Element.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { return T->getTypeClass() == Complex; } + static bool classof(const ComplexType *) { return true; } +}; + +/// PointerType - C99 6.7.5.1 - Pointer Declarators. +/// +class PointerType : public Type, public llvm::FoldingSetNode { + QualType PointeeType; + + PointerType(QualType Pointee, QualType CanonicalPtr) : + Type(Pointer, CanonicalPtr, Pointee->isDependentType()), PointeeType(Pointee) { + } + friend class ASTContext; // ASTContext creates these. +public: + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + QualType getPointeeType() const { return PointeeType; } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getPointeeType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) { + ID.AddPointer(Pointee.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { return T->getTypeClass() == Pointer; } + static bool classof(const PointerType *) { return true; } +}; + +/// BlockPointerType - pointer to a block type. +/// This type is to represent types syntactically represented as +/// "void (^)(int)", etc. Pointee is required to always be a function type. +/// +class BlockPointerType : public Type, public llvm::FoldingSetNode { + QualType PointeeType; // Block is some kind of pointer type + BlockPointerType(QualType Pointee, QualType CanonicalCls) : + Type(BlockPointer, CanonicalCls, Pointee->isDependentType()), + PointeeType(Pointee) { + } + friend class ASTContext; // ASTContext creates these. +public: + + // Get the pointee type. Pointee is required to always be a function type. + QualType getPointeeType() const { return PointeeType; } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getPointeeType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) { + ID.AddPointer(Pointee.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == BlockPointer; + } + static bool classof(const BlockPointerType *) { return true; } +}; + +/// ReferenceType - Base for LValueReferenceType and RValueReferenceType +/// +class ReferenceType : public Type, public llvm::FoldingSetNode { + QualType PointeeType; + +protected: + ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef) : + Type(tc, CanonicalRef, Referencee->isDependentType()), + PointeeType(Referencee) { + } +public: + QualType getPointeeType() const { return PointeeType; } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getPointeeType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Referencee) { + ID.AddPointer(Referencee.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == LValueReference || + T->getTypeClass() == RValueReference; + } + static bool classof(const ReferenceType *) { return true; } +}; + +/// LValueReferenceType - C++ [dcl.ref] - Lvalue reference +/// +class LValueReferenceType : public ReferenceType { + LValueReferenceType(QualType Referencee, QualType CanonicalRef) : + ReferenceType(LValueReference, Referencee, CanonicalRef) { + } + friend class ASTContext; // ASTContext creates these +public: + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { + return T->getTypeClass() == LValueReference; + } + static bool classof(const LValueReferenceType *) { return true; } +}; + +/// RValueReferenceType - C++0x [dcl.ref] - Rvalue reference +/// +class RValueReferenceType : public ReferenceType { + RValueReferenceType(QualType Referencee, QualType CanonicalRef) : + ReferenceType(RValueReference, Referencee, CanonicalRef) { + } + friend class ASTContext; // ASTContext creates these +public: + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { + return T->getTypeClass() == RValueReference; + } + static bool classof(const RValueReferenceType *) { return true; } +}; + +/// MemberPointerType - C++ 8.3.3 - Pointers to members +/// +class MemberPointerType : public Type, public llvm::FoldingSetNode { + QualType PointeeType; + /// The class of which the pointee is a member. Must ultimately be a + /// RecordType, but could be a typedef or a template parameter too. + const Type *Class; + + MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) : + Type(MemberPointer, CanonicalPtr, + Cls->isDependentType() || Pointee->isDependentType()), + PointeeType(Pointee), Class(Cls) { + } + friend class ASTContext; // ASTContext creates these. +public: + + QualType getPointeeType() const { return PointeeType; } + + const Type *getClass() const { return Class; } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getPointeeType(), getClass()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee, + const Type *Class) { + ID.AddPointer(Pointee.getAsOpaquePtr()); + ID.AddPointer(Class); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == MemberPointer; + } + static bool classof(const MemberPointerType *) { return true; } +}; + +/// ArrayType - C99 6.7.5.2 - Array Declarators. +/// +class ArrayType : public Type, public llvm::FoldingSetNode { +public: + /// ArraySizeModifier - Capture whether this is a normal array (e.g. int X[4]) + /// an array with a static size (e.g. int X[static 4]), or an array + /// with a star size (e.g. int X[*]). + /// 'static' is only allowed on function parameters. + enum ArraySizeModifier { + Normal, Static, Star + }; +private: + /// ElementType - The element type of the array. + QualType ElementType; + + // NOTE: VC++ treats enums as signed, avoid using the ArraySizeModifier enum + /// NOTE: These fields are packed into the bitfields space in the Type class. + unsigned SizeModifier : 2; + + /// IndexTypeQuals - Capture qualifiers in declarations like: + /// 'int X[static restrict 4]'. For function parameters only. + unsigned IndexTypeQuals : 3; + +protected: + // C++ [temp.dep.type]p1: + // A type is dependent if it is... + // - an array type constructed from any dependent type or whose + // size is specified by a constant expression that is + // value-dependent, + ArrayType(TypeClass tc, QualType et, QualType can, + ArraySizeModifier sm, unsigned tq) + : Type(tc, can, et->isDependentType() || tc == DependentSizedArray), + ElementType(et), SizeModifier(sm), IndexTypeQuals(tq) {} + + friend class ASTContext; // ASTContext creates these. +public: + QualType getElementType() const { return ElementType; } + ArraySizeModifier getSizeModifier() const { + return ArraySizeModifier(SizeModifier); + } + unsigned getIndexTypeQualifier() const { return IndexTypeQuals; } + + static bool classof(const Type *T) { + return T->getTypeClass() == ConstantArray || + T->getTypeClass() == VariableArray || + T->getTypeClass() == IncompleteArray || + T->getTypeClass() == DependentSizedArray; + } + static bool classof(const ArrayType *) { return true; } +}; + +/// ConstantArrayType - This class represents C arrays with a specified constant +/// size. For example 'int A[100]' has ConstantArrayType where the element type +/// is 'int' and the size is 100. +class ConstantArrayType : public ArrayType { + llvm::APInt Size; // Allows us to unique the type. + + ConstantArrayType(QualType et, QualType can, const llvm::APInt &size, + ArraySizeModifier sm, unsigned tq) + : ArrayType(ConstantArray, et, can, sm, tq), Size(size) {} + friend class ASTContext; // ASTContext creates these. +public: + const llvm::APInt &getSize() const { return Size; } + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getElementType(), getSize(), + getSizeModifier(), getIndexTypeQualifier()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType ET, + const llvm::APInt &ArraySize, ArraySizeModifier SizeMod, + unsigned TypeQuals) { + ID.AddPointer(ET.getAsOpaquePtr()); + ID.AddInteger(ArraySize.getZExtValue()); + ID.AddInteger(SizeMod); + ID.AddInteger(TypeQuals); + } + static bool classof(const Type *T) { + return T->getTypeClass() == ConstantArray; + } + static bool classof(const ConstantArrayType *) { return true; } +}; + +/// IncompleteArrayType - This class represents C arrays with an unspecified +/// size. For example 'int A[]' has an IncompleteArrayType where the element +/// type is 'int' and the size is unspecified. +class IncompleteArrayType : public ArrayType { + IncompleteArrayType(QualType et, QualType can, + ArraySizeModifier sm, unsigned tq) + : ArrayType(IncompleteArray, et, can, sm, tq) {} + friend class ASTContext; // ASTContext creates these. +public: + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { + return T->getTypeClass() == IncompleteArray; + } + static bool classof(const IncompleteArrayType *) { return true; } + + friend class StmtIteratorBase; + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getElementType(), getSizeModifier(), getIndexTypeQualifier()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, QualType ET, + ArraySizeModifier SizeMod, unsigned TypeQuals) { + ID.AddPointer(ET.getAsOpaquePtr()); + ID.AddInteger(SizeMod); + ID.AddInteger(TypeQuals); + } +}; + +/// VariableArrayType - This class represents C arrays with a specified size +/// which is not an integer-constant-expression. For example, 'int s[x+foo()]'. +/// Since the size expression is an arbitrary expression, we store it as such. +/// +/// Note: VariableArrayType's aren't uniqued (since the expressions aren't) and +/// should not be: two lexically equivalent variable array types could mean +/// different things, for example, these variables do not have the same type +/// dynamically: +/// +/// void foo(int x) { +/// int Y[x]; +/// ++x; +/// int Z[x]; +/// } +/// +class VariableArrayType : public ArrayType { + /// SizeExpr - An assignment expression. VLA's are only permitted within + /// a function block. + Stmt *SizeExpr; + + VariableArrayType(QualType et, QualType can, Expr *e, + ArraySizeModifier sm, unsigned tq) + : ArrayType(VariableArray, et, can, sm, tq), SizeExpr((Stmt*) e) {} + friend class ASTContext; // ASTContext creates these. + virtual void Destroy(ASTContext& C); + +public: + Expr *getSizeExpr() const { + // We use C-style casts instead of cast<> here because we do not wish + // to have a dependency of Type.h on Stmt.h/Expr.h. + return (Expr*) SizeExpr; + } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { + return T->getTypeClass() == VariableArray; + } + static bool classof(const VariableArrayType *) { return true; } + + friend class StmtIteratorBase; + + void Profile(llvm::FoldingSetNodeID &ID) { + assert(0 && "Cannnot unique VariableArrayTypes."); + } +}; + +/// DependentSizedArrayType - This type represents an array type in +/// C++ whose size is a value-dependent expression. For example: +/// @code +/// template<typename T, int Size> +/// class array { +/// T data[Size]; +/// }; +/// @endcode +/// For these types, we won't actually know what the array bound is +/// until template instantiation occurs, at which point this will +/// become either a ConstantArrayType or a VariableArrayType. +class DependentSizedArrayType : public ArrayType { + /// SizeExpr - An assignment expression that will instantiate to the + /// size of the array. + Stmt *SizeExpr; + + DependentSizedArrayType(QualType et, QualType can, Expr *e, + ArraySizeModifier sm, unsigned tq) + : ArrayType(DependentSizedArray, et, can, sm, tq), SizeExpr((Stmt*) e) {} + friend class ASTContext; // ASTContext creates these. + virtual void Destroy(ASTContext& C); + +public: + Expr *getSizeExpr() const { + // We use C-style casts instead of cast<> here because we do not wish + // to have a dependency of Type.h on Stmt.h/Expr.h. + return (Expr*) SizeExpr; + } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentSizedArray; + } + static bool classof(const DependentSizedArrayType *) { return true; } + + friend class StmtIteratorBase; + + void Profile(llvm::FoldingSetNodeID &ID) { + assert(0 && "Cannnot unique DependentSizedArrayTypes."); + } +}; + +/// VectorType - GCC generic vector type. This type is created using +/// __attribute__((vector_size(n)), where "n" specifies the vector size in +/// bytes. Since the constructor takes the number of vector elements, the +/// client is responsible for converting the size into the number of elements. +class VectorType : public Type, public llvm::FoldingSetNode { +protected: + /// ElementType - The element type of the vector. + QualType ElementType; + + /// NumElements - The number of elements in the vector. + unsigned NumElements; + + VectorType(QualType vecType, unsigned nElements, QualType canonType) : + Type(Vector, canonType, vecType->isDependentType()), + ElementType(vecType), NumElements(nElements) {} + VectorType(TypeClass tc, QualType vecType, unsigned nElements, + QualType canonType) + : Type(tc, canonType, vecType->isDependentType()), ElementType(vecType), + NumElements(nElements) {} + friend class ASTContext; // ASTContext creates these. +public: + + QualType getElementType() const { return ElementType; } + unsigned getNumElements() const { return NumElements; } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getElementType(), getNumElements(), getTypeClass()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType, + unsigned NumElements, TypeClass TypeClass) { + ID.AddPointer(ElementType.getAsOpaquePtr()); + ID.AddInteger(NumElements); + ID.AddInteger(TypeClass); + } + static bool classof(const Type *T) { + return T->getTypeClass() == Vector || T->getTypeClass() == ExtVector; + } + static bool classof(const VectorType *) { return true; } +}; + +/// ExtVectorType - Extended vector type. This type is created using +/// __attribute__((ext_vector_type(n)), where "n" is the number of elements. +/// Unlike vector_size, ext_vector_type is only allowed on typedef's. This +/// class enables syntactic extensions, like Vector Components for accessing +/// points, colors, and textures (modeled after OpenGL Shading Language). +class ExtVectorType : public VectorType { + ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) : + VectorType(ExtVector, vecType, nElements, canonType) {} + friend class ASTContext; // ASTContext creates these. +public: + static int getPointAccessorIdx(char c) { + switch (c) { + default: return -1; + case 'x': return 0; + case 'y': return 1; + case 'z': return 2; + case 'w': return 3; + } + } + static int getNumericAccessorIdx(char c) { + switch (c) { + default: return -1; + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'a': return 10; + case 'b': return 11; + case 'c': return 12; + case 'd': return 13; + case 'e': return 14; + case 'f': return 15; + } + } + + static int getAccessorIdx(char c) { + if (int idx = getPointAccessorIdx(c)+1) return idx-1; + return getNumericAccessorIdx(c); + } + + bool isAccessorWithinNumElements(char c) const { + if (int idx = getAccessorIdx(c)+1) + return unsigned(idx-1) < NumElements; + return false; + } + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { + return T->getTypeClass() == ExtVector; + } + static bool classof(const ExtVectorType *) { return true; } +}; + +/// FunctionType - C99 6.7.5.3 - Function Declarators. This is the common base +/// class of FunctionNoProtoType and FunctionProtoType. +/// +class FunctionType : public Type { + /// SubClassData - This field is owned by the subclass, put here to pack + /// tightly with the ivars in Type. + bool SubClassData : 1; + + /// TypeQuals - Used only by FunctionProtoType, put here to pack with the + /// other bitfields. + /// The qualifiers are part of FunctionProtoType because... + /// + /// C++ 8.3.5p4: The return type, the parameter type list and the + /// cv-qualifier-seq, [...], are part of the function type. + /// + unsigned TypeQuals : 3; + + // The type returned by the function. + QualType ResultType; +protected: + FunctionType(TypeClass tc, QualType res, bool SubclassInfo, + unsigned typeQuals, QualType Canonical, bool Dependent) + : Type(tc, Canonical, Dependent), + SubClassData(SubclassInfo), TypeQuals(typeQuals), ResultType(res) {} + bool getSubClassData() const { return SubClassData; } + unsigned getTypeQuals() const { return TypeQuals; } +public: + + QualType getResultType() const { return ResultType; } + + + static bool classof(const Type *T) { + return T->getTypeClass() == FunctionNoProto || + T->getTypeClass() == FunctionProto; + } + static bool classof(const FunctionType *) { return true; } +}; + +/// FunctionNoProtoType - Represents a K&R-style 'int foo()' function, which has +/// no information available about its arguments. +class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { + FunctionNoProtoType(QualType Result, QualType Canonical) + : FunctionType(FunctionNoProto, Result, false, 0, Canonical, + /*Dependent=*/false) {} + friend class ASTContext; // ASTContext creates these. +public: + // No additional state past what FunctionType provides. + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getResultType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType) { + ID.AddPointer(ResultType.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == FunctionNoProto; + } + static bool classof(const FunctionNoProtoType *) { return true; } +}; + +/// FunctionProtoType - Represents a prototype with argument type info, e.g. +/// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no +/// arguments, not as having a single void argument. Such a type can have an +/// exception specification, but this specification is not part of the canonical +/// type. +class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { + /// hasAnyDependentType - Determine whether there are any dependent + /// types within the arguments passed in. + static bool hasAnyDependentType(const QualType *ArgArray, unsigned numArgs) { + for (unsigned Idx = 0; Idx < numArgs; ++Idx) + if (ArgArray[Idx]->isDependentType()) + return true; + + return false; + } + + FunctionProtoType(QualType Result, const QualType *ArgArray, unsigned numArgs, + bool isVariadic, unsigned typeQuals, bool hasExs, + bool hasAnyExs, const QualType *ExArray, + unsigned numExs, QualType Canonical) + : FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical, + (Result->isDependentType() || + hasAnyDependentType(ArgArray, numArgs))), + NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs), + AnyExceptionSpec(hasAnyExs) { + // Fill in the trailing argument array. + QualType *ArgInfo = reinterpret_cast<QualType*>(this+1); + for (unsigned i = 0; i != numArgs; ++i) + ArgInfo[i] = ArgArray[i]; + // Fill in the exception array. + QualType *Ex = ArgInfo + numArgs; + for (unsigned i = 0; i != numExs; ++i) + Ex[i] = ExArray[i]; + } + + /// NumArgs - The number of arguments this function has, not counting '...'. + unsigned NumArgs : 20; + + /// NumExceptions - The number of types in the exception spec, if any. + unsigned NumExceptions : 10; + + /// HasExceptionSpec - Whether this function has an exception spec at all. + bool HasExceptionSpec : 1; + + /// AnyExceptionSpec - Whether this function has a throw(...) spec. + bool AnyExceptionSpec : 1; + + /// ArgInfo - There is an variable size array after the class in memory that + /// holds the argument types. + + /// Exceptions - There is another variable size array after ArgInfo that + /// holds the exception types. + + friend class ASTContext; // ASTContext creates these. + +public: + unsigned getNumArgs() const { return NumArgs; } + QualType getArgType(unsigned i) const { + assert(i < NumArgs && "Invalid argument number!"); + return arg_type_begin()[i]; + } + + bool hasExceptionSpec() const { return HasExceptionSpec; } + bool hasAnyExceptionSpec() const { return AnyExceptionSpec; } + unsigned getNumExceptions() const { return NumExceptions; } + QualType getExceptionType(unsigned i) const { + assert(i < NumExceptions && "Invalid exception number!"); + return exception_begin()[i]; + } + bool hasEmptyExceptionSpec() const { + return hasExceptionSpec() && !hasAnyExceptionSpec() && + getNumExceptions() == 0; + } + + bool isVariadic() const { return getSubClassData(); } + unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); } + + typedef const QualType *arg_type_iterator; + arg_type_iterator arg_type_begin() const { + return reinterpret_cast<const QualType *>(this+1); + } + arg_type_iterator arg_type_end() const { return arg_type_begin()+NumArgs; } + + typedef const QualType *exception_iterator; + exception_iterator exception_begin() const { + // exceptions begin where arguments end + return arg_type_end(); + } + exception_iterator exception_end() const { + return exception_begin() + NumExceptions; + } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { + return T->getTypeClass() == FunctionProto; + } + static bool classof(const FunctionProtoType *) { return true; } + + void Profile(llvm::FoldingSetNodeID &ID); + static void Profile(llvm::FoldingSetNodeID &ID, QualType Result, + arg_type_iterator ArgTys, unsigned NumArgs, + bool isVariadic, unsigned TypeQuals, + bool hasExceptionSpec, bool anyExceptionSpec, + unsigned NumExceptions, exception_iterator Exs); +}; + + +class TypedefType : public Type { + TypedefDecl *Decl; +protected: + TypedefType(TypeClass tc, TypedefDecl *D, QualType can) + : Type(tc, can, can->isDependentType()), Decl(D) { + assert(!isa<TypedefType>(can) && "Invalid canonical type"); + } + friend class ASTContext; // ASTContext creates these. +public: + + TypedefDecl *getDecl() const { return Decl; } + + /// LookThroughTypedefs - Return the ultimate type this typedef corresponds to + /// potentially looking through *all* consecutive typedefs. This returns the + /// sum of the type qualifiers, so if you have: + /// typedef const int A; + /// typedef volatile A B; + /// looking through the typedefs for B will give you "const volatile A". + QualType LookThroughTypedefs() const; + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { return T->getTypeClass() == Typedef; } + static bool classof(const TypedefType *) { return true; } +}; + +/// TypeOfExprType (GCC extension). +class TypeOfExprType : public Type { + Expr *TOExpr; + TypeOfExprType(Expr *E, QualType can); + friend class ASTContext; // ASTContext creates these. +public: + Expr *getUnderlyingExpr() const { return TOExpr; } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExpr; } + static bool classof(const TypeOfExprType *) { return true; } +}; + +/// TypeOfType (GCC extension). +class TypeOfType : public Type { + QualType TOType; + TypeOfType(QualType T, QualType can) + : Type(TypeOf, can, T->isDependentType()), TOType(T) { + assert(!isa<TypedefType>(can) && "Invalid canonical type"); + } + friend class ASTContext; // ASTContext creates these. +public: + QualType getUnderlyingType() const { return TOType; } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; } + static bool classof(const TypeOfType *) { return true; } +}; + +class TagType : public Type { + /// Stores the TagDecl associated with this type. The decl will + /// point to the TagDecl that actually defines the entity (or is a + /// definition in progress), if there is such a definition. The + /// single-bit value will be non-zero when this tag is in the + /// process of being defined. + mutable llvm::PointerIntPair<TagDecl *, 1> decl; + friend class ASTContext; + friend class TagDecl; + +protected: + TagType(TypeClass TC, TagDecl *D, QualType can); + +public: + TagDecl *getDecl() const { return decl.getPointer(); } + + /// @brief Determines whether this type is in the process of being + /// defined. + bool isBeingDefined() const { return decl.getInt(); } + void setBeingDefined(bool Def) { decl.setInt(Def? 1 : 0); } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { + return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast; + } + static bool classof(const TagType *) { return true; } + static bool classof(const RecordType *) { return true; } + static bool classof(const EnumType *) { return true; } +}; + +/// RecordType - This is a helper class that allows the use of isa/cast/dyncast +/// to detect TagType objects of structs/unions/classes. +class RecordType : public TagType { +protected: + explicit RecordType(RecordDecl *D) + : TagType(Record, reinterpret_cast<TagDecl*>(D), QualType()) { } + explicit RecordType(TypeClass TC, RecordDecl *D) + : TagType(TC, reinterpret_cast<TagDecl*>(D), QualType()) { } + friend class ASTContext; // ASTContext creates these. +public: + + RecordDecl *getDecl() const { + return reinterpret_cast<RecordDecl*>(TagType::getDecl()); + } + + // FIXME: This predicate is a helper to QualType/Type. It needs to + // recursively check all fields for const-ness. If any field is declared + // const, it needs to return false. + bool hasConstFields() const { return false; } + + // FIXME: RecordType needs to check when it is created that all fields are in + // the same address space, and return that. + unsigned getAddressSpace() const { return 0; } + + static bool classof(const TagType *T); + static bool classof(const Type *T) { + return isa<TagType>(T) && classof(cast<TagType>(T)); + } + static bool classof(const RecordType *) { return true; } +}; + +/// EnumType - This is a helper class that allows the use of isa/cast/dyncast +/// to detect TagType objects of enums. +class EnumType : public TagType { + explicit EnumType(EnumDecl *D) + : TagType(Enum, reinterpret_cast<TagDecl*>(D), QualType()) { } + friend class ASTContext; // ASTContext creates these. +public: + + EnumDecl *getDecl() const { + return reinterpret_cast<EnumDecl*>(TagType::getDecl()); + } + + static bool classof(const TagType *T); + static bool classof(const Type *T) { + return isa<TagType>(T) && classof(cast<TagType>(T)); + } + static bool classof(const EnumType *) { return true; } +}; + +class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { + unsigned Depth : 16; + unsigned Index : 16; + IdentifierInfo *Name; + + TemplateTypeParmType(unsigned D, unsigned I, IdentifierInfo *N, + QualType Canon) + : Type(TemplateTypeParm, Canon, /*Dependent=*/true), + Depth(D), Index(I), Name(N) { } + + TemplateTypeParmType(unsigned D, unsigned I) + : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true), + Depth(D), Index(I), Name(0) { } + + friend class ASTContext; // ASTContext creates these + +public: + unsigned getDepth() const { return Depth; } + unsigned getIndex() const { return Index; } + IdentifierInfo *getName() const { return Name; } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Depth, Index, Name); + } + + static void Profile(llvm::FoldingSetNodeID &ID, unsigned Depth, + unsigned Index, IdentifierInfo *Name) { + ID.AddInteger(Depth); + ID.AddInteger(Index); + ID.AddPointer(Name); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == TemplateTypeParm; + } + static bool classof(const TemplateTypeParmType *T) { return true; } +}; + +/// \brief Represents the type of a template specialization as written +/// in the source code. +/// +/// Template specialization types represent the syntactic form of a +/// template-id that refers to a type, e.g., @c vector<int>. Some +/// template specialization types are syntactic sugar, whose canonical +/// type will point to some other type node that represents the +/// instantiation or class template specialization. For example, a +/// class template specialization type of @c vector<int> will refer to +/// a tag type for the instantiation +/// @c std::vector<int, std::allocator<int>>. +/// +/// Other template specialization types, for which the template name +/// is dependent, may be canonical types. These types are always +/// dependent. +class TemplateSpecializationType + : public Type, public llvm::FoldingSetNode { + + /// \brief The name of the template being specialized. + TemplateName Template; + + /// \brief - The number of template arguments named in this class + /// template specialization. + unsigned NumArgs; + + TemplateSpecializationType(TemplateName T, + const TemplateArgument *Args, + unsigned NumArgs, QualType Canon); + + virtual void Destroy(ASTContext& C); + + friend class ASTContext; // ASTContext creates these + +public: + /// \brief Determine whether any of the given template arguments are + /// dependent. + static bool anyDependentTemplateArguments(const TemplateArgument *Args, + unsigned NumArgs); + + /// \brief Print a template argument list, including the '<' and '>' + /// enclosing the template arguments. + static std::string PrintTemplateArgumentList(const TemplateArgument *Args, + unsigned NumArgs, + const PrintingPolicy &Policy); + + typedef const TemplateArgument * iterator; + + iterator begin() const { return getArgs(); } + iterator end() const; + + /// \brief Retrieve the name of the template that we are specializing. + TemplateName getTemplateName() const { return Template; } + + /// \brief Retrieve the template arguments. + const TemplateArgument *getArgs() const { + return reinterpret_cast<const TemplateArgument *>(this + 1); + } + + /// \brief Retrieve the number of template arguments. + unsigned getNumArgs() const { return NumArgs; } + + /// \brief Retrieve a specific template argument as a type. + /// \precondition @c isArgType(Arg) + const TemplateArgument &getArg(unsigned Idx) const; + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Template, getArgs(), NumArgs); + } + + static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T, + const TemplateArgument *Args, unsigned NumArgs); + + static bool classof(const Type *T) { + return T->getTypeClass() == TemplateSpecialization; + } + static bool classof(const TemplateSpecializationType *T) { return true; } +}; + +/// \brief Represents a type that was referred to via a qualified +/// name, e.g., N::M::type. +/// +/// This type is used to keep track of a type name as written in the +/// source code, including any nested-name-specifiers. The type itself +/// is always "sugar", used to express what was written in the source +/// code but containing no additional semantic information. +class QualifiedNameType : public Type, public llvm::FoldingSetNode { + /// \brief The nested name specifier containing the qualifier. + NestedNameSpecifier *NNS; + + /// \brief The type that this qualified name refers to. + QualType NamedType; + + QualifiedNameType(NestedNameSpecifier *NNS, QualType NamedType, + QualType CanonType) + : Type(QualifiedName, CanonType, NamedType->isDependentType()), + NNS(NNS), NamedType(NamedType) { } + + friend class ASTContext; // ASTContext creates these + +public: + /// \brief Retrieve the qualification on this type. + NestedNameSpecifier *getQualifier() const { return NNS; } + + /// \brief Retrieve the type named by the qualified-id. + QualType getNamedType() const { return NamedType; } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, NNS, NamedType); + } + + static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, + QualType NamedType) { + ID.AddPointer(NNS); + NamedType.Profile(ID); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == QualifiedName; + } + static bool classof(const QualifiedNameType *T) { return true; } +}; + +/// \brief Represents a 'typename' specifier that names a type within +/// a dependent type, e.g., "typename T::type". +/// +/// TypenameType has a very similar structure to QualifiedNameType, +/// which also involves a nested-name-specifier following by a type, +/// and (FIXME!) both can even be prefixed by the 'typename' +/// keyword. However, the two types serve very different roles: +/// QualifiedNameType is a non-semantic type that serves only as sugar +/// to show how a particular type was written in the source +/// code. TypenameType, on the other hand, only occurs when the +/// nested-name-specifier is dependent, such that we cannot resolve +/// the actual type until after instantiation. +class TypenameType : public Type, public llvm::FoldingSetNode { + /// \brief The nested name specifier containing the qualifier. + NestedNameSpecifier *NNS; + + typedef llvm::PointerUnion<const IdentifierInfo *, + const TemplateSpecializationType *> NameType; + + /// \brief The type that this typename specifier refers to. + NameType Name; + + TypenameType(NestedNameSpecifier *NNS, const IdentifierInfo *Name, + QualType CanonType) + : Type(Typename, CanonType, true), NNS(NNS), Name(Name) { + assert(NNS->isDependent() && + "TypenameType requires a dependent nested-name-specifier"); + } + + TypenameType(NestedNameSpecifier *NNS, const TemplateSpecializationType *Ty, + QualType CanonType) + : Type(Typename, CanonType, true), NNS(NNS), Name(Ty) { + assert(NNS->isDependent() && + "TypenameType requires a dependent nested-name-specifier"); + } + + friend class ASTContext; // ASTContext creates these + +public: + /// \brief Retrieve the qualification on this type. + NestedNameSpecifier *getQualifier() const { return NNS; } + + /// \brief Retrieve the type named by the typename specifier as an + /// identifier. + /// + /// This routine will return a non-NULL identifier pointer when the + /// form of the original typename was terminated by an identifier, + /// e.g., "typename T::type". + const IdentifierInfo *getIdentifier() const { + return Name.dyn_cast<const IdentifierInfo *>(); + } + + /// \brief Retrieve the type named by the typename specifier as a + /// type specialization. + const TemplateSpecializationType *getTemplateId() const { + return Name.dyn_cast<const TemplateSpecializationType *>(); + } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, NNS, Name); + } + + static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, + NameType Name) { + ID.AddPointer(NNS); + ID.AddPointer(Name.getOpaqueValue()); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == Typename; + } + static bool classof(const TypenameType *T) { return true; } +}; + +/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for +/// object oriented design. They basically correspond to C++ classes. There +/// are two kinds of interface types, normal interfaces like "NSString" and +/// qualified interfaces, which are qualified with a protocol list like +/// "NSString<NSCopyable, NSAmazing>". Qualified interface types are instances +/// of ObjCQualifiedInterfaceType, which is a subclass of ObjCInterfaceType. +class ObjCInterfaceType : public Type { + ObjCInterfaceDecl *Decl; +protected: + ObjCInterfaceType(TypeClass tc, ObjCInterfaceDecl *D) : + Type(tc, QualType(), /*Dependent=*/false), Decl(D) { } + friend class ASTContext; // ASTContext creates these. +public: + + ObjCInterfaceDecl *getDecl() const { return Decl; } + + /// qual_iterator and friends: this provides access to the (potentially empty) + /// list of protocols qualifying this interface. If this is an instance of + /// ObjCQualifiedInterfaceType it returns the list, otherwise it returns an + /// empty list if there are no qualifying protocols. + typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator; + inline qual_iterator qual_begin() const; + inline qual_iterator qual_end() const; + bool qual_empty() const { return getTypeClass() != ObjCQualifiedInterface; } + + /// getNumProtocols - Return the number of qualifying protocols in this + /// interface type, or 0 if there are none. + inline unsigned getNumProtocols() const; + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + static bool classof(const Type *T) { + return T->getTypeClass() == ObjCInterface || + T->getTypeClass() == ObjCQualifiedInterface; + } + static bool classof(const ObjCInterfaceType *) { return true; } +}; + +/// ObjCQualifiedInterfaceType - This class represents interface types +/// conforming to a list of protocols, such as INTF<Proto1, Proto2, Proto1>. +/// +/// Duplicate protocols are removed and protocol list is canonicalized to be in +/// alphabetical order. +class ObjCQualifiedInterfaceType : public ObjCInterfaceType, + public llvm::FoldingSetNode { + + // List of protocols for this protocol conforming object type + // List is sorted on protocol name. No protocol is enterred more than once. + llvm::SmallVector<ObjCProtocolDecl*, 4> Protocols; + + ObjCQualifiedInterfaceType(ObjCInterfaceDecl *D, + ObjCProtocolDecl **Protos, unsigned NumP) : + ObjCInterfaceType(ObjCQualifiedInterface, D), + Protocols(Protos, Protos+NumP) { } + friend class ASTContext; // ASTContext creates these. +public: + + unsigned getNumProtocols() const { + return Protocols.size(); + } + + qual_iterator qual_begin() const { return Protocols.begin(); } + qual_iterator qual_end() const { return Protocols.end(); } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID); + static void Profile(llvm::FoldingSetNodeID &ID, + const ObjCInterfaceDecl *Decl, + ObjCProtocolDecl **protocols, unsigned NumProtocols); + + static bool classof(const Type *T) { + return T->getTypeClass() == ObjCQualifiedInterface; + } + static bool classof(const ObjCQualifiedInterfaceType *) { return true; } +}; + +inline ObjCInterfaceType::qual_iterator ObjCInterfaceType::qual_begin() const { + if (const ObjCQualifiedInterfaceType *QIT = + dyn_cast<ObjCQualifiedInterfaceType>(this)) + return QIT->qual_begin(); + return 0; +} +inline ObjCInterfaceType::qual_iterator ObjCInterfaceType::qual_end() const { + if (const ObjCQualifiedInterfaceType *QIT = + dyn_cast<ObjCQualifiedInterfaceType>(this)) + return QIT->qual_end(); + return 0; +} + +/// getNumProtocols - Return the number of qualifying protocols in this +/// interface type, or 0 if there are none. +inline unsigned ObjCInterfaceType::getNumProtocols() const { + if (const ObjCQualifiedInterfaceType *QIT = + dyn_cast<ObjCQualifiedInterfaceType>(this)) + return QIT->getNumProtocols(); + return 0; +} + +/// ObjCQualifiedIdType - to represent id<protocol-list>. +/// +/// Duplicate protocols are removed and protocol list is canonicalized to be in +/// alphabetical order. +class ObjCQualifiedIdType : public Type, + public llvm::FoldingSetNode { + // List of protocols for this protocol conforming 'id' type + // List is sorted on protocol name. No protocol is enterred more than once. + llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols; + + ObjCQualifiedIdType(ObjCProtocolDecl **Protos, unsigned NumP) + : Type(ObjCQualifiedId, QualType()/*these are always canonical*/, + /*Dependent=*/false), + Protocols(Protos, Protos+NumP) { } + friend class ASTContext; // ASTContext creates these. +public: + + unsigned getNumProtocols() const { + return Protocols.size(); + } + + typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator; + qual_iterator qual_begin() const { return Protocols.begin(); } + qual_iterator qual_end() const { return Protocols.end(); } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID); + static void Profile(llvm::FoldingSetNodeID &ID, + ObjCProtocolDecl **protocols, unsigned NumProtocols); + + static bool classof(const Type *T) { + return T->getTypeClass() == ObjCQualifiedId; + } + static bool classof(const ObjCQualifiedIdType *) { return true; } + +}; + +// Inline function definitions. + +/// getUnqualifiedType - Return the type without any qualifiers. +inline QualType QualType::getUnqualifiedType() const { + Type *TP = getTypePtr(); + if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(TP)) + TP = EXTQT->getBaseType(); + return QualType(TP, 0); +} + +/// getAddressSpace - Return the address space of this type. +inline unsigned QualType::getAddressSpace() const { + QualType CT = getTypePtr()->getCanonicalTypeInternal(); + if (const ArrayType *AT = dyn_cast<ArrayType>(CT)) + return AT->getElementType().getAddressSpace(); + if (const RecordType *RT = dyn_cast<RecordType>(CT)) + return RT->getAddressSpace(); + if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CT)) + return EXTQT->getAddressSpace(); + return 0; +} + +/// getObjCGCAttr - Return the gc attribute of this type. +inline QualType::GCAttrTypes QualType::getObjCGCAttr() const { + QualType CT = getTypePtr()->getCanonicalTypeInternal(); + if (const ArrayType *AT = dyn_cast<ArrayType>(CT)) + return AT->getElementType().getObjCGCAttr(); + if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CT)) + return EXTQT->getObjCGCAttr(); + if (const PointerType *PT = CT->getAsPointerType()) + return PT->getPointeeType().getObjCGCAttr(); + return GCNone; +} + +/// isMoreQualifiedThan - Determine whether this type is more +/// qualified than the Other type. For example, "const volatile int" +/// is more qualified than "const int", "volatile int", and +/// "int". However, it is not more qualified than "const volatile +/// int". +inline bool QualType::isMoreQualifiedThan(QualType Other) const { + unsigned MyQuals = this->getCVRQualifiers(); + unsigned OtherQuals = Other.getCVRQualifiers(); + if (getAddressSpace() != Other.getAddressSpace()) + return false; + return MyQuals != OtherQuals && (MyQuals | OtherQuals) == MyQuals; +} + +/// isAtLeastAsQualifiedAs - Determine whether this type is at last +/// as qualified as the Other type. For example, "const volatile +/// int" is at least as qualified as "const int", "volatile int", +/// "int", and "const volatile int". +inline bool QualType::isAtLeastAsQualifiedAs(QualType Other) const { + unsigned MyQuals = this->getCVRQualifiers(); + unsigned OtherQuals = Other.getCVRQualifiers(); + if (getAddressSpace() != Other.getAddressSpace()) + return false; + return (MyQuals | OtherQuals) == MyQuals; +} + +/// getNonReferenceType - If Type is a reference type (e.g., const +/// int&), returns the type that the reference refers to ("const +/// int"). Otherwise, returns the type itself. This routine is used +/// throughout Sema to implement C++ 5p6: +/// +/// If an expression initially has the type "reference to T" (8.3.2, +/// 8.5.3), the type is adjusted to "T" prior to any further +/// analysis, the expression designates the object or function +/// denoted by the reference, and the expression is an lvalue. +inline QualType QualType::getNonReferenceType() const { + if (const ReferenceType *RefType = (*this)->getAsReferenceType()) + return RefType->getPointeeType(); + else + return *this; +} + +inline const TypedefType* Type::getAsTypedefType() const { + return dyn_cast<TypedefType>(this); +} +inline const ObjCInterfaceType *Type::getAsPointerToObjCInterfaceType() const { + if (const PointerType *PT = getAsPointerType()) + return PT->getPointeeType()->getAsObjCInterfaceType(); + return 0; +} + +// NOTE: All of these methods use "getUnqualifiedType" to strip off address +// space qualifiers if present. +inline bool Type::isFunctionType() const { + return isa<FunctionType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isPointerType() const { + return isa<PointerType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isBlockPointerType() const { + return isa<BlockPointerType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isReferenceType() const { + return isa<ReferenceType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isLValueReferenceType() const { + return isa<LValueReferenceType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isRValueReferenceType() const { + return isa<RValueReferenceType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isFunctionPointerType() const { + if (const PointerType* T = getAsPointerType()) + return T->getPointeeType()->isFunctionType(); + else + return false; +} +inline bool Type::isMemberPointerType() const { + return isa<MemberPointerType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isMemberFunctionPointerType() const { + if (const MemberPointerType* T = getAsMemberPointerType()) + return T->getPointeeType()->isFunctionType(); + else + return false; +} +inline bool Type::isArrayType() const { + return isa<ArrayType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isConstantArrayType() const { + return isa<ConstantArrayType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isIncompleteArrayType() const { + return isa<IncompleteArrayType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isVariableArrayType() const { + return isa<VariableArrayType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isDependentSizedArrayType() const { + return isa<DependentSizedArrayType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isRecordType() const { + return isa<RecordType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isAnyComplexType() const { + return isa<ComplexType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isVectorType() const { + return isa<VectorType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isExtVectorType() const { + return isa<ExtVectorType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isObjCInterfaceType() const { + return isa<ObjCInterfaceType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isObjCQualifiedInterfaceType() const { + return isa<ObjCQualifiedInterfaceType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isObjCQualifiedIdType() const { + return isa<ObjCQualifiedIdType>(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isTemplateTypeParmType() const { + return isa<TemplateTypeParmType>(CanonicalType.getUnqualifiedType()); +} + +inline bool Type::isSpecificBuiltinType(unsigned K) const { + if (const BuiltinType *BT = getAsBuiltinType()) + if (BT->getKind() == (BuiltinType::Kind) K) + return true; + return false; +} + +/// \brief Determines whether this is a type for which one can define +/// an overloaded operator. +inline bool Type::isOverloadableType() const { + return isDependentType() || isRecordType() || isEnumeralType(); +} + +inline bool Type::hasPointerRepresentation() const { + return (isPointerType() || isReferenceType() || isBlockPointerType() || + isObjCInterfaceType() || isObjCQualifiedIdType() || + isObjCQualifiedInterfaceType() || isNullPtrType()); +} + +inline bool Type::hasObjCPointerRepresentation() const { + return (isObjCInterfaceType() || isObjCQualifiedIdType() || + isObjCQualifiedInterfaceType()); +} + +/// Insertion operator for diagnostics. This allows sending QualType's into a +/// diagnostic with <<. +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + QualType T) { + DB.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()), + Diagnostic::ak_qualtype); + return DB; +} + +} // end namespace clang + +#endif diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def new file mode 100644 index 000000000000..76cbed311d79 --- /dev/null +++ b/include/clang/AST/TypeNodes.def @@ -0,0 +1,85 @@ +//===-- TypeNodes.def - Metadata about Type AST nodes -----------*- 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 AST type info database. Each type node is +// enumerated by providing its name (e.g., "Builtin" or "Enum") and +// base class (e.g., "Type" or "TagType"). Depending on where in the +// abstract syntax tree the type will show up, the enumeration uses +// one of four different macros: +// +// TYPE(Class, Base) - A type that can show up anywhere in the AST, +// and might be dependent, canonical, or non-canonical. All clients +// will need to understand these types. +// +// ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in +// the type hierarchy but has no concrete instances. +// +// NON_CANONICAL_TYPE(Class, Base) - A type that can show up +// anywhere in the AST but will never be a part of a canonical +// type. Clients that only need to deal with canonical types +// (ignoring, e.g., typedefs and other type alises used for +// pretty-printing) can ignore these types. +// +// DEPENDENT_TYPE(Class, Base) - A type that will only show up +// within a C++ template that has not been instantiated, e.g., a +// type that is always dependent. Clients that do not need to deal +// with uninstantiated C++ templates can ignore these types. +// +//===----------------------------------------------------------------------===// + +#ifndef ABSTRACT_TYPE +# define ABSTRACT_TYPE(Class, Base) TYPE(Class, Base) +#endif + +#ifndef NON_CANONICAL_TYPE +# define NON_CANONICAL_TYPE(Class, Base) TYPE(Class, Base) +#endif + +#ifndef DEPENDENT_TYPE +# define DEPENDENT_TYPE(Class, Base) TYPE(Class, Base) +#endif + +TYPE(ExtQual, Type) +TYPE(Builtin, Type) +TYPE(FixedWidthInt, Type) +TYPE(Complex, Type) +TYPE(Pointer, Type) +TYPE(BlockPointer, Type) +ABSTRACT_TYPE(Reference, Type) +TYPE(LValueReference, ReferenceType) +TYPE(RValueReference, ReferenceType) +TYPE(MemberPointer, Type) +ABSTRACT_TYPE(Array, Type) +TYPE(ConstantArray, ArrayType) +TYPE(IncompleteArray, ArrayType) +TYPE(VariableArray, ArrayType) +DEPENDENT_TYPE(DependentSizedArray, ArrayType) +TYPE(Vector, Type) +TYPE(ExtVector, VectorType) +ABSTRACT_TYPE(Function, Type) +TYPE(FunctionProto, FunctionType) +TYPE(FunctionNoProto, FunctionType) +NON_CANONICAL_TYPE(Typedef, Type) +NON_CANONICAL_TYPE(TypeOfExpr, Type) +NON_CANONICAL_TYPE(TypeOf, Type) +ABSTRACT_TYPE(Tag, Type) +TYPE(Record, TagType) +TYPE(Enum, TagType) +DEPENDENT_TYPE(TemplateTypeParm, Type) +TYPE(TemplateSpecialization, Type) +NON_CANONICAL_TYPE(QualifiedName, Type) +DEPENDENT_TYPE(Typename, Type) +TYPE(ObjCInterface, Type) +TYPE(ObjCQualifiedInterface, ObjCInterfaceType) +TYPE(ObjCQualifiedId, Type) + +#undef DEPENDENT_TYPE +#undef NON_CANONICAL_TYPE +#undef ABSTRACT_TYPE +#undef TYPE diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h new file mode 100644 index 000000000000..4f60273d6809 --- /dev/null +++ b/include/clang/AST/TypeOrdering.h @@ -0,0 +1,63 @@ +//===-------------- TypeOrdering.h - Total ordering for types -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a function objects and specializations that +// allow QualType values to be sorted, used in std::maps, std::sets, +// llvm::DenseMaps, and llvm::DenseSets. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TYPE_ORDERING_H +#define LLVM_CLANG_TYPE_ORDERING_H + +#include "clang/AST/Type.h" +#include <functional> + +namespace clang { + +/// QualTypeOrdering - Function object that provides a total ordering +/// on QualType values. +struct QualTypeOrdering : std::binary_function<QualType, QualType, bool> { + bool operator()(QualType T1, QualType T2) const { + return std::less<void*>()(T1.getAsOpaquePtr(), T2.getAsOpaquePtr()); + } +}; + +} + +namespace llvm { + template<class> struct DenseMapInfo; + + template<> struct DenseMapInfo<clang::QualType> { + static inline clang::QualType getEmptyKey() { return clang::QualType(); } + + static inline clang::QualType getTombstoneKey() { + using clang::QualType; + return QualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1)); + } + + static unsigned getHashValue(clang::QualType Val) { + return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^ + ((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9)); + } + + static bool isEqual(clang::QualType LHS, clang::QualType RHS) { + return LHS == RHS; + } + + static bool isPod() { + // QualType isn't *technically* a POD type. However, we can get + // away with calling it a POD type since its copy constructor, + // copy assignment operator, and destructor are all trivial. + return true; + } + }; +} + +#endif diff --git a/include/clang/AST/X86Builtins.def b/include/clang/AST/X86Builtins.def new file mode 100644 index 000000000000..710efa8cee4b --- /dev/null +++ b/include/clang/AST/X86Builtins.def @@ -0,0 +1,427 @@ +//===--- X86Builtins.def - X86 Builtin function database --------*- 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 X86-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// FIXME: this needs to be the full list supported by GCC. Right now, I'm just +// adding stuff on demand. + +// The format of this database matches clang/AST/Builtins.def. + +// FIXME: In GCC, these builtins are defined depending on whether support for +// MMX/SSE/etc is turned on. We should do this too. + +// FIXME: Ideally we would be able to pull this information from what +// LLVM already knows about X86 builtins. We need to match the LLVM +// definition anyway, since code generation will lower to the +// intrinsic if one exists. + +BUILTIN(__builtin_ia32_emms , "v", "") + +// FIXME: Are these nothrow/const? + +// SSE intrinsics. +BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "") +BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "") +BUILTIN(__builtin_ia32_comile, "iV4fV4f", "") +BUILTIN(__builtin_ia32_comigt, "iV4fV4f", "") +BUILTIN(__builtin_ia32_comige, "iV4fV4f", "") +BUILTIN(__builtin_ia32_comineq, "iV4fV4f", "") +BUILTIN(__builtin_ia32_ucomieq, "iV4fV4f", "") +BUILTIN(__builtin_ia32_ucomilt, "iV4fV4f", "") +BUILTIN(__builtin_ia32_ucomile, "iV4fV4f", "") +BUILTIN(__builtin_ia32_ucomigt, "iV4fV4f", "") +BUILTIN(__builtin_ia32_ucomige, "iV4fV4f", "") +BUILTIN(__builtin_ia32_ucomineq, "iV4fV4f", "") +BUILTIN(__builtin_ia32_comisdeq, "iV2dV2d", "") +BUILTIN(__builtin_ia32_comisdlt, "iV2dV2d", "") +BUILTIN(__builtin_ia32_comisdle, "iV2dV2d", "") +BUILTIN(__builtin_ia32_comisdgt, "iV2dV2d", "") +BUILTIN(__builtin_ia32_comisdge, "iV2dV2d", "") +BUILTIN(__builtin_ia32_comisdneq, "iV2dV2d", "") +BUILTIN(__builtin_ia32_ucomisdeq, "iV2dV2d", "") +BUILTIN(__builtin_ia32_ucomisdlt, "iV2dV2d", "") +BUILTIN(__builtin_ia32_ucomisdle, "iV2dV2d", "") +BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "") +BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "") +BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "") +BUILTIN(__builtin_ia32_addps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_subps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_mulps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_divps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_addss, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_subss, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_mulss, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_divss, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fc", "") +BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fc", "") +BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_andps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_andnps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_orps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_xorps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_movss, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_movhlps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_movlhps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_unpckhps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_unpcklps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_addpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_subpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_mulpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_divpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_addsd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_subsd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_mulsd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_divsd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dc", "") +BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dc", "") +BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_andpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_andnpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_orpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_xorpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_movsd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_unpckhpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_unpcklpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_paddb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_paddw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_paddd128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_paddq128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_psubb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_psubw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_psubd128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_psubq128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_paddsb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_paddsw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_psubsb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_psubsw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pmullw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pand128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_pandn128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_por128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_pxor128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_pavgb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_pavgw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pcmpeqb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_pcmpeqw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pcmpeqd128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_pcmpgtb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_pcmpgtw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pcmpgtd128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_pminsw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_punpckhbw128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_punpckhwd128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_punpckhdq128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_punpckhqdq128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_punpcklbw128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_punpcklwd128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_punpckldq128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_punpcklqdq128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_packsswb128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_packssdw128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_packuswb128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_haddps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pmaddubsw128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_pabsb128, "V16cV16c", "") +BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "") +BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "") +BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "") +BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "") +BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "") +BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "") +BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "") +BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "") +BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "") +BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "") +BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "") +BUILTIN(__builtin_ia32_pshufw, "V4sV4si", "") +BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "") +BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "") +BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "") +BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "") +BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "") +BUILTIN(__builtin_ia32_stmxcsr, "Ui", "") +BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "") +BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "") +BUILTIN(__builtin_ia32_cvtsi2ss, "V4fV4fi", "") +BUILTIN(__builtin_ia32_cvtsi642ss, "V4fV4fLLi", "") +BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "") +BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "") +BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "") +BUILTIN(__builtin_ia32_cvttss2si, "iV4f", "") +BUILTIN(__builtin_ia32_cvttss2si64, "LLiV4f", "") +BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "") +BUILTIN(__builtin_ia32_loadups, "V4ffC*", "") +BUILTIN(__builtin_ia32_storeups, "vf*V4f", "") +BUILTIN(__builtin_ia32_loadhps, "V4fV4fV2i*", "") +BUILTIN(__builtin_ia32_loadlps, "V4fV4fV2i*", "") +BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "") +BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "") +BUILTIN(__builtin_ia32_movmskps, "iV4f", "") +BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "") +BUILTIN(__builtin_ia32_movntps, "vf*V4f", "") +BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "") +BUILTIN(__builtin_ia32_sfence, "v", "") +BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "") +BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "") +BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "") +BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "") +BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "") +BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "") +BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "") +BUILTIN(__builtin_ia32_shufps, "V4fV4fV4fi", "") +BUILTIN(__builtin_ia32_femms, "v", "") +BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "") +BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "") +BUILTIN(__builtin_ia32_pfadd, "V2fV2fV2f", "") +BUILTIN(__builtin_ia32_pfcmpeq, "V2iV2fV2f", "") +BUILTIN(__builtin_ia32_pfcmpge, "V2iV2fV2f", "") +BUILTIN(__builtin_ia32_pfcmpgt, "V2iV2fV2f", "") +BUILTIN(__builtin_ia32_pfmax, "V2fV2fV2f", "") +BUILTIN(__builtin_ia32_pfmin, "V2fV2fV2f", "") +BUILTIN(__builtin_ia32_pfmul, "V2fV2fV2f", "") +BUILTIN(__builtin_ia32_pfrcp, "V2fV2f", "") +BUILTIN(__builtin_ia32_pfrcpit1, "V2fV2fV2f", "") +BUILTIN(__builtin_ia32_pfrcpit2, "V2fV2fV2f", "") +BUILTIN(__builtin_ia32_pfrsqrt, "V2fV2f", "") +BUILTIN(__builtin_ia32_pfrsqit1, "V2fV2fV2f", "") +BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "") +BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "") +BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "") +BUILTIN(__builtin_ia32_pmulhrw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pf2iw, "V2iV2f", "") +BUILTIN(__builtin_ia32_pfnacc, "V2fV2fV2f", "") +BUILTIN(__builtin_ia32_pfpnacc, "V2fV2fV2f", "") +BUILTIN(__builtin_ia32_pi2fw, "V2fV2i", "") +BUILTIN(__builtin_ia32_pswapdsf, "V2fV2f", "") +BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "") +BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "") +BUILTIN(__builtin_ia32_loadupd, "V2ddC*", "") +BUILTIN(__builtin_ia32_storeupd, "vd*V2d", "") +BUILTIN(__builtin_ia32_loadhpd, "V2dV2ddC*", "") +BUILTIN(__builtin_ia32_loadlpd, "V2dV2ddC*", "") +BUILTIN(__builtin_ia32_movmskpd, "iV2d", "") +BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "") +BUILTIN(__builtin_ia32_movnti, "vi*i", "") +BUILTIN(__builtin_ia32_movntpd, "vd*V2d", "") +BUILTIN(__builtin_ia32_movntdq, "vV2LLi*V2LLi", "") +BUILTIN(__builtin_ia32_pshufd, "V4iV4ii", "") +BUILTIN(__builtin_ia32_pshuflw, "V8sV8si", "") +BUILTIN(__builtin_ia32_pshufhw, "V8sV8si", "") +BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "") +BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "") +BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "") +BUILTIN(__builtin_ia32_shufpd, "V2dV2dV2di", "") +BUILTIN(__builtin_ia32_cvtdq2pd, "V2dV4i", "") +BUILTIN(__builtin_ia32_cvtdq2ps, "V4fV4i", "") +BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "") +BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "") +BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "") +BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "") +BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "") +BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "") +BUILTIN(__builtin_ia32_cvtsd2si, "iV2d", "") +BUILTIN(__builtin_ia32_cvttsd2si, "iV2d", "") +BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "") +BUILTIN(__builtin_ia32_cvttsd2si64, "LLiV2d", "") +BUILTIN(__builtin_ia32_cvtps2dq, "V4iV4f", "") +BUILTIN(__builtin_ia32_cvtps2pd, "V2dV4f", "") +BUILTIN(__builtin_ia32_cvttps2dq, "V4iV4f", "") +BUILTIN(__builtin_ia32_cvtsi2sd, "V2dV2di", "") +BUILTIN(__builtin_ia32_cvtsi642sd, "V2dV2dLLi", "") +BUILTIN(__builtin_ia32_cvtsd2ss, "V4fV4fV2d", "") +BUILTIN(__builtin_ia32_cvtss2sd, "V2dV2dV4f", "") +BUILTIN(__builtin_ia32_clflush, "vvC*", "") +BUILTIN(__builtin_ia32_lfence, "v", "") +BUILTIN(__builtin_ia32_mfence, "v", "") +BUILTIN(__builtin_ia32_loaddqu, "V16ccC*", "") +BUILTIN(__builtin_ia32_storedqu, "vc*V16c", "") +BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "") +BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "") +BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "") +BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "") +BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "") +BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "") +BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "") +BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "") +BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "") +BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "") +BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_pslldqi128, "V2LLiV2LLii", "") +BUILTIN(__builtin_ia32_psrldqi128, "V2LLiV2LLii", "") +BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_psllq128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_psllwi128, "V8sV8si", "") +BUILTIN(__builtin_ia32_pslldi128, "V4iV4ii", "") +BUILTIN(__builtin_ia32_psllqi128, "V2LLiV2LLii", "") +BUILTIN(__builtin_ia32_psrlwi128, "V8sV8si", "") +BUILTIN(__builtin_ia32_psrldi128, "V4iV4ii", "") +BUILTIN(__builtin_ia32_psrlqi128, "V2LLiV2LLii", "") +BUILTIN(__builtin_ia32_psrawi128, "V8sV8si", "") +BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "") +BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "") +BUILTIN(__builtin_ia32_mwait, "vUiUi", "") +BUILTIN(__builtin_ia32_movshdup, "V4fV4f", "") +BUILTIN(__builtin_ia32_movsldup, "V4fV4f", "") +BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "") +BUILTIN(__builtin_ia32_palignr128, "V2LLiV2LLiV2LLii", "") +BUILTIN(__builtin_ia32_palignr, "V1LLiV1LLiV1LLis", "") +BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "") +BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "") +BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "") +BUILTIN(__builtin_ia32_vec_ext_v2df, "dV2di", "") +BUILTIN(__builtin_ia32_vec_ext_v2di, "LLiV2LLii", "") +BUILTIN(__builtin_ia32_vec_ext_v4sf, "fV4fi", "") +BUILTIN(__builtin_ia32_vec_ext_v4si, "iV4ii", "") +BUILTIN(__builtin_ia32_vec_ext_v8hi, "UsV8si", "") +BUILTIN(__builtin_ia32_vec_ext_v4hi, "sV4si", "") +BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "") +BUILTIN(__builtin_ia32_vec_set_v8hi, "V8sV8ssi", "") +BUILTIN(__builtin_ia32_vec_set_v4hi, "V4sV4ssi", "") +BUILTIN(__builtin_ia32_vec_set_v16qi, "V16cV16cii", "") +BUILTIN(__builtin_ia32_vec_set_v4si, "V4iV4iii", "") +BUILTIN(__builtin_ia32_vec_set_v2di, "V2LLiV2LLiLLii", "") +BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "") + +BUILTIN(__builtin_ia32_loadlv4si, "V4iV2i*", "") +BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "") + +BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "") +BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8si", "") +BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2di", "") +BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fi", "") +BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "") +BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "") + +BUILTIN(__builtin_ia32_packusdw128, "V8sV4iV4i", "") +BUILTIN(__builtin_ia32_pmaxsb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_pmaxsd128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_pmaxud128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_pmaxuw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pminsb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_pminsd128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_pminud128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_pminuw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pmovsxbd128, "V4iV16c", "") +BUILTIN(__builtin_ia32_pmovsxbq128, "V2LLiV16c", "") +BUILTIN(__builtin_ia32_pmovsxbw128, "V8sV16c", "") +BUILTIN(__builtin_ia32_pmovsxdq128, "V2LLiV4i", "") +BUILTIN(__builtin_ia32_pmovsxwd128, "V4iV8s", "") +BUILTIN(__builtin_ia32_pmovsxwq128, "V2LLiV8s", "") +BUILTIN(__builtin_ia32_pmovzxbd128, "V4iV16c", "") +BUILTIN(__builtin_ia32_pmovzxbq128, "V2LLiV16c", "") +BUILTIN(__builtin_ia32_pmovzxbw128, "V8sV16c", "") +BUILTIN(__builtin_ia32_pmovzxdq128, "V2LLiV4i", "") +BUILTIN(__builtin_ia32_pmovzxwd128, "V4iV8s", "") +BUILTIN(__builtin_ia32_pmovzxwq128, "V2LLiV8s", "") +BUILTIN(__builtin_ia32_pmuldq128, "V2LLiV4iV4i", "") +BUILTIN(__builtin_ia32_pmulld128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_roundps, "V4fV4fi", "") +BUILTIN(__builtin_ia32_roundss, "V4fV4fi", "") +BUILTIN(__builtin_ia32_roundsd, "V2dV2di", "") +BUILTIN(__builtin_ia32_roundpd, "V2dV2di", "") + + +#undef BUILTIN |