diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2011-02-20 13:06:31 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2011-02-20 13:06:31 +0000 |
commit | bca07a4524feb4edec581062d631a13116320a24 (patch) | |
tree | a9243275843fbeaa590afc07ee888e006b8d54ea /include/clang/AST | |
parent | 998bc5802ecdd65ce3b270f6c69a8ae8557f0a10 (diff) | |
download | src-test2-bca07a4524feb4edec581062d631a13116320a24.tar.gz src-test2-bca07a4524feb4edec581062d631a13116320a24.zip |
Notes
Diffstat (limited to 'include/clang/AST')
42 files changed, 6396 insertions, 3254 deletions
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index 84833c099f97..08ee4ef40de0 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -19,6 +19,7 @@ namespace clang { class CXXRecordDecl; class DeclGroupRef; class HandleTagDeclDefinition; + class ASTMutationListener; class ASTDeserializationListener; // layering violation because void* is ugly class SemaConsumer; // layering violation required for safe SemaConsumer class TagDecl; @@ -86,10 +87,13 @@ public: /// it was actually used. virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {} + /// \brief If the consumer is interested in entities getting modified after + /// their initial creation, it should return a pointer to + /// a GetASTMutationListener here. + virtual ASTMutationListener *GetASTMutationListener() { return 0; } + /// \brief If the consumer is interested in entities being deserialized from /// AST files, it should return a pointer to a ASTDeserializationListener here - /// - /// The return type is void* because ASTDS lives in Frontend. virtual ASTDeserializationListener *GetASTDeserializationListener() { return 0; } /// PrintStats - If desired, print any statistics. diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index ae4ee946fe27..0e887133d01e 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -45,6 +45,7 @@ namespace clang { class Diagnostic; class Expr; class ExternalASTSource; + class ASTMutationListener; class IdentifierTable; class SelectorTable; class SourceManager; @@ -56,6 +57,7 @@ namespace clang { class CXXRecordDecl; class Decl; class FieldDecl; + class MangleContext; class ObjCIvarDecl; class ObjCIvarRefExpr; class ObjCPropertyDecl; @@ -78,49 +80,61 @@ namespace clang { class ASTContext { ASTContext &this_() { return *this; } - std::vector<Type*> Types; - llvm::FoldingSet<ExtQuals> ExtQualNodes; - 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; - llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes; - llvm::FoldingSet<DependentSizedExtVectorType> DependentSizedExtVectorTypes; - llvm::FoldingSet<VectorType> VectorTypes; - llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes; - llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes; - llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes; - llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes; - llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes; - llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes; - llvm::ContextualFoldingSet<TemplateSpecializationType, ASTContext&> + mutable std::vector<Type*> Types; + mutable llvm::FoldingSet<ExtQuals> ExtQualNodes; + mutable llvm::FoldingSet<ComplexType> ComplexTypes; + mutable llvm::FoldingSet<PointerType> PointerTypes; + mutable llvm::FoldingSet<BlockPointerType> BlockPointerTypes; + mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes; + mutable llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes; + mutable llvm::FoldingSet<MemberPointerType> MemberPointerTypes; + mutable llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes; + mutable llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes; + mutable std::vector<VariableArrayType*> VariableArrayTypes; + mutable llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes; + mutable llvm::FoldingSet<DependentSizedExtVectorType> + DependentSizedExtVectorTypes; + mutable llvm::FoldingSet<VectorType> VectorTypes; + mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes; + mutable llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes; + mutable llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes; + mutable llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes; + mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes; + mutable llvm::FoldingSet<SubstTemplateTypeParmType> + SubstTemplateTypeParmTypes; + mutable llvm::FoldingSet<SubstTemplateTypeParmPackType> + SubstTemplateTypeParmPackTypes; + mutable llvm::ContextualFoldingSet<TemplateSpecializationType, ASTContext&> TemplateSpecializationTypes; - llvm::FoldingSet<ElaboratedType> ElaboratedTypes; - llvm::FoldingSet<DependentNameType> DependentNameTypes; - llvm::ContextualFoldingSet<DependentTemplateSpecializationType, ASTContext&> + mutable llvm::FoldingSet<ParenType> ParenTypes; + mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes; + mutable llvm::FoldingSet<DependentNameType> DependentNameTypes; + mutable llvm::ContextualFoldingSet<DependentTemplateSpecializationType, + ASTContext&> DependentTemplateSpecializationTypes; - llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes; - llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; - - llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; - llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; - + llvm::FoldingSet<PackExpansionType> PackExpansionTypes; + mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes; + mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; + llvm::FoldingSet<AttributedType> AttributedTypes; + + mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; + mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; + mutable llvm::FoldingSet<SubstTemplateTemplateParmPackStorage> + SubstTemplateTemplateParmPacks; + /// \brief The set of nested name specifiers. /// /// This set is managed by the NestedNameSpecifier class. - llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers; - NestedNameSpecifier *GlobalNestedNameSpecifier; + mutable llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers; + mutable 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; + mutable llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> + ASTRecordLayouts; + mutable llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*> + ObjCLayouts; /// KeyFunctions - A cache mapping from CXXRecordDecls to key functions. llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*> KeyFunctions; @@ -128,6 +142,9 @@ class ASTContext { /// \brief Mapping from ObjCContainers to their ObjCImplementations. llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls; + /// \brief Mapping from __block VarDecls to their copy initialization expr. + llvm::DenseMap<const VarDecl*, Expr*> BlockVarCopyInits; + /// \brief Representation of a "canonical" template template parameter that /// is used in canonical template names. class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode { @@ -144,10 +161,11 @@ class ASTContext { static void Profile(llvm::FoldingSetNodeID &ID, TemplateTemplateParmDecl *Parm); }; - llvm::FoldingSet<CanonicalTemplateTemplateParm> CanonTemplateTemplateParms; + mutable llvm::FoldingSet<CanonicalTemplateTemplateParm> + CanonTemplateTemplateParms; - TemplateTemplateParmDecl *getCanonicalTemplateTemplateParmDecl( - TemplateTemplateParmDecl *TTP); + TemplateTemplateParmDecl * + getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const; /// \brief Whether __[u]int128_t identifier is installed. bool IsInt128Installed; @@ -171,11 +189,11 @@ class ASTContext { QualType ObjCClassTypedefType; QualType ObjCConstantStringType; - RecordDecl *CFConstantStringTypeDecl; + mutable RecordDecl *CFConstantStringTypeDecl; - RecordDecl *NSConstantStringTypeDecl; + mutable RecordDecl *NSConstantStringTypeDecl; - RecordDecl *ObjCFastEnumerationStateTypeDecl; + mutable RecordDecl *ObjCFastEnumerationStateTypeDecl; /// \brief The type for the C FILE type. TypeDecl *FILEDecl; @@ -187,10 +205,13 @@ class ASTContext { TypeDecl *sigjmp_bufDecl; /// \brief Type for the Block descriptor for Blocks CodeGen. - RecordDecl *BlockDescriptorType; + mutable RecordDecl *BlockDescriptorType; /// \brief Type for the Block descriptor for Blocks CodeGen. - RecordDecl *BlockDescriptorExtendedType; + mutable RecordDecl *BlockDescriptorExtendedType; + + /// \brief Declaration for the CUDA cudaConfigureCall function. + FunctionDecl *cudaConfigureCallDecl; TypeSourceInfo NullTypeSourceInfo; @@ -279,7 +300,7 @@ class ASTContext { /// /// AST objects are never destructed; rather, all memory associated with the /// AST objects will be released when the ASTContext itself is destroyed. - llvm::BumpPtrAllocator BumpAlloc; + mutable llvm::BumpPtrAllocator BumpAlloc; /// \brief Allocator for partial diagnostics. PartialDiagnostic::StorageAllocator DiagAllocator; @@ -287,14 +308,17 @@ class ASTContext { /// \brief The current C++ ABI. llvm::OwningPtr<CXXABI> ABI; CXXABI *createCXXABI(const TargetInfo &T); - + + friend class ASTDeclReader; + public: const TargetInfo &Target; IdentifierTable &Idents; SelectorTable &Selectors; Builtin::Context &BuiltinInfo; - DeclarationNameTable DeclarationNames; + mutable DeclarationNameTable DeclarationNames; llvm::OwningPtr<ExternalASTSource> ExternalSource; + ASTMutationListener *Listener; clang::PrintingPolicy PrintingPolicy; // Typedefs which may be provided defining the structure of Objective-C @@ -305,10 +329,10 @@ public: SourceManager& getSourceManager() { return SourceMgr; } const SourceManager& getSourceManager() const { return SourceMgr; } - void *Allocate(unsigned Size, unsigned Align = 8) { + void *Allocate(unsigned Size, unsigned Align = 8) const { return BumpAlloc.Allocate(Size, Align); } - void Deallocate(void *Ptr) { } + void Deallocate(void *Ptr) const { } PartialDiagnostic::StorageAllocator &getDiagAllocator() { return DiagAllocator; @@ -316,6 +340,8 @@ public: const LangOptions& getLangOptions() const { return LangOpts; } + Diagnostic &getDiagnostics() const; + FullSourceLoc getFullLoc(SourceLocation Loc) const { return FullSourceLoc(Loc,SourceMgr); } @@ -388,7 +414,6 @@ public: CanQualType VoidPtrTy, NullPtrTy; CanQualType OverloadTy; CanQualType DependentTy; - CanQualType UndeducedAutoTy; CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy; ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t, @@ -409,6 +434,19 @@ public: /// with this AST context, if any. ExternalASTSource *getExternalSource() const { return ExternalSource.get(); } + /// \brief Attach an AST mutation listener to the AST context. + /// + /// The AST mutation listener provides the ability to track modifications to + /// the abstract syntax tree entities committed after they were initially + /// created. + void setASTMutationListener(ASTMutationListener *Listener) { + this->Listener = Listener; + } + + /// \brief Retrieve a pointer to the AST mutation listener associated + /// with this AST context, if any. + ASTMutationListener *getASTMutationListener() const { return Listener; } + void PrintStats() const; const std::vector<Type*>& getTypes() const { return Types; } @@ -418,9 +456,9 @@ public: private: /// getExtQualType - Return a type with extended qualifiers. - QualType getExtQualType(const Type *Base, Qualifiers Quals); + QualType getExtQualType(const Type *Base, Qualifiers Quals) const; - QualType getTypeDeclTypeSlow(const TypeDecl *Decl); + QualType getTypeDeclTypeSlow(const TypeDecl *Decl) const; public: /// getAddSpaceQualType - Return the uniqued reference to the type for an @@ -428,24 +466,26 @@ public: /// 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); + QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace) const; /// 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, Qualifiers::GC gcAttr); + QualType getObjCGCQualType(QualType T, Qualifiers::GC gcAttr) const; /// getRestrictType - Returns the uniqued reference to the type for a /// 'restrict' qualified type. The resulting type has a union of the /// qualifiers from T and 'restrict'. - QualType getRestrictType(QualType T) { + QualType getRestrictType(QualType T) const { return T.withFastQualifiers(Qualifiers::Restrict); } /// getVolatileType - Returns the uniqued reference to the type for a /// 'volatile' qualified type. The resulting type has a union of the /// qualifiers from T and 'volatile'. - QualType getVolatileType(QualType T); + QualType getVolatileType(QualType T) const { + return T.withFastQualifiers(Qualifiers::Volatile); + } /// getConstType - Returns the uniqued reference to the type for a /// 'const' qualified type. The resulting type has a union of the @@ -453,44 +493,33 @@ public: /// /// It can be reasonably expected that this will always be /// equivalent to calling T.withConst(). - QualType getConstType(QualType T) { return T.withConst(); } - - /// getNoReturnType - Add or remove the noreturn attribute to the given type - /// which must be a FunctionType or a pointer to an allowable type or a - /// BlockPointer. - QualType getNoReturnType(QualType T, bool AddNoReturn = true); - - /// getCallConvType - Adds the specified calling convention attribute to - /// the given type, which must be a FunctionType or a pointer to an - /// allowable type. - QualType getCallConvType(QualType T, CallingConv CallConv); + QualType getConstType(QualType T) const { return T.withConst(); } - /// getRegParmType - Sets the specified regparm attribute to - /// the given type, which must be a FunctionType or a pointer to an - /// allowable type. - QualType getRegParmType(QualType T, unsigned RegParm); + /// adjustFunctionType - Change the ExtInfo on a function type. + const FunctionType *adjustFunctionType(const FunctionType *Fn, + FunctionType::ExtInfo EInfo); /// getComplexType - Return the uniqued reference to the type for a complex /// number with the specified element type. - QualType getComplexType(QualType T); - CanQualType getComplexType(CanQualType T) { + QualType getComplexType(QualType T) const; + CanQualType getComplexType(CanQualType T) const { return CanQualType::CreateUnsafe(getComplexType((QualType) T)); } /// getPointerType - Return the uniqued reference to the type for a pointer to /// the specified type. - QualType getPointerType(QualType T); - CanQualType getPointerType(CanQualType T) { + QualType getPointerType(QualType T) const; + CanQualType getPointerType(CanQualType T) const { return CanQualType::CreateUnsafe(getPointerType((QualType) T)); } /// getBlockPointerType - Return the uniqued reference to the type for a block /// of the specified type. - QualType getBlockPointerType(QualType T); + QualType getBlockPointerType(QualType T) const; /// This gets the struct used to keep track of the descriptor for pointer to /// blocks. - QualType getBlockDescriptorType(); + QualType getBlockDescriptorType() const; // Set the type for a Block descriptor type. void setBlockDescriptorType(QualType T); @@ -503,48 +532,56 @@ public: /// This gets the struct used to keep track of the extended descriptor for /// pointer to blocks. - QualType getBlockDescriptorExtendedType(); + QualType getBlockDescriptorExtendedType() const; // Set the type for a Block descriptor extended type. void setBlockDescriptorExtendedType(QualType T); /// Get the BlockDescriptorExtendedType type, or NULL if it hasn't yet been /// built. - QualType getRawBlockdescriptorExtendedType() { + QualType getRawBlockdescriptorExtendedType() const { if (BlockDescriptorExtendedType) return getTagDeclType(BlockDescriptorExtendedType); return QualType(); } + void setcudaConfigureCallDecl(FunctionDecl *FD) { + cudaConfigureCallDecl = FD; + } + FunctionDecl *getcudaConfigureCallDecl() { + return cudaConfigureCallDecl; + } + /// This gets the struct used to keep track of pointer to blocks, complete /// with captured variables. QualType getBlockParmType(bool BlockHasCopyDispose, - llvm::SmallVectorImpl<const Expr *> &Layout); + llvm::SmallVectorImpl<const Expr *> &Layout) const; /// This builds the struct used for __block variables. - QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty); + QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty) const; /// Returns true iff we need copy/dispose helpers for the given type. - bool BlockRequiresCopying(QualType Ty); + bool BlockRequiresCopying(QualType Ty) const; /// getLValueReferenceType - Return the uniqued reference to the type for an /// lvalue reference to the specified type. - QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true); + QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true) + const; /// getRValueReferenceType - Return the uniqued reference to the type for an /// rvalue reference to the specified type. - QualType getRValueReferenceType(QualType T); + QualType getRValueReferenceType(QualType T) const; /// 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); + QualType getMemberPointerType(QualType T, const Type *Cls) const; /// 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, - SourceRange Brackets); + unsigned IndexTypeQuals, + SourceRange Brackets) const; /// getDependentSizedArrayType - Returns a non-unique reference to /// the type for a dependently-sized array of the specified element @@ -552,30 +589,34 @@ public: /// comparable, at some point. QualType getDependentSizedArrayType(QualType EltTy, Expr *NumElts, ArrayType::ArraySizeModifier ASM, - unsigned EltTypeQuals, - SourceRange Brackets); + unsigned IndexTypeQuals, + SourceRange Brackets) const; /// 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); + unsigned IndexTypeQuals) const; /// 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); + unsigned IndexTypeQuals) const; + + /// getVariableArrayDecayedType - Returns a vla type where known sizes + /// are replaced with [*]. + QualType getVariableArrayDecayedType(QualType Ty) const; /// 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, - VectorType::AltiVecSpecific AltiVecSpec); + VectorType::VectorKind VecKind) const; /// 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); + QualType getExtVectorType(QualType VectorType, unsigned NumElts) const; /// getDependentSizedExtVectorType - Returns a non-unique reference to /// the type for a dependently-sized vector of the specified element @@ -583,30 +624,27 @@ public: /// comparable, at some point. QualType getDependentSizedExtVectorType(QualType VectorType, Expr *SizeExpr, - SourceLocation AttrLoc); + SourceLocation AttrLoc) const; /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'. /// QualType getFunctionNoProtoType(QualType ResultTy, - const FunctionType::ExtInfo &Info); + const FunctionType::ExtInfo &Info) const; - QualType getFunctionNoProtoType(QualType ResultTy) { + QualType getFunctionNoProtoType(QualType ResultTy) const { return getFunctionNoProtoType(ResultTy, FunctionType::ExtInfo()); } - /// 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, - bool hasAnyExceptionSpec, - unsigned NumExs, const QualType *ExArray, - const FunctionType::ExtInfo &Info); + /// getFunctionType - Return a normal function type with a typed + /// argument list. + QualType getFunctionType(QualType ResultTy, + const QualType *Args, unsigned NumArgs, + const FunctionProtoType::ExtProtoInfo &EPI) const; /// getTypeDeclType - Return the unique reference to the type for /// the specified type declaration. QualType getTypeDeclType(const TypeDecl *Decl, - const TypeDecl *PrevDecl = 0) { + const TypeDecl *PrevDecl = 0) const { assert(Decl && "Passed null for Decl param"); if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); @@ -621,77 +659,93 @@ public: /// getTypedefType - Return the unique reference to the type for the /// specified typename decl. - QualType getTypedefType(const TypedefDecl *Decl, QualType Canon = QualType()); + QualType getTypedefType(const TypedefDecl *Decl, QualType Canon = QualType()) + const; + + QualType getRecordType(const RecordDecl *Decl) const; - QualType getRecordType(const RecordDecl *Decl); + QualType getEnumType(const EnumDecl *Decl) const; - QualType getEnumType(const EnumDecl *Decl); + QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const; - QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST); + QualType getAttributedType(AttributedType::Kind attrKind, + QualType modifiedType, + QualType equivalentType); QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced, - QualType Replacement); + QualType Replacement) const; + QualType getSubstTemplateTypeParmPackType( + const TemplateTypeParmType *Replaced, + const TemplateArgument &ArgPack); QualType getTemplateTypeParmType(unsigned Depth, unsigned Index, bool ParameterPack, - IdentifierInfo *Name = 0); + IdentifierInfo *Name = 0) const; QualType getTemplateSpecializationType(TemplateName T, const TemplateArgument *Args, unsigned NumArgs, - QualType Canon = QualType()); + QualType Canon = QualType()) const; QualType getCanonicalTemplateSpecializationType(TemplateName T, const TemplateArgument *Args, - unsigned NumArgs); + unsigned NumArgs) const; QualType getTemplateSpecializationType(TemplateName T, const TemplateArgumentListInfo &Args, - QualType Canon = QualType()); + QualType Canon = QualType()) const; TypeSourceInfo * getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc, const TemplateArgumentListInfo &Args, - QualType Canon = QualType()); + QualType Canon = QualType()) const; + + QualType getParenType(QualType NamedType) const; QualType getElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - QualType NamedType); + QualType NamedType) const; QualType getDependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, - QualType Canon = QualType()); + QualType Canon = QualType()) const; QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, - const TemplateArgumentListInfo &Args); + const TemplateArgumentListInfo &Args) const; QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, unsigned NumArgs, - const TemplateArgument *Args); + const TemplateArgument *Args) const; + + QualType getPackExpansionType(QualType Pattern, + llvm::Optional<unsigned> NumExpansions); - QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl); + QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl) const; QualType getObjCObjectType(QualType Base, ObjCProtocolDecl * const *Protocols, - unsigned NumProtocols); + unsigned NumProtocols) const; /// getObjCObjectPointerType - Return a ObjCObjectPointerType type /// for the given ObjCObjectType. - QualType getObjCObjectPointerType(QualType OIT); + QualType getObjCObjectPointerType(QualType OIT) const; /// getTypeOfType - GCC extension. - QualType getTypeOfExprType(Expr *e); - QualType getTypeOfType(QualType t); + QualType getTypeOfExprType(Expr *e) const; + QualType getTypeOfType(QualType t) const; /// getDecltypeType - C++0x decltype. - QualType getDecltypeType(Expr *e); + QualType getDecltypeType(Expr *e) const; + + /// getAutoType - C++0x deduced auto type. + QualType getAutoType(QualType DeducedType) const; /// getTagDeclType - Return the unique reference to the type for the /// specified TagDecl (struct/union/class/enum) decl. - QualType getTagDeclType(const TagDecl *Decl); + QualType getTagDeclType(const TagDecl *Decl) const; /// 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). @@ -716,14 +770,14 @@ public: // getCFConstantStringType - Return the C structure type used to represent // constant CFStrings. - QualType getCFConstantStringType(); + QualType getCFConstantStringType() const; // getNSConstantStringType - Return the C structure type used to represent // constant NSStrings. - QualType getNSConstantStringType(); + QualType getNSConstantStringType() const; /// Get the structure type used to representation NSStrings, or NULL /// if it hasn't yet been built. - QualType getRawNSConstantStringType() { + QualType getRawNSConstantStringType() const { if (NSConstantStringTypeDecl) return getTagDeclType(NSConstantStringTypeDecl); return QualType(); @@ -733,7 +787,7 @@ public: /// Get the structure type used to representation CFStrings, or NULL /// if it hasn't yet been built. - QualType getRawCFConstantStringType() { + QualType getRawCFConstantStringType() const { if (CFConstantStringTypeDecl) return getTagDeclType(CFConstantStringTypeDecl); return QualType(); @@ -747,11 +801,11 @@ public: } //// This gets the struct used to keep track of fast enumerations. - QualType getObjCFastEnumerationStateType(); + QualType getObjCFastEnumerationStateType() const; /// Get the ObjCFastEnumerationState type, or NULL if it hasn't yet /// been built. - QualType getRawObjCFastEnumerationStateType() { + QualType getRawObjCFastEnumerationStateType() const { if (ObjCFastEnumerationStateTypeDecl) return getTagDeclType(ObjCFastEnumerationStateTypeDecl); return QualType(); @@ -763,7 +817,7 @@ public: void setFILEDecl(TypeDecl *FILEDecl) { this->FILEDecl = FILEDecl; } /// \brief Retrieve the C FILE type. - QualType getFILEType() { + QualType getFILEType() const { if (FILEDecl) return getTypeDeclType(FILEDecl); return QualType(); @@ -775,7 +829,7 @@ public: } /// \brief Retrieve the C jmp_buf type. - QualType getjmp_bufType() { + QualType getjmp_bufType() const { if (jmp_bufDecl) return getTypeDeclType(jmp_bufDecl); return QualType(); @@ -787,17 +841,22 @@ public: } /// \brief Retrieve the C sigjmp_buf type. - QualType getsigjmp_bufType() { + QualType getsigjmp_bufType() const { if (sigjmp_bufDecl) return getTypeDeclType(sigjmp_bufDecl); return QualType(); } + /// \brief The result type of logical operations, '<', '>', '!=', etc. + QualType getLogicalOperationType() const { + return getLangOptions().CPlusPlus ? BoolTy : IntTy; + } + /// 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); + const FieldDecl *Field=0) const; void getLegacyIntegralTypeEncoding(QualType &t) const; @@ -805,13 +864,18 @@ public: void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT, std::string &S) const; + /// getObjCEncodingForFunctionDecl - Returns the encoded type for this + //function. This is in the same format as Objective-C method encodings. + void getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, std::string& S); + /// getObjCEncodingForMethodDecl - Return the encoded type for this method /// declaration. - void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S); + void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S) + const; - /// getObjCEncodingForBlockDecl - Return the encoded type for this block + /// getObjCEncodingForBlock - Return the encoded type for this block /// declaration. - void getObjCEncodingForBlock(const BlockExpr *Expr, std::string& S); + std::string getObjCEncodingForBlock(const BlockExpr *blockExpr) const; /// getObjCEncodingForPropertyDecl - Return the encoded type for /// this method declaration. If non-NULL, Container must be either @@ -819,14 +883,14 @@ public: /// only be NULL when getting encodings for protocol properties. void getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, const Decl *Container, - std::string &S); + std::string &S) const; bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, - ObjCProtocolDecl *rProto); + ObjCProtocolDecl *rProto) const; /// getObjCEncodingTypeSize returns size of type for objective-c encoding /// purpose in characters. - CharUnits getObjCEncodingTypeSize(QualType t); + CharUnits getObjCEncodingTypeSize(QualType t) const; /// \brief Whether __[u]int128_t identifier is installed. bool isInt128Installed() const { return IsInt128Installed; } @@ -854,12 +918,12 @@ public: /// getCVRQualifiedType - Returns a type with additional const, /// volatile, or restrict qualifiers. - QualType getCVRQualifiedType(QualType T, unsigned CVR) { + QualType getCVRQualifiedType(QualType T, unsigned CVR) const { return getQualifiedType(T, Qualifiers::fromCVRMask(CVR)); } /// getQualifiedType - Returns a type with additional qualifiers. - QualType getQualifiedType(QualType T, Qualifiers Qs) { + QualType getQualifiedType(QualType T, Qualifiers Qs) const { if (!Qs.hasNonFastQualifiers()) return T.withFastQualifiers(Qs.getFastQualifiers()); QualifierCollector Qc(Qs); @@ -868,35 +932,41 @@ public: } /// getQualifiedType - Returns a type with additional qualifiers. - QualType getQualifiedType(const Type *T, Qualifiers Qs) { + QualType getQualifiedType(const Type *T, Qualifiers Qs) const { if (!Qs.hasNonFastQualifiers()) return QualType(T, Qs.getFastQualifiers()); return getExtQualType(T, Qs); } DeclarationNameInfo getNameForTemplate(TemplateName Name, - SourceLocation NameLoc); + SourceLocation NameLoc) const; TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin, - UnresolvedSetIterator End); + UnresolvedSetIterator End) const; TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, - TemplateDecl *Template); + TemplateDecl *Template) const; TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, - const IdentifierInfo *Name); + const IdentifierInfo *Name) const; TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, - OverloadedOperatorKind Operator); - + OverloadedOperatorKind Operator) const; + TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param, + const TemplateArgument &ArgPack) const; + enum GetBuiltinTypeError { GE_None, //< No error GE_Missing_stdio, //< Missing a type from <stdio.h> GE_Missing_setjmp //< Missing a type from <setjmp.h> }; - /// GetBuiltinType - Return the type for the specified builtin. - QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error); + /// GetBuiltinType - Return the type for the specified builtin. If + /// IntegerConstantArgs is non-null, it is filled in with a bitmask of + /// arguments to the builtin that are required to be integer constant + /// expressions. + QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error, + unsigned *IntegerConstantArgs = 0) const; private: CanQualType getFromTargetType(unsigned Type) const; @@ -909,11 +979,12 @@ public: /// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's /// garbage collection attribute. /// - Qualifiers::GC getObjCGCAttrKind(const QualType &Ty) const; + Qualifiers::GC getObjCGCAttrKind(QualType Ty) const; - /// areCompatibleVectorTypes - Return true if the given vector types either - /// are of the same unqualified type or if one is GCC and other - equivalent - /// AltiVec vector type. + /// areCompatibleVectorTypes - Return true if the given vector types + /// are of the same unqualified type or if they are equivalent to the same + /// GCC vector type, ignoring whether they are target-specific (AltiVec or + /// Neon) types. bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec); /// isObjCNSObjectType - Return true if this is an NSObject object with @@ -930,76 +1001,83 @@ public: /// 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) { + std::pair<uint64_t, unsigned> getTypeInfo(const Type *T) const; + std::pair<uint64_t, unsigned> getTypeInfo(QualType T) const { 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) { + uint64_t getTypeSize(QualType T) const { return getTypeInfo(T).first; } - uint64_t getTypeSize(const Type *T) { + uint64_t getTypeSize(const Type *T) const { return getTypeInfo(T).first; } /// getCharWidth - Return the size of the character type, in bits - uint64_t getCharWidth() { + uint64_t getCharWidth() const { return getTypeSize(CharTy); } + /// toCharUnitsFromBits - Convert a size in bits to a size in characters. + CharUnits toCharUnitsFromBits(int64_t BitSize) const; + + /// toBits - Convert a size in characters to a size in bits. + int64_t toBits(CharUnits CharSize) const; + /// getTypeSizeInChars - Return the size of the specified type, in characters. /// This method does not work on incomplete types. - CharUnits getTypeSizeInChars(QualType T); - CharUnits getTypeSizeInChars(const Type *T); + CharUnits getTypeSizeInChars(QualType T) const; + CharUnits getTypeSizeInChars(const Type *T) const; /// getTypeAlign - Return the ABI-specified alignment of a type, in bits. /// This method does not work on incomplete types. - unsigned getTypeAlign(QualType T) { + unsigned getTypeAlign(QualType T) const { return getTypeInfo(T).second; } - unsigned getTypeAlign(const Type *T) { + unsigned getTypeAlign(const Type *T) const { return getTypeInfo(T).second; } /// getTypeAlignInChars - Return the ABI-specified alignment of a type, in /// characters. This method does not work on incomplete types. - CharUnits getTypeAlignInChars(QualType T); - CharUnits getTypeAlignInChars(const Type *T); + CharUnits getTypeAlignInChars(QualType T) const; + CharUnits getTypeAlignInChars(const Type *T) const; - std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T); - std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T); + std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T) const; + std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T) const; /// 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); + unsigned getPreferredTypeAlign(const Type *T) const; /// getDeclAlign - Return a conservative estimate of the alignment of /// the specified decl. Note that bitfields do not have a valid alignment, so /// this method will assert on them. /// If @p RefAsPointee, references are treated like their underlying type /// (for alignof), else they're treated like pointers (for CodeGen). - CharUnits getDeclAlign(const Decl *D, bool RefAsPointee = false); + CharUnits getDeclAlign(const Decl *D, bool RefAsPointee = false) const; /// 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); + const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const; /// getASTObjCInterfaceLayout - Get or compute information about the /// layout of the specified Objective-C interface. - const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D); + const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) + const; - void DumpRecordLayout(const RecordDecl *RD, llvm::raw_ostream &OS); + void DumpRecordLayout(const RecordDecl *RD, llvm::raw_ostream &OS) const; /// 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); + getASTObjCImplementationLayout(const ObjCImplementationDecl *D) const; /// getKeyFunction - Get the key function for the given record decl, or NULL /// if there isn't one. The key function is, according to the Itanium C++ ABI @@ -1009,13 +1087,18 @@ public: /// of class definition. const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD); + bool isNearlyEmpty(const CXXRecordDecl *RD) const; + + MangleContext *createMangleContext(); + void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, - llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) + const; void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass, - llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) const; - unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI); + unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI) const; void CollectInheritedProtocols(const Decl *CDecl, llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols); @@ -1029,8 +1112,11 @@ public: /// 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. - CanQualType getCanonicalType(QualType T); - const Type *getCanonicalType(const Type *T) { + CanQualType getCanonicalType(QualType T) const { + return CanQualType::CreateUnsafe(T.getCanonicalType()); + } + + const Type *getCanonicalType(const Type *T) const { return T->getCanonicalTypeInternal().getTypePtr(); } @@ -1038,7 +1124,7 @@ public: /// corresponding to the specific potentially non-canonical one. /// Qualifiers are stripped off, functions are turned into function /// pointers, and arrays decay one level into pointers. - CanQualType getCanonicalParamType(QualType T); + CanQualType getCanonicalParamType(QualType T) const; /// \brief Determine whether the given types are equivalent. bool hasSameType(QualType T1, QualType T2) { @@ -1062,13 +1148,8 @@ public: /// \brief Determine whether the given types are equivalent after /// cvr-qualifiers have been removed. bool hasSameUnqualifiedType(QualType T1, QualType T2) { - CanQualType CT1 = getCanonicalType(T1); - CanQualType CT2 = getCanonicalType(T2); - - Qualifiers Quals; - QualType UnqualT1 = getUnqualifiedArrayType(CT1, Quals); - QualType UnqualT2 = getUnqualifiedArrayType(CT2, Quals); - return UnqualT1 == UnqualT2; + return getCanonicalType(T1).getTypePtr() == + getCanonicalType(T2).getTypePtr(); } bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2); @@ -1097,11 +1178,15 @@ public: /// 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); + getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const; + + /// \brief Retrieves the default calling convention to use for + /// C++ instance methods. + CallingConv getDefaultMethodCallConv(); /// \brief Retrieves the canonical representation of the given /// calling convention. - CallingConv getCanonicalCallConv(CallingConv CC) { + CallingConv getCanonicalCallConv(CallingConv CC) const { if (CC == CC_C) return CC_Default; return CC; @@ -1131,7 +1216,7 @@ public: /// 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); + TemplateName getCanonicalTemplateName(TemplateName Name) const; /// \brief Determine whether the given template names refer to the same /// template. @@ -1142,33 +1227,35 @@ public: /// The canonical template argument is the simplest template argument /// (which may be a type, value, expression, or declaration) that /// expresses the value of the argument. - TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg); + TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg) + const; /// 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) { + const ArrayType *getAsArrayType(QualType T) const; + const ConstantArrayType *getAsConstantArrayType(QualType T) const { return dyn_cast_or_null<ConstantArrayType>(getAsArrayType(T)); } - const VariableArrayType *getAsVariableArrayType(QualType T) { + const VariableArrayType *getAsVariableArrayType(QualType T) const { return dyn_cast_or_null<VariableArrayType>(getAsArrayType(T)); } - const IncompleteArrayType *getAsIncompleteArrayType(QualType T) { + const IncompleteArrayType *getAsIncompleteArrayType(QualType T) const { return dyn_cast_or_null<IncompleteArrayType>(getAsArrayType(T)); } - const DependentSizedArrayType *getAsDependentSizedArrayType(QualType T) { + const DependentSizedArrayType *getAsDependentSizedArrayType(QualType T) + const { return dyn_cast_or_null<DependentSizedArrayType>(getAsArrayType(T)); } /// getBaseElementType - Returns the innermost element type of an array type. /// For example, will return "int" for int[m][n] - QualType getBaseElementType(const ArrayType *VAT); + QualType getBaseElementType(const ArrayType *VAT) const; /// getBaseElementType - Returns the innermost element type of a type /// (which needn't actually be an array type). - QualType getBaseElementType(QualType QT); + QualType getBaseElementType(QualType QT) const; /// getConstantArrayElementCount - Returns number of constant array elements. uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const; @@ -1179,30 +1266,30 @@ public: /// 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); + QualType getArrayDecayedType(QualType T) const; /// getPromotedIntegerType - Returns the type that Promotable will /// promote to: C99 6.3.1.1p2, assuming that Promotable is a promotable /// integer type. - QualType getPromotedIntegerType(QualType PromotableType); + QualType getPromotedIntegerType(QualType PromotableType) const; /// \brief Whether this is a promotable bitfield reference according /// to C99 6.3.1.1p2, bullet 2 (and GCC extensions). /// /// \returns the type this bit-field will promote to, or NULL if no /// promotion occurs. - QualType isPromotableBitField(Expr *E); + QualType isPromotableBitField(Expr *E) const; /// 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); + int getIntegerTypeOrder(QualType LHS, QualType RHS) const; /// 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); + int getFloatingTypeOrder(QualType LHS, QualType RHS) const; /// getFloatingTypeOfSizeWithinDomain - Returns a real floating /// point or a complex type (based on typeDomain/typeSize). @@ -1213,7 +1300,7 @@ public: private: // Helper for integer ordering - unsigned getIntegerRank(Type* T); + unsigned getIntegerRank(const Type *T) const; public: @@ -1260,14 +1347,15 @@ public: bool Unqualified = false); QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified = false); + QualType mergeFunctionArgumentTypes(QualType, QualType, + bool OfBlockPointer=false, + bool Unqualified = false); + QualType mergeTransparentUnionType(QualType, QualType, + bool OfBlockPointer=false, + bool Unqualified = false); QualType mergeObjCGCQualifiers(QualType, QualType); - /// UsualArithmeticConversionsType - handles the various conversions - /// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9) - /// and returns the result type of that conversion. - QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs); - void ResetObjCLayout(const ObjCContainerDecl *CD) { ObjCLayouts[CD] = 0; } @@ -1278,7 +1366,7 @@ public: // 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); + unsigned getIntWidth(QualType T) const; // 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 @@ -1303,7 +1391,7 @@ public: /// 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 MakeIntValue(uint64_t Value, QualType Type) const { llvm::APSInt Res(getIntWidth(Type), !Type->isSignedIntegerType()); Res = Value; return Res; @@ -1314,12 +1402,23 @@ public: /// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists. ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D); + /// \brief returns true if there is at lease one @implementation in TU. + bool AnyObjCImplementation() { + return !ObjCImpls.empty(); + } + /// \brief Set the implementation of ObjCInterfaceDecl. void setObjCImplementation(ObjCInterfaceDecl *IFaceD, ObjCImplementationDecl *ImplD); /// \brief Set the implementation of ObjCCategoryDecl. void setObjCImplementation(ObjCCategoryDecl *CatD, ObjCCategoryImplDecl *ImplD); + + /// \brief Set the copy inialization expression of a block var decl. + void setBlockVarCopyInits(VarDecl*VD, Expr* Init); + /// \brief Get the copy initialization expression of VarDecl,or NULL if + /// none exists. + Expr *getBlockVarCopyInits(const VarDecl*VD); /// \brief Allocate an uninitialized TypeSourceInfo. /// @@ -1332,13 +1431,14 @@ public: /// /// \param Size the size of the type info to create, or 0 if the size /// should be calculated based on the type. - TypeSourceInfo *CreateTypeSourceInfo(QualType T, unsigned Size = 0); + TypeSourceInfo *CreateTypeSourceInfo(QualType T, unsigned Size = 0) const; /// \brief Allocate a TypeSourceInfo where all locations have been /// initialized to a given location, which defaults to the empty /// location. TypeSourceInfo * - getTrivialTypeSourceInfo(QualType T, SourceLocation Loc = SourceLocation()); + getTrivialTypeSourceInfo(QualType T, + SourceLocation Loc = SourceLocation()) const; TypeSourceInfo *getNullTypeSourceInfo() { return &NullTypeSourceInfo; } @@ -1407,10 +1507,11 @@ private: bool ExpandStructures, const FieldDecl *Field, bool OutermostType = false, - bool EncodingProperty = false); + bool EncodingProperty = false) const; - const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D, - const ObjCImplementationDecl *Impl); + const ASTRecordLayout & + getObjCLayout(const ObjCInterfaceDecl *D, + const ObjCImplementationDecl *Impl) const; private: /// \brief A set of deallocations that should be performed when the @@ -1423,8 +1524,8 @@ private: llvm::PointerIntPair<StoredDeclsMap*,1> LastSDM; /// \brief A counter used to uniquely identify "blocks". - unsigned int UniqueBlockByRefTypeID; - unsigned int UniqueBlockParmTypeID; + mutable unsigned int UniqueBlockByRefTypeID; + mutable unsigned int UniqueBlockParmTypeID; friend class DeclContext; friend class DeclarationNameTable; @@ -1469,7 +1570,7 @@ static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) { /// @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, +inline void *operator new(size_t Bytes, const clang::ASTContext &C, size_t Alignment) throw () { return C.Allocate(Bytes, Alignment); } @@ -1479,7 +1580,7 @@ inline void *operator new(size_t Bytes, clang::ASTContext &C, /// 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) +inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t) throw () { C.Deallocate(Ptr); } @@ -1503,7 +1604,7 @@ inline void operator delete(void *Ptr, clang::ASTContext &C, size_t) /// @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, +inline void *operator new[](size_t Bytes, const clang::ASTContext& C, size_t Alignment = 8) throw () { return C.Allocate(Bytes, Alignment); } @@ -1514,7 +1615,7 @@ inline void *operator new[](size_t Bytes, clang::ASTContext& C, /// 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) +inline void operator delete[](void *Ptr, const clang::ASTContext &C, size_t) throw () { C.Deallocate(Ptr); } diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h index 7cbf3a511705..1ab53b3e9148 100644 --- a/include/clang/AST/ASTDiagnostic.h +++ b/include/clang/AST/ASTDiagnostic.h @@ -15,7 +15,7 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, #define ASTSTART #include "clang/Basic/DiagnosticASTKinds.inc" #undef DIAG diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index 9380058118c5..b659ce74bb7c 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -45,13 +45,13 @@ namespace clang { /// \brief The file managers we're importing to and from. FileManager &ToFileManager, &FromFileManager; - - /// \brief The diagnostics object that we should use to emit diagnostics. - Diagnostic &Diags; + + /// \brief Whether to perform a minimal import. + bool Minimal; /// \brief Mapping from the already-imported types in the "from" context /// to the corresponding types in the "to" context. - llvm::DenseMap<Type *, Type *> ImportedTypes; + llvm::DenseMap<const Type *, const Type *> ImportedTypes; /// \brief Mapping from the already-imported declarations in the "from" /// context to the corresponding declarations in the "to" context. @@ -63,7 +63,7 @@ namespace clang { /// \brief Mapping from the already-imported FileIDs in the "from" source /// manager to the corresponding FileIDs in the "to" source manager. - llvm::DenseMap<unsigned, FileID> ImportedFileIDs; + llvm::DenseMap<FileID, FileID> ImportedFileIDs; /// \brief Imported, anonymous tag declarations that are missing their /// corresponding typedefs. @@ -74,12 +74,29 @@ namespace clang { NonEquivalentDeclSet NonEquivalentDecls; public: - ASTImporter(Diagnostic &Diags, - ASTContext &ToContext, FileManager &ToFileManager, - ASTContext &FromContext, FileManager &FromFileManager); + /// \brief Create a new AST importer. + /// + /// \param ToContext The context we'll be importing into. + /// + /// \param ToFileManager The file manager we'll be importing into. + /// + /// \param FromContext The context we'll be importing from. + /// + /// \param FromFileManager The file manager we'll be importing into. + /// + /// \param MinimalImport If true, the importer will attempt to import + /// as little as it can, e.g., by importing declarations as forward + /// declarations that can be completed at a later point. + ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, + ASTContext &FromContext, FileManager &FromFileManager, + bool MinimalImport); virtual ~ASTImporter(); + /// \brief Whether the importer will perform a minimal import, creating + /// to-be-completed forward declarations when possible. + bool isMinimalImport() const { return Minimal; } + /// \brief Import the given type from the "from" context into the "to" /// context. /// @@ -129,6 +146,10 @@ namespace clang { /// context, or NULL if an error occurred. NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS); + /// \brief Import the goven template name from the "from" context into the + /// "to" context. + TemplateName Import(TemplateName From); + /// \brief Import the given source location from the "from" context into /// the "to" context. /// @@ -154,7 +175,7 @@ namespace clang { /// into the "to" context. /// /// \returns the equivalent identifier in the "to" context. - IdentifierInfo *Import(IdentifierInfo *FromId); + IdentifierInfo *Import(const IdentifierInfo *FromId); /// \brief Import the given Objective-C selector from the "from" /// context into the "to" context. @@ -169,6 +190,12 @@ namespace clang { /// context. FileID Import(FileID); + /// \brief Import the definition of the given declaration, including all of + /// the declarations it contains. + /// + /// This routine is intended to be used + void ImportDefinition(Decl *From); + /// \brief Cope with a name conflict when importing a declaration into the /// given context. /// @@ -212,9 +239,6 @@ namespace clang { /// \brief Retrieve the file manager that AST nodes are being imported from. FileManager &getFromFileManager() const { return FromFileManager; } - - /// \brief Retrieve the diagnostic formatter. - Diagnostic &getDiags() const { return Diags; } /// \brief Report a diagnostic in the "to" context. DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID); @@ -228,12 +252,13 @@ namespace clang { /// \brief Note that we have imported the "from" declaration by mapping it /// to the (potentially-newly-created) "to" declaration. /// - /// \returns \p To - Decl *Imported(Decl *From, Decl *To); + /// Subclasses can override this function to observe all of the \c From -> + /// \c To declaration mappings as they are imported. + virtual Decl *Imported(Decl *From, Decl *To); /// \brief Determine whether the given types are structurally /// equivalent. - bool IsStructurallyEquivalent(QualType From, QualType To); + bool IsStructurallyEquivalent(QualType From, QualType To); }; } diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h new file mode 100644 index 000000000000..01e618024913 --- /dev/null +++ b/include/clang/AST/ASTMutationListener.h @@ -0,0 +1,48 @@ +//===--- ASTMutationListener.h - AST Mutation 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 ASTMutationListener interface. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_ASTMUTATIONLISTENER_H +#define LLVM_CLANG_AST_ASTMUTATIONLISTENER_H + +namespace clang { + class Decl; + class DeclContext; + class TagDecl; + class CXXRecordDecl; + class ClassTemplateDecl; + class ClassTemplateSpecializationDecl; + +/// \brief An abstract interface that should be implemented by listeners +/// that want to be notified when an AST entity gets modified after its +/// initial creation. +class ASTMutationListener { +public: + virtual ~ASTMutationListener(); + + /// \brief A new TagDecl definition was completed. + virtual void CompletedTagDefinition(const TagDecl *D) { } + + /// \brief A new declaration with name has been added to a DeclContext. + virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D) {} + + /// \brief An implicit member was added after the definition was completed. + virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {} + + /// \brief A template specialization (or partial one) was added to the + /// template declaration. + virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, + const ClassTemplateSpecializationDecl *D) {} +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 62ca49fbf3b1..67968fde2d6b 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -36,19 +36,19 @@ namespace clang { } // Defined in ASTContext.h -void *operator new(size_t Bytes, clang::ASTContext &C, +void *operator new(size_t Bytes, const clang::ASTContext &C, size_t Alignment = 16) throw (); // FIXME: Being forced to not have a default argument here due to redeclaration // rules on default arguments sucks -void *operator new[](size_t Bytes, clang::ASTContext &C, +void *operator new[](size_t Bytes, const clang::ASTContext &C, size_t Alignment) throw (); // It is good practice to pair new/delete operators. Also, MSVC gives many // warnings if a matching delete overload is not declared, even though the // throw() spec guarantees it will not be implicitly called. -void operator delete(void *Ptr, clang::ASTContext &C, size_t) +void operator delete(void *Ptr, const clang::ASTContext &C, size_t) throw (); -void operator delete[](void *Ptr, clang::ASTContext &C, size_t) +void operator delete[](void *Ptr, const clang::ASTContext &C, size_t) throw (); namespace clang { @@ -58,9 +58,10 @@ class Attr { private: SourceLocation Loc; unsigned AttrKind : 16; - bool Inherited : 1; protected: + bool Inherited : 1; + virtual ~Attr(); void* operator new(size_t bytes) throw() { @@ -88,10 +89,6 @@ protected: public: - /// \brief Whether this attribute should be merged to new - /// declarations. - virtual bool isMerged() const { return true; } - attr::Kind getKind() const { return static_cast<attr::Kind>(AttrKind); } @@ -100,7 +97,6 @@ public: void setLocation(SourceLocation L) { Loc = L; } bool isInherited() const { return Inherited; } - void setInherited(bool I) { Inherited = I; } // Clone this attribute. virtual Attr* clone(ASTContext &C) const = 0; @@ -109,6 +105,21 @@ public: static bool classof(const Attr *) { return true; } }; +class InheritableAttr : public Attr { +protected: + InheritableAttr(attr::Kind AK, SourceLocation L) + : Attr(AK, L) {} + +public: + void setInherited(bool I) { Inherited = I; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() <= attr::LAST_INHERITABLE; + } + static bool classof(const InheritableAttr *) { return true; } +}; + #include "clang/AST/Attrs.inc" /// AttrVec - A vector of Attr, which is how they are stored on the AST. diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index 5a84e404a1b6..2d30cb3b8b62 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -20,6 +20,7 @@ #include "clang/AST/Type.h" #include "clang/AST/TypeOrdering.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include <list> #include <map> @@ -359,7 +360,11 @@ public: /// subobjects of that type. class CXXFinalOverriderMap : public llvm::DenseMap<const CXXMethodDecl *, OverridingMethods> { }; - + +/// \brief A set of all the primary bases for a class. +class CXXIndirectPrimaryBaseSet + : public llvm::SmallSet<const CXXRecordDecl*, 32> { }; + } // end namespace clang #endif diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index dad4dfc926e1..4d7fcfd1d121 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -66,7 +66,16 @@ public: /// \brief Retrieve the underlying type pointer, which refers to a /// canonical type. - T *getTypePtr() const { return cast_or_null<T>(Stored.getTypePtr()); } + /// + /// The underlying pointer must not be NULL. + const T *getTypePtr() const { return cast<T>(Stored.getTypePtr()); } + + /// \brief Retrieve the underlying type pointer, which refers to a + /// canonical type, or NULL. + /// + const T *getTypePtrOrNull() const { + return cast_or_null<T>(Stored.getTypePtrOrNull()); + } /// \brief Implicit conversion to a qualified type. operator QualType() const { return Stored; } @@ -78,6 +87,8 @@ public: return Stored.isNull(); } + SplitQualType split() const { return Stored.split(); } + /// \brief Retrieve a canonical type pointer with a different static type, /// upcasting or downcasting as needed. /// @@ -216,7 +227,7 @@ protected: public: /// \brief Retrieve the pointer to the underlying Type - T* getTypePtr() const { return Stored.getTypePtr(); } + const T *getTypePtr() const { return Stored.getTypePtr(); } /// \brief Implicit conversion to the underlying pointer. /// @@ -225,7 +236,7 @@ public: /// @code /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... } /// @endcode - operator const T*() const { return this->Stored.getTypePtr(); } + operator const T*() const { return this->Stored.getTypePtrOrNull(); } /// \brief Try to convert the given canonical type to a specific structural /// type. @@ -336,7 +347,7 @@ namespace llvm { /// to return smart pointer (proxies?). template<typename T> struct simplify_type<const ::clang::CanQual<T> > { - typedef T* SimpleType; + typedef const T *SimpleType; static SimpleType getSimplifiedValue(const ::clang::CanQual<T> &Val) { return Val.getTypePtr(); } @@ -630,7 +641,6 @@ struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> { LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getAddressSpace) }; template<> diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h index 0bb4b769d0f3..cf909e88220f 100644 --- a/include/clang/AST/CharUnits.h +++ b/include/clang/AST/CharUnits.h @@ -14,7 +14,9 @@ #ifndef LLVM_CLANG_AST_CHARUNITS_H #define LLVM_CLANG_AST_CHARUNITS_H -#include "llvm/System/DataTypes.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/MathExtras.h" namespace clang { @@ -131,12 +133,24 @@ namespace clang { CharUnits operator- (const CharUnits &Other) const { return CharUnits(Quantity - Other.Quantity); } + CharUnits operator- () const { + return CharUnits(-Quantity); + } + // Conversions. /// getQuantity - Get the raw integer representation of this quantity. QuantityType getQuantity() const { return Quantity; } + /// RoundUpToAlignment - Returns the next integer (mod 2**64) that is + /// greater than or equal to this quantity and is a multiple of \arg + /// Align. Align must be non-zero. + CharUnits RoundUpToAlignment(const CharUnits &Align) { + return CharUnits(llvm::RoundUpToAlignment(Quantity, + Align.Quantity)); + } + }; // class CharUnit } // namespace clang @@ -146,4 +160,38 @@ inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale, return CU * Scale; } +namespace llvm { + +template<> struct DenseMapInfo<clang::CharUnits> { + static clang::CharUnits getEmptyKey() { + clang::CharUnits::QuantityType Quantity = + DenseMapInfo<clang::CharUnits::QuantityType>::getEmptyKey(); + + return clang::CharUnits::fromQuantity(Quantity); + } + + static clang::CharUnits getTombstoneKey() { + clang::CharUnits::QuantityType Quantity = + DenseMapInfo<clang::CharUnits::QuantityType>::getTombstoneKey(); + + return clang::CharUnits::fromQuantity(Quantity); + } + + static unsigned getHashValue(const clang::CharUnits &CU) { + clang::CharUnits::QuantityType Quantity = CU.getQuantity(); + return DenseMapInfo<clang::CharUnits::QuantityType>::getHashValue(Quantity); + } + + static bool isEqual(const clang::CharUnits &LHS, + const clang::CharUnits &RHS) { + return LHS == RHS; + } +}; + +template <> struct isPodLike<clang::CharUnits> { + static const bool value = true; +}; + +} // end namespace llvm + #endif // LLVM_CLANG_AST_CHARUNITS_H diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 674925532210..ee515da0835c 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -36,6 +36,7 @@ class FunctionTemplateSpecializationInfo; class DependentFunctionTemplateSpecializationInfo; class TypeLoc; class UnresolvedSetImpl; +class LabelStmt; /// \brief A container of type source information. /// @@ -196,9 +197,86 @@ public: /// determine whether it's an instance member of its class. bool isCXXInstanceMember() const; + class LinkageInfo { + Linkage linkage_; + Visibility visibility_; + bool explicit_; + + public: + LinkageInfo() : linkage_(ExternalLinkage), visibility_(DefaultVisibility), + explicit_(false) {} + LinkageInfo(Linkage L, Visibility V, bool E) + : linkage_(L), visibility_(V), explicit_(E) {} + + static LinkageInfo external() { + return LinkageInfo(); + } + static LinkageInfo internal() { + return LinkageInfo(InternalLinkage, DefaultVisibility, false); + } + static LinkageInfo uniqueExternal() { + return LinkageInfo(UniqueExternalLinkage, DefaultVisibility, false); + } + static LinkageInfo none() { + return LinkageInfo(NoLinkage, DefaultVisibility, false); + } + + Linkage linkage() const { return linkage_; } + Visibility visibility() const { return visibility_; } + bool visibilityExplicit() const { return explicit_; } + + void setLinkage(Linkage L) { linkage_ = L; } + void setVisibility(Visibility V) { visibility_ = V; } + void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; } + void setVisibility(LinkageInfo Other) { + setVisibility(Other.visibility(), Other.visibilityExplicit()); + } + + void mergeLinkage(Linkage L) { + setLinkage(minLinkage(linkage(), L)); + } + void mergeLinkage(LinkageInfo Other) { + setLinkage(minLinkage(linkage(), Other.linkage())); + } + + void mergeVisibility(Visibility V) { + setVisibility(minVisibility(visibility(), V)); + } + void mergeVisibility(Visibility V, bool E) { + setVisibility(minVisibility(visibility(), V), visibilityExplicit() || E); + } + void mergeVisibility(LinkageInfo Other) { + mergeVisibility(Other.visibility(), Other.visibilityExplicit()); + } + + void merge(LinkageInfo Other) { + mergeLinkage(Other); + mergeVisibility(Other); + } + void merge(std::pair<Linkage,Visibility> LV) { + mergeLinkage(LV.first); + mergeVisibility(LV.second); + } + + friend LinkageInfo merge(LinkageInfo L, LinkageInfo R) { + L.merge(R); + return L; + } + }; + /// \brief Determine what kind of linkage this entity has. Linkage getLinkage() const; + /// \brief Determines the visibility of this entity. + Visibility getVisibility() const { return getLinkageAndVisibility().visibility(); } + + /// \brief Determines the linkage and visibility of this entity. + LinkageInfo getLinkageAndVisibility() const; + + /// \brief Clear the linkage cache in response to a change + /// to the declaration. + void ClearLinkageCache(); + /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for /// the underlying named decl. NamedDecl *getUnderlyingDecl(); @@ -217,6 +295,29 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, return OS; } +/// LabelDecl - Represents the declaration of a label. Labels also have a +/// corresponding LabelStmt, which indicates the position that the label was +/// defined at. For normal labels, the location of the decl is the same as the +/// location of the statement. For GNU local labels (__label__), the decl +/// location is where the __label__ is. +class LabelDecl : public NamedDecl { + LabelStmt *TheStmt; + LabelDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *II, LabelStmt *S) + : NamedDecl(Label, DC, L, II), TheStmt(S) {} + +public: + static LabelDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *II); + + LabelStmt *getStmt() const { return TheStmt; } + void setStmt(LabelStmt *T) { TheStmt = T; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const LabelDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Label; } +}; + /// NamespaceDecl - Represent a C++ namespace. class NamespaceDecl : public NamedDecl, public DeclContext { bool IsInline : 1; @@ -232,7 +333,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext { // NextNamespace points to the next extended declaration. // OrigNamespace points to the original namespace declaration. // OrigNamespace of the first namespace decl points to its anonymous namespace - NamespaceDecl *NextNamespace; + LazyDeclPtr NextNamespace; /// \brief A pointer to either the original namespace definition for /// this namespace (if the boolean value is false) or the anonymous @@ -250,7 +351,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext { NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace), - IsInline(false), NextNamespace(0), OrigOrAnonNamespace(0, true) { } + IsInline(false), NextNamespace(), OrigOrAnonNamespace(0, true) { } public: static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, @@ -281,8 +382,10 @@ public: /// \brief Return the next extended namespace declaration or null if there /// is none. - NamespaceDecl *getNextNamespace() { return NextNamespace; } - const NamespaceDecl *getNextNamespace() const { return NextNamespace; } + NamespaceDecl *getNextNamespace(); + const NamespaceDecl *getNextNamespace() const { + return const_cast<NamespaceDecl *>(this)->getNextNamespace(); + } /// \brief Set the next extended namespace declaration. void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; } @@ -331,9 +434,9 @@ public: SourceLocation getLBracLoc() const { return LBracLoc; } SourceLocation getRBracLoc() const { return RBracLoc; } - void setLBracLoc(SourceLocation LBrace) { LBracLoc = LBrace; } - void setRBracLoc(SourceLocation RBrace) { RBracLoc = RBrace; } - + void setLBracLoc(SourceLocation L) { LBracLoc = L; } + void setRBracLoc(SourceLocation R) { RBracLoc = R; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const NamespaceDecl *D) { return true; } @@ -471,6 +574,9 @@ public: static bool classofKind(Kind K) { return K >= firstDeclarator && K <= lastDeclarator; } + + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// \brief Structure used to store a statement, the constant value to @@ -545,15 +651,21 @@ private: /// \brief Whether this local variable could be allocated in the return /// slot of its function, enabling the named return value optimization (NRVO). bool NRVOVariable : 1; + + /// \brief Whether this variable has a deduced C++0x auto type for which we're + /// currently parsing the initializer. + bool ParsingAutoInit : 1; friend class StmtIteratorBase; + friend class ASTDeclReader; + protected: VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass SC, StorageClass SCAsWritten) : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(), ThreadSpecified(false), HasCXXDirectInit(false), - ExceptionVar(false), NRVOVariable(false) { + ExceptionVar(false), NRVOVariable(false), ParsingAutoInit(false) { SClass = SC; SClassAsWritten = SCAsWritten; } @@ -582,10 +694,7 @@ public: StorageClass getStorageClassAsWritten() const { return (StorageClass) SClassAsWritten; } - void setStorageClass(StorageClass SC) { - assert(isLegalForVariable(SC)); - SClass = SC; - } + void setStorageClass(StorageClass SC); void setStorageClassAsWritten(StorageClass SC) { assert(isLegalForVariable(SC)); SClassAsWritten = SC; @@ -630,13 +739,13 @@ public: /// external, C linkage. bool isExternC() const; - /// isBlockVarDecl - Returns true for local variable declarations. Note that - /// this includes static variables inside of functions. It also includes - /// variables inside blocks. + /// isLocalVarDecl - Returns true for local variable declarations + /// other than parameters. Note that this includes static variables + /// inside of functions. It also includes variables inside blocks. /// /// void foo() { int x; static int y; extern int z; } /// - bool isBlockVarDecl() const { + bool isLocalVarDecl() const { if (getKind() != Decl::Var) return false; if (const DeclContext *DC = getDeclContext()) @@ -644,8 +753,8 @@ public: return false; } - /// isFunctionOrMethodVarDecl - Similar to isBlockVarDecl, but excludes - /// variables declared in blocks. + /// isFunctionOrMethodVarDecl - Similar to isLocalVarDecl, but + /// excludes variables declared in blocks. bool isFunctionOrMethodVarDecl() const { if (getKind() != Decl::Var) return false; @@ -683,6 +792,10 @@ public: /// definition. DefinitionKind isThisDeclarationADefinition() const; + /// \brief Check whether this variable is defined in this + /// translation unit. + DefinitionKind hasDefinition() const; + /// \brief Get the tentative definition that acts as the real definition in /// a TU. Returns null if there is a proper definition available. VarDecl *getActingDefinition(); @@ -733,7 +846,7 @@ public: const Expr *getAnyInitializer(const VarDecl *&D) const; bool hasInit() const { - return !Init.isNull(); + return !Init.isNull() && (Init.is<Stmt *>() || Init.is<EvaluatedStmt *>()); } const Expr *getInit() const { if (Init.isNull()) @@ -776,6 +889,18 @@ public: void setInit(Expr *I); + /// \brief Check whether we are in the process of parsing an initializer + /// needed to deduce the type of this variable. + bool isParsingAutoInit() const { + return ParsingAutoInit; + } + + /// \brief Note whether we are currently parsing an initializer needed to + /// deduce the type of this variable. + void setParsingAutoInit(bool P) { + ParsingAutoInit = P; + } + EvaluatedStmt *EnsureEvaluatedStmt() const { EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>(); if (!Eval) { @@ -928,7 +1053,9 @@ class ImplicitParamDecl : public VarDecl { protected: ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType Tw) - : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, SC_None, SC_None) {} + : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, SC_None, SC_None) { + setImplicit(); + } public: static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, @@ -1046,6 +1173,10 @@ public: return getType(); } + /// \brief Determine whether this parameter is actually a function + /// parameter pack. + bool isParameterPack() 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 @@ -1096,13 +1227,13 @@ private: unsigned SClass : 2; unsigned SClassAsWritten : 2; bool IsInline : 1; + bool IsInlineSpecified : 1; bool IsVirtualAsWritten : 1; bool IsPure : 1; bool HasInheritedPrototype : 1; bool HasWrittenPrototype : 1; bool IsDeleted : 1; bool IsTrivial : 1; // sunk from CXXMethodDecl - bool IsCopyAssignment : 1; // sunk from CXXMethodDecl bool HasImplicitReturnZero : 1; /// \brief End part of this FunctionDecl's source range. @@ -1136,19 +1267,54 @@ private: /// declaration name embedded in the DeclaratorDecl base class. DeclarationNameLoc DNLoc; + /// \brief Specify that this function declaration is actually a function + /// template specialization. + /// + /// \param C the ASTContext. + /// + /// \param Template the function template that this function template + /// specialization specializes. + /// + /// \param TemplateArgs the template arguments that produced this + /// function template specialization from the template. + /// + /// \param InsertPos If non-NULL, the position in the function template + /// specialization set where the function template specialization data will + /// be inserted. + /// + /// \param TSK the kind of template specialization this is. + /// + /// \param TemplateArgsAsWritten location info of template arguments. + /// + /// \param PointOfInstantiation point at which the function template + /// specialization was first instantiated. + void setFunctionTemplateSpecialization(ASTContext &C, + FunctionTemplateDecl *Template, + const TemplateArgumentList *TemplateArgs, + void *InsertPos, + TemplateSpecializationKind TSK, + const TemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation PointOfInstantiation); + + /// \brief Specify that this record is an instantiation of the + /// member function FD. + void setInstantiationOfMemberFunction(ASTContext &C, FunctionDecl *FD, + TemplateSpecializationKind TSK); + + void setParams(ASTContext &C, ParmVarDecl **NewParamInfo, unsigned NumParams); + protected: FunctionDecl(Kind DK, DeclContext *DC, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - StorageClass S, StorageClass SCAsWritten, bool isInline) + StorageClass S, StorageClass SCAsWritten, bool isInlineSpecified) : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo), DeclContext(DK), ParamInfo(0), Body(), - SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInline), + SClass(S), SClassAsWritten(SCAsWritten), + IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), - IsCopyAssignment(false), - HasImplicitReturnZero(false), - EndRangeLoc(NameInfo.getEndLoc()), + HasImplicitReturnZero(false), EndRangeLoc(NameInfo.getEndLoc()), TemplateOrSpecialization(), DNLoc(NameInfo.getInfo()) {} @@ -1169,11 +1335,11 @@ public: TypeSourceInfo *TInfo, StorageClass S = SC_None, StorageClass SCAsWritten = SC_None, - bool isInline = false, + bool isInlineSpecified = false, bool hasWrittenPrototype = true) { DeclarationNameInfo NameInfo(N, L); return FunctionDecl::Create(C, DC, NameInfo, T, TInfo, S, SCAsWritten, - isInline, hasWrittenPrototype); + isInlineSpecified, hasWrittenPrototype); } static FunctionDecl *Create(ASTContext &C, DeclContext *DC, @@ -1181,7 +1347,7 @@ public: QualType T, TypeSourceInfo *TInfo, StorageClass S = SC_None, StorageClass SCAsWritten = SC_None, - bool isInline = false, + bool isInlineSpecified = false, bool hasWrittenPrototype = true); DeclarationNameInfo getNameInfo() const { @@ -1246,7 +1412,7 @@ public: /// 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; } + void setPure(bool P = true); /// Whether this function is "trivial" in some specialized C++ senses. /// Can only be true for default constructors, copy constructors, @@ -1255,9 +1421,6 @@ public: bool isTrivial() const { return IsTrivial; } void setTrivial(bool IT) { IsTrivial = IT; } - bool isCopyAssignment() const { return IsCopyAssignment; } - void setCopyAssignment(bool CA) { IsCopyAssignment = CA; } - /// Whether falling off this function implicitly returns null/zero. /// If a more specific implicit return value is required, front-ends /// should synthesize the appropriate return statements. @@ -1273,7 +1436,6 @@ public: } bool hasWrittenPrototype() const { return HasWrittenPrototype; } - void setHasWrittenPrototype(bool P) { HasWrittenPrototype = P; } /// \brief Whether this function inherited its prototype from a /// previous declaration. @@ -1343,7 +1505,9 @@ public: assert(i < getNumParams() && "Illegal param #"); return ParamInfo[i]; } - void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams); + void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) { + setParams(getASTContext(), NewParamInfo, NumParams); + } /// getMinRequiredArguments - Returns the minimum number of arguments /// needed to call this function. This may be fewer than the number of @@ -1361,31 +1525,32 @@ public: } StorageClass getStorageClass() const { return StorageClass(SClass); } - void setStorageClass(StorageClass SC) { - assert(isLegalForFunction(SC)); - SClass = SC; - } + void setStorageClass(StorageClass SC); StorageClass getStorageClassAsWritten() const { return StorageClass(SClassAsWritten); } - void setStorageClassAsWritten(StorageClass SC) { - assert(isLegalForFunction(SC)); - SClassAsWritten = SC; - } /// \brief Determine whether the "inline" keyword was specified for this /// function. - bool isInlineSpecified() const { return IsInline; } + bool isInlineSpecified() const { return IsInlineSpecified; } /// Set whether the "inline" keyword was specified for this function. - void setInlineSpecified(bool I) { IsInline = I; } + void setInlineSpecified(bool I) { + IsInlineSpecified = I; + IsInline = I; + } + + /// Flag that this function is implicitly inline. + void setImplicitlyInline() { + IsInline = true; + } /// \brief Determine whether this function should be inlined, because it is /// either marked "inline" or is a member function of a C++ class that /// was defined in the class body. bool isInlined() const; - + bool isInlineDefinitionExternallyVisible() const; /// isOverloadedOperator - Whether this function declaration @@ -1432,7 +1597,9 @@ public: /// \brief Specify that this record is an instantiation of the /// member function FD. void setInstantiationOfMemberFunction(FunctionDecl *FD, - TemplateSpecializationKind TSK); + TemplateSpecializationKind TSK) { + setInstantiationOfMemberFunction(getASTContext(), FD, TSK); + } /// \brief Retrieves the function template that is described by this /// function declaration. @@ -1526,43 +1693,11 @@ public: void *InsertPos, TemplateSpecializationKind TSK = TSK_ImplicitInstantiation, const TemplateArgumentListInfo *TemplateArgsAsWritten = 0, - SourceLocation PointOfInstantiation = SourceLocation()); - - /// \brief Specify that this function declaration is actually a function - /// template specialization. - /// - /// \param Template the function template that this function template - /// specialization specializes. - /// - /// \param NumTemplateArgs number of template arguments that produced this - /// function template specialization from the template. - /// - /// \param TemplateArgs array of template arguments that produced this - /// function template specialization from the template. - /// - /// \param TSK the kind of template specialization this is. - /// - /// \param NumTemplateArgsAsWritten number of template arguments that produced - /// this function template specialization from the template. - /// - /// \param TemplateArgsAsWritten array of location info for the template - /// arguments. - /// - /// \param LAngleLoc location of left angle token. - /// - /// \param RAngleLoc location of right angle token. - /// - /// \param PointOfInstantiation point at which the function template - /// specialization was first instantiated. - void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, - unsigned NumTemplateArgs, - const TemplateArgument *TemplateArgs, - TemplateSpecializationKind TSK, - unsigned NumTemplateArgsAsWritten, - TemplateArgumentLoc *TemplateArgsAsWritten, - SourceLocation LAngleLoc, - SourceLocation RAngleLoc, - SourceLocation PointOfInstantiation); + SourceLocation PointOfInstantiation = SourceLocation()) { + setFunctionTemplateSpecialization(getASTContext(), Template, TemplateArgs, + InsertPos, TSK, TemplateArgsAsWritten, + PointOfInstantiation); + } /// \brief Specifies that this function declaration is actually a /// dependent function template specialization. @@ -1620,19 +1755,26 @@ public: class FieldDecl : public DeclaratorDecl { // FIXME: This can be packed into the bitfields in Decl. bool Mutable : 1; + mutable unsigned CachedFieldIndex : 31; + Expr *BitWidth; protected: FieldDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable) - : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Mutable(Mutable), BitWidth(BW) { + : DeclaratorDecl(DK, DC, L, Id, T, TInfo), + Mutable(Mutable), CachedFieldIndex(0), BitWidth(BW) { } public: - static FieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, + static FieldDecl *Create(const ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable); + /// getFieldIndex - Returns the index of this field within its record, + /// as appropriate for passing to ASTRecordLayout::getFieldOffset. + unsigned getFieldIndex() const; + /// isMutable - Determines whether this field is mutable (C++ only). bool isMutable() const { return Mutable; } @@ -1707,6 +1849,45 @@ public: friend class StmtIteratorBase; }; +/// IndirectFieldDecl - An instance of this class is created to represent a +/// field injected from an anonymous union/struct into the parent scope. +/// IndirectFieldDecl are always implicit. +class IndirectFieldDecl : public ValueDecl { + NamedDecl **Chaining; + unsigned ChainingSize; + + IndirectFieldDecl(DeclContext *DC, SourceLocation L, + DeclarationName N, QualType T, + NamedDecl **CH, unsigned CHS) + : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {} + +public: + static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + QualType T, NamedDecl **CH, unsigned CHS); + + typedef NamedDecl * const *chain_iterator; + chain_iterator chain_begin() const { return Chaining; } + chain_iterator chain_end() const { return Chaining+ChainingSize; } + + unsigned getChainingSize() const { return ChainingSize; } + + FieldDecl *getAnonField() const { + assert(ChainingSize >= 2); + return cast<FieldDecl>(Chaining[ChainingSize - 1]); + } + + VarDecl *getVarDecl() const { + assert(ChainingSize >= 2); + return dyn_cast<VarDecl>(*chain_begin()); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const IndirectFieldDecl *D) { return true; } + static bool classofKind(Kind K) { return K == IndirectField; } + friend class ASTDeclReader; +}; /// TypeDecl - Represents a declaration of a type. /// @@ -1715,7 +1896,7 @@ class TypeDecl : public NamedDecl { /// this TypeDecl. It is a cache maintained by /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and /// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl. - mutable Type *TypeForDecl; + mutable const Type *TypeForDecl; friend class ASTContext; friend class DeclContext; friend class TagDecl; @@ -1729,8 +1910,8 @@ protected: public: // Low-level accessor - Type *getTypeForDecl() const { return TypeForDecl; } - void setTypeForDecl(Type *TD) { TypeForDecl = TD; } + const Type *getTypeForDecl() const { return TypeForDecl; } + void setTypeForDecl(const Type *TD) { TypeForDecl = TD; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -1820,6 +2001,19 @@ protected: unsigned NumPositiveBits : 8; unsigned NumNegativeBits : 8; + /// IsScoped - True if this tag declaration is a scoped enumeration. Only + /// possible in C++0x mode. + bool IsScoped : 1; + /// IsScopedUsingClassTag - If this tag declaration is a scoped enum, + /// then this is true if the scoped enum was declared using the class + /// tag, false if it was declared with the struct tag. No meaning is + /// associated if this tag declaration is not a scoped enum. + bool IsScopedUsingClassTag : 1; + + /// IsFixed - True if this is an enumeration with fixed underlying type. Only + /// possible in C++0x mode. + bool IsFixed : 1; + private: SourceLocation TagKeywordLoc; SourceLocation RBraceLoc; @@ -1859,6 +2053,11 @@ protected: typedef Redeclarable<TagDecl> redeclarable_base; virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + /// @brief Completes the definition of this tag declaration. + /// + /// This is a helper function for derived classes. + void completeDefinition(); + public: typedef redeclarable_base::redecl_iterator redecl_iterator; redecl_iterator redecls_begin() const { @@ -1923,9 +2122,6 @@ public: /// 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 @@ -2001,7 +2197,19 @@ 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; + /// + /// If the underlying integer type was explicitly stated in the source + /// code, this is a TypeSourceInfo* for that type. Otherwise this type + /// was automatically deduced somehow, and this is a Type*. + /// + /// Normally if IsFixed(), this would contain a TypeSourceInfo*, but in + /// some cases it won't. + /// + /// The underlying type of an enumeration never has any qualifiers, so + /// we can get away with just storing a raw Type*, and thus save an + /// extra pointer when TypeSourceInfo is needed. + + llvm::PointerUnion<const Type*, TypeSourceInfo*> IntegerType; /// PromotionType - The integer type that values of this type should /// promote to. In C, enumerators are generally of an integer type @@ -2022,11 +2230,16 @@ class EnumDecl : public TagDecl { }; EnumDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL) + IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL, + bool Scoped, bool ScopedUsingClassTag, bool Fixed) : TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { - IntegerType = QualType(); + assert(Scoped || !ScopedUsingClassTag); + IntegerType = (const Type*)0; NumNegativeBits = 0; NumPositiveBits = 0; + IsScoped = Scoped; + IsScopedUsingClassTag = ScopedUsingClassTag; + IsFixed = Fixed; } public: EnumDecl *getCanonicalDecl() { @@ -2045,7 +2258,9 @@ public: static EnumDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - SourceLocation TKL, EnumDecl *PrevDecl); + SourceLocation TKL, EnumDecl *PrevDecl, + bool IsScoped, bool IsScopedUsingClassTag, + bool IsFixed); static EnumDecl *Create(ASTContext &C, EmptyShell Empty); /// completeDefinition - When created, the EnumDecl corresponds to a @@ -2085,10 +2300,25 @@ public: /// 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; } + QualType getIntegerType() const { + if (!IntegerType) + return QualType(); + if (const Type* T = IntegerType.dyn_cast<const Type*>()) + return QualType(T, 0); + return IntegerType.get<TypeSourceInfo*>()->getType(); + } /// \brief Set the underlying integer type. - void setIntegerType(QualType T) { IntegerType = T; } + void setIntegerType(QualType T) { IntegerType = T.getTypePtrOrNull(); } + + /// \brief Set the underlying integer type source info. + void setIntegerTypeSourceInfo(TypeSourceInfo* TInfo) { IntegerType = TInfo; } + + /// \brief Return the type source info for the underlying integer type, + /// if no type source info exists, return 0. + TypeSourceInfo* getIntegerTypeSourceInfo() const { + return IntegerType.dyn_cast<TypeSourceInfo*>(); + } /// \brief Returns the width in bits requred to store all the /// non-negative enumerators of this enum. @@ -2116,6 +2346,27 @@ public: NumNegativeBits = Num; } + /// \brief Returns true if this is a C++0x scoped enumeration. + bool isScoped() const { + return IsScoped; + } + + /// \brief Returns true if this is a C++0x scoped enumeration. + bool isScopedUsingClassTag() const { + return IsScopedUsingClassTag; + } + + /// \brief Returns true if this is a C++0x enumeration with fixed underlying + /// type. + bool isFixed() const { + return IsFixed; + } + + /// \brief Returns true if this can be considered a complete type. + bool isComplete() const { + return isDefinition() || isFixed(); + } + /// \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. @@ -2128,6 +2379,8 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const EnumDecl *D) { return true; } static bool classofKind(Kind K) { return K == Enum; } + + friend class ASTDeclReader; }; @@ -2151,17 +2404,24 @@ class RecordDecl : public TagDecl { /// containing an object. bool HasObjectMember : 1; + /// \brief Whether the field declarations of this record have been loaded + /// from external storage. To avoid unnecessary deserialization of + /// methods/nested types we allow deserialization of just the fields + /// when needed. + mutable bool LoadedFieldsFromExternalStorage : 1; + friend class DeclContext; + protected: RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, RecordDecl *PrevDecl, SourceLocation TKL); public: - static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC, + static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation TKL = SourceLocation(), RecordDecl* PrevDecl = 0); - static RecordDecl *Create(ASTContext &C, EmptyShell Empty); + static RecordDecl *Create(const ASTContext &C, EmptyShell Empty); const RecordDecl *getPreviousDeclaration() const { return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration()); @@ -2190,11 +2450,6 @@ public: AnonymousStructOrUnion = Anon; } - ValueDecl *getAnonymousStructOrUnionObject(); - const ValueDecl *getAnonymousStructOrUnionObject() const { - return const_cast<RecordDecl*>(this)->getAnonymousStructOrUnionObject(); - } - bool hasObjectMember() const { return HasObjectMember; } void setHasObjectMember (bool val) { HasObjectMember = val; } @@ -2229,11 +2484,10 @@ public: // data members, functions, constructors, destructors, etc. typedef specific_decl_iterator<FieldDecl> field_iterator; - field_iterator field_begin() const { - return field_iterator(decls_begin()); - } + field_iterator field_begin() const; + field_iterator field_end() const { - return field_iterator(decls_end()); + return field_iterator(decl_iterator()); } // field_empty - Whether there are any fields (non-static data @@ -2244,13 +2498,17 @@ public: /// completeDefinition - Notes that the definition of this type is /// now complete. - void completeDefinition(); + virtual void completeDefinition(); static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const RecordDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstRecord && K <= lastRecord; } + +private: + /// \brief Deserialize just the fields. + void LoadFieldsFromExternalStorage() const; }; class FileScopeAsmDecl : public Decl { @@ -2275,8 +2533,49 @@ public: /// ^{ statement-body } or ^(int arg1, float arg2){ statement-body } /// class BlockDecl : public Decl, public DeclContext { +public: + /// A class which contains all the information about a particular + /// captured value. + class Capture { + enum { + flag_isByRef = 0x1, + flag_isNested = 0x2 + }; + + /// The variable being captured. + llvm::PointerIntPair<VarDecl*, 2> VariableAndFlags; + + /// The copy expression, expressed in terms of a DeclRef (or + /// BlockDeclRef) to the captured variable. Only required if the + /// variable has a C++ class type. + Expr *CopyExpr; + + public: + Capture(VarDecl *variable, bool byRef, bool nested, Expr *copy) + : VariableAndFlags(variable, + (byRef ? flag_isByRef : 0) | (nested ? flag_isNested : 0)), + CopyExpr(copy) {} + + /// The variable being captured. + VarDecl *getVariable() const { return VariableAndFlags.getPointer(); } + + /// Whether this is a "by ref" capture, i.e. a capture of a __block + /// variable. + bool isByRef() const { return VariableAndFlags.getInt() & flag_isByRef; } + + /// Whether this is a nested capture, i.e. the variable captured + /// is not from outside the immediately enclosing function/block. + bool isNested() const { return VariableAndFlags.getInt() & flag_isNested; } + + bool hasCopyExpr() const { return CopyExpr != 0; } + Expr *getCopyExpr() const { return CopyExpr; } + void setCopyExpr(Expr *e) { CopyExpr = e; } + }; + +private: // FIXME: This can be packed into the bitfields in Decl. bool IsVariadic : 1; + bool CapturesCXXThis : 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. @@ -2286,11 +2585,15 @@ class BlockDecl : public Decl, public DeclContext { Stmt *Body; TypeSourceInfo *SignatureAsWritten; + Capture *Captures; + unsigned NumCaptures; + protected: BlockDecl(DeclContext *DC, SourceLocation CaretLoc) : Decl(Block, DC, CaretLoc), DeclContext(Block), - IsVariadic(false), ParamInfo(0), NumParams(0), Body(0), - SignatureAsWritten(0) {} + IsVariadic(false), CapturesCXXThis(false), + ParamInfo(0), NumParams(0), Body(0), + SignatureAsWritten(0), Captures(0), NumCaptures(0) {} public: static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); @@ -2319,7 +2622,7 @@ public: param_const_iterator param_begin() const { return ParamInfo; } param_const_iterator param_end() const { return ParamInfo+param_size(); } - unsigned getNumParams() const; + unsigned getNumParams() const { return NumParams; } const ParmVarDecl *getParamDecl(unsigned i) const { assert(i < getNumParams() && "Illegal param #"); return ParamInfo[i]; @@ -2330,6 +2633,30 @@ public: } void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams); + /// hasCaptures - True if this block (or its nested blocks) captures + /// anything of local storage from its enclosing scopes. + bool hasCaptures() const { return NumCaptures != 0 || CapturesCXXThis; } + + /// getNumCaptures - Returns the number of captured variables. + /// Does not include an entry for 'this'. + unsigned getNumCaptures() const { return NumCaptures; } + + typedef const Capture *capture_iterator; + typedef const Capture *capture_const_iterator; + capture_iterator capture_begin() { return Captures; } + capture_iterator capture_end() { return Captures + NumCaptures; } + capture_const_iterator capture_begin() const { return Captures; } + capture_const_iterator capture_end() const { return Captures + NumCaptures; } + + bool capturesCXXThis() const { return CapturesCXXThis; } + + void setCaptures(ASTContext &Context, + const Capture *begin, + const Capture *end, + bool capturesCXXThis); + + virtual SourceRange getSourceRange() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const BlockDecl *D) { return true; } @@ -2350,6 +2677,32 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, return DB; } +template<typename decl_type> +void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *PrevDecl) { + // Note: This routine is implemented here because we need both NamedDecl + // and Redeclarable to be defined. + + decl_type *First; + + if (PrevDecl) { + // Point to previous. Make sure that this is actually the most recent + // redeclaration, or we can build invalid chains. If the most recent + // redeclaration is invalid, it won't be PrevDecl, but we want it anyway. + RedeclLink = PreviousDeclLink(llvm::cast<decl_type>( + PrevDecl->getMostRecentDeclaration())); + First = PrevDecl->getFirstDeclaration(); + assert(First->RedeclLink.NextIsLatest() && "Expected first"); + } else { + // Make this first. + First = static_cast<decl_type*>(this); + } + + // First one will point to this one as latest. + First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this)); + if (NamedDecl *ND = dyn_cast<NamedDecl>(static_cast<decl_type*>(this))) + ND->ClearLinkageCache(); +} + } // end namespace clang #endif diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 1369c2b5955a..bf249cea9d5f 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -43,6 +43,7 @@ class DeclarationName; class CompoundStmt; class StoredDeclsMap; class DependentDiagnostic; +class ASTMutationListener; } namespace llvm { @@ -197,25 +198,25 @@ private: return DeclCtx.get<DeclContext*>(); } - /// Loc - The location that this decl. + /// Loc - The location of this decl. SourceLocation Loc; /// DeclKind - This indicates which class this is. - Kind DeclKind : 8; + unsigned DeclKind : 8; /// InvalidDecl - This indicates a semantic error occurred. - unsigned int InvalidDecl : 1; + unsigned InvalidDecl : 1; /// HasAttrs - This indicates whether the decl has attributes or not. - unsigned int HasAttrs : 1; + unsigned HasAttrs : 1; /// Implicit - Whether this declaration was implicitly generated by /// the implementation rather than explicitly written by the user. - bool Implicit : 1; + unsigned Implicit : 1; /// \brief Whether this declaration was "used", meaning that a definition is /// required. - bool Used : 1; + unsigned Used : 1; protected: /// Access - Used by C++ decls for the access specifier. @@ -227,17 +228,24 @@ protected: unsigned PCHLevel : 2; /// ChangedAfterLoad - if this declaration has changed since being loaded - bool ChangedAfterLoad : 1; + unsigned ChangedAfterLoad : 1; /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. - unsigned IdentifierNamespace : 15; + unsigned IdentifierNamespace : 12; + /// \brief Whether the \c CachedLinkage field is active. + /// + /// This field is only valid for NamedDecls subclasses. + mutable unsigned HasCachedLinkage : 1; + + /// \brief If \c HasCachedLinkage, the linkage of this declaration. + /// + /// This field is only valid for NamedDecls subclasses. + mutable unsigned CachedLinkage : 2; + + private: -#ifndef NDEBUG void CheckAccessDeclContext() const; -#else - void CheckAccessDeclContext() const { } -#endif protected: @@ -246,7 +254,9 @@ protected: Loc(L), DeclKind(DK), InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false), Access(AS_none), PCHLevel(0), ChangedAfterLoad(false), - IdentifierNamespace(getIdentifierNamespaceForKind(DK)) { + IdentifierNamespace(getIdentifierNamespaceForKind(DK)), + HasCachedLinkage(0) + { if (Decl::CollectingStats()) add(DK); } @@ -254,7 +264,9 @@ protected: : NextDeclInContext(0), DeclKind(DK), InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false), Access(AS_none), PCHLevel(0), ChangedAfterLoad(false), - IdentifierNamespace(getIdentifierNamespaceForKind(DK)) { + IdentifierNamespace(getIdentifierNamespaceForKind(DK)), + HasCachedLinkage(0) + { if (Decl::CollectingStats()) add(DK); } @@ -272,7 +284,7 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - Kind getKind() const { return DeclKind; } + Kind getKind() const { return static_cast<Kind>(DeclKind); } const char *getDeclKindName() const; Decl *getNextDeclInContext() { return NextDeclInContext; } @@ -298,17 +310,21 @@ public: void setAccess(AccessSpecifier AS) { Access = AS; +#ifndef NDEBUG CheckAccessDeclContext(); +#endif } AccessSpecifier getAccess() const { +#ifndef NDEBUG CheckAccessDeclContext(); +#endif return AccessSpecifier(Access); } bool hasAttrs() const { return HasAttrs; } void setAttrs(const AttrVec& Attrs); - AttrVec& getAttrs() { + AttrVec &getAttrs() { return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs()); } const AttrVec &getAttrs() const; @@ -551,6 +567,9 @@ public: /// template parameter pack. bool isTemplateParameterPack() const; + /// \brief Whether this declaration is a parameter pack. + bool isParameterPack() const; + /// \brief Whether this declaration is a function or function template. bool isFunctionOrFunctionTemplate() const; @@ -621,10 +640,14 @@ public: llvm::raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation = 0); void dump() const; + void dumpXML() const; + void dumpXML(llvm::raw_ostream &OS) const; private: const Attr *getAttrsImpl() const; +protected: + ASTMutationListener *getASTMutationListener() const; }; /// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when @@ -681,23 +704,24 @@ public: /// class DeclContext { /// DeclKind - This indicates which class this is. - Decl::Kind DeclKind : 8; + unsigned 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; + mutable unsigned 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; + mutable unsigned ExternalVisibleStorage : 1; /// \brief Pointer to the data structure used to lookup declarations /// within this context (or a DependentStoredDeclsMap if this is a /// dependent context). mutable StoredDeclsMap *LookupPtr; +protected: /// FirstDecl - The first declaration stored within this declaration /// context. mutable Decl *FirstDecl; @@ -710,7 +734,12 @@ class DeclContext { friend class ExternalASTSource; -protected: + /// \brief Build up a chain of declarations. + /// + /// \returns the first/last pair of declarations. + static std::pair<Decl *, Decl *> + BuildDeclChain(const llvm::SmallVectorImpl<Decl*> &Decls); + DeclContext(Decl::Kind K) : DeclKind(K), ExternalLexicalStorage(false), ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0), @@ -720,7 +749,7 @@ public: ~DeclContext(); Decl::Kind getDeclKind() const { - return DeclKind; + return static_cast<Decl::Kind>(DeclKind); } const char *getDeclKindName() const; @@ -807,6 +836,10 @@ public: /// C++0x scoped enums), and C++ linkage specifications. bool isTransparentContext() const; + /// \brief Determines whether this context is, or is nested within, + /// a C++ extern "C" linkage spec. + bool isExternCContext() const; + /// \brief Determine whether this declaration context is equivalent /// to the declaration context DC. bool Equals(const DeclContext *DC) const { diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index a9802bfcaf4e..d11ee8f7fd64 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -35,6 +35,7 @@ class CXXMethodDecl; class CXXRecordDecl; class CXXMemberLookupCriteria; class CXXFinalOverriderMap; +class CXXIndirectPrimaryBaseSet; class FriendDecl; /// \brief Represents any kind of function declaration, whether it is a @@ -112,6 +113,8 @@ class AccessSpecDecl : public Decl { : Decl(AccessSpec, DC, ASLoc), ColonLoc(ColonLoc) { setAccess(AS); } + AccessSpecDecl(EmptyShell Empty) + : Decl(AccessSpec, Empty) { } public: /// getAccessSpecifierLoc - The location of the access specifier. SourceLocation getAccessSpecifierLoc() const { return getLocation(); } @@ -132,6 +135,9 @@ public: SourceLocation ColonLoc) { return new (C) AccessSpecDecl(AS, DC, ASLoc, ColonLoc); } + static AccessSpecDecl *Create(ASTContext &C, EmptyShell Empty) { + return new (C) AccessSpecDecl(Empty); + } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -162,6 +168,10 @@ class CXXBaseSpecifier { /// specifier (if present). SourceRange Range; + /// \brief The source location of the ellipsis, if this is a pack + /// expansion. + SourceLocation EllipsisLoc; + /// Virtual - Whether this is a virtual base class or not. bool Virtual : 1; @@ -177,6 +187,10 @@ class CXXBaseSpecifier { /// VC++ bug. unsigned Access : 2; + /// InheritConstructors - Whether the class contains a using declaration + /// to inherit the named class's constructors. + bool InheritConstructors : 1; + /// BaseTypeInfo - The type of the base class. This will be a class or struct /// (or a typedef of such). The source code range does not include the /// "virtual" or access specifier. @@ -186,8 +200,9 @@ public: CXXBaseSpecifier() { } CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, - TypeSourceInfo *TInfo) - : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseTypeInfo(TInfo) { } + TypeSourceInfo *TInfo, SourceLocation EllipsisLoc) + : Range(R), EllipsisLoc(EllipsisLoc), Virtual(V), BaseOfClass(BC), + Access(A), InheritConstructors(false), BaseTypeInfo(TInfo) { } /// getSourceRange - Retrieves the source range that contains the /// entire base specifier. @@ -201,6 +216,22 @@ public: /// with the 'class' keyword (vs. one declared with the 'struct' keyword). bool isBaseOfClass() const { return BaseOfClass; } + /// \brief Determine whether this base specifier is a pack expansion. + bool isPackExpansion() const { return EllipsisLoc.isValid(); } + + /// \brief Determine whether this base class's constructors get inherited. + bool getInheritConstructors() const { return InheritConstructors; } + + /// \brief Set that this base class's constructors should be inherited. + void setInheritConstructors(bool Inherit = true) { + InheritConstructors = Inherit; + } + + /// \brief For a pack expansion, determine the location of the ellipsis. + SourceLocation getEllipsisLoc() const { + return EllipsisLoc; + } + /// 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 @@ -336,20 +367,20 @@ class CXXRecordDecl : public RecordDecl { /// \brief Whether we have already declared a destructor within the class. bool DeclaredDestructor : 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; - - /// VBases - direct and indirect virtual base classes of this class. - CXXBaseSpecifier *VBases; - + /// NumVBases - The number of virtual base class specifiers in VBases. unsigned NumVBases; + /// Bases - Base classes of this class. + /// FIXME: This is wasted space for a union. + LazyCXXBaseSpecifiersPtr Bases; + + /// VBases - direct and indirect virtual base classes of this class. + LazyCXXBaseSpecifiersPtr VBases; + /// 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 @@ -371,6 +402,15 @@ class CXXRecordDecl : public RecordDecl { /// in reverse order. FriendDecl *FirstFriend; + /// \brief Retrieve the set of direct base classes. + CXXBaseSpecifier *getBases() const { + return Bases.get(Definition->getASTContext().getExternalSource()); + } + + /// \brief Retrieve the set of virtual base classes. + CXXBaseSpecifier *getVBases() const { + return VBases.get(Definition->getASTContext().getExternalSource()); + } } *DefinitionData; struct DefinitionData &data() { @@ -395,9 +435,17 @@ class CXXRecordDecl : public RecordDecl { llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*> TemplateOrInstantiation; -#ifndef NDEBUG - void CheckConversionFunction(NamedDecl *D); -#endif + friend class DeclContext; + + /// \brief Notify the class that member has been added. + /// + /// This routine helps maintain information about the class based on which + /// members have been added. It will be invoked by DeclContext::addDecl() + /// whenever a member is added to this record. + void addedMember(Decl *D); + + void markedVirtualFunctionPure(); + friend void FunctionDecl::setPure(bool); protected: CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, @@ -445,12 +493,12 @@ public: bool hasDefinition() const { return DefinitionData != 0; } - static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC, + static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation TKL = SourceLocation(), CXXRecordDecl* PrevDecl=0, bool DelayTypeCreation = false); - static CXXRecordDecl *Create(ASTContext &C, EmptyShell Empty); + static CXXRecordDecl *Create(const ASTContext &C, EmptyShell Empty); bool isDynamicClass() const { return data().Polymorphic || data().NumVBases != 0; @@ -463,8 +511,8 @@ public: /// class. unsigned getNumBases() const { return data().NumBases; } - base_class_iterator bases_begin() { return data().Bases; } - base_class_const_iterator bases_begin() const { return data().Bases; } + base_class_iterator bases_begin() { return data().getBases(); } + base_class_const_iterator bases_begin() const { return data().getBases(); } base_class_iterator bases_end() { return bases_begin() + data().NumBases; } base_class_const_iterator bases_end() const { return bases_begin() + data().NumBases; @@ -486,8 +534,8 @@ public: /// class. unsigned getNumVBases() const { return data().NumVBases; } - base_class_iterator vbases_begin() { return data().VBases; } - base_class_const_iterator vbases_begin() const { return data().VBases; } + base_class_iterator vbases_begin() { return data().getVBases(); } + base_class_const_iterator vbases_begin() const { return data().getVBases(); } base_class_iterator vbases_end() { return vbases_begin() + data().NumVBases; } base_class_const_iterator vbases_end() const { return vbases_begin() + data().NumVBases; @@ -553,18 +601,12 @@ public: return data().DeclaredDefaultConstructor; } - /// \brief Note whether this class has already had its default constructor - /// implicitly declared or doesn't need one. - void setDeclaredDefaultConstructor(bool DDC) { - data().DeclaredDefaultConstructor = DDC; - } - /// hasConstCopyConstructor - Determines whether this class has a /// copy constructor that accepts a const-qualified argument. - bool hasConstCopyConstructor(ASTContext &Context) const; + bool hasConstCopyConstructor(const ASTContext &Context) const; /// getCopyConstructor - Returns the copy constructor for this class - CXXConstructorDecl *getCopyConstructor(ASTContext &Context, + CXXConstructorDecl *getCopyConstructor(const ASTContext &Context, unsigned TypeQuals) const; /// \brief Retrieve the copy-assignment operator for this class, if available. @@ -579,11 +621,6 @@ public: /// a unique copy-assignment operator could not be found. CXXMethodDecl *getCopyAssignmentOperator(bool ArgIsConst) 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. @@ -606,17 +643,6 @@ public: return data().DeclaredCopyConstructor; } - /// \brief Note whether this class has already had its copy constructor - /// declared. - void setDeclaredCopyConstructor(bool DCC) { - data().DeclaredCopyConstructor = DCC; - } - - /// 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. @@ -632,12 +658,6 @@ public: return data().DeclaredCopyAssignment; } - /// \brief Note whether this class has already had its copy assignment - /// operator declared. - void setDeclaredCopyAssignment(bool DCA) { - data().DeclaredCopyAssignment = DCA; - } - /// hasUserDeclaredDestructor - Whether this class has a /// user-declared destructor. When false, a destructor will be /// implicitly declared. @@ -645,26 +665,12 @@ public: return data().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) { - data().UserDeclaredDestructor = UCD; - if (UCD) - data().DeclaredDestructor = true; - } - /// \brief Determine whether this class has had its destructor declared, /// either via the user or via an implicit declaration. /// /// This value is used for lazy creation of destructors. bool hasDeclaredDestructor() const { return data().DeclaredDestructor; } - - /// \brief Note whether this class has already had its destructor declared. - void setDeclaredDestructor(bool DD) { - data().DeclaredDestructor = DD; - } - + /// getConversions - Retrieve the overload set containing all of the /// conversion functions in this class. UnresolvedSetImpl *getConversionFunctions() { @@ -682,13 +688,6 @@ public: return getConversionFunctions()->end(); } - /// Replaces a conversion function with a new declaration. - /// - /// Returns true if the old conversion was found. - bool replaceConversion(const NamedDecl* Old, NamedDecl *New) { - return getConversionFunctions()->replace(Old, New); - } - /// Removes a conversion function from this class. The conversion /// function must currently be a member of this class. Furthermore, /// this class must currently be in the process of being defined. @@ -698,105 +697,52 @@ public: /// in current class; including conversion function templates. const UnresolvedSetImpl *getVisibleConversionFunctions(); - /// addConversionFunction - Registers a conversion function which - /// this class declares directly. - void addConversionFunction(NamedDecl *Decl) { -#ifndef NDEBUG - CheckConversionFunction(Decl); -#endif - - // We intentionally don't use the decl's access here because it - // hasn't been set yet. That's really just a misdesign in Sema. - data().Conversions.addDecl(Decl); - } - /// 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 data().Aggregate; } - /// setAggregate - Set whether this class is an aggregate (C++ - /// [dcl.init.aggr]). - void setAggregate(bool Agg) { data().Aggregate = Agg; } - - /// setMethodAsVirtual - Make input method virtual and set the necesssary - /// special function bits and other bits accordingly. - void setMethodAsVirtual(FunctionDecl *Method); - /// 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 data().PlainOldData; } - /// setPOD - Set whether this class is a POD-type (C++ [class]p4). - void setPOD(bool POD) { data().PlainOldData = POD; } - /// isEmpty - Whether this class is empty (C++0x [meta.unary.prop]), which /// means it has a virtual function, virtual base, data member (other than /// 0-width bit-field) or inherits from a non-empty class. Does NOT include /// a check for union-ness. bool isEmpty() const { return data().Empty; } - /// Set whether this class is empty (C++0x [meta.unary.prop]) - void setEmpty(bool Emp) { data().Empty = Emp; } - /// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]), /// which means that the class contains or inherits a virtual function. bool isPolymorphic() const { return data().Polymorphic; } - /// setPolymorphic - Set whether this class is polymorphic (C++ - /// [class.virtual]). - void setPolymorphic(bool Poly) { data().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 data().Abstract; } - /// setAbstract - Set whether this class is abstract (C++ [class.abstract]) - void setAbstract(bool Abs) { data().Abstract = Abs; } - // hasTrivialConstructor - Whether this class has a trivial constructor // (C++ [class.ctor]p5) bool hasTrivialConstructor() const { return data().HasTrivialConstructor; } - // setHasTrivialConstructor - Set whether this class has a trivial constructor - // (C++ [class.ctor]p5) - void setHasTrivialConstructor(bool TC) { data().HasTrivialConstructor = TC; } - // hasTrivialCopyConstructor - Whether this class has a trivial copy // constructor (C++ [class.copy]p6) bool hasTrivialCopyConstructor() const { return data().HasTrivialCopyConstructor; } - // setHasTrivialCopyConstructor - Set whether this class has a trivial - // copy constructor (C++ [class.copy]p6) - void setHasTrivialCopyConstructor(bool TC) { - data().HasTrivialCopyConstructor = TC; - } - // hasTrivialCopyAssignment - Whether this class has a trivial copy // assignment operator (C++ [class.copy]p11) bool hasTrivialCopyAssignment() const { return data().HasTrivialCopyAssignment; } - // setHasTrivialCopyAssignment - Set whether this class has a - // trivial copy assignment operator (C++ [class.copy]p11) - void setHasTrivialCopyAssignment(bool TC) { - data().HasTrivialCopyAssignment = TC; - } - // hasTrivialDestructor - Whether this class has a trivial destructor // (C++ [class.dtor]p3) bool hasTrivialDestructor() const { return data().HasTrivialDestructor; } - // setHasTrivialDestructor - Set whether this class has a trivial destructor - // (C++ [class.dtor]p3) - void setHasTrivialDestructor(bool TC) { data().HasTrivialDestructor = TC; } - /// \brief If this record is an instantiation of a member class, /// retrieves the member class from which it was instantiated. /// @@ -854,9 +800,6 @@ public: /// \brief Set the kind of specialization or template instantiation this is. void setTemplateSpecializationKind(TemplateSpecializationKind TSK); - - /// getDefaultConstructor - Returns the default constructor for this class - CXXConstructorDecl *getDefaultConstructor(); /// getDestructor - Returns the destructor decl for this class. CXXDestructorDecl *getDestructor() const; @@ -880,7 +823,7 @@ public: /// \param Base the base class we are searching for. /// /// \returns true if this class is derived from Base, false otherwise. - bool isDerivedFrom(CXXRecordDecl *Base) const; + bool isDerivedFrom(const CXXRecordDecl *Base) const; /// \brief Determine whether this class is derived from the type \p Base. /// @@ -898,7 +841,7 @@ public: /// /// \todo add a separate paramaeter to configure IsDerivedFrom, rather than /// tangling input and output in \p Paths - bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const; + bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths) const; /// \brief Determine whether this class is virtually derived from /// the class \p Base. @@ -1034,6 +977,9 @@ public: /// most-derived class in the class hierarchy. void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const; + /// \brief Get the indirect primary bases for this class. + void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const; + /// viewInheritance - Renders and displays an inheritance diagram /// for this C++ class and all of its base classes (transitively) using /// GraphViz. @@ -1048,6 +994,27 @@ public: return (PathAccess > DeclAccess ? PathAccess : DeclAccess); } + /// \brief Indicates that the definition of this class is now complete. + virtual void completeDefinition(); + + /// \brief Indicates that the definition of this class is now complete, + /// and provides a final overrider map to help determine + /// + /// \param FinalOverriders The final overrider map for this class, which can + /// be provided as an optimization for abstract-class checking. If NULL, + /// final overriders will be computed if they are needed to complete the + /// definition. + void completeDefinition(CXXFinalOverriderMap *FinalOverriders); + + /// \brief Determine whether this class may end up being abstract, even though + /// it is not yet known to be abstract. + /// + /// \returns true if this class is not known to be abstract but has any + /// base classes that are abstract. In this case, \c completeDefinition() + /// will need to compute final overriders to determine whether the class is + /// actually abstract. + bool mayBeAbstract() const; + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstCXXRecord && K <= lastCXXRecord; @@ -1059,6 +1026,8 @@ public: friend class ASTDeclReader; friend class ASTDeclWriter; + friend class ASTReader; + friend class ASTWriter; }; /// CXXMethodDecl - Represents a static or instance method of a @@ -1139,6 +1108,20 @@ public: return getType()->getAs<FunctionProtoType>()->getTypeQuals(); } + /// \brief Retrieve the ref-qualifier associated with this method. + /// + /// In the following example, \c f() has an lvalue ref-qualifier, \c g() + /// has an rvalue ref-qualifier, and \c h() has no ref-qualifier. + /// \code + /// struct X { + /// void f() &; + /// void g() &&; + /// void h(); + /// }; + RefQualifierKind getRefQualifier() const { + return getType()->getAs<FunctionProtoType>()->getRefQualifier(); + } + bool hasInlineBody() const; // Implement isa/cast/dyncast/etc. @@ -1149,7 +1132,7 @@ public: } }; -/// CXXBaseOrMemberInitializer - Represents a C++ base or member +/// CXXCtorInitializer - 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 @@ -1163,37 +1146,20 @@ public: /// B(A& a) : A(a), f(3.14159) { } /// }; /// @endcode -class CXXBaseOrMemberInitializer { - /// \brief Either the base class name (stored as a TypeSourceInfo*) or the - /// field being initialized. - llvm::PointerUnion<TypeSourceInfo *, FieldDecl *> BaseOrMember; +class CXXCtorInitializer { + /// \brief Either the base class name (stored as a TypeSourceInfo*), an normal + /// field (FieldDecl) or an anonymous field (IndirectFieldDecl*) being + /// initialized. + llvm::PointerUnion3<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *> + Initializee; - /// \brief The source location for the field name. - SourceLocation MemberLocation; + /// \brief The source location for the field name or, for a base initializer + /// pack expansion, the location of the ellipsis. + SourceLocation MemberOrEllipsisLocation; /// \brief The argument used to initialize the base or member, which may /// end up constructing an object (when multiple arguments are involved). Stmt *Init; - - /// \brief Stores either the constructor to call to initialize this base or - /// member (a CXXConstructorDecl pointer), or stores the anonymous union of - /// which the initialized value is a member. - /// - /// When the value is a FieldDecl pointer, 'BaseOrMember' is class's - /// anonymous union data member, this field holds the FieldDecl for the - /// member of the anonymous union being initialized. - /// @code - /// struct X { - /// X() : au_i1(123) {} - /// union { - /// int au_i1; - /// float au_f1; - /// }; - /// }; - /// @endcode - /// In above example, BaseOrMember holds the field decl. for anonymous union - /// and AnonUnionMember holds field decl for au_i1. - FieldDecl *AnonUnionMember; /// LParenLoc - Location of the left paren of the ctor-initializer. SourceLocation LParenLoc; @@ -1208,6 +1174,7 @@ class CXXBaseOrMemberInitializer { /// IsWritten - Whether or not the initializer is explicitly written /// in the sources. bool IsWritten : 1; + /// SourceOrderOrNumArrayIndices - If IsWritten is true, then this /// number keeps track of the textual order of this initializer in the /// original sources, counting from 0; otherwise, if IsWritten is false, @@ -1215,50 +1182,62 @@ class CXXBaseOrMemberInitializer { /// object in memory. unsigned SourceOrderOrNumArrayIndices : 14; - CXXBaseOrMemberInitializer(ASTContext &Context, - FieldDecl *Member, SourceLocation MemberLoc, - SourceLocation L, - Expr *Init, - SourceLocation R, - VarDecl **Indices, - unsigned NumIndices); + CXXCtorInitializer(ASTContext &Context, FieldDecl *Member, + SourceLocation MemberLoc, SourceLocation L, Expr *Init, + SourceLocation R, VarDecl **Indices, unsigned NumIndices); public: - /// CXXBaseOrMemberInitializer - Creates a new base-class initializer. + /// CXXCtorInitializer - Creates a new base-class initializer. explicit - CXXBaseOrMemberInitializer(ASTContext &Context, - TypeSourceInfo *TInfo, bool IsVirtual, - SourceLocation L, - Expr *Init, - SourceLocation R); + CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual, + SourceLocation L, Expr *Init, SourceLocation R, + SourceLocation EllipsisLoc); - /// CXXBaseOrMemberInitializer - Creates a new member initializer. + /// CXXCtorInitializer - Creates a new member initializer. explicit - CXXBaseOrMemberInitializer(ASTContext &Context, - FieldDecl *Member, SourceLocation MemberLoc, - SourceLocation L, - Expr *Init, - SourceLocation R); + CXXCtorInitializer(ASTContext &Context, FieldDecl *Member, + SourceLocation MemberLoc, SourceLocation L, Expr *Init, + SourceLocation R); + + explicit + CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member, + SourceLocation MemberLoc, SourceLocation L, Expr *Init, + SourceLocation R); /// \brief Creates a new member initializer that optionally contains /// array indices used to describe an elementwise initialization. - static CXXBaseOrMemberInitializer *Create(ASTContext &Context, - FieldDecl *Member, - SourceLocation MemberLoc, - SourceLocation L, - Expr *Init, - SourceLocation R, - VarDecl **Indices, - unsigned NumIndices); + static CXXCtorInitializer *Create(ASTContext &Context, FieldDecl *Member, + SourceLocation MemberLoc, SourceLocation L, + Expr *Init, SourceLocation R, + VarDecl **Indices, unsigned NumIndices); /// isBaseInitializer - Returns true when this initializer is /// initializing a base class. - bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); } + bool isBaseInitializer() const { return Initializee.is<TypeSourceInfo*>(); } /// isMemberInitializer - Returns true when this initializer is /// initializing a non-static data member. - bool isMemberInitializer() const { return BaseOrMember.is<FieldDecl*>(); } + bool isMemberInitializer() const { return Initializee.is<FieldDecl*>(); } + + bool isAnyMemberInitializer() const { + return isMemberInitializer() || isIndirectMemberInitializer(); + } + bool isIndirectMemberInitializer() const { + return Initializee.is<IndirectFieldDecl*>(); + } + + /// \brief Determine whether this initializer is a pack expansion. + bool isPackExpansion() const { + return isBaseInitializer() && MemberOrEllipsisLocation.isValid(); + } + + // \brief For a pack expansion, returns the location of the ellipsis. + SourceLocation getEllipsisLoc() const { + assert(isPackExpansion() && "Initializer is not a pack expansion"); + return MemberOrEllipsisLocation; + } + /// If this is a base class initializer, returns the type of the /// base class with location information. Otherwise, returns an NULL /// type location. @@ -1267,7 +1246,6 @@ public: /// If this is a base class initializer, returns the type of the base class. /// Otherwise, returns NULL. const Type *getBaseClass() const; - Type *getBaseClass(); /// Returns whether the base is virtual or not. bool isBaseVirtual() const { @@ -1278,7 +1256,7 @@ public: /// \brief Returns the declarator information for a base class initializer. TypeSourceInfo *getBaseClassInfo() const { - return BaseOrMember.dyn_cast<TypeSourceInfo *>(); + return Initializee.dyn_cast<TypeSourceInfo *>(); } /// getMember - If this is a member initializer, returns the @@ -1286,18 +1264,28 @@ public: /// initialized. Otherwise, returns NULL. FieldDecl *getMember() const { if (isMemberInitializer()) - return BaseOrMember.get<FieldDecl*>(); + return Initializee.get<FieldDecl*>(); + else + return 0; + } + FieldDecl *getAnyMember() const { + if (isMemberInitializer()) + return Initializee.get<FieldDecl*>(); + else if (isIndirectMemberInitializer()) + return Initializee.get<IndirectFieldDecl*>()->getAnonField(); else return 0; } - SourceLocation getMemberLocation() const { - return MemberLocation; + IndirectFieldDecl *getIndirectMember() const { + if (isIndirectMemberInitializer()) + return Initializee.get<IndirectFieldDecl*>(); + else + return 0; } - void setMember(FieldDecl *Member) { - assert(isMemberInitializer()); - BaseOrMember = Member; + SourceLocation getMemberLocation() const { + return MemberOrEllipsisLocation; } /// \brief Determine the source location of the initializer. @@ -1329,15 +1317,7 @@ public: IsWritten = true; SourceOrderOrNumArrayIndices = static_cast<unsigned>(pos); } - - FieldDecl *getAnonUnionMember() const { - return AnonUnionMember; - } - void setAnonUnionMember(FieldDecl *anonMember) { - AnonUnionMember = anonMember; - } - SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } @@ -1388,10 +1368,10 @@ class CXXConstructorDecl : public CXXMethodDecl { bool ImplicitlyDefined : 1; /// Support for base and member initializers. - /// BaseOrMemberInitializers - The arguments used to initialize the base + /// CtorInitializers - The arguments used to initialize the base /// or member. - CXXBaseOrMemberInitializer **BaseOrMemberInitializers; - unsigned NumBaseOrMemberInitializers; + CXXCtorInitializer **CtorInitializers; + unsigned NumCtorInitializers; CXXConstructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, @@ -1400,7 +1380,7 @@ class CXXConstructorDecl : public CXXMethodDecl { : CXXMethodDecl(CXXConstructor, RD, NameInfo, T, TInfo, false, SC_None, isInline), IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false), - BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) { + CtorInitializers(0), NumCtorInitializers(0) { setImplicit(isImplicitlyDeclared); } @@ -1443,37 +1423,54 @@ public: } /// init_iterator - Iterates through the member/base initializer list. - typedef CXXBaseOrMemberInitializer **init_iterator; + typedef CXXCtorInitializer **init_iterator; /// init_const_iterator - Iterates through the memberbase initializer list. - typedef CXXBaseOrMemberInitializer * const * init_const_iterator; + typedef CXXCtorInitializer * const * init_const_iterator; /// init_begin() - Retrieve an iterator to the first initializer. - init_iterator init_begin() { return BaseOrMemberInitializers; } + init_iterator init_begin() { return CtorInitializers; } /// begin() - Retrieve an iterator to the first initializer. - init_const_iterator init_begin() const { return BaseOrMemberInitializers; } + init_const_iterator init_begin() const { return CtorInitializers; } /// init_end() - Retrieve an iterator past the last initializer. init_iterator init_end() { - return BaseOrMemberInitializers + NumBaseOrMemberInitializers; + return CtorInitializers + NumCtorInitializers; } /// end() - Retrieve an iterator past the last initializer. init_const_iterator init_end() const { - return BaseOrMemberInitializers + NumBaseOrMemberInitializers; + return CtorInitializers + NumCtorInitializers; + } + + typedef std::reverse_iterator<init_iterator> init_reverse_iterator; + typedef std::reverse_iterator<init_const_iterator> init_const_reverse_iterator; + + init_reverse_iterator init_rbegin() { + return init_reverse_iterator(init_end()); + } + init_const_reverse_iterator init_rbegin() const { + return init_const_reverse_iterator(init_end()); + } + + init_reverse_iterator init_rend() { + return init_reverse_iterator(init_begin()); + } + init_const_reverse_iterator init_rend() const { + return init_const_reverse_iterator(init_begin()); } /// getNumArgs - Determine the number of arguments used to /// initialize the member or base. - unsigned getNumBaseOrMemberInitializers() const { - return NumBaseOrMemberInitializers; + unsigned getNumCtorInitializers() const { + return NumCtorInitializers; } - void setNumBaseOrMemberInitializers(unsigned numBaseOrMemberInitializers) { - NumBaseOrMemberInitializers = numBaseOrMemberInitializers; + void setNumCtorInitializers(unsigned numCtorInitializers) { + NumCtorInitializers = numCtorInitializers; } - void setBaseOrMemberInitializers(CXXBaseOrMemberInitializer ** initializers) { - BaseOrMemberInitializers = initializers; + void setCtorInitializers(CXXCtorInitializer ** initializers) { + CtorInitializers = initializers; } /// isDefaultConstructor - Whether this constructor is a default /// constructor (C++ [class.ctor]p5), which can be used to @@ -1502,15 +1499,44 @@ public: return isCopyConstructor(TypeQuals); } + /// \brief Determine whether this constructor is a move constructor + /// (C++0x [class.copy]p3), which can be used to move values of the class. + /// + /// \param TypeQuals If this constructor is a move constructor, will be set + /// to the type qualifiers on the referent of the first parameter's type. + bool isMoveConstructor(unsigned &TypeQuals) const; + + /// \brief Determine whether this constructor is a move constructor + /// (C++0x [class.copy]p3), which can be used to move values of the class. + bool isMoveConstructor() const; + + /// \brief Determine whether this is a copy or move constructor. + /// + /// \param TypeQuals Will be set to the type qualifiers on the reference + /// parameter, if in fact this is a copy or move constructor. + bool isCopyOrMoveConstructor(unsigned &TypeQuals) const; + + /// \brief Determine whether this a copy or move constructor. + bool isCopyOrMoveConstructor() const { + unsigned Quals; + return isCopyOrMoveConstructor(Quals); + } + /// isConvertingConstructor - Whether this constructor is a /// converting constructor (C++ [class.conv.ctor]), which can be /// used for user-defined conversions. bool isConvertingConstructor(bool AllowExplicit) const; /// \brief Determine whether this is a member template specialization that - /// looks like a copy constructor. Such constructors are never used to copy + /// would copy the object to itself. Such constructors are never used to copy /// an object. - bool isCopyConstructorLikeSpecialization() const; + bool isSpecializationCopyingObject() const; + + /// \brief Get the constructor that this inheriting constructor is based on. + const CXXConstructorDecl *getInheritedConstructor() const; + + /// \brief Set the constructor that this inheriting constructor is based on. + void setInheritedConstructor(const CXXConstructorDecl *BaseCtor); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -1542,8 +1568,9 @@ class CXXDestructorDecl : public CXXMethodDecl { FunctionDecl *OperatorDelete; CXXDestructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, - QualType T, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXDestructor, RD, NameInfo, T, /*TInfo=*/0, false, + QualType T, TypeSourceInfo *TInfo, + bool isInline, bool isImplicitlyDeclared) + : CXXMethodDecl(CXXDestructor, RD, NameInfo, T, TInfo, false, SC_None, isInline), ImplicitlyDefined(false), OperatorDelete(0) { setImplicit(isImplicitlyDeclared); @@ -1553,7 +1580,8 @@ public: static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty); static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, - QualType T, bool isInline, + QualType T, TypeSourceInfo* TInfo, + bool isInline, bool isImplicitlyDeclared); /// isImplicitlyDefined - Whether this destructor was implicitly @@ -1918,13 +1946,16 @@ class UsingShadowDecl : public NamedDecl { /// The referenced declaration. NamedDecl *Underlying; - /// The using declaration which introduced this decl. - UsingDecl *Using; + /// \brief The using declaration which introduced this decl or the next using + /// shadow declaration contained in the aforementioned using declaration. + NamedDecl *UsingOrNextShadow; + friend class UsingDecl; UsingShadowDecl(DeclContext *DC, SourceLocation Loc, UsingDecl *Using, NamedDecl *Target) : NamedDecl(UsingShadow, DC, Loc, DeclarationName()), - Underlying(Target), Using(Using) { + Underlying(Target), + UsingOrNextShadow(reinterpret_cast<NamedDecl *>(Using)) { if (Target) { setDeclName(Target->getDeclName()); IdentifierNamespace = Target->getIdentifierNamespace(); @@ -1952,15 +1983,20 @@ public: } /// \brief Gets the using declaration to which this declaration is tied. - UsingDecl *getUsingDecl() const { return Using; } + UsingDecl *getUsingDecl() const; - /// \brief Sets the using declaration that introduces this target - /// declaration. - void setUsingDecl(UsingDecl* UD) { Using = UD; } + /// \brief The next using shadow declaration contained in the shadow decl + /// chain of the using declaration which introduced this decl. + UsingShadowDecl *getNextUsingShadowDecl() const { + return dyn_cast_or_null<UsingShadowDecl>(UsingOrNextShadow); + } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UsingShadowDecl *D) { return true; } static bool classofKind(Kind K) { return K == Decl::UsingShadow; } + + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// UsingDecl - Represents a C++ using-declaration. For example: @@ -1980,10 +2016,9 @@ class UsingDecl : public NamedDecl { /// declaration name embedded in the ValueDecl base class. DeclarationNameLoc DNLoc; - /// \brief The collection of shadow declarations associated with - /// this using declaration. This set can change as a class is - /// processed. - llvm::SmallPtrSet<UsingShadowDecl*, 8> Shadows; + /// \brief The first shadow declaration of the shadow decl chain associated + /// with this using declaration. + UsingShadowDecl *FirstUsingShadow; // \brief Has 'typename' keyword. bool IsTypeName; @@ -1993,7 +2028,7 @@ class UsingDecl : public NamedDecl { const DeclarationNameInfo &NameInfo, bool IsTypeNameArg) : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()), NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS), - DNLoc(NameInfo.getInfo()), IsTypeName(IsTypeNameArg) { + DNLoc(NameInfo.getInfo()), FirstUsingShadow(0),IsTypeName(IsTypeNameArg) { } public: @@ -2031,29 +2066,58 @@ public: /// \brief Sets whether the using declaration has 'typename'. void setTypeName(bool TN) { IsTypeName = TN; } - typedef llvm::SmallPtrSet<UsingShadowDecl*,8>::const_iterator shadow_iterator; - shadow_iterator shadow_begin() const { return Shadows.begin(); } - shadow_iterator shadow_end() const { return Shadows.end(); } + /// \brief Iterates through the using shadow declarations assosiated with + /// this using declaration. + class shadow_iterator { + /// \brief The current using shadow declaration. + UsingShadowDecl *Current; + + public: + typedef UsingShadowDecl* value_type; + typedef UsingShadowDecl* reference; + typedef UsingShadowDecl* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + shadow_iterator() : Current(0) { } + explicit shadow_iterator(UsingShadowDecl *C) : Current(C) { } - void addShadowDecl(UsingShadowDecl *S) { - assert(S->getUsingDecl() == this); - if (!Shadows.insert(S)) { - assert(false && "declaration already in set"); + reference operator*() const { return Current; } + pointer operator->() const { return Current; } + + shadow_iterator& operator++() { + Current = Current->getNextUsingShadowDecl(); + return *this; } - } - void removeShadowDecl(UsingShadowDecl *S) { - assert(S->getUsingDecl() == this); - if (!Shadows.erase(S)) { - assert(false && "declaration not in set"); + + shadow_iterator operator++(int) { + shadow_iterator tmp(*this); + ++(*this); + return tmp; } + + friend bool operator==(shadow_iterator x, shadow_iterator y) { + return x.Current == y.Current; + } + friend bool operator!=(shadow_iterator x, shadow_iterator y) { + return x.Current != y.Current; + } + }; + + shadow_iterator shadow_begin() const { + return shadow_iterator(FirstUsingShadow); } + shadow_iterator shadow_end() const { return shadow_iterator(); } /// \brief Return the number of shadowed declarations associated with this /// using declaration. - unsigned getNumShadowDecls() const { - return Shadows.size(); + unsigned shadow_size() const { + return std::distance(shadow_begin(), shadow_end()); } + void addShadowDecl(UsingShadowDecl *S); + void removeShadowDecl(UsingShadowDecl *S); + static UsingDecl *Create(ASTContext &C, DeclContext *DC, SourceRange NNR, SourceLocation UsingL, NestedNameSpecifier* TargetNNS, @@ -2145,6 +2209,9 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UnresolvedUsingValueDecl *D) { return true; } static bool classofKind(Kind K) { return K == UnresolvedUsingValue; } + + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// UnresolvedUsingTypenameDecl - Represents a dependent using diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 4b5e6fd48bb3..20d6da19b8ca 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -43,11 +43,16 @@ private: FriendUnion Friend; // A pointer to the next friend in the sequence. - FriendDecl *NextFriend; + LazyDeclPtr NextFriend; // Location of the 'friend' specifier. SourceLocation FriendLoc; + /// True if this 'friend' declaration is unsupported. Eventually we + /// will support every possible friend declaration, but for now we + /// silently ignore some and set this flag to authorize all access. + bool UnsupportedFriend; + friend class CXXRecordDecl::friend_iterator; friend class CXXRecordDecl; @@ -55,13 +60,19 @@ private: SourceLocation FriendL) : Decl(Decl::Friend, DC, L), Friend(Friend), - NextFriend(0), - FriendLoc(FriendL) { + NextFriend(), + FriendLoc(FriendL), + UnsupportedFriend(false) { } explicit FriendDecl(EmptyShell Empty) - : Decl(Decl::Friend, Empty), NextFriend(0) { } + : Decl(Decl::Friend, Empty), NextFriend() { } + FriendDecl *getNextFriend() { + return cast_or_null<FriendDecl>( + NextFriend.get(getASTContext().getExternalSource())); + } + public: static FriendDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_, @@ -87,6 +98,14 @@ public: return FriendLoc; } + /// Determines if this friend kind is unsupported. + bool isUnsupportedFriend() const { + return UnsupportedFriend; + } + void setUnsupportedFriend(bool Unsupported) { + UnsupportedFriend = Unsupported; + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FriendDecl *D) { return true; } @@ -115,7 +134,7 @@ public: friend_iterator &operator++() { assert(Ptr && "attempt to increment past end of friend list"); - Ptr = Ptr->NextFriend; + Ptr = Ptr->getNextFriend(); return *this; } diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h index 030291ea7345..cb9e1681cc06 100644 --- a/include/clang/AST/DeclGroup.h +++ b/include/clang/AST/DeclGroup.h @@ -14,7 +14,7 @@ #ifndef LLVM_CLANG_AST_DECLGROUP_H #define LLVM_CLANG_AST_DECLGROUP_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace clang { diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index ad26748e1343..b3ca474fcc19 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -28,7 +28,7 @@ class ObjCProtocolDecl; class ObjCCategoryDecl; class ObjCPropertyDecl; class ObjCPropertyImplDecl; -class CXXBaseOrMemberInitializer; +class CXXCtorInitializer; class ObjCListBase { void operator=(const ObjCListBase &); // DO NOT IMPLEMENT @@ -437,7 +437,7 @@ public: 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; + mutable const Type *TypeForDecl; friend class ASTContext; /// Class's super class. @@ -449,8 +449,11 @@ class ObjCInterfaceDecl : public ObjCContainerDecl { /// Protocols reference in both the @interface and class extensions. ObjCList<ObjCProtocolDecl> AllReferencedProtocols; - /// List of categories defined for this class. - /// FIXME: Why is this a linked list?? + /// \brief List of categories and class extensions defined for this class. + /// + /// Categories are stored as a linked list in the AST, since the categories + /// and class extensions come long after the initial interface declaration, + /// and we avoid dynamically-resized arrays in the AST whereever possible. ObjCCategoryDecl *CategoryList; /// IvarList - List of all ivars defined by this class; including class @@ -459,7 +462,11 @@ class ObjCInterfaceDecl : public ObjCContainerDecl { bool ForwardDecl:1; // declared with @class. bool InternalInterface:1; // true - no @interface for @implementation - + + /// \brief Indicates that the contents of this Objective-C class will be + /// completed by the external AST source when required. + mutable bool ExternallyCompleted : 1; + SourceLocation ClassLoc; // location of the class identifier. SourceLocation SuperClassLoc; // location of the super class identifier. SourceLocation EndLoc; // marks the '>', '}', or identifier. @@ -467,6 +474,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl { ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, SourceLocation CLoc, bool FD, bool isInternal); + void LoadExternalDefinition() const; public: static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation atLoc, @@ -474,7 +482,16 @@ public: SourceLocation ClassLoc = SourceLocation(), bool ForwardDecl = false, bool isInternal = false); + + /// \brief Indicate that this Objective-C class is complete, but that + /// the external AST source will be responsible for filling in its contents + /// when a complete class is required. + void setExternallyCompleted(); + const ObjCProtocolList &getReferencedProtocols() const { + if (ExternallyCompleted) + LoadExternalDefinition(); + return ReferencedProtocols; } @@ -494,29 +511,47 @@ public: typedef ObjCProtocolList::iterator protocol_iterator; protocol_iterator protocol_begin() const { + if (ExternallyCompleted) + LoadExternalDefinition(); + return ReferencedProtocols.begin(); } protocol_iterator protocol_end() const { + if (ExternallyCompleted) + LoadExternalDefinition(); + return ReferencedProtocols.end(); } typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; protocol_loc_iterator protocol_loc_begin() const { + if (ExternallyCompleted) + LoadExternalDefinition(); + return ReferencedProtocols.loc_begin(); } protocol_loc_iterator protocol_loc_end() const { + if (ExternallyCompleted) + LoadExternalDefinition(); + return ReferencedProtocols.loc_end(); } typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator; all_protocol_iterator all_referenced_protocol_begin() const { + if (ExternallyCompleted) + LoadExternalDefinition(); + return AllReferencedProtocols.empty() ? protocol_begin() : AllReferencedProtocols.begin(); } all_protocol_iterator all_referenced_protocol_end() const { + if (ExternallyCompleted) + LoadExternalDefinition(); + return AllReferencedProtocols.empty() ? protocol_end() : AllReferencedProtocols.end(); } @@ -551,10 +586,22 @@ public: bool isForwardDecl() const { return ForwardDecl; } void setForwardDecl(bool val) { ForwardDecl = val; } - ObjCInterfaceDecl *getSuperClass() const { return SuperClass; } + ObjCInterfaceDecl *getSuperClass() const { + if (ExternallyCompleted) + LoadExternalDefinition(); + + return SuperClass; + } + void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; } - ObjCCategoryDecl* getCategoryList() const { return CategoryList; } + ObjCCategoryDecl* getCategoryList() const { + if (ExternallyCompleted) + LoadExternalDefinition(); + + return CategoryList; + } + void setCategoryList(ObjCCategoryDecl *category) { CategoryList = category; } @@ -595,7 +642,7 @@ public: ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName); // Lookup a method in the classes implementation hierarchy. - ObjCMethodDecl *lookupPrivateInstanceMethod(const Selector &Sel); + ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel, bool Instance=true); // Location information, modeled after the Stmt API. SourceLocation getLocStart() const { return getLocation(); } // '@'interface @@ -621,8 +668,8 @@ public: bool RHSIsQualifiedID = false); // Low-level accessor - Type *getTypeForDecl() const { return TypeForDecl; } - void setTypeForDecl(Type *TD) const { TypeForDecl = TD; } + const Type *getTypeForDecl() const { return TypeForDecl; } + void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCInterfaceDecl *D) { return true; } @@ -991,6 +1038,7 @@ public: void insertNextClassCategory() { NextClassCategory = ClassInterface->getCategoryList(); ClassInterface->setCategoryList(this); + ClassInterface->setChangedSinceDeserialization(true); } bool IsClassExtension() const { return getIdentifier() == 0; } @@ -1168,7 +1216,7 @@ class ObjCImplementationDecl : public ObjCImplDecl { ObjCInterfaceDecl *SuperClass; /// Support for ivar initialization. /// IvarInitializers - The arguments used to initialize the ivars - CXXBaseOrMemberInitializer **IvarInitializers; + CXXCtorInitializer **IvarInitializers; unsigned NumIvarInitializers; /// true of class extension has at least one bitfield ivar. @@ -1187,10 +1235,10 @@ public: ObjCInterfaceDecl *superDecl); /// init_iterator - Iterates through the ivar initializer list. - typedef CXXBaseOrMemberInitializer **init_iterator; + typedef CXXCtorInitializer **init_iterator; /// init_const_iterator - Iterates through the ivar initializer list. - typedef CXXBaseOrMemberInitializer * const * init_const_iterator; + typedef CXXCtorInitializer * const * init_const_iterator; /// init_begin() - Retrieve an iterator to the first initializer. init_iterator init_begin() { return IvarInitializers; } @@ -1215,7 +1263,7 @@ public: } void setIvarInitializers(ASTContext &C, - CXXBaseOrMemberInitializer ** initializers, + CXXCtorInitializer ** initializers, unsigned numInitializers); bool hasSynthBitfield() const { return HasSynthBitfield; } @@ -1322,7 +1370,8 @@ public: OBJC_PR_retain = 0x10, OBJC_PR_copy = 0x20, OBJC_PR_nonatomic = 0x40, - OBJC_PR_setter = 0x80 + OBJC_PR_setter = 0x80, + OBJC_PR_atomic = 0x100 }; enum SetterKind { Assign, Retain, Copy }; @@ -1330,8 +1379,8 @@ public: private: SourceLocation AtLoc; // location of @property TypeSourceInfo *DeclType; - unsigned PropertyAttributes : 8; - unsigned PropertyAttributesAsWritten : 8; + unsigned PropertyAttributes : 9; + unsigned PropertyAttributesAsWritten : 9; // @required/@optional unsigned PropertyImplementation : 2; @@ -1429,6 +1478,10 @@ public: return PropertyIvarDecl; } + virtual SourceRange getSourceRange() const { + return SourceRange(AtLoc, getLocation()); + } + /// Lookup a property by name in the specified DeclContext. static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC, IdentifierInfo *propertyID); @@ -1450,6 +1503,15 @@ public: }; private: SourceLocation AtLoc; // location of @synthesize or @dynamic + + /// \brief For @synthesize, the location of the ivar, if it was written in + /// the source code. + /// + /// \code + /// @synthesize int a = b + /// \endcode + SourceLocation IvarLoc; + /// Property declaration being implemented ObjCPropertyDecl *PropertyDecl; @@ -1466,9 +1528,10 @@ private: ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L, ObjCPropertyDecl *property, Kind PK, - ObjCIvarDecl *ivarDecl) + ObjCIvarDecl *ivarDecl, + SourceLocation ivarLoc) : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc), - PropertyDecl(property), PropertyIvarDecl(ivarDecl), + IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl), GetterCXXConstructor(0), SetterCXXAssignment(0) { assert (PK == Dynamic || PropertyIvarDecl); } @@ -1478,11 +1541,11 @@ public: SourceLocation atLoc, SourceLocation L, ObjCPropertyDecl *property, Kind PK, - ObjCIvarDecl *ivarDecl); + ObjCIvarDecl *ivarDecl, + SourceLocation ivarLoc); - virtual SourceRange getSourceRange() const { - return SourceRange(AtLoc, getLocation()); - } + virtual SourceRange getSourceRange() const; + SourceLocation getLocStart() const { return AtLoc; } void setAtLoc(SourceLocation Loc) { AtLoc = Loc; } @@ -1498,7 +1561,13 @@ public: ObjCIvarDecl *getPropertyIvarDecl() const { return PropertyIvarDecl; } - void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { PropertyIvarDecl = Ivar; } + SourceLocation getPropertyIvarDeclLoc() const { return IvarLoc; } + + void setPropertyIvarDecl(ObjCIvarDecl *Ivar, + SourceLocation IvarLoc) { + PropertyIvarDecl = Ivar; + this->IvarLoc = IvarLoc; + } Expr *getGetterCXXConstructor() const { return GetterCXXConstructor; @@ -1517,6 +1586,8 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCPropertyImplDecl *D) { return true; } static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; } + + friend class ASTDeclReader; }; } // end namespace clang diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index b532668242fd..176c6badae16 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -53,7 +53,7 @@ class TemplateParameterList { SourceLocation RAngleLoc); public: - static TemplateParameterList *Create(ASTContext &C, + static TemplateParameterList *Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, NamedDecl **Params, @@ -85,7 +85,7 @@ public: return begin()[Idx]; } - /// \btief Returns the minimum number of arguments needed to form a + /// \brief 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 or if there is a parameter pack. @@ -107,101 +107,57 @@ public: } }; -/// \brief A helper class for making template argument lists. -class TemplateArgumentListBuilder { - TemplateArgument *StructuredArgs; - unsigned MaxStructuredArgs; - unsigned NumStructuredArgs; - - llvm::SmallVector<TemplateArgument, 4> FlatArgs; - unsigned MaxFlatArgs; - unsigned NumFlatArgs; - - bool AddingToPack; - unsigned PackBeginIndex; - -public: - TemplateArgumentListBuilder(const TemplateParameterList *Parameters, - unsigned NumTemplateArgs) - : StructuredArgs(0), MaxStructuredArgs(Parameters->size()), - NumStructuredArgs(0), FlatArgs(0), - MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0), - AddingToPack(false), PackBeginIndex(0) { } - - void Append(const TemplateArgument &Arg); - void BeginPack(); - void EndPack(); - - unsigned flatSize() const { return FlatArgs.size(); } - const TemplateArgument *getFlatArguments() const { return FlatArgs.data(); } - - unsigned structuredSize() const { - // If we don't have any structured args, just reuse the flat size. - if (!StructuredArgs) - return flatSize(); - - return NumStructuredArgs; - } - const TemplateArgument *getStructuredArguments() const { - // If we don't have any structured args, just reuse the flat args. - if (!StructuredArgs) - return getFlatArguments(); - - return StructuredArgs; - } -}; - /// \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 own the pointer. - llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments; + llvm::PointerIntPair<const TemplateArgument *, 1> Arguments; /// \brief The number of template arguments in this template /// argument list. - unsigned NumFlatArguments; - - llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments; - unsigned NumStructuredArguments; + unsigned NumArguments; TemplateArgumentList(const TemplateArgumentList &Other); // DO NOT IMPL void operator=(const TemplateArgumentList &Other); // DO NOT IMPL + + TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs, + bool Owned) + : Arguments(Args, Owned), NumArguments(NumArgs) { } + public: - /// TemplateArgumentList - If this constructor is passed "true" for 'TakeArgs' - /// it copies them into a locally new[]'d array. If passed "false", then it - /// just references the array passed in. This is only safe if the builder - /// outlives it, but saves a copy. - TemplateArgumentList(ASTContext &Context, - TemplateArgumentListBuilder &Builder, - bool TakeArgs); - - /// TemplateArgumentList - It copies the template arguments into a locally - /// new[]'d array. - TemplateArgumentList(ASTContext &Context, - const TemplateArgument *Args, unsigned NumArgs); - - /// Produces a shallow copy of the given template argument list. This - /// assumes that the input argument list outlives it. This takes the list as - /// a pointer to avoid looking like a copy constructor, since this really - /// really isn't safe to use that way. - explicit TemplateArgumentList(const TemplateArgumentList *Other); - - TemplateArgumentList() : NumFlatArguments(0), NumStructuredArguments(0) { } - - /// \brief Copies the template arguments into a locally new[]'d array. - void init(ASTContext &Context, - const TemplateArgument *Args, unsigned NumArgs); + /// \brief Type used to indicate that the template argument list itself is a + /// stack object. It does not own its template arguments. + enum OnStackType { OnStack }; + + /// \brief Create a new template argument list that copies the given set of + /// template arguments. + static TemplateArgumentList *CreateCopy(ASTContext &Context, + const TemplateArgument *Args, + unsigned NumArgs); + + /// \brief Construct a new, temporary template argument list on the stack. + /// + /// The template argument list does not own the template arguments + /// provided. + explicit TemplateArgumentList(OnStackType, + const TemplateArgument *Args, unsigned NumArgs) + : Arguments(Args, false), NumArguments(NumArgs) { } + + /// \brief Produces a shallow copy of the given template argument list. + /// + /// This operation assumes that the input argument list outlives it. + /// This takes the list as a pointer to avoid looking like a copy + /// constructor, since this really really isn't safe to use that + /// way. + explicit TemplateArgumentList(const TemplateArgumentList *Other) + : Arguments(Other->data(), false), NumArguments(Other->size()) { } /// \brief Retrieve the template argument at a given index. const TemplateArgument &get(unsigned Idx) const { - assert(Idx < NumFlatArguments && "Invalid template argument index"); - return getFlatArgumentList()[Idx]; + assert(Idx < NumArguments && "Invalid template argument index"); + return data()[Idx]; } /// \brief Retrieve the template argument at a given index. @@ -209,15 +165,11 @@ public: /// \brief Retrieve the number of template arguments in this /// template argument list. - unsigned size() const { return NumFlatArguments; } - - /// \brief Retrieve the number of template arguments in the - /// flattened template argument list. - unsigned flat_size() const { return NumFlatArguments; } + unsigned size() const { return NumArguments; } - /// \brief Retrieve the flattened template argument list. - const TemplateArgument *getFlatArgumentList() const { - return FlatArguments.getPointer(); + /// \brief Retrieve a pointer to the template argument list. + const TemplateArgument *data() const { + return Arguments.getPointer(); } }; @@ -292,7 +244,31 @@ public: /// which is a FunctionDecl that has been explicitly specialization or /// instantiated from a function template. class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode { + FunctionTemplateSpecializationInfo(FunctionDecl *FD, + FunctionTemplateDecl *Template, + TemplateSpecializationKind TSK, + const TemplateArgumentList *TemplateArgs, + const TemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation POI) + : Function(FD), + Template(Template, TSK - 1), + TemplateArguments(TemplateArgs), + TemplateArgumentsAsWritten(TemplateArgsAsWritten), + PointOfInstantiation(POI) { } + public: + static FunctionTemplateSpecializationInfo * + Create(ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template, + TemplateSpecializationKind TSK, + const TemplateArgumentList *TemplateArgs, + const TemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation POI) { + return new (C) FunctionTemplateSpecializationInfo(FD, Template, TSK, + TemplateArgs, + TemplateArgsAsWritten, + POI); + } + /// \brief The function template specialization that this structure /// describes. FunctionDecl *Function; @@ -345,8 +321,8 @@ public: } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, TemplateArguments->getFlatArgumentList(), - TemplateArguments->flat_size(), + Profile(ID, TemplateArguments->data(), + TemplateArguments->size(), Function->getASTContext()); } @@ -441,11 +417,6 @@ class DependentFunctionTemplateSpecializationInfo { return reinterpret_cast<FunctionTemplateDecl*const*>(this+1); } - const TemplateArgumentLoc *getTemplateArgs() const { - return reinterpret_cast<const TemplateArgumentLoc*>( - &getTemplates()[getNumTemplates()]); - } - public: DependentFunctionTemplateSpecializationInfo( const UnresolvedSetImpl &Templates, @@ -463,6 +434,12 @@ public: return getTemplates()[I]; } + /// \brief Returns the explicit template arguments that were given. + const TemplateArgumentLoc *getTemplateArgs() const { + return reinterpret_cast<const TemplateArgumentLoc*>( + &getTemplates()[getNumTemplates()]); + } + /// \brief Returns the number of explicit template arguments that were given. unsigned getNumTemplateArgs() const { return d.NumArgs; @@ -584,7 +561,7 @@ protected: /// for the common pointer. CommonBase *getCommonPtr(); - virtual CommonBase *newCommon() = 0; + virtual CommonBase *newCommon(ASTContext &C) = 0; // Construct a template decl with name, parameters, and templated element. RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, @@ -789,19 +766,13 @@ protected: TemplateParameterList *Params, NamedDecl *Decl) : RedeclarableTemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { } - CommonBase *newCommon(); + CommonBase *newCommon(ASTContext &C); Common *getCommonPtr() { return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); } - friend void FunctionDecl::setFunctionTemplateSpecialization( - FunctionTemplateDecl *Template, - const TemplateArgumentList *TemplateArgs, - void *InsertPos, - TemplateSpecializationKind TSK, - const TemplateArgumentListInfo *TemplateArgsAsWritten, - SourceLocation PointOfInstantiation); + friend class FunctionDecl; /// \brief Retrieve the set of function template specializations of this /// function template. @@ -940,15 +911,15 @@ class TemplateTypeParmDecl : public TypeDecl { bool Typename, QualType Type, bool ParameterPack) : TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename), InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() { - TypeForDecl = Type.getTypePtr(); + TypeForDecl = Type.getTypePtrOrNull(); } public: - static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC, + static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, bool Typename, bool ParameterPack); - static TemplateTypeParmDecl *Create(ASTContext &C, EmptyShell Empty); + static TemplateTypeParmDecl *Create(const ASTContext &C, EmptyShell Empty); /// \brief Whether this template type parameter was declared with /// the 'typename' keyword. If not, it was declared with the 'class' @@ -1014,22 +985,54 @@ public: /// template<int Size> class array { }; /// @endcode class NonTypeTemplateParmDecl - : public VarDecl, protected TemplateParmPosition { + : public DeclaratorDecl, protected TemplateParmPosition { /// \brief The default template argument, if any, and whether or not /// it was inherited. llvm::PointerIntPair<Expr*, 1, bool> DefaultArgumentAndInherited; + // FIXME: Collapse this into TemplateParamPosition; or, just move depth/index + // down here to save memory. + + /// \brief Whether this non-type template parameter is a parameter pack. + bool ParameterPack; + + /// \brief Whether this non-type template parameter is an "expanded" + /// parameter pack, meaning that its type is a pack expansion and we + /// already know the set of types that expansion expands to. + bool ExpandedParameterPack; + + /// \brief The number of types in an expanded parameter pack. + unsigned NumExpandedTypes; + NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, - TypeSourceInfo *TInfo) - : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None), - TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false) + bool ParameterPack, TypeSourceInfo *TInfo) + : DeclaratorDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo), + TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false), + ParameterPack(ParameterPack), ExpandedParameterPack(false), + NumExpandedTypes(0) { } + NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, + unsigned P, IdentifierInfo *Id, QualType T, + TypeSourceInfo *TInfo, + const QualType *ExpandedTypes, + unsigned NumExpandedTypes, + TypeSourceInfo **ExpandedTInfos); + + friend class ASTDeclReader; + public: static NonTypeTemplateParmDecl * - Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo); + Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, + unsigned P, IdentifierInfo *Id, QualType T, bool ParameterPack, + TypeSourceInfo *TInfo); + + static NonTypeTemplateParmDecl * + Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, + unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + const QualType *ExpandedTypes, unsigned NumExpandedTypes, + TypeSourceInfo **ExpandedTInfos); using TemplateParmPosition::getDepth; using TemplateParmPosition::setDepth; @@ -1037,6 +1040,9 @@ public: using TemplateParmPosition::setPosition; using TemplateParmPosition::getIndex; + SourceLocation getInnerLocStart() const; + SourceRange getSourceRange() const; + /// \brief Determine whether this template parameter has a default /// argument. bool hasDefaultArgument() const { @@ -1071,6 +1077,65 @@ public: DefaultArgumentAndInherited.setInt(false); } + /// \brief Whether this parameter is a non-type template parameter pack. + /// + /// If the parameter is a parameter pack, the type may be a + /// \c PackExpansionType. In the following example, the \c Dims parameter + /// is a parameter pack (whose type is 'unsigned'). + /// + /// \code + /// template<typename T, unsigned ...Dims> struct multi_array; + /// \endcode + bool isParameterPack() const { return ParameterPack; } + + /// \brief Whether this parameter is a non-type template parameter pack + /// that has different types at different positions. + /// + /// A parameter pack is an expanded parameter pack when the original + /// parameter pack's type was itself a pack expansion, and that expansion + /// has already been expanded. For example, given: + /// + /// \code + /// template<typename ...Types> + /// struct X { + /// template<Types ...Values> + /// struct Y { /* ... */ }; + /// }; + /// \endcode + /// + /// The parameter pack \c Values has a \c PackExpansionType as its type, + /// which expands \c Types. When \c Types is supplied with template arguments + /// by instantiating \c X, the instantiation of \c Values becomes an + /// expanded parameter pack. For example, instantiating + /// \c X<int, unsigned int> results in \c Values being an expanded parameter + /// pack with expansion types \c int and \c unsigned int. + /// + /// The \c getExpansionType() and \c getExpansionTypeSourceInfo() functions + /// return the expansion types. + bool isExpandedParameterPack() const { return ExpandedParameterPack; } + + /// \brief Retrieves the number of expansion types in an expanded parameter pack. + unsigned getNumExpansionTypes() const { + assert(ExpandedParameterPack && "Not an expansion parameter pack"); + return NumExpandedTypes; + } + + /// \brief Retrieve a particular expansion type within an expanded parameter + /// pack. + QualType getExpansionType(unsigned I) const { + assert(I < NumExpandedTypes && "Out-of-range expansion type index"); + void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1); + return QualType::getFromOpaquePtr(TypesAndInfos[2*I]); + } + + /// \brief Retrieve a particular expansion type source info within an + /// expanded parameter pack. + TypeSourceInfo *getExpansionTypeSourceInfo(unsigned I) const { + assert(I < NumExpandedTypes && "Out-of-range expansion type index"); + void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1); + return static_cast<TypeSourceInfo *>(TypesAndInfos[2*I+1]); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const NonTypeTemplateParmDecl *D) { return true; } @@ -1092,24 +1157,36 @@ class TemplateTemplateParmDecl /// Whether or not the default argument was inherited. bool DefaultArgumentWasInherited; + /// \brief Whether this parameter is a parameter pack. + bool ParameterPack; + TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, - unsigned D, unsigned P, + unsigned D, unsigned P, bool ParameterPack, IdentifierInfo *Id, TemplateParameterList *Params) : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), TemplateParmPosition(D, P), DefaultArgument(), - DefaultArgumentWasInherited(false) + DefaultArgumentWasInherited(false), ParameterPack(ParameterPack) { } public: - static TemplateTemplateParmDecl *Create(ASTContext &C, DeclContext *DC, + static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, + unsigned P, bool ParameterPack, + IdentifierInfo *Id, TemplateParameterList *Params); using TemplateParmPosition::getDepth; using TemplateParmPosition::getPosition; using TemplateParmPosition::getIndex; + /// \brief Whether this template template parameter is a template + /// parameter pack. + /// + /// \code + /// template<template <class T> ...MetaFunctions> struct Apply; + /// \endcode + bool isParameterPack() const { return ParameterPack; } + /// \brief Determine whether this template parameter has a default /// argument. bool hasDefaultArgument() const { @@ -1211,7 +1288,7 @@ class ClassTemplateSpecializationDecl ExplicitSpecializationInfo *ExplicitInfo; /// \brief The template arguments used to describe this specialization. - TemplateArgumentList TemplateArgs; + TemplateArgumentList *TemplateArgs; /// \brief The point where this template was instantiated (if any) SourceLocation PointOfInstantiation; @@ -1224,7 +1301,8 @@ protected: ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, ClassTemplateDecl *SpecializedTemplate, - TemplateArgumentListBuilder &Builder, + const TemplateArgument *Args, + unsigned NumArgs, ClassTemplateSpecializationDecl *PrevDecl); explicit ClassTemplateSpecializationDecl(Kind DK); @@ -1233,7 +1311,8 @@ public: static ClassTemplateSpecializationDecl * Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L, ClassTemplateDecl *SpecializedTemplate, - TemplateArgumentListBuilder &Builder, + const TemplateArgument *Args, + unsigned NumArgs, ClassTemplateSpecializationDecl *PrevDecl); static ClassTemplateSpecializationDecl * Create(ASTContext &Context, EmptyShell Empty); @@ -1259,15 +1338,7 @@ public: /// \brief Retrieve the template arguments of the class template /// specialization. const TemplateArgumentList &getTemplateArgs() const { - return TemplateArgs; - } - - /// \brief Initialize the template arguments of the class template - /// specialization. - void initTemplateArgs(TemplateArgument *Args, unsigned NumArgs) { - assert(TemplateArgs.flat_size() == 0 && - "Template arguments already initialized!"); - TemplateArgs.init(getASTContext(), Args, NumArgs); + return *TemplateArgs; } /// \brief Determine the kind of specialization that this @@ -1357,18 +1428,6 @@ public: SpecializedTemplate = PS; } - /// \brief Note that this class template specialization is actually an - /// instantiation of the given class template partial specialization whose - /// template arguments have been deduced. - void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec, - TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs) { - ASTContext &Ctx = getASTContext(); - setInstantiationOf(PartialSpec, - new (Ctx) TemplateArgumentList(Ctx, TemplateArgs, - NumTemplateArgs)); - } - /// \brief Note that this class template specialization is an instantiation /// of the given class template. void setInstantiationOf(ClassTemplateDecl *TemplDecl) { @@ -1415,8 +1474,7 @@ public: SourceLocation getInnerLocStart() const { return getTemplateKeywordLoc(); } void Profile(llvm::FoldingSetNodeID &ID) const { - Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size(), - getASTContext()); + Profile(ID, TemplateArgs->data(), TemplateArgs->size(), getASTContext()); } static void @@ -1440,6 +1498,9 @@ public: static bool classof(const ClassTemplatePartialSpecializationDecl *) { return true; } + + friend class ASTDeclReader; + friend class ASTDeclWriter; }; class ClassTemplatePartialSpecializationDecl @@ -1469,15 +1530,16 @@ class ClassTemplatePartialSpecializationDecl DeclContext *DC, SourceLocation L, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, - TemplateArgumentListBuilder &Builder, + const TemplateArgument *Args, + unsigned NumArgs, TemplateArgumentLoc *ArgInfos, unsigned NumArgInfos, ClassTemplatePartialSpecializationDecl *PrevDecl, unsigned SequenceNumber) : ClassTemplateSpecializationDecl(Context, ClassTemplatePartialSpecialization, - TK, DC, L, SpecializedTemplate, Builder, - PrevDecl), + TK, DC, L, SpecializedTemplate, + Args, NumArgs, PrevDecl), TemplateParams(Params), ArgsAsWritten(ArgInfos), NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber), InstantiatedFromMember(0, false) { } @@ -1493,7 +1555,8 @@ public: Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, - TemplateArgumentListBuilder &Builder, + const TemplateArgument *Args, + unsigned NumArgs, const TemplateArgumentListInfo &ArgInfos, QualType CanonInjectedType, ClassTemplatePartialSpecializationDecl *PrevDecl, @@ -1512,18 +1575,11 @@ public: return TemplateParams; } - void initTemplateParameters(TemplateParameterList *Params) { - assert(TemplateParams == 0 && "TemplateParams already set"); - TemplateParams = Params; - } - /// Get the template arguments as written. TemplateArgumentLoc *getTemplateArgsAsWritten() const { return ArgsAsWritten; } - void initTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgInfos); - /// Get the number of template arguments as written. unsigned getNumTemplateArgsAsWritten() const { return NumArgsAsWritten; @@ -1532,8 +1588,7 @@ public: /// \brief Get the sequence number for this class template partial /// specialization. unsigned getSequenceNumber() const { return SequenceNumber; } - void setSequenceNumber(unsigned N) { SequenceNumber = N; } - + /// \brief Retrieve the member class template partial specialization from /// which this particular class template partial specialization was /// instantiated. @@ -1617,6 +1672,9 @@ public: static bool classof(const ClassTemplatePartialSpecializationDecl *) { return true; } + + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// Declaration of a class template. @@ -1630,6 +1688,8 @@ protected: /// \brief Data that is common to all of the declarations of a given /// class template. struct Common : CommonBase { + Common() : LazySpecializations() { } + /// \brief The class template specializations for this class /// template, including explicit specializations and instantiations. llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations; @@ -1641,25 +1701,31 @@ protected: /// \brief The injected-class-name type for this class template. QualType InjectedClassNameType; + + /// \brief If non-null, points to an array of specializations (including + /// partial specializations) known ownly by their external declaration IDs. + /// + /// The first value in the array is the number of of specializations/ + /// partial specializations that follow. + uint32_t *LazySpecializations; }; + /// \brief Load any lazily-loaded specializations from the external source. + void LoadLazySpecializations(); + /// \brief Retrieve the set of specializations of this class template. - llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() { - return getCommonPtr()->Specializations; - } + llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations(); /// \brief Retrieve the set of partial specializations of this class /// template. llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> & - getPartialSpecializations() { - return getCommonPtr()->PartialSpecializations; - } + getPartialSpecializations(); ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) : RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { } - CommonBase *newCommon(); + CommonBase *newCommon(ASTContext &C); Common *getCommonPtr() { return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); @@ -1693,9 +1759,7 @@ public: /// \brief Insert the specified specialization knowing that it is not already /// in. InsertPos must be obtained from findSpecialization. - void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos) { - getSpecializations().InsertNode(D, InsertPos); - } + void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos); ClassTemplateDecl *getCanonicalDecl() { return redeclarable_base::getCanonicalDecl(); @@ -1729,9 +1793,7 @@ public: /// \brief Insert the specified partial specialization knowing that it is not /// already in. InsertPos must be obtained from findPartialSpecialization. void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D, - void *InsertPos) { - getPartialSpecializations().InsertNode(D, InsertPos); - } + void *InsertPos); /// \brief Return the next partial specialization sequence number. unsigned getNextPartialSpecSequenceNumber() { diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 8bb627597520..e54719b33d30 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -315,7 +315,7 @@ inline bool operator>=(DeclarationName LHS, DeclarationName RHS) { /// retrieved using its member functions (e.g., /// getCXXConstructorName). class DeclarationNameTable { - ASTContext &Ctx; + const ASTContext &Ctx; void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> * CXXOperatorIdName *CXXOperatorNames; // Operator names void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName* @@ -324,7 +324,7 @@ class DeclarationNameTable { DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE public: - DeclarationNameTable(ASTContext &C); + DeclarationNameTable(const ASTContext &C); ~DeclarationNameTable(); /// getIdentifier - Create a declaration name that is a simple @@ -402,7 +402,7 @@ struct DeclarationNameLoc { DeclarationNameLoc(DeclarationName Name); // FIXME: this should go away once all DNLocs are properly initialized. - DeclarationNameLoc() { NamedType.TInfo = 0; } + DeclarationNameLoc() { memset((void*) this, 0, sizeof(*this)); } }; // struct DeclarationNameLoc @@ -492,6 +492,10 @@ public: LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding(); } + /// \brief Determine whether this name contains an unexpanded + /// parameter pack. + bool containsUnexpandedParameterPack() const; + /// getAsString - Retrieve the human-readable string for this name. std::string getAsString() const; diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h new file mode 100644 index 000000000000..035f57c12ea7 --- /dev/null +++ b/include/clang/AST/EvaluatedExprVisitor.h @@ -0,0 +1,82 @@ +//===--- EvaluatedExprVisitor.h - Evaluated expression visitor --*- 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 EvaluatedExprVisitor class template, which visits +// the potentially-evaluated subexpressions of a potentially-evaluated +// expression. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H +#define LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H + +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" + +namespace clang { + +class ASTContext; + +/// \begin Given a potentially-evaluated expression, this visitor visits all +/// of its potentially-evaluated subexpressions, recursively. +template<typename ImplClass> +class EvaluatedExprVisitor : public StmtVisitor<ImplClass> { + ASTContext &Context; + +public: + explicit EvaluatedExprVisitor(ASTContext &Context) : Context(Context) { } + + // Expressions that have no potentially-evaluated subexpressions (but may have + // other sub-expressions). + void VisitDeclRefExpr(DeclRefExpr *E) { } + void VisitOffsetOfExpr(OffsetOfExpr *E) { } + void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { } + void VisitBlockExpr(BlockExpr *E) { } + void VisitCXXUuidofExpr(CXXUuidofExpr *E) { } + void VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { } + + void VisitMemberExpr(MemberExpr *E) { + // Only the base matters. + return this->Visit(E->getBase()); + } + + void VisitChooseExpr(ChooseExpr *E) { + // Only the selected subexpression matters; the other one is not evaluated. + return this->Visit(E->getChosenSubExpr(Context)); + } + + void VisitDesignatedInitExpr(DesignatedInitExpr *E) { + // Only the actual initializer matters; the designators are all constant + // expressions. + return this->Visit(E->getInit()); + } + + void VisitCXXTypeidExpr(CXXTypeidExpr *E) { + // typeid(expression) is potentially evaluated when the argument is + // a glvalue of polymorphic type. (C++ 5.2.8p2-3) + if (!E->isTypeOperand() && E->Classify(Context).isGLValue()) + if (const RecordType *Record + = E->getExprOperand()->getType()->template getAs<RecordType>()) + if (cast<CXXRecordDecl>(Record->getDecl())->isPolymorphic()) + return this->Visit(E->getExprOperand()); + } + + /// \brief The basis case walks all of the children of the statement or + /// expression, assuming they are all potentially evaluated. + void VisitStmt(Stmt *S) { + for (Stmt::child_range C = S->children(); C; ++C) + if (*C) + this->Visit(*C); + } +}; + +} + +#endif // LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 48130becf3b5..a17205c2b6b9 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -25,6 +25,7 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include <cctype> #include <vector> namespace clang { @@ -39,8 +40,10 @@ namespace clang { class CXXBaseSpecifier; class CXXOperatorCallExpr; class CXXMemberCallExpr; + class ObjCPropertyRefExpr; class TemplateArgumentLoc; class TemplateArgumentListInfo; + class OpaqueValueExpr; /// \brief A simple array of base specifiers. typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath; @@ -52,24 +55,14 @@ typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath; class Expr : public Stmt { QualType TR; - virtual void ANCHOR(); // key function. 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; - - /// ValueKind - The value classification of this expression. - /// Only actually used by certain subclasses. - unsigned ValueKind : 2; - - enum { BitsRemaining = 28 }; - - Expr(StmtClass SC, QualType T, bool TD, bool VD) - : Stmt(SC), TypeDependent(TD), ValueDependent(VD), ValueKind(0) { + Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK, + bool TD, bool VD, bool ContainsUnexpandedParameterPack) : Stmt(SC) { + ExprBits.TypeDependent = TD; + ExprBits.ValueDependent = VD; + ExprBits.ValueKind = VK; + ExprBits.ObjectKind = OK; + ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; setType(T); } @@ -77,15 +70,6 @@ protected: explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { } public: - /// \brief Increases the reference count for this expression. - /// - /// Invoke the Retain() operation when this expression - /// is being shared by another owner. - Expr *Retain() { - Stmt::Retain(); - return this; - } - QualType getType() const { return TR; } void setType(QualType t) { // In C++, the type of an expression is always adjusted so that it @@ -108,10 +92,10 @@ public: /// @code /// template<int Size, char (&Chars)[Size]> struct meta_string; /// @endcode - bool isValueDependent() const { return ValueDependent; } + bool isValueDependent() const { return ExprBits.ValueDependent; } /// \brief Set whether this expression is value-dependent or not. - void setValueDependent(bool VD) { ValueDependent = VD; } + void setValueDependent(bool VD) { ExprBits.ValueDependent = VD; } /// isTypeDependent - Determines whether this expression is /// type-dependent (C++ [temp.dep.expr]), which means that its type @@ -124,19 +108,38 @@ public: /// x + y; /// } /// @endcode - bool isTypeDependent() const { return TypeDependent; } + bool isTypeDependent() const { return ExprBits.TypeDependent; } /// \brief Set whether this expression is type-dependent or not. - void setTypeDependent(bool TD) { TypeDependent = TD; } + void setTypeDependent(bool TD) { ExprBits.TypeDependent = TD; } + + /// \brief Whether this expression contains an unexpanded parameter + /// pack (for C++0x variadic templates). + /// + /// Given the following function template: + /// + /// \code + /// template<typename F, typename ...Types> + /// void forward(const F &f, Types &&...args) { + /// f(static_cast<Types&&>(args)...); + /// } + /// \endcode + /// + /// The expressions \c args and \c static_cast<Types&&>(args) both + /// contain parameter packs. + bool containsUnexpandedParameterPack() const { + return ExprBits.ContainsUnexpandedParameterPack; + } - /// 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; + /// \brief Set the bit that describes whether this expression + /// contains an unexpanded parameter pack. + void setContainsUnexpandedParameterPack(bool PP = true) { + ExprBits.ContainsUnexpandedParameterPack = PP; + } /// getExprLoc - Return the preferred location for the arrow when diagnosing /// a problem with a generic expression. - virtual SourceLocation getExprLoc() const { return getLocStart(); } + SourceLocation getExprLoc() const; /// isUnusedResultAWarning - Return true if this immediate expression should /// be warned about if the result is unused. If so, fill in Loc and Ranges @@ -145,19 +148,25 @@ public: bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, SourceRange &R2, ASTContext &Ctx) 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++] + /// isLValue - True if this expression is an "l-value" according to + /// the rules of the current language. C and C++ give somewhat + /// different rules for this concept, but in general, the result of + /// an l-value expression identifies a specific object whereas the + /// result of an r-value expression is a value detached from any + /// specific storage. /// - enum isLvalueResult { + /// C++0x divides the concept of "r-value" into pure r-values + /// ("pr-values") and so-called expiring values ("x-values"), which + /// identify specific objects that can be safely cannibalized for + /// their resources. This is an unfortunate abuse of terminology on + /// the part of the C++ committee. In Clang, when we say "r-value", + /// we generally mean a pr-value. + bool isLValue() const { return getValueKind() == VK_LValue; } + bool isRValue() const { return getValueKind() == VK_RValue; } + bool isXValue() const { return getValueKind() == VK_XValue; } + bool isGLValue() const { return getValueKind() != VK_RValue; } + + enum LValueClassification { LV_Valid, LV_NotObjectType, LV_IncompleteVoidType, @@ -167,7 +176,8 @@ public: LV_SubObjCPropertySetting, LV_ClassTemporary }; - isLvalueResult isLvalue(ASTContext &Ctx) const; + /// Reasons why an expression might not be an l-value. + LValueClassification ClassifyLValue(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, @@ -252,8 +262,14 @@ public: bool isPRValue() const { return Kind >= CL_Function; } bool isRValue() const { return Kind >= CL_XValue; } bool isModifiable() const { return getModifiable() == CM_Modifiable; } + + /// \brief Create a simple, modifiably lvalue + static Classification makeSimpleLValue() { + return Classification(CL_LValue, CM_Modifiable); + } + }; - /// \brief classify - Classify this expression according to the C++0x + /// \brief Classify - Classify this expression according to the C++0x /// expression taxonomy. /// /// C++0x defines ([basic.lval]) a new taxonomy of expressions to replace the @@ -269,7 +285,7 @@ public: return ClassifyImpl(Ctx, 0); } - /// \brief classifyModifiable - Classify this expression according to the + /// \brief ClassifyModifiable - Classify this expression according to the /// C++0x expression taxonomy, and see if it is valid on the left side /// of an assignment. /// @@ -281,6 +297,40 @@ public: return ClassifyImpl(Ctx, &Loc); } + /// getValueKindForType - Given a formal return or parameter type, + /// give its value kind. + static ExprValueKind getValueKindForType(QualType T) { + if (const ReferenceType *RT = T->getAs<ReferenceType>()) + return (isa<LValueReferenceType>(RT) + ? VK_LValue + : (RT->getPointeeType()->isFunctionType() + ? VK_LValue : VK_XValue)); + return VK_RValue; + } + + /// getValueKind - The value kind that this expression produces. + ExprValueKind getValueKind() const { + return static_cast<ExprValueKind>(ExprBits.ValueKind); + } + + /// getObjectKind - The object kind that this expression produces. + /// Object kinds are meaningful only for expressions that yield an + /// l-value or x-value. + ExprObjectKind getObjectKind() const { + return static_cast<ExprObjectKind>(ExprBits.ObjectKind); + } + + bool isOrdinaryOrBitFieldObject() const { + ExprObjectKind OK = getObjectKind(); + return (OK == OK_Ordinary || OK == OK_BitField); + } + + /// setValueKind - Set the value kind produced by this expression. + void setValueKind(ExprValueKind Cat) { ExprBits.ValueKind = Cat; } + + /// setObjectKind - Set the object kind produced by this expression. + void setObjectKind(ExprObjectKind Cat) { ExprBits.ObjectKind = Cat; } + private: Classification ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const; @@ -294,6 +344,10 @@ public: return const_cast<Expr*>(this)->getBitField(); } + /// \brief If this expression is an l-value for an Objective C + /// property, find the underlying property reference expression. + const ObjCPropertyRefExpr *getObjCProperty() const; + /// \brief Returns whether this expression refers to a vector element. bool refersToVectorElement() const; @@ -355,33 +409,49 @@ public: /// 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; + bool Evaluate(EvalResult &Result, const ASTContext &Ctx) const; /// EvaluateAsBooleanCondition - Return true if this is a constant /// which we we can fold and convert to a boolean condition using /// any crazy technique that we want to. - bool EvaluateAsBooleanCondition(bool &Result, ASTContext &Ctx) const; + bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const; /// isEvaluatable - Call Evaluate to see if this expression can be constant /// folded, but discard the result. - bool isEvaluatable(ASTContext &Ctx) const; + bool isEvaluatable(const ASTContext &Ctx) const; /// HasSideEffects - This routine returns true for all those expressions - /// which must be evaluated each time and must not be optimization away + /// which must be evaluated each time and must not be optimized away /// or evaluated at compile time. Example is a function call, volatile /// variable read. - bool HasSideEffects(ASTContext &Ctx) const; + bool HasSideEffects(const 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; + llvm::APSInt EvaluateAsInt(const ASTContext &Ctx) const; /// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue /// with link time known address. - bool EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const; + bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const; /// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue. - bool EvaluateAsAnyLValue(EvalResult &Result, ASTContext &Ctx) const; + bool EvaluateAsAnyLValue(EvalResult &Result, const ASTContext &Ctx) const; + + /// \brief Enumeration used to describe the kind of Null pointer constant + /// returned from \c isNullPointerConstant(). + enum NullPointerConstantKind { + /// \brief Expression is not a Null pointer constant. + NPCK_NotNull = 0, + + /// \brief Expression is a Null pointer constant built from a zero integer. + NPCK_ZeroInteger, + + /// \brief Expression is a C++0X nullptr. + NPCK_CXX0X_nullptr, + + /// \brief Expression is a GNU-style __null constant. + NPCK_GNUNull + }; /// \brief Enumeration used to describe how \c isNullPointerConstant() /// should cope with value-dependent expressions. @@ -398,16 +468,30 @@ public: NPC_ValueDependentIsNotNull }; - /// isNullPointerConstant - C99 6.3.2.3p3 - Return true if this is either an - /// integer constant expression with the value zero, or if this is one that is - /// cast to void*. - bool isNullPointerConstant(ASTContext &Ctx, - NullPointerConstantValueDependence NPC) const; + /// isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to + /// a Null pointer constant. The return value can further distinguish the + /// kind of NULL pointer constant that was detected. + NullPointerConstantKind isNullPointerConstant( + ASTContext &Ctx, + NullPointerConstantValueDependence NPC) const; /// isOBJCGCCandidate - Return true if this expression may be used in a read/ /// write barrier. bool isOBJCGCCandidate(ASTContext &Ctx) const; + /// \brief Returns true if this expression is a bound member function. + bool isBoundMemberFunction(ASTContext &Ctx) const; + + /// \brief Result type of CanThrow(). + enum CanThrowResult { + CT_Cannot, + CT_Dependent, + CT_Can + }; + /// \brief Test if this expression, if evaluated, might throw, according to + /// the rules of C++ [expr.unary.noexcept]. + CanThrowResult CanThrow(ASTContext &C) 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. @@ -422,6 +506,18 @@ public: /// ParenExpr or ImplicitCastExprs, returning their operand. Expr *IgnoreParenImpCasts(); + const Expr *IgnoreParenImpCasts() const { + return const_cast<Expr*>(this)->IgnoreParenImpCasts(); + } + + /// Ignore parentheses and lvalue casts. Strip off any ParenExpr and + /// CastExprs that represent lvalue casts, returning their operand. + Expr *IgnoreParenLValueCasts(); + + const Expr *IgnoreParenLValueCasts() const { + return const_cast<Expr*>(this)->IgnoreParenLValueCasts(); + } + /// 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. @@ -436,14 +532,9 @@ public: /// the expression is a default argument. bool isDefaultArgument() const; - /// \brief Determine whether this expression directly creates a - /// temporary object (of class type). - bool isTemporaryObject() const { return getTemporaryObject() != 0; } - - /// \brief If this expression directly creates a temporary object of - /// class type, return the expression that actually constructs that - /// temporary object. - const Expr *getTemporaryObject() const; + /// \brief Determine whether the result of this expression is a + /// temporary object of the given class type. + bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const; const Expr *IgnoreParens() const { return const_cast<Expr*>(this)->IgnoreParens(); @@ -470,6 +561,63 @@ public: // Primary Expressions. //===----------------------------------------------------------------------===// +/// OpaqueValueExpr - An expression referring to an opaque object of a +/// fixed type and value class. These don't correspond to concrete +/// syntax; instead they're used to express operations (usually copy +/// operations) on values whose source is generally obvious from +/// context. +class OpaqueValueExpr : public Expr { + friend class ASTStmtReader; + Expr *SourceExpr; + SourceLocation Loc; + +public: + OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK, + ExprObjectKind OK = OK_Ordinary) + : Expr(OpaqueValueExprClass, T, VK, OK, + T->isDependentType(), T->isDependentType(), false), + SourceExpr(0), Loc(Loc) { + } + + /// Given an expression which invokes a copy constructor --- i.e. a + /// CXXConstructExpr, possibly wrapped in an ExprWithCleanups --- + /// find the OpaqueValueExpr that's the source of the construction. + static const OpaqueValueExpr *findInCopyConstruct(const Expr *expr); + + explicit OpaqueValueExpr(EmptyShell Empty) + : Expr(OpaqueValueExprClass, Empty) { } + + /// \brief Retrieve the location of this expression. + SourceLocation getLocation() const { return Loc; } + + SourceRange getSourceRange() const { + if (SourceExpr) return SourceExpr->getSourceRange(); + return Loc; + } + SourceLocation getExprLoc() const { + if (SourceExpr) return SourceExpr->getExprLoc(); + return Loc; + } + + child_range children() { return child_range(); } + + /// The source expression of an opaque value expression is the + /// expression which originally generated the value. This is + /// provided as a convenience for analyses that don't wish to + /// precisely model the execution behavior of the program. + /// + /// The source expression is typically set when building the + /// expression which binds the opaque value expression in the first + /// place. + Expr *getSourceExpr() const { return SourceExpr; } + void setSourceExpr(Expr *e) { SourceExpr = e; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OpaqueValueExprClass; + } + static bool classof(const OpaqueValueExpr *) { return true; } +}; + /// \brief Represents the qualifier that may precede a C++ name, e.g., the /// "std::" in "std::sort". struct NameQualifier { @@ -505,6 +653,8 @@ struct ExplicitTemplateArgumentList { } void initializeFrom(const TemplateArgumentListInfo &List); + void initializeFrom(const TemplateArgumentListInfo &List, + bool &Dependent, bool &ContainsUnexpandedParameterPack); void copyInto(TemplateArgumentListInfo &List) const; static std::size_t sizeFor(unsigned NumTemplateArgs); static std::size_t sizeFor(const TemplateArgumentListInfo &List); @@ -551,12 +701,12 @@ class DeclRefExpr : public Expr { DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, ValueDecl *D, SourceLocation NameLoc, const TemplateArgumentListInfo *TemplateArgs, - QualType T); + QualType T, ExprValueKind VK); DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, ValueDecl *D, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, - QualType T); + QualType T, ExprValueKind VK); /// \brief Construct an empty declaration reference expression. explicit DeclRefExpr(EmptyShell Empty) @@ -567,8 +717,9 @@ class DeclRefExpr : public Expr { void computeDependence(); public: - DeclRefExpr(ValueDecl *d, QualType t, SourceLocation l) : - Expr(DeclRefExprClass, t, false, false), DecoratedD(d, 0), Loc(l) { + DeclRefExpr(ValueDecl *d, QualType t, ExprValueKind VK, SourceLocation l) : + Expr(DeclRefExprClass, t, VK, OK_Ordinary, false, false, false), + DecoratedD(d, 0), Loc(l) { computeDependence(); } @@ -577,7 +728,7 @@ public: SourceRange QualifierRange, ValueDecl *D, SourceLocation NameLoc, - QualType T, + QualType T, ExprValueKind VK, const TemplateArgumentListInfo *TemplateArgs = 0); static DeclRefExpr *Create(ASTContext &Context, @@ -585,12 +736,14 @@ public: SourceRange QualifierRange, ValueDecl *D, const DeclarationNameInfo &NameInfo, - QualType T, + QualType T, ExprValueKind VK, const TemplateArgumentListInfo *TemplateArgs = 0); /// \brief Construct an empty declaration reference expression. static DeclRefExpr *CreateEmpty(ASTContext &Context, - bool HasQualifier, unsigned NumTemplateArgs); + bool HasQualifier, + bool HasExplicitTemplateArgs, + unsigned NumTemplateArgs); ValueDecl *getDecl() { return DecoratedD.getPointer(); } const ValueDecl *getDecl() const { return DecoratedD.getPointer(); } @@ -602,7 +755,7 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - virtual SourceRange getSourceRange() const; + SourceRange getSourceRange() const; /// \brief Determine whether this declaration reference was preceded by a /// C++ nested-name-specifier, e.g., \c N::foo. @@ -706,8 +859,7 @@ public: static bool classof(const DeclRefExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } friend class ASTStmtReader; friend class ASTStmtWriter; @@ -730,8 +882,10 @@ private: IdentType Type; public: PredefinedExpr(SourceLocation l, QualType type, IdentType IT) - : Expr(PredefinedExprClass, type, type->isDependentType(), - type->isDependentType()), Loc(l), Type(IT) {} + : Expr(PredefinedExprClass, type, VK_LValue, OK_Ordinary, + type->isDependentType(), type->isDependentType(), + /*ContainsUnexpandedParameterPack=*/false), + Loc(l), Type(IT) {} /// \brief Construct an empty predefined expression. explicit PredefinedExpr(EmptyShell Empty) @@ -745,7 +899,7 @@ public: static std::string ComputeName(IdentType IT, const Decl *CurrentDecl); - virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const { return SourceRange(Loc); } static bool classof(const Stmt *T) { return T->getStmtClass() == PredefinedExprClass; @@ -753,8 +907,7 @@ public: static bool classof(const PredefinedExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; /// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without @@ -817,7 +970,9 @@ public: // or UnsignedLongLongTy IntegerLiteral(ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l) - : Expr(IntegerLiteralClass, type, false, false), Loc(l) { + : Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary, false, false, + false), + Loc(l) { assert(type->isIntegerType() && "Illegal type in IntegerLiteral"); setValue(C, V); } @@ -829,7 +984,7 @@ public: static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty); llvm::APInt getValue() const { return Num.getValue(); } - virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const { return SourceRange(Loc); } /// \brief Retrieve the location of the literal. SourceLocation getLocation() const { return Loc; } @@ -843,8 +998,7 @@ public: static bool classof(const IntegerLiteral *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; class CharacterLiteral : public Expr { @@ -854,8 +1008,9 @@ class CharacterLiteral : public Expr { public: // type should be IntTy CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l) - : Expr(CharacterLiteralClass, type, false, false), Value(value), Loc(l), - IsWide(iswide) { + : Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary, false, false, + false), + Value(value), Loc(l), IsWide(iswide) { } /// \brief Construct an empty character literal. @@ -864,7 +1019,7 @@ public: SourceLocation getLocation() const { return Loc; } bool isWide() const { return IsWide; } - virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const { return SourceRange(Loc); } unsigned getValue() const { return Value; } @@ -878,8 +1033,7 @@ public: static bool classof(const CharacterLiteral *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; class FloatingLiteral : public Expr { @@ -889,7 +1043,8 @@ class FloatingLiteral : public Expr { FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L) - : Expr(FloatingLiteralClass, Type, false, false), + : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false, + false), IsExact(isexact), Loc(L) { setValue(C, V); } @@ -919,7 +1074,7 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const { return SourceRange(Loc); } static bool classof(const Stmt *T) { return T->getStmtClass() == FloatingLiteralClass; @@ -927,8 +1082,7 @@ public: static bool classof(const FloatingLiteral *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; /// ImaginaryLiteral - We support imaginary integer and floating point literals, @@ -940,7 +1094,9 @@ class ImaginaryLiteral : public Expr { Stmt *Val; public: ImaginaryLiteral(Expr *val, QualType Ty) - : Expr(ImaginaryLiteralClass, Ty, false, false), Val(val) {} + : Expr(ImaginaryLiteralClass, Ty, VK_RValue, OK_Ordinary, false, false, + false), + Val(val) {} /// \brief Build an empty imaginary literal. explicit ImaginaryLiteral(EmptyShell Empty) @@ -950,15 +1106,14 @@ public: Expr *getSubExpr() { return cast<Expr>(Val); } void setSubExpr(Expr *E) { Val = E; } - virtual SourceRange getSourceRange() const { return Val->getSourceRange(); } + 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(); + child_range children() { return child_range(&Val, &Val+1); } }; /// StringLiteral - This represents a string literal expression, e.g. "foo" @@ -984,7 +1139,8 @@ class StringLiteral : public Expr { unsigned NumConcatenated; SourceLocation TokLocs[1]; - StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty, false, false) {} + StringLiteral(QualType Ty) : + Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false) {} public: /// This is the "fully general" constructor that allows representation of @@ -1034,12 +1190,23 @@ public: assert(TokNum < NumConcatenated && "Invalid tok number"); TokLocs[TokNum] = L; } + + /// getLocationOfByte - Return a source location that points to the specified + /// byte of this string literal. + /// + /// Strings are amazingly complex. They can be formed from multiple tokens + /// and can have escape sequences in them in addition to the usual trigraph + /// and escaped newline business. This routine handles this complexity. + /// + SourceLocation getLocationOfByte(unsigned ByteNo, const SourceManager &SM, + const LangOptions &Features, + const TargetInfo &Target) const; typedef const SourceLocation *tokloc_iterator; tokloc_iterator tokloc_begin() const { return TokLocs; } tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]); } static bool classof(const Stmt *T) { @@ -1048,8 +1215,7 @@ public: static bool classof(const StringLiteral *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; /// ParenExpr - This represents a parethesized expression, e.g. "(1)". This @@ -1060,7 +1226,9 @@ class ParenExpr : public Expr { public: ParenExpr(SourceLocation l, SourceLocation r, Expr *val) : Expr(ParenExprClass, val->getType(), - val->isTypeDependent(), val->isValueDependent()), + val->getValueKind(), val->getObjectKind(), + val->isTypeDependent(), val->isValueDependent(), + val->containsUnexpandedParameterPack()), L(l), R(r), Val(val) {} /// \brief Construct an empty parenthesized expression. @@ -1071,7 +1239,7 @@ public: Expr *getSubExpr() { return cast<Expr>(Val); } void setSubExpr(Expr *E) { Val = E; } - virtual SourceRange getSourceRange() const { return SourceRange(L, R); } + SourceRange getSourceRange() const { return SourceRange(L, R); } /// \brief Get the location of the left parentheses '('. SourceLocation getLParen() const { return L; } @@ -1087,8 +1255,7 @@ public: static bool classof(const ParenExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&Val, &Val+1); } }; @@ -1112,10 +1279,12 @@ private: Stmt *Val; public: - UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l) - : Expr(UnaryOperatorClass, type, + UnaryOperator(Expr *input, Opcode opc, QualType type, + ExprValueKind VK, ExprObjectKind OK, SourceLocation l) + : Expr(UnaryOperatorClass, type, VK, OK, input->isTypeDependent() || type->isDependentType(), - input->isValueDependent()), + input->isValueDependent(), + input->containsUnexpandedParameterPack()), Opc(opc), Loc(l), Val(input) {} /// \brief Build an empty unary operator. @@ -1137,7 +1306,7 @@ public: return Op == UO_PostInc || Op == UO_PostDec; } - /// isPostfix - Return true if this is a prefix operation, like --x. + /// isPrefix - Return true if this is a prefix operation, like --x. static bool isPrefix(Opcode Op) { return Op == UO_PreInc || Op == UO_PreDec; } @@ -1167,13 +1336,13 @@ public: /// the given unary opcode. static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { if (isPostfix()) return SourceRange(Val->getLocStart(), Loc); else return SourceRange(Loc, Val->getLocEnd()); } - virtual SourceLocation getExprLoc() const { return Loc; } + SourceLocation getExprLoc() const { return Loc; } static bool classof(const Stmt *T) { return T->getStmtClass() == UnaryOperatorClass; @@ -1181,8 +1350,7 @@ public: static bool classof(const UnaryOperator *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&Val, &Val+1); } }; /// OffsetOfExpr - [C99 7.17] - This represents an expression of the form @@ -1369,7 +1537,7 @@ public: return NumExprs; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(OperatorLoc, RParenLoc); } @@ -1380,8 +1548,12 @@ public: static bool classof(const OffsetOfExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + Stmt **begin = + reinterpret_cast<Stmt**>(reinterpret_cast<OffsetOfNode*>(this + 1) + + NumComps); + return child_range(begin, begin + NumExprs); + } }; /// SizeOfAlignOfExpr - [C99 6.5.3.4] - This is for sizeof/alignof, both of @@ -1399,10 +1571,11 @@ public: SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo, QualType resultType, SourceLocation op, SourceLocation rp) : - Expr(SizeOfAlignOfExprClass, resultType, + Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary, false, // Never type-dependent (C++ [temp.dep.expr]p3). // Value-dependent if the argument is type-dependent. - TInfo->getType()->isDependentType()), + TInfo->getType()->isDependentType(), + TInfo->getType()->containsUnexpandedParameterPack()), isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) { Argument.Ty = TInfo; } @@ -1410,10 +1583,11 @@ public: SizeOfAlignOfExpr(bool issizeof, Expr *E, QualType resultType, SourceLocation op, SourceLocation rp) : - Expr(SizeOfAlignOfExprClass, resultType, + Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary, false, // Never type-dependent (C++ [temp.dep.expr]p3). // Value-dependent if the argument is type-dependent. - E->isTypeDependent()), + E->isTypeDependent(), + E->containsUnexpandedParameterPack()), isSizeof(issizeof), isType(false), OpLoc(op), RParenLoc(rp) { Argument.Ex = E; } @@ -1459,7 +1633,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(OpLoc, RParenLoc); } @@ -1469,8 +1643,7 @@ public: static bool classof(const SizeOfAlignOfExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children(); }; //===----------------------------------------------------------------------===// @@ -1484,10 +1657,13 @@ class ArraySubscriptExpr : public Expr { SourceLocation RBracketLoc; public: ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t, + ExprValueKind VK, ExprObjectKind OK, SourceLocation rbracketloc) - : Expr(ArraySubscriptExprClass, t, + : Expr(ArraySubscriptExprClass, t, VK, OK, lhs->isTypeDependent() || rhs->isTypeDependent(), - lhs->isValueDependent() || rhs->isValueDependent()), + lhs->isValueDependent() || rhs->isValueDependent(), + (lhs->containsUnexpandedParameterPack() || + rhs->containsUnexpandedParameterPack())), RBracketLoc(rbracketloc) { SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; @@ -1530,14 +1706,14 @@ public: return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS()); } - virtual SourceRange getSourceRange() const { + 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(); } + SourceLocation getExprLoc() const { return getBase()->getExprLoc(); } static bool classof(const Stmt *T) { return T->getStmtClass() == ArraySubscriptExprClass; @@ -1545,8 +1721,9 @@ public: static bool classof(const ArraySubscriptExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); + } }; @@ -1557,19 +1734,36 @@ public: /// 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 }; + enum { FN=0, PREARGS_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); + // These versions of the constructor are for derived classes. + CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs, + Expr **args, unsigned numargs, QualType t, ExprValueKind VK, + SourceLocation rparenloc); + CallExpr(ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty); + + Stmt *getPreArg(unsigned i) { + assert(i < getNumPreArgs() && "Prearg access out of range!"); + return SubExprs[PREARGS_START+i]; + } + const Stmt *getPreArg(unsigned i) const { + assert(i < getNumPreArgs() && "Prearg access out of range!"); + return SubExprs[PREARGS_START+i]; + } + void setPreArg(unsigned i, Stmt *PreArg) { + assert(i < getNumPreArgs() && "Prearg access out of range!"); + SubExprs[PREARGS_START+i] = PreArg; + } + + unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; } public: CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t, - SourceLocation rparenloc); + ExprValueKind VK, SourceLocation rparenloc); /// \brief Build an empty call expression. CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty); @@ -1593,20 +1787,25 @@ public: /// unsigned getNumArgs() const { return NumArgs; } + /// \brief Retrieve the call arguments. + Expr **getArgs() { + return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START); + } + /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) { assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(SubExprs[Arg+ARGS_START]); + return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]); } const Expr *getArg(unsigned Arg) const { assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(SubExprs[Arg+ARGS_START]); + return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_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; + SubExprs[Arg+getNumPreArgs()+PREARGS_START] = ArgExpr; } /// setNumArgs - This changes the number of arguments present in this call. @@ -1617,10 +1816,16 @@ public: typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; - arg_iterator arg_begin() { return SubExprs+ARGS_START; } - arg_iterator arg_end() { return SubExprs+ARGS_START+getNumArgs(); } - const_arg_iterator arg_begin() const { return SubExprs+ARGS_START; } - const_arg_iterator arg_end() const { return SubExprs+ARGS_START+getNumArgs();} + arg_iterator arg_begin() { return SubExprs+PREARGS_START+getNumPreArgs(); } + arg_iterator arg_end() { + return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs(); + } + const_arg_iterator arg_begin() const { + return SubExprs+PREARGS_START+getNumPreArgs(); + } + const_arg_iterator arg_end() const { + return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs(); + } /// getNumCommas - Return the number of commas that must have been present in /// this function call. @@ -1628,7 +1833,7 @@ public: /// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If /// not, return 0. - unsigned isBuiltinCall(ASTContext &Context) const; + unsigned isBuiltinCall(const 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 @@ -1638,7 +1843,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(getCallee()->getLocStart(), RParenLoc); } @@ -1649,8 +1854,10 @@ public: static bool classof(const CallExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&SubExprs[0], + &SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START); + } }; /// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F. @@ -1705,9 +1912,11 @@ class MemberExpr : public Expr { public: MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl, - const DeclarationNameInfo &NameInfo, QualType ty) - : Expr(MemberExprClass, ty, - base->isTypeDependent(), base->isValueDependent()), + const DeclarationNameInfo &NameInfo, QualType ty, + ExprValueKind VK, ExprObjectKind OK) + : Expr(MemberExprClass, ty, VK, OK, + base->isTypeDependent(), base->isValueDependent(), + base->containsUnexpandedParameterPack()), Base(base), MemberDecl(memberdecl), MemberLoc(NameInfo.getLoc()), MemberDNLoc(NameInfo.getInfo()), IsArrow(isarrow), HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) { @@ -1719,9 +1928,11 @@ public: // (i.e., source locations for C++ operator names or type source info // for constructors, destructors and conversion oeprators). MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl, - SourceLocation l, QualType ty) - : Expr(MemberExprClass, ty, - base->isTypeDependent(), base->isValueDependent()), + SourceLocation l, QualType ty, + ExprValueKind VK, ExprObjectKind OK) + : Expr(MemberExprClass, ty, VK, OK, + base->isTypeDependent(), base->isValueDependent(), + base->containsUnexpandedParameterPack()), Base(base), MemberDecl(memberdecl), MemberLoc(l), MemberDNLoc(), IsArrow(isarrow), HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {} @@ -1731,7 +1942,7 @@ public: ValueDecl *memberdecl, DeclAccessPair founddecl, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *targs, - QualType ty); + QualType ty, ExprValueKind VK, ExprObjectKind OK); void setBase(Expr *E) { Base = E; } Expr *getBase() const { return cast<Expr>(Base); } @@ -1866,7 +2077,7 @@ public: SourceLocation getMemberLoc() const { return MemberLoc; } void setMemberLoc(SourceLocation L) { MemberLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { // If we have an implicit base (like a C++ implicit this), // make sure not to return its location SourceLocation EndLoc = (HasExplicitTemplateArgumentList) @@ -1878,7 +2089,7 @@ public: return SourceRange(BaseLoc, EndLoc); } - virtual SourceLocation getExprLoc() const { return MemberLoc; } + SourceLocation getExprLoc() const { return MemberLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == MemberExprClass; @@ -1886,8 +2097,10 @@ public: static bool classof(const MemberExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&Base, &Base+1); } + + friend class ASTReader; + friend class ASTStmtWriter; }; /// CompoundLiteralExpr - [C99 6.5.2.5] @@ -1904,11 +2117,12 @@ class CompoundLiteralExpr : public Expr { Stmt *Init; bool FileScope; public: - // FIXME: Can compound literals be value-dependent? CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo, - QualType T, Expr *init, bool fileScope) - : Expr(CompoundLiteralExprClass, T, - tinfo->getType()->isDependentType(), false), + QualType T, ExprValueKind VK, Expr *init, bool fileScope) + : Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary, + tinfo->getType()->isDependentType(), + init->isValueDependent(), + init->containsUnexpandedParameterPack()), LParenLoc(lparenloc), TInfo(tinfo), Init(init), FileScope(fileScope) {} /// \brief Construct an empty compound literal. @@ -1928,7 +2142,7 @@ public: TypeSourceInfo *getTypeSourceInfo() const { return TInfo; } void setTypeSourceInfo(TypeSourceInfo* tinfo) { TInfo = tinfo; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { // FIXME: Init should never be null. if (!Init) return SourceRange(); @@ -1943,8 +2157,7 @@ public: static bool classof(const CompoundLiteralExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&Init, &Init+1); } }; /// CastExpr - Base class for type casts, including both implicit @@ -1956,11 +2169,9 @@ public: typedef clang::CastKind CastKind; private: - unsigned Kind : 5; - unsigned BasePathSize : BitsRemaining - 5; Stmt *Op; - void CheckBasePath() const { + void CheckCastConsistency() const { #ifndef NDEBUG switch (getCastKind()) { case CK_DerivedToBase: @@ -1972,16 +2183,13 @@ private: break; // These should not have an inheritance path. - case CK_Unknown: case CK_BitCast: - case CK_LValueBitCast: - case CK_NoOp: case CK_Dynamic: case CK_ToUnion: case CK_ArrayToPointerDecay: case CK_FunctionToPointerDecay: case CK_NullToMemberPointer: - case CK_UserDefinedConversion: + case CK_NullToPointer: case CK_ConstructorConversion: case CK_IntegralToPointer: case CK_PointerToIntegral: @@ -1991,10 +2199,32 @@ private: case CK_IntegralToFloating: case CK_FloatingToIntegral: case CK_FloatingCast: - case CK_MemberPointerToBoolean: case CK_AnyPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_ObjCObjectLValueCast: + case CK_FloatingRealToComplex: + case CK_FloatingComplexToReal: + case CK_FloatingComplexCast: + case CK_FloatingComplexToIntegralComplex: + case CK_IntegralRealToComplex: + case CK_IntegralComplexToReal: + case CK_IntegralComplexCast: + case CK_IntegralComplexToFloatingComplex: + assert(!getType()->isBooleanType() && "unheralded conversion to bool"); + // fallthrough to check for null base path + + case CK_Dependent: + case CK_LValueToRValue: + case CK_GetObjCProperty: + case CK_NoOp: + case CK_PointerToBoolean: + case CK_IntegralToBoolean: + case CK_FloatingToBoolean: + case CK_MemberPointerToBoolean: + case CK_FloatingComplexToBoolean: + case CK_IntegralComplexToBoolean: + case CK_LValueBitCast: // -> bool& + case CK_UserDefinedConversion: // operator bool() assert(path_empty() && "Cast kind should not have a base path!"); break; } @@ -2007,26 +2237,33 @@ private: CXXBaseSpecifier **path_buffer(); protected: - CastExpr(StmtClass SC, QualType ty, const CastKind kind, Expr *op, - unsigned BasePathSize) : - Expr(SC, ty, + CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, + const CastKind kind, Expr *op, unsigned BasePathSize) : + Expr(SC, ty, VK, OK_Ordinary, // 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())), - Kind(kind), BasePathSize(BasePathSize), Op(op) { - CheckBasePath(); + ty->isDependentType() || (op && op->isValueDependent()), + (ty->containsUnexpandedParameterPack() || + op->containsUnexpandedParameterPack())), + Op(op) { + assert(kind != CK_Invalid && "creating cast with invalid cast kind"); + CastExprBits.Kind = kind; + CastExprBits.BasePathSize = BasePathSize; + CheckCastConsistency(); } /// \brief Construct an empty cast. CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize) - : Expr(SC, Empty), BasePathSize(BasePathSize) { } + : Expr(SC, Empty) { + CastExprBits.BasePathSize = BasePathSize; + } public: - CastKind getCastKind() const { return static_cast<CastKind>(Kind); } - void setCastKind(CastKind K) { Kind = K; } + CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; } + void setCastKind(CastKind K) { CastExprBits.Kind = K; } const char *getCastKindName() const; Expr *getSubExpr() { return cast<Expr>(Op); } @@ -2043,8 +2280,8 @@ public: typedef CXXBaseSpecifier **path_iterator; typedef const CXXBaseSpecifier * const *path_const_iterator; - bool path_empty() const { return BasePathSize == 0; } - unsigned path_size() const { return BasePathSize; } + bool path_empty() const { return CastExprBits.BasePathSize == 0; } + unsigned path_size() const { return CastExprBits.BasePathSize; } path_iterator path_begin() { return path_buffer(); } path_iterator path_end() { return path_buffer() + path_size(); } path_const_iterator path_begin() const { return path_buffer(); } @@ -2059,8 +2296,7 @@ public: static bool classof(const CastExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&Op, &Op+1); } }; /// ImplicitCastExpr - Allows us to explicitly represent implicit type @@ -2087,8 +2323,7 @@ class ImplicitCastExpr : public CastExpr { private: ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, unsigned BasePathLength, ExprValueKind VK) - : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePathLength) { - ValueKind = VK; + : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) { } /// \brief Construct an empty implicit cast. @@ -2099,8 +2334,7 @@ public: enum OnStack_t { OnStack }; ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op, ExprValueKind VK) - : CastExpr(ImplicitCastExprClass, ty, kind, op, 0) { - ValueKind = VK; + : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) { } static ImplicitCastExpr *Create(ASTContext &Context, QualType T, @@ -2110,18 +2344,10 @@ public: static ImplicitCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize); - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return getSubExpr()->getSourceRange(); } - /// getValueKind - The value kind that this cast produces. - ExprValueKind getValueKind() const { - return static_cast<ExprValueKind>(ValueKind); - } - - /// setValueKind - Set the value kind this cast produces. - void setValueKind(ExprValueKind Cat) { ValueKind = Cat; } - static bool classof(const Stmt *T) { return T->getStmtClass() == ImplicitCastExprClass; } @@ -2150,9 +2376,10 @@ class ExplicitCastExpr : public CastExpr { TypeSourceInfo *TInfo; protected: - ExplicitCastExpr(StmtClass SC, QualType exprTy, CastKind kind, - Expr *op, unsigned PathSize, TypeSourceInfo *writtenTy) - : CastExpr(SC, exprTy, kind, op, PathSize), TInfo(writtenTy) {} + ExplicitCastExpr(StmtClass SC, QualType exprTy, ExprValueKind VK, + CastKind kind, Expr *op, unsigned PathSize, + TypeSourceInfo *writtenTy) + : CastExpr(SC, exprTy, VK, kind, op, PathSize), TInfo(writtenTy) {} /// \brief Construct an empty explicit cast. ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize) @@ -2182,10 +2409,10 @@ class CStyleCastExpr : public ExplicitCastExpr { SourceLocation LPLoc; // the location of the left paren SourceLocation RPLoc; // the location of the right paren - CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op, + CStyleCastExpr(QualType exprTy, ExprValueKind vk, CastKind kind, Expr *op, unsigned PathSize, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation r) - : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, PathSize, + : ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize, writtenTy), LPLoc(l), RPLoc(r) {} /// \brief Construct an empty C-style explicit cast. @@ -2193,7 +2420,8 @@ class CStyleCastExpr : public ExplicitCastExpr { : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { } public: - static CStyleCastExpr *Create(ASTContext &Context, QualType T, CastKind K, + static CStyleCastExpr *Create(ASTContext &Context, QualType T, + ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation R); @@ -2206,7 +2434,7 @@ public: SourceLocation getRParenLoc() const { return RPLoc; } void setRParenLoc(SourceLocation L) { RPLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(LPLoc, getSubExpr()->getSourceRange().getEnd()); } static bool classof(const Stmt *T) { @@ -2246,10 +2474,13 @@ private: public: BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, + ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc) - : Expr(BinaryOperatorClass, ResTy, + : Expr(BinaryOperatorClass, ResTy, VK, OK, lhs->isTypeDependent() || rhs->isTypeDependent(), - lhs->isValueDependent() || rhs->isValueDependent()), + lhs->isValueDependent() || rhs->isValueDependent(), + (lhs->containsUnexpandedParameterPack() || + rhs->containsUnexpandedParameterPack())), Opc(opc), OpLoc(opLoc) { SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; @@ -2272,7 +2503,7 @@ public: Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } void setRHS(Expr *E) { SubExprs[RHS] = E; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(getLHS()->getLocStart(), getRHS()->getLocEnd()); } @@ -2291,6 +2522,7 @@ public: static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); /// predicates to categorize the respective opcodes. + bool isPtrMemOp() const { return Opc == BO_PtrMemD || Opc == BO_PtrMemI; } bool isMultiplicativeOp() const { return Opc >= BO_Mul && Opc <= BO_Rem; } static bool isAdditiveOp(Opcode Opc) { return Opc == BO_Add || Opc==BO_Sub; } bool isAdditiveOp() const { return isAdditiveOp(getOpcode()); } @@ -2312,13 +2544,24 @@ public: static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; } bool isLogicalOp() const { return isLogicalOp(getOpcode()); } - bool isAssignmentOp() const { return Opc >= BO_Assign && Opc <= BO_OrAssign; } - bool isCompoundAssignmentOp() const { + static bool isAssignmentOp(Opcode Opc) { + return Opc >= BO_Assign && Opc <= BO_OrAssign; + } + bool isAssignmentOp() const { return isAssignmentOp(getOpcode()); } + + static bool isCompoundAssignmentOp(Opcode Opc) { return Opc > BO_Assign && Opc <= BO_OrAssign; } - bool isShiftAssignOp() const { + bool isCompoundAssignmentOp() const { + return isCompoundAssignmentOp(getOpcode()); + } + + static bool isShiftAssignOp(Opcode Opc) { return Opc == BO_ShlAssign || Opc == BO_ShrAssign; } + bool isShiftAssignOp() const { + return isShiftAssignOp(getOpcode()); + } static bool classof(const Stmt *S) { return S->getStmtClass() >= firstBinaryOperatorConstant && @@ -2327,15 +2570,19 @@ public: static bool classof(const BinaryOperator *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); + } protected: BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, + ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, bool dead) - : Expr(CompoundAssignOperatorClass, ResTy, + : Expr(CompoundAssignOperatorClass, ResTy, VK, OK, lhs->isTypeDependent() || rhs->isTypeDependent(), - lhs->isValueDependent() || rhs->isValueDependent()), + lhs->isValueDependent() || rhs->isValueDependent(), + (lhs->containsUnexpandedParameterPack() || + rhs->containsUnexpandedParameterPack())), Opc(opc), OpLoc(opLoc) { SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; @@ -2355,11 +2602,11 @@ class CompoundAssignOperator : public BinaryOperator { QualType ComputationLHSType; QualType ComputationResultType; public: - CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, - QualType ResType, QualType CompLHSType, - QualType CompResultType, + CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType, + ExprValueKind VK, ExprObjectKind OK, + QualType CompLHSType, QualType CompResultType, SourceLocation OpLoc) - : BinaryOperator(lhs, rhs, opc, ResType, OpLoc, true), + : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, true), ComputationLHSType(CompLHSType), ComputationResultType(CompResultType) { assert(isCompoundAssignmentOp() && @@ -2385,75 +2632,97 @@ public: } }; -/// ConditionalOperator - The ?: operator. Note that LHS may be null when the -/// GNU "missing LHS" extension is in use. -/// -class ConditionalOperator : public Expr { +/// AbstractConditionalOperator - An abstract base class for +/// ConditionalOperator and BinaryConditionalOperator. +class AbstractConditionalOperator : public Expr { + SourceLocation QuestionLoc, ColonLoc; + friend class ASTStmtReader; + +protected: + AbstractConditionalOperator(StmtClass SC, QualType T, + ExprValueKind VK, ExprObjectKind OK, + bool TD, bool VD, + bool ContainsUnexpandedParameterPack, + SourceLocation qloc, + SourceLocation cloc) + : Expr(SC, T, VK, OK, TD, VD, ContainsUnexpandedParameterPack), + QuestionLoc(qloc), ColonLoc(cloc) {} + + AbstractConditionalOperator(StmtClass SC, EmptyShell Empty) + : Expr(SC, Empty) { } + +public: + // getCond - Return the expression representing the condition for + // the ?: operator. + Expr *getCond() const; + + // getTrueExpr - Return the subexpression representing the value of + // the expression if the condition evaluates to true. + Expr *getTrueExpr() const; + + // getFalseExpr - Return the subexpression representing the value of + // the expression if the condition evaluates to false. This is + // the same as getRHS. + Expr *getFalseExpr() const; + + SourceLocation getQuestionLoc() const { return QuestionLoc; } + SourceLocation getColonLoc() const { return ColonLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ConditionalOperatorClass || + T->getStmtClass() == BinaryConditionalOperatorClass; + } + static bool classof(const AbstractConditionalOperator *) { return true; } +}; + +/// ConditionalOperator - The ?: ternary operator. The GNU "missing +/// middle" extension is a BinaryConditionalOperator. +class ConditionalOperator : public AbstractConditionalOperator { enum { COND, LHS, RHS, END_EXPR }; Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides. - Stmt* Save; - SourceLocation QuestionLoc, ColonLoc; + + friend class ASTStmtReader; public: ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs, - SourceLocation CLoc, Expr *rhs, Expr *save, QualType t) - : Expr(ConditionalOperatorClass, t, + SourceLocation CLoc, Expr *rhs, + QualType t, ExprValueKind VK, ExprObjectKind OK) + : AbstractConditionalOperator(ConditionalOperatorClass, t, VK, OK, // 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()))), - QuestionLoc(QLoc), - ColonLoc(CLoc) { + (lhs->isTypeDependent() || rhs->isTypeDependent()), + (cond->isValueDependent() || lhs->isValueDependent() || + rhs->isValueDependent()), + (cond->containsUnexpandedParameterPack() || + lhs->containsUnexpandedParameterPack() || + rhs->containsUnexpandedParameterPack()), + QLoc, CLoc) { SubExprs[COND] = cond; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; - Save = save; } /// \brief Build an empty conditional operator. explicit ConditionalOperator(EmptyShell Empty) - : Expr(ConditionalOperatorClass, Empty) { } + : AbstractConditionalOperator(ConditionalOperatorClass, Empty) { } // getCond - Return the expression representing the condition for - // the ?: operator. + // 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. - Expr *getTrueExpr() const { - return cast<Expr>(!Save ? SubExprs[LHS] : SubExprs[COND]); - } + // getTrueExpr - Return the subexpression representing the value of + // the expression if the condition evaluates to true. + Expr *getTrueExpr() const { return cast<Expr>(SubExprs[LHS]); } - // getFalseExpr - Return the subexpression representing the value of the ?: - // expression if the condition evaluates to false. This is the same as getRHS. + // getFalseExpr - 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]); } - // getSaveExpr - In most cases this value will be null. Except a GCC extension - // allows the left subexpression to be omitted, and instead of that condition - // be returned. e.g: x ?: y is shorthand for x ? x : y, except that the - // expression "x" is only evaluated once. Under this senario, this function - // returns the original, non-converted condition expression for the ?:operator - Expr *getSaveExpr() const { return Save? cast<Expr>(Save) : (Expr*)0; } - - Expr *getLHS() const { return Save ? 0 : cast<Expr>(SubExprs[LHS]); } - void setLHS(Expr *E) { SubExprs[LHS] = E; } - + Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } - void setRHS(Expr *E) { SubExprs[RHS] = E; } - - Expr *getSAVE() const { return Save? cast<Expr>(Save) : (Expr*)0; } - void setSAVE(Expr *E) { Save = E; } - - SourceLocation getQuestionLoc() const { return QuestionLoc; } - void setQuestionLoc(SourceLocation L) { QuestionLoc = L; } - SourceLocation getColonLoc() const { return ColonLoc; } - void setColonLoc(SourceLocation L) { ColonLoc = L; } - - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd()); } static bool classof(const Stmt *T) { @@ -2462,18 +2731,118 @@ public: static bool classof(const ConditionalOperator *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); + } +}; + +/// BinaryConditionalOperator - The GNU extension to the conditional +/// operator which allows the middle operand to be omitted. +/// +/// This is a different expression kind on the assumption that almost +/// every client ends up needing to know that these are different. +class BinaryConditionalOperator : public AbstractConditionalOperator { + enum { COMMON, COND, LHS, RHS, NUM_SUBEXPRS }; + + /// - the common condition/left-hand-side expression, which will be + /// evaluated as the opaque value + /// - the condition, expressed in terms of the opaque value + /// - the left-hand-side, expressed in terms of the opaque value + /// - the right-hand-side + Stmt *SubExprs[NUM_SUBEXPRS]; + OpaqueValueExpr *OpaqueValue; + + friend class ASTStmtReader; +public: + BinaryConditionalOperator(Expr *common, OpaqueValueExpr *opaqueValue, + Expr *cond, Expr *lhs, Expr *rhs, + SourceLocation qloc, SourceLocation cloc, + QualType t, ExprValueKind VK, ExprObjectKind OK) + : AbstractConditionalOperator(BinaryConditionalOperatorClass, t, VK, OK, + (common->isTypeDependent() || rhs->isTypeDependent()), + (common->isValueDependent() || rhs->isValueDependent()), + (common->containsUnexpandedParameterPack() || + rhs->containsUnexpandedParameterPack()), + qloc, cloc), + OpaqueValue(opaqueValue) { + SubExprs[COMMON] = common; + SubExprs[COND] = cond; + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + + OpaqueValue->setSourceExpr(common); + } + + /// \brief Build an empty conditional operator. + explicit BinaryConditionalOperator(EmptyShell Empty) + : AbstractConditionalOperator(BinaryConditionalOperatorClass, Empty) { } + + /// \brief getCommon - Return the common expression, written to the + /// left of the condition. The opaque value will be bound to the + /// result of this expression. + Expr *getCommon() const { return cast<Expr>(SubExprs[COMMON]); } + + /// \brief getOpaqueValue - Return the opaque value placeholder. + OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; } + + /// \brief getCond - Return the condition expression; this is defined + /// in terms of the opaque value. + Expr *getCond() const { return cast<Expr>(SubExprs[COND]); } + + /// \brief getTrueExpr - Return the subexpression which will be + /// evaluated if the condition evaluates to true; this is defined + /// in terms of the opaque value. + Expr *getTrueExpr() const { + return cast<Expr>(SubExprs[LHS]); + } + + /// \brief getFalseExpr - Return the subexpression which will be + /// evaluated if the condnition evaluates to false; this is + /// defined in terms of the opaque value. + Expr *getFalseExpr() const { + return cast<Expr>(SubExprs[RHS]); + } + + SourceRange getSourceRange() const { + return SourceRange(getCommon()->getLocStart(), getFalseExpr()->getLocEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == BinaryConditionalOperatorClass; + } + static bool classof(const BinaryConditionalOperator *) { return true; } + + // Iterators + child_range children() { + return child_range(SubExprs, SubExprs + NUM_SUBEXPRS); + } }; +inline Expr *AbstractConditionalOperator::getCond() const { + if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this)) + return co->getCond(); + return cast<BinaryConditionalOperator>(this)->getCond(); +} + +inline Expr *AbstractConditionalOperator::getTrueExpr() const { + if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this)) + return co->getTrueExpr(); + return cast<BinaryConditionalOperator>(this)->getTrueExpr(); +} + +inline Expr *AbstractConditionalOperator::getFalseExpr() const { + if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this)) + return co->getFalseExpr(); + return cast<BinaryConditionalOperator>(this)->getFalseExpr(); +} + /// AddrLabelExpr - The GNU address of label extension, representing &&label. class AddrLabelExpr : public Expr { SourceLocation AmpAmpLoc, LabelLoc; - LabelStmt *Label; + LabelDecl *Label; public: - AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelStmt *L, + AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelDecl *L, QualType t) - : Expr(AddrLabelExprClass, t, false, false), + : Expr(AddrLabelExprClass, t, VK_RValue, OK_Ordinary, false, false, false), AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {} /// \brief Build an empty address of a label expression. @@ -2485,12 +2854,12 @@ public: SourceLocation getLabelLoc() const { return LabelLoc; } void setLabelLoc(SourceLocation L) { LabelLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(AmpAmpLoc, LabelLoc); } - LabelStmt *getLabel() const { return Label; } - void setLabel(LabelStmt *S) { Label = S; } + LabelDecl *getLabel() const { return Label; } + void setLabel(LabelDecl *L) { Label = L; } static bool classof(const Stmt *T) { return T->getStmtClass() == AddrLabelExprClass; @@ -2498,13 +2867,15 @@ public: static bool classof(const AddrLabelExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; /// 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. +/// +/// A StmtExpr is always an r-value; values "returned" out of a +/// StmtExpr will be copied. class StmtExpr : public Expr { Stmt *SubStmt; SourceLocation LParenLoc, RParenLoc; @@ -2512,7 +2883,8 @@ public: // FIXME: Does type-dependence need to be computed differently? StmtExpr(CompoundStmt *substmt, QualType T, SourceLocation lp, SourceLocation rp) : - Expr(StmtExprClass, T, T->isDependentType(), false), + Expr(StmtExprClass, T, VK_RValue, OK_Ordinary, + T->isDependentType(), false, false), SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { } /// \brief Build an empty statement expression. @@ -2522,7 +2894,7 @@ public: const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); } void setSubStmt(CompoundStmt *S) { SubStmt = S; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(LParenLoc, RParenLoc); } @@ -2537,55 +2909,9 @@ public: static bool classof(const StmtExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&SubStmt, &SubStmt+1); } }; -/// 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 { - TypeSourceInfo *TInfo1; - TypeSourceInfo *TInfo2; - SourceLocation BuiltinLoc, RParenLoc; -public: - TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc, - TypeSourceInfo *tinfo1, TypeSourceInfo *tinfo2, - SourceLocation RP) : - Expr(TypesCompatibleExprClass, ReturnType, false, false), - TInfo1(tinfo1), TInfo2(tinfo2), BuiltinLoc(BLoc), RParenLoc(RP) {} - - /// \brief Build an empty __builtin_type_compatible_p expression. - explicit TypesCompatibleExpr(EmptyShell Empty) - : Expr(TypesCompatibleExprClass, Empty) { } - - TypeSourceInfo *getArgTInfo1() const { return TInfo1; } - void setArgTInfo1(TypeSourceInfo *TInfo) { TInfo1 = TInfo; } - TypeSourceInfo *getArgTInfo2() const { return TInfo2; } - void setArgTInfo2(TypeSourceInfo *TInfo) { TInfo2 = TInfo; } - - QualType getArgType1() const { return TInfo1->getType(); } - QualType getArgType2() const { return TInfo2->getType(); } - - 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. @@ -2604,18 +2930,9 @@ class ShuffleVectorExpr : public Expr { unsigned NumExprs; public: - // FIXME: Can a shufflevector be value-dependent? Does type-dependence need - // to be computed differently? ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr, QualType Type, SourceLocation BLoc, - SourceLocation RP) : - Expr(ShuffleVectorExprClass, Type, Type->isDependentType(), false), - BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(nexpr) { - - SubExprs = new (C) Stmt*[nexpr]; - for (unsigned i = 0; i < nexpr; i++) - SubExprs[i] = args[i]; - } + SourceLocation RP); /// \brief Build an empty vector-shuffle expression. explicit ShuffleVectorExpr(EmptyShell Empty) @@ -2627,7 +2944,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(BuiltinLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -2640,6 +2957,9 @@ public: /// pointers. unsigned getNumSubExprs() const { return NumExprs; } + /// \brief Retrieve the array of expressions. + Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); } + /// getExpr - Return the Expr at the specified index. Expr *getExpr(unsigned Index) { assert((Index < NumExprs) && "Arg access out of range!"); @@ -2658,8 +2978,9 @@ public: } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&SubExprs[0], &SubExprs[0]+NumExprs); + } }; /// ChooseExpr - GNU builtin-in function __builtin_choose_expr. @@ -2676,9 +2997,13 @@ class ChooseExpr : public 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, + ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, + QualType t, ExprValueKind VK, ExprObjectKind OK, SourceLocation RP, bool TypeDependent, bool ValueDependent) - : Expr(ChooseExprClass, t, TypeDependent, ValueDependent), + : Expr(ChooseExprClass, t, VK, OK, TypeDependent, ValueDependent, + (cond->containsUnexpandedParameterPack() || + lhs->containsUnexpandedParameterPack() || + rhs->containsUnexpandedParameterPack())), BuiltinLoc(BLoc), RParenLoc(RP) { SubExprs[COND] = cond; SubExprs[LHS] = lhs; @@ -2690,11 +3015,11 @@ public: /// isConditionTrue - Return whether the condition is true (i.e. not /// equal to zero). - bool isConditionTrue(ASTContext &C) const; + bool isConditionTrue(const ASTContext &C) const; /// getChosenSubExpr - Return the subexpression chosen according to the /// condition. - Expr *getChosenSubExpr(ASTContext &C) const { + Expr *getChosenSubExpr(const ASTContext &C) const { return isConditionTrue(C) ? getLHS() : getRHS(); } @@ -2711,7 +3036,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(BuiltinLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -2720,8 +3045,9 @@ public: static bool classof(const ChooseExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); + } }; /// GNUNullExpr - Implements the GNU __null extension, which is a name @@ -2736,7 +3062,8 @@ class GNUNullExpr : public Expr { public: GNUNullExpr(QualType Ty, SourceLocation Loc) - : Expr(GNUNullExprClass, Ty, false, false), TokenLoc(Loc) { } + : Expr(GNUNullExprClass, Ty, VK_RValue, OK_Ordinary, false, false, false), + TokenLoc(Loc) { } /// \brief Build an empty GNU __null expression. explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { } @@ -2745,7 +3072,7 @@ public: SourceLocation getTokenLocation() const { return TokenLoc; } void setTokenLocation(SourceLocation L) { TokenLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(TokenLoc); } static bool classof(const Stmt *T) { @@ -2754,8 +3081,7 @@ public: static bool classof(const GNUNullExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; /// VAArgExpr, used for the builtin function __builtin_va_arg. @@ -2766,7 +3092,10 @@ class VAArgExpr : public Expr { public: VAArgExpr(SourceLocation BLoc, Expr* e, TypeSourceInfo *TInfo, SourceLocation RPLoc, QualType t) - : Expr(VAArgExprClass, t, t->isDependentType(), false), + : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary, + t->isDependentType(), false, + (TInfo->getType()->containsUnexpandedParameterPack() || + e->containsUnexpandedParameterPack())), Val(e), TInfo(TInfo), BuiltinLoc(BLoc), RParenLoc(RPLoc) { } @@ -2787,7 +3116,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(BuiltinLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -2796,8 +3125,7 @@ public: static bool classof(const VAArgExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&Val, &Val+1); } }; /// @brief Describes an C or C++ initializer list. @@ -2866,12 +3194,15 @@ public: unsigned getNumInits() const { return InitExprs.size(); } - const Expr* getInit(unsigned Init) const { + /// \brief Retrieve the set of initializers. + Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); } + + const Expr *getInit(unsigned Init) const { assert(Init < getNumInits() && "Initializer access out of range!"); return cast_or_null<Expr>(InitExprs[Init]); } - Expr* getInit(unsigned Init) { + Expr *getInit(unsigned Init) { assert(Init < getNumInits() && "Initializer access out of range!"); return cast_or_null<Expr>(InitExprs[Init]); } @@ -2933,17 +3264,18 @@ public: HadArrayRangeDesignator = ARD; } - virtual SourceRange getSourceRange() const { - return SourceRange(LBraceLoc, RBraceLoc); - } + SourceRange getSourceRange() const; + 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(); + child_range children() { + if (InitExprs.empty()) return child_range(); + return child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size()); + } typedef InitExprsTy::iterator iterator; typedef InitExprsTy::const_iterator const_iterator; @@ -3182,6 +3514,15 @@ public: return Designators + NumDesignators; } + typedef std::reverse_iterator<designators_iterator> + reverse_designators_iterator; + reverse_designators_iterator designators_rbegin() { + return reverse_designators_iterator(designators_end()); + } + reverse_designators_iterator designators_rend() { + return reverse_designators_iterator(designators_begin()); + } + Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; } void setDesignators(ASTContext &C, const Designator *Desigs, @@ -3235,7 +3576,7 @@ public: void ExpandDesignator(ASTContext &C, unsigned Idx, const Designator *First, const Designator *Last); - virtual SourceRange getSourceRange() const; + SourceRange getSourceRange() const; static bool classof(const Stmt *T) { return T->getStmtClass() == DesignatedInitExprClass; @@ -3243,8 +3584,10 @@ public: static bool classof(const DesignatedInitExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + Stmt **begin = reinterpret_cast<Stmt**>(this + 1); + return child_range(begin, begin + NumSubExprs); + } }; /// \brief Represents an implicitly-generated value initialization of @@ -3258,7 +3601,8 @@ public: class ImplicitValueInitExpr : public Expr { public: explicit ImplicitValueInitExpr(QualType ty) - : Expr(ImplicitValueInitExprClass, ty, false, false) { } + : Expr(ImplicitValueInitExprClass, ty, VK_RValue, OK_Ordinary, + false, false, false) { } /// \brief Construct an empty implicit value initialization. explicit ImplicitValueInitExpr(EmptyShell Empty) @@ -3269,13 +3613,12 @@ public: } static bool classof(const ImplicitValueInitExpr *) { return true; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(); } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; @@ -3308,7 +3651,7 @@ public: SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(LParenLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -3317,8 +3660,9 @@ public: static bool classof(const ParenListExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&Exprs[0], &Exprs[0]+NumExprs); + } friend class ASTStmtReader; friend class ASTStmtWriter; @@ -3342,10 +3686,12 @@ class ExtVectorElementExpr : public Expr { IdentifierInfo *Accessor; SourceLocation AccessorLoc; public: - ExtVectorElementExpr(QualType ty, Expr *base, IdentifierInfo &accessor, - SourceLocation loc) - : Expr(ExtVectorElementExprClass, ty, base->isTypeDependent(), - base->isValueDependent()), + ExtVectorElementExpr(QualType ty, ExprValueKind VK, Expr *base, + IdentifierInfo &accessor, SourceLocation loc) + : Expr(ExtVectorElementExprClass, ty, VK, + (VK == VK_RValue ? OK_Ordinary : OK_VectorComponent), + base->isTypeDependent(), base->isValueDependent(), + base->containsUnexpandedParameterPack()), Base(base), Accessor(&accessor), AccessorLoc(loc) {} /// \brief Build an empty vector element expression. @@ -3373,7 +3719,7 @@ public: /// aggregate Constant of ConstantInt(s). void getEncodedElementAccess(llvm::SmallVectorImpl<unsigned> &Elts) const; - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(getBase()->getLocStart(), AccessorLoc); } @@ -3387,8 +3733,7 @@ public: static bool classof(const ExtVectorElementExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&Base, &Base+1); } }; @@ -3397,11 +3742,11 @@ public: class BlockExpr : public Expr { protected: BlockDecl *TheBlock; - bool HasBlockDeclRefExprs; public: - BlockExpr(BlockDecl *BD, QualType ty, bool hasBlockDeclRefExprs) - : Expr(BlockExprClass, ty, ty->isDependentType(), false), - TheBlock(BD), HasBlockDeclRefExprs(hasBlockDeclRefExprs) {} + BlockExpr(BlockDecl *BD, QualType ty) + : Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary, + ty->isDependentType(), false, false), + TheBlock(BD) {} /// \brief Build an empty block expression. explicit BlockExpr(EmptyShell Empty) : Expr(BlockExprClass, Empty) { } @@ -3415,58 +3760,46 @@ public: const Stmt *getBody() const; Stmt *getBody(); - virtual SourceRange getSourceRange() const { + 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(); + child_range children() { return child_range(); } }; -/// BlockDeclRefExpr - A reference to a declared variable, function, -/// enum, etc. +/// BlockDeclRefExpr - A reference to a local variable declared in an +/// enclosing scope. class BlockDeclRefExpr : public Expr { - ValueDecl *D; + VarDecl *D; SourceLocation Loc; bool IsByRef : 1; bool ConstQualAdded : 1; - Stmt *CopyConstructorVal; public: - // FIXME: Fix type/value dependence! - BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef, - bool constAdded = false, - Stmt *copyConstructorVal = 0) - : Expr(BlockDeclRefExprClass, t, (!t.isNull() && t->isDependentType()),false), - D(d), Loc(l), IsByRef(ByRef), - ConstQualAdded(constAdded), CopyConstructorVal(copyConstructorVal) {} + BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK, + SourceLocation l, bool ByRef, bool constAdded = false); // \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; } + VarDecl *getDecl() { return D; } + const VarDecl *getDecl() const { return D; } + void setDecl(VarDecl *VD) { D = VD; } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const { return SourceRange(Loc); } bool isByRef() const { return IsByRef; } void setByRef(bool BR) { IsByRef = BR; } @@ -3474,20 +3807,13 @@ public: bool isConstQualAdded() const { return ConstQualAdded; } void setConstQualAdded(bool C) { ConstQualAdded = C; } - const Expr *getCopyConstructorExpr() const - { return cast_or_null<Expr>(CopyConstructorVal); } - Expr *getCopyConstructorExpr() - { return cast_or_null<Expr>(CopyConstructorVal); } - void setCopyConstructorExpr(Expr *E) { CopyConstructorVal = E; } - 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(); + child_range children() { return child_range(); } }; } // end namespace clang diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 0a9435479d93..85ce9621d928 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -21,11 +21,11 @@ namespace clang { - class CXXConstructorDecl; - class CXXDestructorDecl; - class CXXMethodDecl; - class CXXTemporary; - class TemplateArgumentListInfo; +class CXXConstructorDecl; +class CXXDestructorDecl; +class CXXMethodDecl; +class CXXTemporary; +class TemplateArgumentListInfo; //===--------------------------------------------------------------------===// // C++ Expressions. @@ -51,8 +51,9 @@ class CXXOperatorCallExpr : public CallExpr { public: CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn, Expr **args, unsigned numargs, QualType t, - SourceLocation operatorloc) - : CallExpr(C, CXXOperatorCallExprClass, fn, args, numargs, t, operatorloc), + ExprValueKind VK, SourceLocation operatorloc) + : CallExpr(C, CXXOperatorCallExprClass, fn, 0, args, numargs, t, VK, + operatorloc), Operator(Op) {} explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) : CallExpr(C, CXXOperatorCallExprClass, Empty) { } @@ -70,7 +71,7 @@ public: /// bracket. SourceLocation getOperatorLoc() const { return getRParenLoc(); } - virtual SourceRange getSourceRange() const; + SourceRange getSourceRange() const; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXOperatorCallExprClass; @@ -89,8 +90,8 @@ public: 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) {} + QualType t, ExprValueKind VK, SourceLocation RP) + : CallExpr(C, CXXMemberCallExprClass, fn, 0, args, numargs, t, VK, RP) {} CXXMemberCallExpr(ASTContext &C, EmptyShell Empty) : CallExpr(C, CXXMemberCallExprClass, Empty) { } @@ -100,7 +101,14 @@ public: /// operation would return "x". Expr *getImplicitObjectArgument(); - virtual SourceRange getSourceRange() const; + /// getRecordDecl - Retrieves the CXXRecordDecl for the underlying type of + /// the implicit object argument. Note that this is may not be the same + /// declaration as that of the class context of the CXXMethodDecl which this + /// function is calling. + /// FIXME: Returns 0 for member pointer call exprs. + CXXRecordDecl *getRecordDecl(); + + SourceRange getSourceRange() const; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXMemberCallExprClass; @@ -108,6 +116,35 @@ public: static bool classof(const CXXMemberCallExpr *) { return true; } }; +/// CUDAKernelCallExpr - Represents a call to a CUDA kernel function. +class CUDAKernelCallExpr : public CallExpr { +private: + enum { CONFIG, END_PREARG }; + +public: + CUDAKernelCallExpr(ASTContext &C, Expr *fn, CallExpr *Config, + Expr **args, unsigned numargs, QualType t, + ExprValueKind VK, SourceLocation RP) + : CallExpr(C, CUDAKernelCallExprClass, fn, END_PREARG, args, numargs, t, VK, + RP) { + setConfig(Config); + } + + CUDAKernelCallExpr(ASTContext &C, EmptyShell Empty) + : CallExpr(C, CUDAKernelCallExprClass, END_PREARG, Empty) { } + + const CallExpr *getConfig() const { + return cast_or_null<CallExpr>(getPreArg(CONFIG)); + } + CallExpr *getConfig() { return cast_or_null<CallExpr>(getPreArg(CONFIG)); } + void setConfig(CallExpr *E) { setPreArg(CONFIG, E); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CUDAKernelCallExprClass; + } + static bool classof(const CUDAKernelCallExpr *) { 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. @@ -118,26 +155,33 @@ public: class CXXNamedCastExpr : public ExplicitCastExpr { private: SourceLocation Loc; // the location of the casting op - + SourceLocation RParenLoc; // the location of the right parenthesis + protected: - CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op, - unsigned PathSize, TypeSourceInfo *writtenTy, - SourceLocation l) - : ExplicitCastExpr(SC, ty, kind, op, PathSize, writtenTy), Loc(l) {} + CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK, + CastKind kind, Expr *op, unsigned PathSize, + TypeSourceInfo *writtenTy, SourceLocation l, + SourceLocation RParenLoc) + : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, writtenTy), Loc(l), + RParenLoc(RParenLoc) {} explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize) : ExplicitCastExpr(SC, Shell, PathSize) { } + friend class ASTStmtReader; + 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()); + /// \brief Retrieve the location of the closing parenthesis. + SourceLocation getRParenLoc() const { return RParenLoc; } + + SourceRange getSourceRange() const { + return SourceRange(Loc, RParenLoc); } static bool classof(const Stmt *T) { switch (T->getStmtClass()) { @@ -158,20 +202,21 @@ public: /// This expression node represents a C++ static cast, e.g., /// @c static_cast<int>(1.0). class CXXStaticCastExpr : public CXXNamedCastExpr { - CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op, + CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, - SourceLocation l) - : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, pathSize, - writtenTy, l) {} + SourceLocation l, SourceLocation RParenLoc) + : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize, + writtenTy, l, RParenLoc) {} explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize) : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { } public: static CXXStaticCastExpr *Create(ASTContext &Context, QualType T, - CastKind K, Expr *Op, + ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *Path, - TypeSourceInfo *Written, SourceLocation L); + TypeSourceInfo *Written, SourceLocation L, + SourceLocation RParenLoc); static CXXStaticCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize); @@ -188,20 +233,21 @@ public: /// This expression node represents a dynamic cast, e.g., /// @c dynamic_cast<Derived*>(BasePtr). class CXXDynamicCastExpr : public CXXNamedCastExpr { - CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op, - unsigned pathSize, TypeSourceInfo *writtenTy, - SourceLocation l) - : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, pathSize, - writtenTy, l) {} + CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind, + Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, + SourceLocation l, SourceLocation RParenLoc) + : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize, + writtenTy, l, RParenLoc) {} explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize) : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { } public: static CXXDynamicCastExpr *Create(ASTContext &Context, QualType T, - CastKind Kind, Expr *Op, + ExprValueKind VK, CastKind Kind, Expr *Op, const CXXCastPath *Path, - TypeSourceInfo *Written, SourceLocation L); + TypeSourceInfo *Written, SourceLocation L, + SourceLocation RParenLoc); static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context, unsigned pathSize); @@ -219,20 +265,22 @@ public: /// This expression node represents a reinterpret cast, e.g., /// @c reinterpret_cast<int>(VoidPtr). class CXXReinterpretCastExpr : public CXXNamedCastExpr { - CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op, - unsigned pathSize, - TypeSourceInfo *writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, pathSize, - writtenTy, l) {} + CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind, + Expr *op, unsigned pathSize, + TypeSourceInfo *writtenTy, SourceLocation l, + SourceLocation RParenLoc) + : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op, + pathSize, writtenTy, l, RParenLoc) {} CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize) : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { } public: static CXXReinterpretCastExpr *Create(ASTContext &Context, QualType T, - CastKind Kind, Expr *Op, - const CXXCastPath *Path, - TypeSourceInfo *WrittenTy, SourceLocation L); + ExprValueKind VK, CastKind Kind, + Expr *Op, const CXXCastPath *Path, + TypeSourceInfo *WrittenTy, SourceLocation L, + SourceLocation RParenLoc); static CXXReinterpretCastExpr *CreateEmpty(ASTContext &Context, unsigned pathSize); @@ -248,17 +296,20 @@ public: /// This expression node represents a const cast, e.g., /// @c const_cast<char*>(PtrToConstChar). class CXXConstCastExpr : public CXXNamedCastExpr { - CXXConstCastExpr(QualType ty, Expr *op, TypeSourceInfo *writtenTy, - SourceLocation l) - : CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op, - 0, writtenTy, l) {} + CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op, + TypeSourceInfo *writtenTy, SourceLocation l, + SourceLocation RParenLoc) + : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op, + 0, writtenTy, l, RParenLoc) {} explicit CXXConstCastExpr(EmptyShell Empty) : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { } public: - static CXXConstCastExpr *Create(ASTContext &Context, QualType T, Expr *Op, - TypeSourceInfo *WrittenTy, SourceLocation L); + static CXXConstCastExpr *Create(ASTContext &Context, QualType T, + ExprValueKind VK, Expr *Op, + TypeSourceInfo *WrittenTy, SourceLocation L, + SourceLocation RParenLoc); static CXXConstCastExpr *CreateEmpty(ASTContext &Context); static bool classof(const Stmt *T) { @@ -274,7 +325,9 @@ class CXXBoolLiteralExpr : public Expr { SourceLocation Loc; public: CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) : - Expr(CXXBoolLiteralExprClass, Ty, false, false), Value(val), Loc(l) {} + Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, + false), + Value(val), Loc(l) {} explicit CXXBoolLiteralExpr(EmptyShell Empty) : Expr(CXXBoolLiteralExprClass, Empty) { } @@ -282,7 +335,7 @@ public: bool getValue() const { return Value; } void setValue(bool V) { Value = V; } - virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const { return SourceRange(Loc); } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } @@ -293,8 +346,7 @@ public: static bool classof(const CXXBoolLiteralExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; /// CXXNullPtrLiteralExpr - [C++0x 2.14.7] C++ Pointer Literal @@ -302,12 +354,14 @@ class CXXNullPtrLiteralExpr : public Expr { SourceLocation Loc; public: CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) : - Expr(CXXNullPtrLiteralExprClass, Ty, false, false), Loc(l) {} + Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, + false), + Loc(l) {} explicit CXXNullPtrLiteralExpr(EmptyShell Empty) : Expr(CXXNullPtrLiteralExprClass, Empty) { } - virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const { return SourceRange(Loc); } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } @@ -317,8 +371,7 @@ public: } static bool classof(const CXXNullPtrLiteralExpr *) { return true; } - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; /// CXXTypeidExpr - A C++ @c typeid expression (C++ [expr.typeid]), which gets @@ -333,19 +386,21 @@ private: public: CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R) - : Expr(CXXTypeidExprClass, Ty, + : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary, // typeid is never type-dependent (C++ [temp.dep.expr]p4) false, // typeid is value-dependent if the type or expression are dependent - Operand->getType()->isDependentType()), + Operand->getType()->isDependentType(), + Operand->getType()->containsUnexpandedParameterPack()), Operand(Operand), Range(R) { } CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R) - : Expr(CXXTypeidExprClass, Ty, + : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary, // typeid is never type-dependent (C++ [temp.dep.expr]p4) - false, + false, // typeid is value-dependent if the type or expression are dependent - Operand->isTypeDependent() || Operand->isValueDependent()), + Operand->isTypeDependent() || Operand->isValueDependent(), + Operand->containsUnexpandedParameterPack()), Operand(Operand), Range(R) { } CXXTypeidExpr(EmptyShell Empty, bool isExpr) @@ -383,7 +438,7 @@ public: Operand = E; } - virtual SourceRange getSourceRange() const { return Range; } + SourceRange getSourceRange() const { return Range; } void setSourceRange(SourceRange R) { Range = R; } static bool classof(const Stmt *T) { @@ -392,8 +447,84 @@ public: static bool classof(const CXXTypeidExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + if (isTypeOperand()) return child_range(); + Stmt **begin = reinterpret_cast<Stmt**>(&Operand); + return child_range(begin, begin + 1); + } +}; + +/// CXXUuidofExpr - A microsoft C++ @c __uuidof expression, which gets +/// the _GUID that corresponds to the supplied type or expression. +/// +/// This represents code like @c __uuidof(COMTYPE) or @c __uuidof(*comPtr) +class CXXUuidofExpr : public Expr { +private: + llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand; + SourceRange Range; + +public: + CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R) + : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, + false, Operand->getType()->isDependentType(), + Operand->getType()->containsUnexpandedParameterPack()), + Operand(Operand), Range(R) { } + + CXXUuidofExpr(QualType Ty, Expr *Operand, SourceRange R) + : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, + false, Operand->isTypeDependent(), + Operand->containsUnexpandedParameterPack()), + Operand(Operand), Range(R) { } + + CXXUuidofExpr(EmptyShell Empty, bool isExpr) + : Expr(CXXUuidofExprClass, Empty) { + if (isExpr) + Operand = (Expr*)0; + else + Operand = (TypeSourceInfo*)0; + } + + bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } + + /// \brief Retrieves the type operand of this __uuidof() expression after + /// various required adjustments (removing reference types, cv-qualifiers). + QualType getTypeOperand() const; + + /// \brief Retrieve source information for the type operand. + TypeSourceInfo *getTypeOperandSourceInfo() const { + assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)"); + return Operand.get<TypeSourceInfo *>(); + } + + void setTypeOperandSourceInfo(TypeSourceInfo *TSI) { + assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)"); + Operand = TSI; + } + + Expr *getExprOperand() const { + assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)"); + return static_cast<Expr*>(Operand.get<Stmt *>()); + } + + void setExprOperand(Expr *E) { + assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)"); + Operand = E; + } + + SourceRange getSourceRange() const { return Range; } + void setSourceRange(SourceRange R) { Range = R; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXUuidofExprClass; + } + static bool classof(const CXXUuidofExpr *) { return true; } + + // Iterators + child_range children() { + if (isTypeOperand()) return child_range(); + Stmt **begin = reinterpret_cast<Stmt**>(&Operand); + return child_range(begin, begin + 1); + } }; /// CXXThisExpr - Represents the "this" expression in C++, which is a @@ -413,10 +544,11 @@ class CXXThisExpr : public Expr { public: CXXThisExpr(SourceLocation L, QualType Type, bool isImplicit) - : Expr(CXXThisExprClass, Type, + : Expr(CXXThisExprClass, Type, VK_RValue, OK_Ordinary, // 'this' is type-dependent if the class type of the enclosing // member function is dependent (C++ [temp.dep.expr]p2) - Type->isDependentType(), Type->isDependentType()), + Type->isDependentType(), Type->isDependentType(), + /*ContainsUnexpandedParameterPack=*/false), Loc(L), Implicit(isImplicit) { } CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {} @@ -424,7 +556,7 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const { return SourceRange(Loc); } bool isImplicit() const { return Implicit; } void setImplicit(bool I) { Implicit = I; } @@ -435,8 +567,7 @@ public: static bool classof(const CXXThisExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; /// CXXThrowExpr - [C++ 15] C++ Throw Expression. This handles @@ -451,7 +582,9 @@ public: // 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) {} + Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false, + expr && expr->containsUnexpandedParameterPack()), + Op(expr), ThrowLoc(l) {} CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {} const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); } @@ -461,7 +594,7 @@ public: SourceLocation getThrowLoc() const { return ThrowLoc; } void setThrowLoc(SourceLocation L) { ThrowLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { if (getSubExpr() == 0) return SourceRange(ThrowLoc, ThrowLoc); return SourceRange(ThrowLoc, getSubExpr()->getSourceRange().getEnd()); @@ -473,8 +606,9 @@ public: static bool classof(const CXXThrowExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&Op, Op ? &Op+1 : &Op); + } }; /// CXXDefaultArgExpr - C++ [dcl.fct.default]. This wraps up a @@ -497,12 +631,16 @@ class CXXDefaultArgExpr : public Expr { param->hasUnparsedDefaultArg() ? param->getType().getNonReferenceType() : param->getDefaultArg()->getType(), - false, false), + param->getDefaultArg()->getValueKind(), + param->getDefaultArg()->getObjectKind(), false, false, false), Param(param, false), Loc(Loc) { } CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param, Expr *SubExpr) - : Expr(SC, SubExpr->getType(), false, false), Param(param, true), Loc(Loc) { + : Expr(SC, SubExpr->getType(), + SubExpr->getValueKind(), SubExpr->getObjectKind(), + false, false, false), + Param(param, true), Loc(Loc) { *reinterpret_cast<Expr **>(this + 1) = SubExpr; } @@ -544,7 +682,7 @@ public: /// used. SourceLocation getUsedLocation() const { return Loc; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { // Default argument expressions have no representation in the // source, so they have an empty source range. return SourceRange(); @@ -556,8 +694,7 @@ public: static bool classof(const CXXDefaultArgExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } friend class ASTStmtReader; friend class ASTStmtWriter; @@ -597,9 +734,12 @@ class CXXBindTemporaryExpr : public Expr { Stmt *SubExpr; - CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr) - : Expr(CXXBindTemporaryExprClass, subexpr->getType(), false, false), - Temp(temp), SubExpr(subexpr) { } + CXXBindTemporaryExpr(CXXTemporary *temp, Expr* SubExpr) + : Expr(CXXBindTemporaryExprClass, SubExpr->getType(), + VK_RValue, OK_Ordinary, SubExpr->isTypeDependent(), + SubExpr->isValueDependent(), + SubExpr->containsUnexpandedParameterPack()), + Temp(temp), SubExpr(SubExpr) { } public: CXXBindTemporaryExpr(EmptyShell Empty) @@ -616,7 +756,7 @@ public: Expr *getSubExpr() { return cast<Expr>(SubExpr); } void setSubExpr(Expr *E) { SubExpr = E; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SubExpr->getSourceRange(); } @@ -627,8 +767,7 @@ public: static bool classof(const CXXBindTemporaryExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&SubExpr, &SubExpr + 1); } }; /// CXXConstructExpr - Represents a call to a C++ constructor. @@ -644,6 +783,7 @@ private: CXXConstructorDecl *Constructor; SourceLocation Loc; + SourceRange ParenRange; bool Elidable : 1; bool ZeroInitialization : 1; unsigned ConstructKind : 2; @@ -656,7 +796,8 @@ protected: CXXConstructorDecl *d, bool elidable, Expr **args, unsigned numargs, bool ZeroInitialization = false, - ConstructionKind ConstructKind = CK_Complete); + ConstructionKind ConstructKind = CK_Complete, + SourceRange ParenRange = SourceRange()); /// \brief Construct an empty C++ construction expression. CXXConstructExpr(StmtClass SC, EmptyShell Empty) @@ -675,7 +816,8 @@ public: CXXConstructorDecl *D, bool Elidable, Expr **Args, unsigned NumArgs, bool ZeroInitialization = false, - ConstructionKind ConstructKind = CK_Complete); + ConstructionKind ConstructKind = CK_Complete, + SourceRange ParenRange = SourceRange()); CXXConstructorDecl* getConstructor() const { return Constructor; } @@ -731,7 +873,8 @@ public: Args[Arg] = ArgExpr; } - virtual SourceRange getSourceRange() const; + SourceRange getSourceRange() const; + SourceRange getParenRange() const { return ParenRange; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConstructExprClass || @@ -740,8 +883,9 @@ public: static bool classof(const CXXConstructExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&Args[0], &Args[0]+NumArgs); + } friend class ASTStmtReader; }; @@ -753,12 +897,13 @@ class CXXFunctionalCastExpr : public ExplicitCastExpr { SourceLocation TyBeginLoc; SourceLocation RParenLoc; - CXXFunctionalCastExpr(QualType ty, TypeSourceInfo *writtenTy, + CXXFunctionalCastExpr(QualType ty, ExprValueKind VK, + TypeSourceInfo *writtenTy, SourceLocation tyBeginLoc, CastKind kind, Expr *castExpr, unsigned pathSize, SourceLocation rParenLoc) - : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr, - pathSize, writtenTy), + : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind, + castExpr, pathSize, writtenTy), TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize) @@ -766,6 +911,7 @@ class CXXFunctionalCastExpr : public ExplicitCastExpr { public: static CXXFunctionalCastExpr *Create(ASTContext &Context, QualType T, + ExprValueKind VK, TypeSourceInfo *Written, SourceLocation TyBeginLoc, CastKind Kind, Expr *Op, @@ -779,7 +925,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(TyBeginLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -804,24 +950,21 @@ public: /// }; /// @endcode class CXXTemporaryObjectExpr : public CXXConstructExpr { - SourceLocation TyBeginLoc; - SourceLocation RParenLoc; + TypeSourceInfo *Type; public: CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons, - QualType writtenTy, SourceLocation tyBeginLoc, + TypeSourceInfo *Type, Expr **Args,unsigned NumArgs, - SourceLocation rParenLoc, + SourceRange parenRange, bool ZeroInitialization = false); explicit CXXTemporaryObjectExpr(EmptyShell Empty) - : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty) { } + : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { } - SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } - SourceLocation getRParenLoc() const { return RParenLoc; } + TypeSourceInfo *getTypeSourceInfo() const { return Type; } - virtual SourceRange getSourceRange() const { - return SourceRange(TyBeginLoc, RParenLoc); - } + SourceRange getSourceRange() const; + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXTemporaryObjectExprClass; } @@ -835,32 +978,31 @@ public: /// T, which is a non-class type. /// class CXXScalarValueInitExpr : public Expr { - SourceLocation TyBeginLoc; SourceLocation RParenLoc; + TypeSourceInfo *TypeInfo; + friend class ASTStmtReader; + public: - CXXScalarValueInitExpr(QualType ty, SourceLocation tyBeginLoc, - SourceLocation rParenLoc ) : - Expr(CXXScalarValueInitExprClass, ty, false, false), - TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} + /// \brief Create an explicitly-written scalar-value initialization + /// expression. + CXXScalarValueInitExpr(QualType Type, + TypeSourceInfo *TypeInfo, + SourceLocation rParenLoc ) : + Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary, + false, false, false), + RParenLoc(rParenLoc), TypeInfo(TypeInfo) {} + explicit CXXScalarValueInitExpr(EmptyShell Shell) : Expr(CXXScalarValueInitExprClass, Shell) { } - SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } - SourceLocation getRParenLoc() const { return RParenLoc; } - - void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - - /// @brief Whether this initialization expression was - /// implicitly-generated. - bool isImplicit() const { - return TyBeginLoc.isInvalid() && RParenLoc.isInvalid(); + TypeSourceInfo *getTypeSourceInfo() const { + return TypeInfo; } + + SourceLocation getRParenLoc() const { return RParenLoc; } - virtual SourceRange getSourceRange() const { - return SourceRange(TyBeginLoc, RParenLoc); - } + SourceRange getSourceRange() const; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXScalarValueInitExprClass; @@ -868,8 +1010,7 @@ public: static bool classof(const CXXScalarValueInitExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; /// CXXNewExpr - A new expression for memory allocation and constructor calls, @@ -882,8 +1023,11 @@ class CXXNewExpr : public Expr { bool Initializer : 1; // Do we allocate an array? If so, the first SubExpr is the size expression. bool Array : 1; + // If this is an array allocation, does the usual deallocation + // function for the allocated type want to know the allocated size? + bool UsualArrayDeleteWantsSize : 1; // The number of placement new arguments. - unsigned NumPlacementArgs : 15; + 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; @@ -900,12 +1044,17 @@ class CXXNewExpr : public Expr { // Must be null for all other types. CXXConstructorDecl *Constructor; + /// \brief The allocated type-source information, as written in the source. + TypeSourceInfo *AllocatedTypeInfo; + /// \brief If the allocated type was expressed as a parenthesized type-id, /// the source range covering the parenthesized type-id. SourceRange TypeIdParens; SourceLocation StartLoc; SourceLocation EndLoc; + SourceLocation ConstructorLParen; + SourceLocation ConstructorRParen; friend class ASTStmtReader; public: @@ -914,8 +1063,11 @@ public: SourceRange TypeIdParens, Expr *arraySize, CXXConstructorDecl *constructor, bool initializer, Expr **constructorArgs, unsigned numConsArgs, - FunctionDecl *operatorDelete, QualType ty, - SourceLocation startLoc, SourceLocation endLoc); + FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize, + QualType ty, TypeSourceInfo *AllocatedTypeInfo, + SourceLocation startLoc, SourceLocation endLoc, + SourceLocation constructorLParen, + SourceLocation constructorRParen); explicit CXXNewExpr(EmptyShell Shell) : Expr(CXXNewExprClass, Shell), SubExprs(0) { } @@ -927,6 +1079,10 @@ public: return getType()->getAs<PointerType>()->getPointeeType(); } + TypeSourceInfo *getAllocatedTypeSourceInfo() const { + return AllocatedTypeInfo; + } + FunctionDecl *getOperatorNew() const { return OperatorNew; } void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } FunctionDecl *getOperatorDelete() const { return OperatorDelete; } @@ -943,6 +1099,10 @@ public: } unsigned getNumPlacementArgs() const { return NumPlacementArgs; } + Expr **getPlacementArgs() { + return reinterpret_cast<Expr **>(SubExprs + Array); + } + Expr *getPlacementArg(unsigned i) { assert(i < NumPlacementArgs && "Index out of range"); return cast<Expr>(SubExprs[Array + i]); @@ -956,11 +1116,21 @@ public: SourceRange getTypeIdParens() const { return TypeIdParens; } bool isGlobalNew() const { return GlobalNew; } - void setGlobalNew(bool V) { GlobalNew = V; } bool hasInitializer() const { return Initializer; } - void setHasInitializer(bool V) { Initializer = V; } + + /// Answers whether the usual array deallocation function for the + /// allocated type expects the size of the allocation as a + /// parameter. + bool doesUsualArrayDeleteWantSize() const { + return UsualArrayDeleteWantsSize; + } unsigned getNumConstructorArgs() const { return NumConstructorArgs; } + + Expr **getConstructorArgs() { + return reinterpret_cast<Expr **>(SubExprs + Array + NumPlacementArgs); + } + Expr *getConstructorArg(unsigned i) { assert(i < NumConstructorArgs && "Index out of range"); return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]); @@ -1007,13 +1177,13 @@ public: const_arg_iterator raw_arg_begin() const { return SubExprs; } const_arg_iterator raw_arg_end() const { return constructor_arg_end(); } - SourceLocation getStartLoc() const { return StartLoc; } - void setStartLoc(SourceLocation L) { StartLoc = L; } SourceLocation getEndLoc() const { return EndLoc; } - void setEndLoc(SourceLocation L) { EndLoc = L; } - - virtual SourceRange getSourceRange() const { + + SourceLocation getConstructorLParen() const { return ConstructorLParen; } + SourceLocation getConstructorRParen() const { return ConstructorRParen; } + + SourceRange getSourceRange() const { return SourceRange(StartLoc, EndLoc); } @@ -1023,8 +1193,11 @@ public: static bool classof(const CXXNewExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&SubExprs[0], + &SubExprs[0] + Array + getNumPlacementArgs() + + getNumConstructorArgs()); + } }; /// CXXDeleteExpr - A delete expression for memory deallocation and destructor @@ -1034,6 +1207,13 @@ class CXXDeleteExpr : public Expr { bool GlobalDelete : 1; // Is this the array form of delete, i.e. "delete[]"? bool ArrayForm : 1; + // ArrayFormAsWritten can be different from ArrayForm if 'delete' is applied + // to pointer-to-array type (ArrayFormAsWritten will be false while ArrayForm + // will be true). + bool ArrayFormAsWritten : 1; + // Does the usual deallocation function for the element type require + // a size_t argument? + bool UsualArrayDeleteWantsSize : 1; // Points to the operator delete overload that is used. Could be a member. FunctionDecl *OperatorDelete; // The pointer expression to be deleted. @@ -1042,30 +1222,42 @@ class CXXDeleteExpr : public Expr { SourceLocation Loc; public: CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm, + bool arrayFormAsWritten, bool usualArrayDeleteWantsSize, FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc) - : Expr(CXXDeleteExprClass, ty, false, false), GlobalDelete(globalDelete), - ArrayForm(arrayForm), OperatorDelete(operatorDelete), Argument(arg), - Loc(loc) { } + : Expr(CXXDeleteExprClass, ty, VK_RValue, OK_Ordinary, false, false, + arg->containsUnexpandedParameterPack()), + GlobalDelete(globalDelete), + ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten), + UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize), + OperatorDelete(operatorDelete), Argument(arg), Loc(loc) { } explicit CXXDeleteExpr(EmptyShell Shell) : Expr(CXXDeleteExprClass, Shell), OperatorDelete(0), Argument(0) { } bool isGlobalDelete() const { return GlobalDelete; } bool isArrayForm() const { return ArrayForm; } - - void setGlobalDelete(bool V) { GlobalDelete = V; } - void setArrayForm(bool V) { ArrayForm = V; } + bool isArrayFormAsWritten() const { return ArrayFormAsWritten; } + + /// Answers whether the usual array deallocation function for the + /// allocated type expects the size of the allocation as a + /// parameter. This can be true even if the actual deallocation + /// function that we're using doesn't want a size. + bool doesUsualArrayDeleteWantSize() const { + return UsualArrayDeleteWantsSize; + } FunctionDecl *getOperatorDelete() const { return OperatorDelete; } - void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; } Expr *getArgument() { return cast<Expr>(Argument); } const Expr *getArgument() const { return cast<Expr>(Argument); } - void setArgument(Expr *E) { Argument = E; } - virtual SourceRange getSourceRange() const { + /// \brief Retrieve the type being destroyed. If the type being + /// destroyed is a dependent type which may or may not be a pointer, + /// return an invalid type. + QualType getDestroyedType() const; + + SourceRange getSourceRange() const { return SourceRange(Loc, Argument->getLocEnd()); } - void setStartLoc(SourceLocation L) { Loc = L; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDeleteExprClass; @@ -1073,8 +1265,9 @@ public: static bool classof(const CXXDeleteExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&Argument, &Argument+1); } + + friend class ASTStmtReader; }; /// \brief Structure used to store the type being destroyed by a @@ -1171,21 +1364,7 @@ public: TypeSourceInfo *ScopeType, SourceLocation ColonColonLoc, SourceLocation TildeLoc, - PseudoDestructorTypeStorage DestroyedType) - : Expr(CXXPseudoDestructorExprClass, - Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0, - false, 0, false, - false, 0, 0, - FunctionType::ExtInfo())), - /*isTypeDependent=*/(Base->isTypeDependent() || - (DestroyedType.getTypeSourceInfo() && - DestroyedType.getTypeSourceInfo()->getType()->isDependentType())), - /*isValueDependent=*/Base->isValueDependent()), - Base(static_cast<Stmt *>(Base)), IsArrow(isArrow), - OperatorLoc(OperatorLoc), Qualifier(Qualifier), - QualifierRange(QualifierRange), - ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc), - DestroyedType(DestroyedType) { } + PseudoDestructorTypeStorage DestroyedType); explicit CXXPseudoDestructorExpr(EmptyShell Shell) : Expr(CXXPseudoDestructorExprClass, Shell), @@ -1278,7 +1457,7 @@ public: DestroyedType = PseudoDestructorTypeStorage(Info); } - virtual SourceRange getSourceRange() const; + SourceRange getSourceRange() const; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXPseudoDestructorExprClass; @@ -1286,8 +1465,7 @@ public: static bool classof(const CXXPseudoDestructorExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&Base, &Base + 1); } }; /// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the @@ -1296,8 +1474,10 @@ public: /// __is_pod(int) == true /// __is_enum(std::string) == false class UnaryTypeTraitExpr : public Expr { - /// UTT - The trait. - UnaryTypeTrait UTT; + /// UTT - The trait. A UnaryTypeTrait enum in MSVC compat unsigned. + unsigned UTT : 31; + /// The value of the type trait. Unspecified if dependent. + bool Value : 1; /// Loc - The location of the type trait keyword. SourceLocation Loc; @@ -1305,25 +1485,31 @@ class UnaryTypeTraitExpr : public Expr { /// RParen - The location of the closing paren. SourceLocation RParen; - /// QueriedType - The type we're testing. - QualType QueriedType; + /// The type being queried. + TypeSourceInfo *QueriedType; public: - UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt, QualType queried, + UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt, + TypeSourceInfo *queried, bool value, SourceLocation rparen, QualType ty) - : Expr(UnaryTypeTraitExprClass, ty, false, queried->isDependentType()), - UTT(utt), Loc(loc), RParen(rparen), QueriedType(queried) { } + : Expr(UnaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, + false, queried->getType()->isDependentType(), + queried->getType()->containsUnexpandedParameterPack()), + UTT(utt), Value(value), Loc(loc), RParen(rparen), QueriedType(queried) { } explicit UnaryTypeTraitExpr(EmptyShell Empty) - : Expr(UnaryTypeTraitExprClass, Empty), UTT((UnaryTypeTrait)0) { } + : Expr(UnaryTypeTraitExprClass, Empty), UTT(0), Value(false), + QueriedType() { } - virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen);} + SourceRange getSourceRange() const { return SourceRange(Loc, RParen);} - UnaryTypeTrait getTrait() const { return UTT; } + UnaryTypeTrait getTrait() const { return static_cast<UnaryTypeTrait>(UTT); } - QualType getQueriedType() const { return QueriedType; } + QualType getQueriedType() const { return QueriedType->getType(); } - bool EvaluateTrait(ASTContext&) const; + TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; } + + bool getValue() const { return Value; } static bool classof(const Stmt *T) { return T->getStmtClass() == UnaryTypeTraitExprClass; @@ -1331,8 +1517,74 @@ public: static bool classof(const UnaryTypeTraitExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } + + friend class ASTStmtReader; +}; + +/// BinaryTypeTraitExpr - A GCC or MS binary type trait, as used in the +/// implementation of TR1/C++0x type trait templates. +/// Example: +/// __is_base_of(Base, Derived) == true +class BinaryTypeTraitExpr : public Expr { + /// BTT - The trait. A BinaryTypeTrait enum in MSVC compat unsigned. + unsigned BTT : 8; + + /// The value of the type trait. Unspecified if dependent. + bool Value : 1; + + /// Loc - The location of the type trait keyword. + SourceLocation Loc; + + /// RParen - The location of the closing paren. + SourceLocation RParen; + + /// The lhs type being queried. + TypeSourceInfo *LhsType; + + /// The rhs type being queried. + TypeSourceInfo *RhsType; + +public: + BinaryTypeTraitExpr(SourceLocation loc, BinaryTypeTrait btt, + TypeSourceInfo *lhsType, TypeSourceInfo *rhsType, + bool value, SourceLocation rparen, QualType ty) + : Expr(BinaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, false, + lhsType->getType()->isDependentType() || + rhsType->getType()->isDependentType(), + (lhsType->getType()->containsUnexpandedParameterPack() || + rhsType->getType()->containsUnexpandedParameterPack())), + BTT(btt), Value(value), Loc(loc), RParen(rparen), + LhsType(lhsType), RhsType(rhsType) { } + + + explicit BinaryTypeTraitExpr(EmptyShell Empty) + : Expr(BinaryTypeTraitExprClass, Empty), BTT(0), Value(false), + LhsType(), RhsType() { } + + SourceRange getSourceRange() const { + return SourceRange(Loc, RParen); + } + + BinaryTypeTrait getTrait() const { + return static_cast<BinaryTypeTrait>(BTT); + } + + QualType getLhsType() const { return LhsType->getType(); } + QualType getRhsType() const { return RhsType->getType(); } + + TypeSourceInfo *getLhsTypeSourceInfo() const { return LhsType; } + TypeSourceInfo *getRhsTypeSourceInfo() const { return RhsType; } + + bool getValue() const { assert(!isTypeDependent()); return Value; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == BinaryTypeTraitExprClass; + } + static bool classof(const BinaryTypeTraitExpr *) { return true; } + + // Iterators + child_range children() { return child_range(); } friend class ASTStmtReader; }; @@ -1360,23 +1612,23 @@ protected: /// True if the name was a template-id. bool HasExplicitTemplateArgs; - OverloadExpr(StmtClass K, ASTContext &C, QualType T, bool Dependent, + OverloadExpr(StmtClass K, ASTContext &C, NestedNameSpecifier *Qualifier, SourceRange QRange, const DeclarationNameInfo &NameInfo, - bool HasTemplateArgs, - UnresolvedSetIterator Begin, UnresolvedSetIterator End); + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End, + bool KnownDependent = false, + bool KnownContainsUnexpandedParameterPack = false); OverloadExpr(StmtClass K, EmptyShell Empty) : Expr(K, Empty), Results(0), NumResults(0), Qualifier(0), HasExplicitTemplateArgs(false) { } -public: - /// Computes whether an unresolved lookup on the given declarations - /// and optional template arguments is type- and value-dependent. - static bool ComputeDependence(UnresolvedSetIterator Begin, - UnresolvedSetIterator End, - const TemplateArgumentListInfo *Args); + void initializeResults(ASTContext &C, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End); +public: struct FindResult { OverloadExpr *Expression; bool IsAddressOfOperand; @@ -1420,9 +1672,6 @@ public: return UnresolvedSetIterator(Results + NumResults); } - void initializeResults(ASTContext &C, - UnresolvedSetIterator Begin,UnresolvedSetIterator End); - /// Gets the number of declarations in the unresolved set. unsigned getNumDecls() const { return NumResults; } @@ -1469,6 +1718,9 @@ public: T->getStmtClass() == UnresolvedMemberExprClass; } static bool classof(const OverloadExpr *) { return true; } + + friend class ASTStmtReader; + friend class ASTStmtWriter; }; /// \brief A reference to a name which we were able to look up during @@ -1498,14 +1750,15 @@ class UnresolvedLookupExpr : public OverloadExpr { /// against the qualified-lookup bits. CXXRecordDecl *NamingClass; - UnresolvedLookupExpr(ASTContext &C, QualType T, bool Dependent, + UnresolvedLookupExpr(ASTContext &C, CXXRecordDecl *NamingClass, NestedNameSpecifier *Qualifier, SourceRange QRange, const DeclarationNameInfo &NameInfo, - bool RequiresADL, bool Overloaded, bool HasTemplateArgs, + bool RequiresADL, bool Overloaded, + const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End) - : OverloadExpr(UnresolvedLookupExprClass, C, T, Dependent, Qualifier, - QRange, NameInfo, HasTemplateArgs, Begin, End), + : OverloadExpr(UnresolvedLookupExprClass, C, Qualifier, QRange, NameInfo, + TemplateArgs, Begin, End), RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass) {} @@ -1516,7 +1769,6 @@ class UnresolvedLookupExpr : public OverloadExpr { public: static UnresolvedLookupExpr *Create(ASTContext &C, - bool Dependent, CXXRecordDecl *NamingClass, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, @@ -1524,16 +1776,12 @@ public: bool ADL, bool Overloaded, UnresolvedSetIterator Begin, UnresolvedSetIterator End) { - return new(C) UnresolvedLookupExpr(C, - Dependent ? C.DependentTy : C.OverloadTy, - Dependent, NamingClass, - Qualifier, QualifierRange, NameInfo, - ADL, Overloaded, false, - Begin, End); + return new(C) UnresolvedLookupExpr(C, NamingClass, Qualifier, + QualifierRange, NameInfo, ADL, + Overloaded, 0, Begin, End); } static UnresolvedLookupExpr *Create(ASTContext &C, - bool Dependent, CXXRecordDecl *NamingClass, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, @@ -1544,6 +1792,7 @@ public: UnresolvedSetIterator End); static UnresolvedLookupExpr *CreateEmpty(ASTContext &C, + bool HasExplicitTemplateArgs, unsigned NumTemplateArgs); /// True if this declaration should be extended by @@ -1606,15 +1855,14 @@ public: return getExplicitTemplateArgs().NumTemplateArgs; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { SourceRange Range(getNameInfo().getSourceRange()); if (getQualifier()) Range.setBegin(getQualifierRange().getBegin()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); return Range; } - virtual StmtIterator child_begin(); - virtual StmtIterator child_end(); + child_range children() { return child_range(); } static bool classof(const Stmt *T) { return T->getStmtClass() == UnresolvedLookupExprClass; @@ -1655,11 +1903,7 @@ class DependentScopeDeclRefExpr : public Expr { NestedNameSpecifier *Qualifier, SourceRange QualifierRange, const DeclarationNameInfo &NameInfo, - bool HasExplicitTemplateArgs) - : Expr(DependentScopeDeclRefExprClass, T, true, true), - NameInfo(NameInfo), QualifierRange(QualifierRange), Qualifier(Qualifier), - HasExplicitTemplateArgs(HasExplicitTemplateArgs) - {} + const TemplateArgumentListInfo *Args); public: static DependentScopeDeclRefExpr *Create(ASTContext &C, @@ -1669,6 +1913,7 @@ public: const TemplateArgumentListInfo *TemplateArgs = 0); static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C, + bool HasExplicitTemplateArgs, unsigned NumTemplateArgs); /// \brief Retrieve the name that this expression refers to. @@ -1740,7 +1985,7 @@ public: return getExplicitTemplateArgs().NumTemplateArgs; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { SourceRange Range(QualifierRange.getBegin(), getLocation()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); @@ -1752,25 +1997,32 @@ public: } static bool classof(const DependentScopeDeclRefExpr *) { return true; } - virtual StmtIterator child_begin(); - virtual StmtIterator child_end(); + child_range children() { return child_range(); } + + friend class ASTStmtReader; + friend class ASTStmtWriter; }; -class CXXExprWithTemporaries : public Expr { +/// Represents an expression --- generally a full-expression --- which +/// introduces cleanups to be run at the end of the sub-expression's +/// evaluation. The most common source of expression-introduced +/// cleanups is temporary objects in C++, but several other C++ +/// expressions can create cleanups. +class ExprWithCleanups : public Expr { Stmt *SubExpr; CXXTemporary **Temps; unsigned NumTemps; - CXXExprWithTemporaries(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps, - unsigned NumTemps); - + ExprWithCleanups(ASTContext &C, Expr *SubExpr, + CXXTemporary **Temps, unsigned NumTemps); + public: - CXXExprWithTemporaries(EmptyShell Empty) - : Expr(CXXExprWithTemporariesClass, Empty), + ExprWithCleanups(EmptyShell Empty) + : Expr(ExprWithCleanupsClass, Empty), SubExpr(0), Temps(0), NumTemps(0) {} - static CXXExprWithTemporaries *Create(ASTContext &C, Expr *SubExpr, + static ExprWithCleanups *Create(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps, unsigned NumTemps); @@ -1782,7 +2034,7 @@ public: return Temps[i]; } const CXXTemporary *getTemporary(unsigned i) const { - return const_cast<CXXExprWithTemporaries*>(this)->getTemporary(i); + return const_cast<ExprWithCleanups*>(this)->getTemporary(i); } void setTemporary(unsigned i, CXXTemporary *T) { assert(i < NumTemps && "Index out of range"); @@ -1793,19 +2045,18 @@ public: const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } void setSubExpr(Expr *E) { SubExpr = E; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SubExpr->getSourceRange(); } // Implement isa/cast/dyncast/etc. static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXExprWithTemporariesClass; + return T->getStmtClass() == ExprWithCleanupsClass; } - static bool classof(const CXXExprWithTemporaries *) { return true; } + static bool classof(const ExprWithCleanups *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&SubExpr, &SubExpr + 1); } }; /// \brief Describes an explicit type conversion that uses functional @@ -1830,12 +2081,9 @@ public: /// 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; - + TypeSourceInfo *Type; + /// \brief The location of the left parentheses ('('). SourceLocation LParenLoc; @@ -1845,20 +2093,20 @@ class CXXUnresolvedConstructExpr : public Expr { /// \brief The number of arguments used to construct the type. unsigned NumArgs; - CXXUnresolvedConstructExpr(SourceLocation TyBegin, - QualType T, + CXXUnresolvedConstructExpr(TypeSourceInfo *Type, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc); CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs) - : Expr(CXXUnresolvedConstructExprClass, Empty), NumArgs(NumArgs) { } + : Expr(CXXUnresolvedConstructExprClass, Empty), Type(), NumArgs(NumArgs) { } + friend class ASTStmtReader; + public: static CXXUnresolvedConstructExpr *Create(ASTContext &C, - SourceLocation TyBegin, - QualType T, + TypeSourceInfo *Type, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, @@ -1867,15 +2115,14 @@ public: static CXXUnresolvedConstructExpr *CreateEmpty(ASTContext &C, unsigned NumArgs); - /// \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; } + QualType getTypeAsWritten() const { return Type->getType(); } + /// \brief Retrieve the type source information for the type being + /// constructed. + TypeSourceInfo *getTypeSourceInfo() const { return Type; } + /// \brief Retrieve the location of the left parentheses ('(') that /// precedes the argument list. SourceLocation getLParenLoc() const { return LParenLoc; } @@ -1916,17 +2163,18 @@ public: *(arg_begin() + I) = E; } - virtual SourceRange getSourceRange() const { - return SourceRange(TyBeginLoc, RParenLoc); - } + SourceRange getSourceRange() const; + 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(); + child_range children() { + Stmt **begin = reinterpret_cast<Stmt**>(this+1); + return child_range(begin, begin + NumArgs); + } }; /// \brief Represents a C++ member access expression where the actual @@ -1987,19 +2235,13 @@ class CXXDependentScopeMemberExpr : public Expr { public: CXXDependentScopeMemberExpr(ASTContext &C, - Expr *Base, QualType BaseType, - bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - NamedDecl *FirstQualifierFoundInScope, - DeclarationNameInfo MemberNameInfo) - : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true), - Base(Base), BaseType(BaseType), IsArrow(IsArrow), - HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc), - Qualifier(Qualifier), QualifierRange(QualifierRange), - FirstQualifierFoundInScope(FirstQualifierFoundInScope), - MemberNameInfo(MemberNameInfo) { } + Expr *Base, QualType BaseType, + bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *FirstQualifierFoundInScope, + DeclarationNameInfo MemberNameInfo); static CXXDependentScopeMemberExpr * Create(ASTContext &C, @@ -2012,7 +2254,8 @@ public: const TemplateArgumentListInfo *TemplateArgs); static CXXDependentScopeMemberExpr * - CreateEmpty(ASTContext &C, unsigned NumTemplateArgs); + CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs, + unsigned NumTemplateArgs); /// \brief True if this is an implicit access, i.e. one in which the /// member being accessed was not written in the source. The source @@ -2147,7 +2390,7 @@ public: return getExplicitTemplateArgs().RAngleLoc; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { SourceRange Range; if (!isImplicitAccess()) Range.setBegin(Base->getSourceRange().getBegin()); @@ -2169,8 +2412,13 @@ public: static bool classof(const CXXDependentScopeMemberExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + if (isImplicitAccess()) return child_range(); + return child_range(&Base, &Base + 1); + } + + friend class ASTStmtReader; + friend class ASTStmtWriter; }; /// \brief Represents a C++ member access expression for which lookup @@ -2206,8 +2454,7 @@ class UnresolvedMemberExpr : public OverloadExpr { /// \brief The location of the '->' or '.' operator. SourceLocation OperatorLoc; - UnresolvedMemberExpr(ASTContext &C, QualType T, bool Dependent, - bool HasUnresolvedUsing, + UnresolvedMemberExpr(ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, @@ -2222,7 +2469,7 @@ class UnresolvedMemberExpr : public OverloadExpr { public: static UnresolvedMemberExpr * - Create(ASTContext &C, bool Dependent, bool HasUnresolvedUsing, + Create(ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, @@ -2232,7 +2479,8 @@ public: UnresolvedSetIterator Begin, UnresolvedSetIterator End); static UnresolvedMemberExpr * - CreateEmpty(ASTContext &C, unsigned NumTemplateArgs); + CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs, + unsigned NumTemplateArgs); /// \brief True if this is an implicit access, i.e. one in which the /// member being accessed was not written in the source. The source @@ -2337,7 +2585,7 @@ public: return getExplicitTemplateArgs().RAngleLoc; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { SourceRange Range = getMemberNameInfo().getSourceRange(); if (!isImplicitAccess()) Range.setBegin(Base->getSourceRange().getBegin()); @@ -2355,10 +2603,130 @@ public: static bool classof(const UnresolvedMemberExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + if (isImplicitAccess()) return child_range(); + return child_range(&Base, &Base + 1); + } +}; + +/// \brief Represents a C++0x noexcept expression (C++ [expr.unary.noexcept]). +/// +/// The noexcept expression tests whether a given expression might throw. Its +/// result is a boolean constant. +class CXXNoexceptExpr : public Expr { + bool Value : 1; + Stmt *Operand; + SourceRange Range; + + friend class ASTStmtReader; + +public: + CXXNoexceptExpr(QualType Ty, Expr *Operand, CanThrowResult Val, + SourceLocation Keyword, SourceLocation RParen) + : Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary, + /*TypeDependent*/false, + /*ValueDependent*/Val == CT_Dependent, + Operand->containsUnexpandedParameterPack()), + Value(Val == CT_Cannot), Operand(Operand), Range(Keyword, RParen) + { } + + CXXNoexceptExpr(EmptyShell Empty) + : Expr(CXXNoexceptExprClass, Empty) + { } + + Expr *getOperand() const { return static_cast<Expr*>(Operand); } + + SourceRange getSourceRange() const { return Range; } + + bool getValue() const { return Value; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXNoexceptExprClass; + } + static bool classof(const CXXNoexceptExpr *) { return true; } + + // Iterators + child_range children() { return child_range(&Operand, &Operand + 1); } }; +/// \brief Represents a C++0x pack expansion that produces a sequence of +/// expressions. +/// +/// A pack expansion expression contains a pattern (which itself is an +/// expression) followed by an ellipsis. For example: +/// +/// \code +/// template<typename F, typename ...Types> +/// void forward(F f, Types &&...args) { +/// f(static_cast<Types&&>(args)...); +/// } +/// \endcode +/// +/// Here, the argument to the function object \c f is a pack expansion whose +/// pattern is \c static_cast<Types&&>(args). When the \c forward function +/// template is instantiated, the pack expansion will instantiate to zero or +/// or more function arguments to the function object \c f. +class PackExpansionExpr : public Expr { + SourceLocation EllipsisLoc; + + /// \brief The number of expansions that will be produced by this pack + /// expansion expression, if known. + /// + /// When zero, the number of expansions is not known. Otherwise, this value + /// is the number of expansions + 1. + unsigned NumExpansions; + + Stmt *Pattern; + + friend class ASTStmtReader; + friend class ASTStmtWriter; + +public: + PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc, + llvm::Optional<unsigned> NumExpansions) + : Expr(PackExpansionExprClass, T, Pattern->getValueKind(), + Pattern->getObjectKind(), /*TypeDependent=*/true, + /*ValueDependent=*/true, /*ContainsUnexpandedParameterPack=*/false), + EllipsisLoc(EllipsisLoc), + NumExpansions(NumExpansions? *NumExpansions + 1 : 0), + Pattern(Pattern) { } + + PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) { } + + /// \brief Retrieve the pattern of the pack expansion. + Expr *getPattern() { return reinterpret_cast<Expr *>(Pattern); } + + /// \brief Retrieve the pattern of the pack expansion. + const Expr *getPattern() const { return reinterpret_cast<Expr *>(Pattern); } + + /// \brief Retrieve the location of the ellipsis that describes this pack + /// expansion. + SourceLocation getEllipsisLoc() const { return EllipsisLoc; } + + /// \brief Determine the number of expansions that will be produced when + /// this pack expansion is instantiated, if already known. + llvm::Optional<unsigned> getNumExpansions() const { + if (NumExpansions) + return NumExpansions - 1; + + return llvm::Optional<unsigned>(); + } + + SourceRange getSourceRange() const { + return SourceRange(Pattern->getLocStart(), EllipsisLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == PackExpansionExprClass; + } + static bool classof(const PackExpansionExpr *) { return true; } + + // Iterators + child_range children() { + return child_range(&Pattern, &Pattern + 1); + } +}; + inline ExplicitTemplateArgumentList &OverloadExpr::getExplicitTemplateArgs() { if (isa<UnresolvedLookupExpr>(this)) return cast<UnresolvedLookupExpr>(this)->getExplicitTemplateArgs(); @@ -2366,6 +2734,159 @@ inline ExplicitTemplateArgumentList &OverloadExpr::getExplicitTemplateArgs() { return cast<UnresolvedMemberExpr>(this)->getExplicitTemplateArgs(); } +/// \brief Represents an expression that computes the length of a parameter +/// pack. +/// +/// \code +/// template<typename ...Types> +/// struct count { +/// static const unsigned value = sizeof...(Types); +/// }; +/// \endcode +class SizeOfPackExpr : public Expr { + /// \brief The location of the 'sizeof' keyword. + SourceLocation OperatorLoc; + + /// \brief The location of the name of the parameter pack. + SourceLocation PackLoc; + + /// \brief The location of the closing parenthesis. + SourceLocation RParenLoc; + + /// \brief The length of the parameter pack, if known. + /// + /// When this expression is value-dependent, the length of the parameter pack + /// is unknown. When this expression is not value-dependent, the length is + /// known. + unsigned Length; + + /// \brief The parameter pack itself. + NamedDecl *Pack; + + friend class ASTStmtReader; + friend class ASTStmtWriter; + +public: + /// \brief Creates a value-dependent expression that computes the length of + /// the given parameter pack. + SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, + SourceLocation PackLoc, SourceLocation RParenLoc) + : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary, + /*TypeDependent=*/false, /*ValueDependent=*/true, + /*ContainsUnexpandedParameterPack=*/false), + OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc), + Length(0), Pack(Pack) { } + + /// \brief Creates an expression that computes the length of + /// the given parameter pack, which is already known. + SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, + SourceLocation PackLoc, SourceLocation RParenLoc, + unsigned Length) + : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary, + /*TypeDependent=*/false, /*ValueDependent=*/false, + /*ContainsUnexpandedParameterPack=*/false), + OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc), + Length(Length), Pack(Pack) { } + + /// \brief Create an empty expression. + SizeOfPackExpr(EmptyShell Empty) : Expr(SizeOfPackExprClass, Empty) { } + + /// \brief Determine the location of the 'sizeof' keyword. + SourceLocation getOperatorLoc() const { return OperatorLoc; } + + /// \brief Determine the location of the parameter pack. + SourceLocation getPackLoc() const { return PackLoc; } + + /// \brief Determine the location of the right parenthesis. + SourceLocation getRParenLoc() const { return RParenLoc; } + + /// \brief Retrieve the parameter pack. + NamedDecl *getPack() const { return Pack; } + + /// \brief Retrieve the length of the parameter pack. + /// + /// This routine may only be invoked when the expression is not + /// value-dependent. + unsigned getPackLength() const { + assert(!isValueDependent() && + "Cannot get the length of a value-dependent pack size expression"); + return Length; + } + + SourceRange getSourceRange() const { + return SourceRange(OperatorLoc, RParenLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SizeOfPackExprClass; + } + static bool classof(const SizeOfPackExpr *) { return true; } + + // Iterators + child_range children() { return child_range(); } +}; + +/// \brief Represents a reference to a non-type template parameter pack that +/// has been substituted with a non-template argument pack. +/// +/// When a pack expansion in the source code contains multiple parameter packs +/// and those parameter packs correspond to different levels of template +/// parameter lists, this node node is used to represent a non-type template +/// parameter pack from an outer level, which has already had its argument pack +/// substituted but that still lives within a pack expansion that itself +/// could not be instantiated. When actually performing a substitution into +/// that pack expansion (e.g., when all template parameters have corresponding +/// arguments), this type will be replaced with the appropriate underlying +/// expression at the current pack substitution index. +class SubstNonTypeTemplateParmPackExpr : public Expr { + /// \brief The non-type template parameter pack itself. + NonTypeTemplateParmDecl *Param; + + /// \brief A pointer to the set of template arguments that this + /// parameter pack is instantiated with. + const TemplateArgument *Arguments; + + /// \brief The number of template arguments in \c Arguments. + unsigned NumArguments; + + /// \brief The location of the non-type template parameter pack reference. + SourceLocation NameLoc; + + friend class ASTStmtReader; + friend class ASTStmtWriter; + +public: + SubstNonTypeTemplateParmPackExpr(QualType T, + NonTypeTemplateParmDecl *Param, + SourceLocation NameLoc, + const TemplateArgument &ArgPack); + + SubstNonTypeTemplateParmPackExpr(EmptyShell Empty) + : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) { } + + /// \brief Retrieve the non-type template parameter pack being substituted. + NonTypeTemplateParmDecl *getParameterPack() const { return Param; } + + /// \brief Retrieve the location of the parameter pack name. + SourceLocation getParameterPackLocation() const { return NameLoc; } + + /// \brief Retrieve the template argument pack containing the substituted + /// template arguments. + TemplateArgument getArgumentPack() const; + + SourceRange getSourceRange() const { return NameLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SubstNonTypeTemplateParmPackExprClass; + } + static bool classof(const SubstNonTypeTemplateParmPackExpr *) { + return true; + } + + // Iterators + child_range children() { return child_range(); } +}; + } // end namespace clang #endif diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 8a09f4e9a6a9..285efb757bbb 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -14,14 +14,13 @@ #ifndef LLVM_CLANG_AST_EXPROBJC_H #define LLVM_CLANG_AST_EXPROBJC_H +#include "clang/AST/DeclObjC.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". @@ -30,7 +29,9 @@ class ObjCStringLiteral : public Expr { SourceLocation AtLoc; public: ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L) - : Expr(ObjCStringLiteralClass, T, false, false), String(SL), AtLoc(L) {} + : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false, + false), + String(SL), AtLoc(L) {} explicit ObjCStringLiteral(EmptyShell Empty) : Expr(ObjCStringLiteralClass, Empty) {} @@ -41,7 +42,7 @@ public: SourceLocation getAtLoc() const { return AtLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(AtLoc, String->getLocEnd()); } @@ -51,8 +52,7 @@ public: static bool classof(const ObjCStringLiteral *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&String, &String+1); } }; /// ObjCEncodeExpr, used for @encode in Objective-C. @encode has the same type @@ -64,8 +64,10 @@ class ObjCEncodeExpr : public Expr { public: ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType, SourceLocation at, SourceLocation rp) - : Expr(ObjCEncodeExprClass, T, EncodedType->getType()->isDependentType(), - EncodedType->getType()->isDependentType()), + : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary, + EncodedType->getType()->isDependentType(), + EncodedType->getType()->isDependentType(), + EncodedType->getType()->containsUnexpandedParameterPack()), EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {} explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){} @@ -83,7 +85,7 @@ public: EncodedType = EncType; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(AtLoc, RParenLoc); } @@ -93,8 +95,7 @@ public: static bool classof(const ObjCEncodeExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; /// ObjCSelectorExpr used for @selector in Objective-C. @@ -104,8 +105,9 @@ class ObjCSelectorExpr : public Expr { public: ObjCSelectorExpr(QualType T, Selector selInfo, SourceLocation at, SourceLocation rp) - : Expr(ObjCSelectorExprClass, T, false, false), SelName(selInfo), AtLoc(at), - RParenLoc(rp){} + : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false, + false), + SelName(selInfo), AtLoc(at), RParenLoc(rp){} explicit ObjCSelectorExpr(EmptyShell Empty) : Expr(ObjCSelectorExprClass, Empty) {} @@ -117,7 +119,7 @@ public: void setAtLoc(SourceLocation L) { AtLoc = L; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(AtLoc, RParenLoc); } @@ -130,8 +132,7 @@ public: static bool classof(const ObjCSelectorExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; /// ObjCProtocolExpr used for protocol expression in Objective-C. This is used @@ -144,8 +145,9 @@ class ObjCProtocolExpr : public Expr { public: ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, SourceLocation at, SourceLocation rp) - : Expr(ObjCProtocolExprClass, T, false, false), TheProtocol(protocol), - AtLoc(at), RParenLoc(rp) {} + : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false, + false), + TheProtocol(protocol), AtLoc(at), RParenLoc(rp) {} explicit ObjCProtocolExpr(EmptyShell Empty) : Expr(ObjCProtocolExprClass, Empty) {} @@ -157,7 +159,7 @@ public: void setAtLoc(SourceLocation L) { AtLoc = L; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(AtLoc, RParenLoc); } @@ -167,8 +169,7 @@ public: static bool classof(const ObjCProtocolExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; /// ObjCIvarRefExpr - A reference to an ObjC instance variable. @@ -180,13 +181,13 @@ class ObjCIvarRefExpr : public Expr { bool IsFreeIvar:1; // True if ivar reference has no base (self assumed). public: - ObjCIvarRefExpr(ObjCIvarDecl *d, - QualType t, SourceLocation l, Expr *base, + ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, + SourceLocation l, Expr *base, bool arrow = false, bool freeIvar = false) : - Expr(ObjCIvarRefExprClass, t, /*TypeDependent=*/false, - base->isValueDependent()), D(d), - Loc(l), Base(base), IsArrow(arrow), - IsFreeIvar(freeIvar) {} + Expr(ObjCIvarRefExprClass, t, VK_LValue, OK_Ordinary, + /*TypeDependent=*/false, base->isValueDependent(), + base->containsUnexpandedParameterPack()), + D(d), Loc(l), Base(base), IsArrow(arrow), IsFreeIvar(freeIvar) {} explicit ObjCIvarRefExpr(EmptyShell Empty) : Expr(ObjCIvarRefExprClass, Empty) {} @@ -207,7 +208,7 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return isFreeIvar() ? SourceRange(Loc) : SourceRange(getBase()->getLocStart(), Loc); } @@ -218,8 +219,7 @@ public: static bool classof(const ObjCIvarRefExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&Base, &Base+1); } }; /// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC @@ -227,32 +227,127 @@ public: /// class ObjCPropertyRefExpr : public Expr { private: - ObjCPropertyDecl *AsProperty; + /// If the bool is true, this is an implicit property reference; the + /// pointer is an (optional) ObjCMethodDecl and Setter may be set. + /// if the bool is false, this is an explicit property reference; + /// the pointer is an ObjCPropertyDecl and Setter is always null. + llvm::PointerIntPair<NamedDecl*, 1, bool> PropertyOrGetter; + ObjCMethodDecl *Setter; + SourceLocation IdLoc; - Stmt *Base; + + /// \brief When the receiver in property access is 'super', this is + /// the location of the 'super' keyword. When it's an interface, + /// this is that interface. + SourceLocation ReceiverLoc; + llvm::PointerUnion3<Stmt*, const Type*, ObjCInterfaceDecl*> Receiver; + public: ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, + ExprValueKind VK, ExprObjectKind OK, SourceLocation l, Expr *base) - : Expr(ObjCPropertyRefExprClass, t, /*TypeDependent=*/false, - base->isValueDependent()), - AsProperty(PD), IdLoc(l), Base(base) { + : Expr(ObjCPropertyRefExprClass, t, VK, OK, + /*TypeDependent=*/false, base->isValueDependent(), + base->containsUnexpandedParameterPack()), + PropertyOrGetter(PD, false), Setter(0), + IdLoc(l), ReceiverLoc(), Receiver(base) { + } + + ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, + ExprValueKind VK, ExprObjectKind OK, + SourceLocation l, SourceLocation sl, QualType st) + : Expr(ObjCPropertyRefExprClass, t, VK, OK, + /*TypeDependent=*/false, false, + st->containsUnexpandedParameterPack()), + PropertyOrGetter(PD, false), Setter(0), + IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) { + } + + ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, + QualType T, ExprValueKind VK, ExprObjectKind OK, + SourceLocation IdLoc, Expr *Base) + : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, + Base->isValueDependent(), + Base->containsUnexpandedParameterPack()), + PropertyOrGetter(Getter, true), Setter(Setter), + IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) { + } + + ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, + QualType T, ExprValueKind VK, ExprObjectKind OK, + SourceLocation IdLoc, + SourceLocation SuperLoc, QualType SuperTy) + : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false), + PropertyOrGetter(Getter, true), Setter(Setter), + IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) { + } + + ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, + QualType T, ExprValueKind VK, ExprObjectKind OK, + SourceLocation IdLoc, + SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver) + : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false), + PropertyOrGetter(Getter, true), Setter(Setter), + IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) { } explicit ObjCPropertyRefExpr(EmptyShell Empty) : Expr(ObjCPropertyRefExprClass, Empty) {} - ObjCPropertyDecl *getProperty() const { return AsProperty; } - void setProperty(ObjCPropertyDecl *D) { AsProperty = D; } + bool isImplicitProperty() const { return PropertyOrGetter.getInt(); } + bool isExplicitProperty() const { return !PropertyOrGetter.getInt(); } - const Expr *getBase() const { return cast<Expr>(Base); } - Expr *getBase() { return cast<Expr>(Base); } - void setBase(Expr *base) { Base = base; } + ObjCPropertyDecl *getExplicitProperty() const { + assert(!isImplicitProperty()); + return cast<ObjCPropertyDecl>(PropertyOrGetter.getPointer()); + } + + ObjCMethodDecl *getImplicitPropertyGetter() const { + assert(isImplicitProperty()); + return cast_or_null<ObjCMethodDecl>(PropertyOrGetter.getPointer()); + } + + ObjCMethodDecl *getImplicitPropertySetter() const { + assert(isImplicitProperty()); + return Setter; + } + + Selector getGetterSelector() const { + if (isImplicitProperty()) + return getImplicitPropertyGetter()->getSelector(); + return getExplicitProperty()->getGetterName(); + } + + Selector getSetterSelector() const { + if (isImplicitProperty()) + return getImplicitPropertySetter()->getSelector(); + return getExplicitProperty()->getSetterName(); + } + + const Expr *getBase() const { + return cast<Expr>(Receiver.get<Stmt*>()); + } + Expr *getBase() { + return cast<Expr>(Receiver.get<Stmt*>()); + } SourceLocation getLocation() const { return IdLoc; } - void setLocation(SourceLocation L) { IdLoc = L; } + + SourceLocation getReceiverLocation() const { return ReceiverLoc; } + QualType getSuperReceiverType() const { + return QualType(Receiver.get<const Type*>(), 0); + } + ObjCInterfaceDecl *getClassReceiver() const { + return Receiver.get<ObjCInterfaceDecl*>(); + } + bool isObjectReceiver() const { return Receiver.is<Stmt*>(); } + bool isSuperReceiver() const { return Receiver.is<const Type*>(); } + bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); } - virtual SourceRange getSourceRange() const { - return SourceRange(getBase()->getLocStart(), IdLoc); + SourceRange getSourceRange() const { + return SourceRange((isObjectReceiver() ? getBase()->getLocStart() + : getReceiverLocation()), + IdLoc); } static bool classof(const Stmt *T) { @@ -261,89 +356,32 @@ public: static bool classof(const ObjCPropertyRefExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); -}; - -/// ObjCImplicitSetterGetterRefExpr - A dot-syntax expression to access two -/// methods; one to set a value to an 'ivar' (Setter) and the other to access -/// an 'ivar' (Setter). -/// An example for use of this AST is: -/// @code -/// @interface Test { } -/// - (Test *)crash; -/// - (void)setCrash: (Test*)value; -/// @end -/// void foo(Test *p1, Test *p2) -/// { -/// p2.crash = p1.crash; // Uses ObjCImplicitSetterGetterRefExpr AST -/// } -/// @endcode -class ObjCImplicitSetterGetterRefExpr : public Expr { - /// Setter - Setter method user declared for setting its 'ivar' to a value - ObjCMethodDecl *Setter; - /// Getter - Getter method user declared for accessing 'ivar' it controls. - ObjCMethodDecl *Getter; - /// Location of the member in the dot syntax notation. This is location - /// of the getter method. - SourceLocation MemberLoc; - // FIXME: Swizzle these into a single pointer. - Stmt *Base; - ObjCInterfaceDecl *InterfaceDecl; - /// Location of the receiver class in the dot syntax notation - /// used to call a class method setter/getter. - SourceLocation ClassLoc; - -public: - ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter, - QualType t, - ObjCMethodDecl *setter, - SourceLocation l, Expr *base) - : Expr(ObjCImplicitSetterGetterRefExprClass, t, /*TypeDependent=*/false, - base->isValueDependent()), - Setter(setter), Getter(getter), MemberLoc(l), Base(base), - InterfaceDecl(0), ClassLoc(SourceLocation()) { - } - ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter, - QualType t, - ObjCMethodDecl *setter, - SourceLocation l, ObjCInterfaceDecl *C, SourceLocation CL) - : Expr(ObjCImplicitSetterGetterRefExprClass, t, false, false), - Setter(setter), Getter(getter), MemberLoc(l), Base(0), InterfaceDecl(C), - ClassLoc(CL) { + child_range children() { + if (Receiver.is<Stmt*>()) { + Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack! + return child_range(begin, begin+1); } - explicit ObjCImplicitSetterGetterRefExpr(EmptyShell Empty) - : Expr(ObjCImplicitSetterGetterRefExprClass, Empty){} - - ObjCMethodDecl *getGetterMethod() const { return Getter; } - ObjCMethodDecl *getSetterMethod() const { return Setter; } - ObjCInterfaceDecl *getInterfaceDecl() const { return InterfaceDecl; } - void setGetterMethod(ObjCMethodDecl *D) { Getter = D; } - void setSetterMethod(ObjCMethodDecl *D) { Setter = D; } - void setInterfaceDecl(ObjCInterfaceDecl *D) { InterfaceDecl = D; } - - virtual SourceRange getSourceRange() const { - if (Base) - return SourceRange(getBase()->getLocStart(), MemberLoc); - return SourceRange(ClassLoc, MemberLoc); - } - const Expr *getBase() const { return cast_or_null<Expr>(Base); } - Expr *getBase() { return cast_or_null<Expr>(Base); } - void setBase(Expr *base) { Base = base; } - - SourceLocation getLocation() const { return MemberLoc; } - void setLocation(SourceLocation L) { MemberLoc = L; } - SourceLocation getClassLoc() const { return ClassLoc; } - void setClassLoc(SourceLocation L) { ClassLoc = L; } + return child_range(); + } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCImplicitSetterGetterRefExprClass; +private: + friend class ASTStmtReader; + void setExplicitProperty(ObjCPropertyDecl *D) { + PropertyOrGetter.setPointer(D); + PropertyOrGetter.setInt(false); + Setter = 0; + } + void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter) { + PropertyOrGetter.setPointer(Getter); + PropertyOrGetter.setInt(true); + this->Setter = Setter; } - static bool classof(const ObjCImplicitSetterGetterRefExpr *) { return true; } + void setBase(Expr *Base) { Receiver = Base; } + void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); } + void setClassReceiver(ObjCInterfaceDecl *D) { Receiver = D; } - // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + void setLocation(SourceLocation L) { IdLoc = L; } + void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; } }; /// \brief An expression that sends a message to the given Objective-C @@ -396,6 +434,9 @@ class ObjCMessageExpr : public Expr { /// referring to the method that we type-checked against. uintptr_t SelectorOrMethod; + /// \brief Location of the selector. + SourceLocation SelectorLoc; + /// \brief The source locations of the open and close square /// brackets ('[' and ']', respectively). SourceLocation LBracLoc, RBracLoc; @@ -404,26 +445,29 @@ class ObjCMessageExpr : public Expr { : Expr(ObjCMessageExprClass, Empty), NumArgs(NumArgs), Kind(0), HasMethod(0), SelectorOrMethod(0) { } - ObjCMessageExpr(QualType T, + ObjCMessageExpr(QualType T, ExprValueKind VK, SourceLocation LBracLoc, SourceLocation SuperLoc, bool IsInstanceSuper, QualType SuperType, Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc); - ObjCMessageExpr(QualType T, + ObjCMessageExpr(QualType T, ExprValueKind VK, SourceLocation LBracLoc, TypeSourceInfo *Receiver, Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc); - ObjCMessageExpr(QualType T, + ObjCMessageExpr(QualType T, ExprValueKind VK, SourceLocation LBracLoc, Expr *Receiver, Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc); @@ -458,6 +502,10 @@ public: /// /// \param T The result type of this message. /// + /// \param VK The value kind of this message. A message returning + /// a l-value or r-value reference will be an l-value or x-value, + /// respectively. + /// /// \param LBrac The location of the open square bracket '['. /// /// \param SuperLoc The location of the "super" keyword. @@ -475,12 +523,14 @@ public: /// \param NumArgs The number of arguments. /// /// \param RBracLoc The location of the closing square bracket ']'. - static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + ExprValueKind VK, SourceLocation LBracLoc, SourceLocation SuperLoc, bool IsInstanceSuper, QualType SuperType, Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc); @@ -491,6 +541,10 @@ public: /// /// \param T The result type of this message. /// + /// \param VK The value kind of this message. A message returning + /// a l-value or r-value reference will be an l-value or x-value, + /// respectively. + /// /// \param LBrac The location of the open square bracket '['. /// /// \param Receiver The type of the receiver, including @@ -507,9 +561,11 @@ public: /// /// \param RBracLoc The location of the closing square bracket ']'. static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + ExprValueKind VK, SourceLocation LBracLoc, TypeSourceInfo *Receiver, Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc); @@ -520,6 +576,10 @@ public: /// /// \param T The result type of this message. /// + /// \param VK The value kind of this message. A message returning + /// a l-value or r-value reference will be an l-value or x-value, + /// respectively. + /// /// \param LBrac The location of the open square bracket '['. /// /// \param Receiver The expression used to produce the object that @@ -536,9 +596,11 @@ public: /// /// \param RBracLoc The location of the closing square bracket ']'. static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + ExprValueKind VK, SourceLocation LBracLoc, Expr *Receiver, Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc); @@ -556,6 +618,9 @@ public: /// sent to. ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; } + /// \brief Source range of the receiver. + SourceRange getReceiverRange() const; + /// \brief Determine whether this is an instance message to either a /// computed object or to super. bool isInstanceMessage() const { @@ -682,11 +747,11 @@ public: /// \brief Retrieve the arguments to this message, not including the /// receiver. - Stmt **getArgs() { - return reinterpret_cast<Stmt **>(this + 1) + 1; + Expr **getArgs() { + return reinterpret_cast<Expr **>(this + 1) + 1; } - const Stmt * const *getArgs() const { - return reinterpret_cast<const Stmt * const *>(this + 1) + 1; + const Expr * const *getArgs() const { + return reinterpret_cast<const Expr * const *>(this + 1) + 1; } /// getArg - Return the specified argument. @@ -706,15 +771,13 @@ public: SourceLocation getLeftLoc() const { return LBracLoc; } SourceLocation getRightLoc() const { return RBracLoc; } - - void setLeftLoc(SourceLocation L) { LBracLoc = L; } - void setRightLoc(SourceLocation L) { RBracLoc = L; } + SourceLocation getSelectorLoc() const { return SelectorLoc; } void setSourceRange(SourceRange R) { LBracLoc = R.getBegin(); RBracLoc = R.getEnd(); } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(LBracLoc, RBracLoc); } @@ -724,43 +787,24 @@ public: static bool classof(const ObjCMessageExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children(); typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; - arg_iterator arg_begin() { return getArgs(); } - arg_iterator arg_end() { return getArgs() + NumArgs; } - const_arg_iterator arg_begin() const { return getArgs(); } - const_arg_iterator arg_end() const { return getArgs() + NumArgs; } -}; - -/// ObjCSuperExpr - Represents the "super" expression in Objective-C, -/// which refers to the object on which the current method is executing. -/// -/// FIXME: This class is intended for removal, once its remaining -/// clients have been altered to represent "super" internally. -class ObjCSuperExpr : public Expr { - SourceLocation Loc; -public: - ObjCSuperExpr(SourceLocation L, QualType Type) - : Expr(ObjCSuperExprClass, Type, false, false), 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; + arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); } + arg_iterator arg_end() { + return reinterpret_cast<Stmt **>(getArgs() + NumArgs); + } + const_arg_iterator arg_begin() const { + return reinterpret_cast<Stmt const * const*>(getArgs()); + } + const_arg_iterator arg_end() const { + return reinterpret_cast<Stmt const * const*>(getArgs() + NumArgs); } - static bool classof(const ObjCSuperExpr *) { return true; } - // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + friend class ASTStmtReader; + friend class ASTStmtWriter; }; /// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type. @@ -776,8 +820,9 @@ class ObjCIsaExpr : public Expr { bool IsArrow; public: ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty) - : Expr(ObjCIsaExprClass, ty, /*TypeDependent=*/false, - base->isValueDependent()), + : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary, + /*TypeDependent=*/false, base->isValueDependent(), + /*ContainsUnexpandedParameterPack=*/false), Base(base), IsaMemberLoc(l), IsArrow(isarrow) {} /// \brief Build an empty expression. @@ -794,11 +839,11 @@ public: SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; } void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(getBase()->getLocStart(), IsaMemberLoc); } - virtual SourceLocation getExprLoc() const { return IsaMemberLoc; } + SourceLocation getExprLoc() const { return IsaMemberLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCIsaExprClass; @@ -806,8 +851,7 @@ public: static bool classof(const ObjCIsaExpr *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&Base, &Base+1); } }; } // end namespace clang diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index a8ef0053a442..7b23766b0714 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H #define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H +#include "clang/AST/DeclBase.h" #include <cassert> #include <vector> @@ -24,6 +25,7 @@ template <class T> class SmallVectorImpl; namespace clang { class ASTConsumer; +class CXXBaseSpecifier; class Decl; class DeclContext; class DeclContextLookupResult; @@ -32,6 +34,7 @@ class ExternalSemaSource; // layering violation required for downcasting class NamedDecl; class Selector; class Stmt; +class TagDecl; /// \brief Abstract interface for external sources of AST nodes. /// @@ -91,6 +94,10 @@ public: /// FunctionDecl::setLazyBody when building decls. virtual Stmt *GetExternalDeclStmt(uint64_t Offset) = 0; + /// \brief Resolve the offset of a set of C++ base specifiers in the decl + /// stream into an array of specifiers. + virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) = 0; + /// \brief Finds all declarations with the given name in the /// given context. /// @@ -110,12 +117,44 @@ public: virtual void MaterializeVisibleDecls(const DeclContext *DC) = 0; /// \brief Finds all declarations lexically contained within the given - /// DeclContext. + /// DeclContext, after applying an optional filter predicate. + /// + /// \param isKindWeWant a predicate function that returns true if the passed + /// declaration kind is one we are looking for. If NULL, all declarations + /// are returned. /// /// \return true if an error occurred virtual bool FindExternalLexicalDecls(const DeclContext *DC, - llvm::SmallVectorImpl<Decl*> &Result) = 0; + bool (*isKindWeWant)(Decl::Kind), + llvm::SmallVectorImpl<Decl*> &Result) = 0; + + /// \brief Finds all declarations lexically contained within the given + /// DeclContext. + /// + /// \return true if an error occurred + bool FindExternalLexicalDecls(const DeclContext *DC, + llvm::SmallVectorImpl<Decl*> &Result) { + return FindExternalLexicalDecls(DC, 0, Result); + } + + template <typename DeclTy> + bool FindExternalLexicalDeclsBy(const DeclContext *DC, + llvm::SmallVectorImpl<Decl*> &Result) { + return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result); + } + + /// \brief Gives the external AST source an opportunity to complete + /// an incomplete type. + virtual void CompleteType(TagDecl *Tag) {} + /// \brief Gives the external AST source an opportunity to complete an + /// incomplete Objective-C class. + /// + /// This routine will only be invoked if the "externally completed" bit is + /// set on the ObjCInterfaceDecl via the function + /// \c ObjCInterfaceDecl::setExternallyCompleted(). + virtual void CompleteType(ObjCInterfaceDecl *Class) { } + /// \brief Notify ExternalASTSource that we started deserialization of /// a decl or type so until FinishedDeserializing is called there may be /// decls that are initializing. Must be paired with FinishedDeserializing. @@ -227,6 +266,11 @@ typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt> typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl> LazyDeclPtr; +/// \brief A lazy pointer to a set of CXXBaseSpecifiers. +typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, + &ExternalASTSource::GetExternalCXXBaseSpecifiers> + LazyCXXBaseSpecifiersPtr; + } // end namespace clang #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H diff --git a/include/clang/AST/FullExpr.h b/include/clang/AST/FullExpr.h deleted file mode 100644 index 6ceefed8a63a..000000000000 --- a/include/clang/AST/FullExpr.h +++ /dev/null @@ -1,88 +0,0 @@ -//===--- FullExpr.h - C++ full expression class -----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the FullExpr interface, to be used for type safe handling -// of full expressions. -// -// Full expressions are described in C++ [intro.execution]p12. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_FULLEXPR_H -#define LLVM_CLANG_AST_FULLEXPR_H - -#include "llvm/ADT/PointerUnion.h" - -namespace clang { - class ASTContext; - class CXXTemporary; - class Expr; - -class FullExpr { - struct ExprAndTemporaries { - Expr *SubExpr; - - unsigned NumTemps; - - typedef CXXTemporary** temps_iterator; - - temps_iterator temps_begin() { - return reinterpret_cast<CXXTemporary **>(this + 1); - } - temps_iterator temps_end() { - return temps_begin() + NumTemps; - } - }; - - typedef llvm::PointerUnion<Expr *, ExprAndTemporaries *> SubExprTy; - SubExprTy SubExpr; - - FullExpr() { } - -public: - static FullExpr Create(ASTContext &Context, Expr *SubExpr, - CXXTemporary **Temps, unsigned NumTemps); - - Expr *getExpr() { - if (Expr *E = SubExpr.dyn_cast<Expr *>()) - return E; - - return SubExpr.get<ExprAndTemporaries *>()->SubExpr; - } - - const Expr *getExpr() const { - return const_cast<FullExpr*>(this)->getExpr(); - } - - typedef CXXTemporary** temps_iterator; - - temps_iterator temps_begin() { - if (ExprAndTemporaries *ET = SubExpr.dyn_cast<ExprAndTemporaries *>()) - return ET->temps_begin(); - - return 0; - } - temps_iterator temps_end() { - if (ExprAndTemporaries *ET = SubExpr.dyn_cast<ExprAndTemporaries *>()) - return ET->temps_end(); - - return 0; - } - - void *getAsOpaquePtr() const { return SubExpr.getOpaqueValue(); } - - static FullExpr getFromOpaquePtr(void *Ptr) { - FullExpr E; - E.SubExpr = SubExprTy::getFromOpaqueValue(Ptr); - return E; - } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h new file mode 100644 index 000000000000..7af7702027a4 --- /dev/null +++ b/include/clang/AST/Mangle.h @@ -0,0 +1,150 @@ +//===--- Mangle.h - Mangle C++ Names ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines the C++ name mangling interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_MANGLE_H +#define LLVM_CLANG_AST_MANGLE_H + +#include "clang/AST/Type.h" +#include "clang/Basic/ABI.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" + +namespace clang { + class ASTContext; + class BlockDecl; + class CXXConstructorDecl; + class CXXDestructorDecl; + class CXXMethodDecl; + class FunctionDecl; + class NamedDecl; + class ObjCMethodDecl; + class VarDecl; + struct ThisAdjustment; + struct ThunkInfo; + +/// MangleBuffer - a convenient class for storing a name which is +/// either the result of a mangling or is a constant string with +/// external memory ownership. +class MangleBuffer { +public: + void setString(llvm::StringRef Ref) { + String = Ref; + } + + llvm::SmallVectorImpl<char> &getBuffer() { + return Buffer; + } + + llvm::StringRef getString() const { + if (!String.empty()) return String; + return Buffer.str(); + } + + operator llvm::StringRef() const { + return getString(); + } + +private: + llvm::StringRef String; + llvm::SmallString<256> Buffer; +}; + +/// MangleContext - Context for tracking state which persists across multiple +/// calls to the C++ name mangler. +class MangleContext { + ASTContext &Context; + Diagnostic &Diags; + + llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds; + llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds; + +public: + explicit MangleContext(ASTContext &Context, + Diagnostic &Diags) + : Context(Context), Diags(Diags) { } + + virtual ~MangleContext() { } + + ASTContext &getASTContext() const { return Context; } + + Diagnostic &getDiags() const { return Diags; } + + virtual void startNewFunction() { LocalBlockIds.clear(); } + + unsigned getBlockId(const BlockDecl *BD, bool Local) { + llvm::DenseMap<const BlockDecl *, unsigned> &BlockIds + = Local? LocalBlockIds : GlobalBlockIds; + std::pair<llvm::DenseMap<const BlockDecl *, unsigned>::iterator, bool> + Result = BlockIds.insert(std::make_pair(BD, BlockIds.size())); + return Result.first->second; + } + + /// @name Mangler Entry Points + /// @{ + + virtual bool shouldMangleDeclName(const NamedDecl *D) = 0; + virtual void mangleName(const NamedDecl *D, llvm::raw_ostream &)=0; + virtual void mangleThunk(const CXXMethodDecl *MD, + const ThunkInfo &Thunk, + llvm::raw_ostream &) = 0; + virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, + const ThisAdjustment &ThisAdjustment, + llvm::raw_ostream &) = 0; + virtual void mangleReferenceTemporary(const VarDecl *D, + llvm::raw_ostream &) = 0; + virtual void mangleCXXVTable(const CXXRecordDecl *RD, + llvm::raw_ostream &) = 0; + virtual void mangleCXXVTT(const CXXRecordDecl *RD, + llvm::raw_ostream &) = 0; + virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, + const CXXRecordDecl *Type, + llvm::raw_ostream &) = 0; + virtual void mangleCXXRTTI(QualType T, llvm::raw_ostream &) = 0; + virtual void mangleCXXRTTIName(QualType T, llvm::raw_ostream &) = 0; + virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, + llvm::raw_ostream &) = 0; + virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, + llvm::raw_ostream &) = 0; + + void mangleGlobalBlock(const BlockDecl *BD, + llvm::raw_ostream &Out); + void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT, + const BlockDecl *BD, llvm::raw_ostream &Out); + void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT, + const BlockDecl *BD, llvm::raw_ostream &Out); + void mangleBlock(const DeclContext *DC, const BlockDecl *BD, + llvm::raw_ostream &Out); + // Do the right thing. + void mangleBlock(const BlockDecl *BD, llvm::raw_ostream &Out); + + void mangleObjCMethodName(const ObjCMethodDecl *MD, + llvm::raw_ostream &); + + // This is pretty lame. + virtual void mangleItaniumGuardVariable(const VarDecl *D, + llvm::raw_ostream &) { + assert(0 && "Target does not support mangling guard variables"); + } + /// @} +}; + +MangleContext *createItaniumMangleContext(ASTContext &Context, + Diagnostic &Diags); +MangleContext *createMicrosoftMangleContext(ASTContext &Context, + Diagnostic &Diags); + +} + +#endif diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index 3b25f3bb403f..99cc1f268fb2 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -90,7 +90,7 @@ private: /// \brief Either find or insert the given nested name specifier /// mockup in the given context. - static NestedNameSpecifier *FindOrInsert(ASTContext &Context, + static NestedNameSpecifier *FindOrInsert(const ASTContext &Context, const NestedNameSpecifier &Mockup); public: @@ -99,19 +99,19 @@ public: /// The prefix must be dependent, since nested name specifiers /// referencing an identifier are only permitted when the identifier /// cannot be resolved. - static NestedNameSpecifier *Create(ASTContext &Context, + static NestedNameSpecifier *Create(const ASTContext &Context, NestedNameSpecifier *Prefix, IdentifierInfo *II); /// \brief Builds a nested name specifier that names a namespace. - static NestedNameSpecifier *Create(ASTContext &Context, + static NestedNameSpecifier *Create(const ASTContext &Context, NestedNameSpecifier *Prefix, NamespaceDecl *NS); /// \brief Builds a nested name specifier that names a type. - static NestedNameSpecifier *Create(ASTContext &Context, + static NestedNameSpecifier *Create(const ASTContext &Context, NestedNameSpecifier *Prefix, - bool Template, Type *T); + bool Template, const Type *T); /// \brief Builds a specifier that consists of just an identifier. /// @@ -119,11 +119,12 @@ public: /// prefix because the prefix is implied by something outside of the /// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent /// type. - static NestedNameSpecifier *Create(ASTContext &Context, IdentifierInfo *II); + static NestedNameSpecifier *Create(const ASTContext &Context, + IdentifierInfo *II); /// \brief Returns the nested name specifier representing the global /// scope. - static NestedNameSpecifier *GlobalSpecifier(ASTContext &Context); + static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context); /// \brief Return the prefix of this nested name specifier. /// @@ -160,10 +161,10 @@ public: } /// \brief Retrieve the type stored in this nested name specifier. - Type *getAsType() const { + const Type *getAsType() const { if (Prefix.getInt() == TypeSpec || Prefix.getInt() == TypeSpecWithTemplate) - return (Type *)Specifier; + return (const Type *)Specifier; return 0; } @@ -172,6 +173,10 @@ public: /// type or not. bool isDependent() const; + /// \brief Whether this nested-name-specifier contains an unexpanded + /// parameter pack (for C++0x variadic templates). + bool containsUnexpandedParameterPack() const; + /// \brief Print this nested name specifier to the given output /// stream. void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const; diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index 804531192971..35c72c45ce7c 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -17,107 +17,238 @@ namespace clang { -/// CastKind - the kind of cast this represents. +/// CastKind - The kind of operation required for a conversion. enum CastKind { - /// CK_Unknown - Unknown cast kind. - /// FIXME: The goal is to get rid of this and make all casts have a - /// kind so that the AST client doesn't have to try to figure out what's - /// going on. - CK_Unknown, + /// CK_Dependent - A conversion which cannot yet be analyzed because + /// either the expression or target type is dependent. These are + /// created only for explicit casts; dependent ASTs aren't required + /// to even approximately type-check. + /// (T*) malloc(sizeof(T)) + /// reinterpret_cast<intptr_t>(A<T>::alloc()); + CK_Dependent, - /// CK_BitCast - Used for reinterpret_cast. + /// CK_BitCast - A conversion which causes a bit pattern of one type + /// to be reinterpreted as a bit pattern of another type. Generally + /// the operands must have equivalent size and unrelated types. + /// + /// The pointer conversion char* -> int* is a bitcast. Many other + /// pointer conversions which are "physically" bitcasts are given + /// special cast kinds. + /// + /// Vector coercions are bitcasts. CK_BitCast, - /// CK_LValueBitCast - Used for reinterpret_cast of expressions to - /// a reference type. + /// CK_LValueBitCast - A conversion which reinterprets the address of + /// an l-value as an l-value of a different kind. Used for + /// reinterpret_casts of l-value expressions to reference types. + /// bool b; reinterpret_cast<char&>(b) = 'a'; CK_LValueBitCast, + + /// CK_LValueToRValue - A conversion which causes the extraction of + /// an r-value from the operand gl-value. The result of an r-value + /// conversion is always unqualified. + CK_LValueToRValue, + + /// CK_GetObjCProperty - A conversion which calls an Objective-C + /// property getter. The operand is an OK_ObjCProperty l-value; the + /// result will generally be an r-value, but could be an ordinary + /// gl-value if the property reference is to an implicit property + /// for a method that returns a reference type. + CK_GetObjCProperty, - /// CK_NoOp - Used for const_cast. + /// CK_NoOp - A conversion which does not affect the type other than + /// (possibly) adding qualifiers. + /// int -> int + /// char** -> const char * const * CK_NoOp, - /// CK_BaseToDerived - Base to derived class casts. + /// CK_BaseToDerived - A conversion from a C++ class pointer/reference + /// to a derived class pointer/reference. + /// B *b = static_cast<B*>(a); CK_BaseToDerived, - /// CK_DerivedToBase - Derived to base class casts. + /// CK_DerivedToBase - A conversion from a C++ class pointer + /// to a base class pointer. + /// A *a = new B(); CK_DerivedToBase, - /// CK_UncheckedDerivedToBase - Derived to base class casts that - /// assume that the derived pointer is not null. + /// CK_UncheckedDerivedToBase - A conversion from a C++ class + /// pointer/reference to a base class that can assume that the + /// derived pointer is not null. + /// const A &a = B(); + /// b->method_from_a(); CK_UncheckedDerivedToBase, - /// CK_Dynamic - Dynamic cast. + /// CK_Dynamic - A C++ dynamic_cast. CK_Dynamic, - /// CK_ToUnion - Cast to union (GCC extension). + /// CK_ToUnion - The GCC cast-to-union extension. + /// int -> union { int x; float y; } + /// float -> union { int x; float y; } CK_ToUnion, /// CK_ArrayToPointerDecay - Array to pointer decay. + /// int[10] -> int* + /// char[5][6] -> char(*)[6] CK_ArrayToPointerDecay, - // CK_FunctionToPointerDecay - Function to pointer decay. + /// CK_FunctionToPointerDecay - Function to pointer decay. + /// void(int) -> void(*)(int) CK_FunctionToPointerDecay, - /// CK_NullToMemberPointer - Null pointer to member pointer. + /// CK_NullToPointer - Null pointer constant to pointer, ObjC + /// pointer, or block pointer. + /// (void*) 0 + /// void (^block)() = 0; + CK_NullToPointer, + + /// CK_NullToMemberPointer - Null pointer constant to member pointer. + /// int A::*mptr = 0; + /// int (A::*fptr)(int) = nullptr; CK_NullToMemberPointer, /// CK_BaseToDerivedMemberPointer - Member pointer in base class to /// member pointer in derived class. + /// int B::*mptr = &A::member; CK_BaseToDerivedMemberPointer, /// CK_DerivedToBaseMemberPointer - Member pointer in derived class to /// member pointer in base class. + /// int A::*mptr = static_cast<int A::*>(&B::member); CK_DerivedToBaseMemberPointer, + /// CK_MemberPointerToBoolean - Member pointer to boolean. A check + /// against the null member pointer. + CK_MemberPointerToBoolean, + /// CK_UserDefinedConversion - Conversion using a user defined type /// conversion function. + /// struct A { operator int(); }; int i = int(A()); CK_UserDefinedConversion, - /// CK_ConstructorConversion - Conversion by constructor + /// CK_ConstructorConversion - Conversion by constructor. + /// struct A { A(int); }; A a = A(10); CK_ConstructorConversion, - /// CK_IntegralToPointer - Integral to pointer + /// CK_IntegralToPointer - Integral to pointer. A special kind of + /// reinterpreting conversion. Applies to normal, ObjC, and block + /// pointers. + /// (char*) 0x1001aab0 + /// reinterpret_cast<int*>(0) CK_IntegralToPointer, - /// CK_PointerToIntegral - Pointer to integral + /// CK_PointerToIntegral - Pointer to integral. A special kind of + /// reinterpreting conversion. Applies to normal, ObjC, and block + /// pointers. + /// (intptr_t) "help!" CK_PointerToIntegral, + + /// CK_PointerToBoolean - Pointer to boolean conversion. A check + /// against null. Applies to normal, ObjC, and block pointers. + CK_PointerToBoolean, - /// CK_ToVoid - Cast to void. + /// CK_ToVoid - Cast to void, discarding the computed value. + /// (void) malloc(2048) CK_ToVoid, - /// CK_VectorSplat - Casting from an integer/floating type to an extended - /// vector type with the same element type as the src type. Splats the - /// src expression into the destination expression. + /// CK_VectorSplat - A conversion from an arithmetic type to a + /// vector of that element type. Fills all elements ("splats") with + /// the source value. + /// __attribute__((ext_vector_type(4))) int v = 5; CK_VectorSplat, - /// CK_IntegralCast - Casting between integral types of different size. + /// CK_IntegralCast - A cast between integral types (other than to + /// boolean). Variously a bitcast, a truncation, a sign-extension, + /// or a zero-extension. + /// long l = 5; + /// (unsigned) i CK_IntegralCast, + /// CK_IntegralToBoolean - Integral to boolean. A check against zero. + /// (bool) i + CK_IntegralToBoolean, + /// CK_IntegralToFloating - Integral to floating point. + /// float f = i; CK_IntegralToFloating, - /// CK_FloatingToIntegral - Floating point to integral. + /// CK_FloatingToIntegral - Floating point to integral. Rounds + /// towards zero, discarding any fractional component. + /// (int) f CK_FloatingToIntegral, + + /// CK_FloatingToBoolean - Floating point to boolean. + /// (bool) f + CK_FloatingToBoolean, /// CK_FloatingCast - Casting between floating types of different size. + /// (double) f + /// (float) ld CK_FloatingCast, - /// CK_MemberPointerToBoolean - Member pointer to boolean - CK_MemberPointerToBoolean, - - /// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c - /// pointer + /// CK_AnyPointerToObjCPointerCast - Casting any other pointer kind + /// to an Objective-C pointer. CK_AnyPointerToObjCPointerCast, - /// CK_AnyPointerToBlockPointerCast - Casting any pointer to block - /// pointer + /// CK_AnyPointerToBlockPointerCast - Casting any other pointer kind + /// to a block pointer. CK_AnyPointerToBlockPointerCast, /// \brief Converting between two Objective-C object types, which /// can occur when performing reference binding to an Objective-C /// object. - CK_ObjCObjectLValueCast + CK_ObjCObjectLValueCast, + + /// \brief A conversion of a floating point real to a floating point + /// complex of the original type. Injects the value as the real + /// component with a zero imaginary component. + /// float -> _Complex float + CK_FloatingRealToComplex, + + /// \brief Converts a floating point complex to floating point real + /// of the source's element type. Just discards the imaginary + /// component. + /// _Complex long double -> long double + CK_FloatingComplexToReal, + + /// \brief Converts a floating point complex to bool by comparing + /// against 0+0i. + CK_FloatingComplexToBoolean, + + /// \brief Converts between different floating point complex types. + /// _Complex float -> _Complex double + CK_FloatingComplexCast, + + /// \brief Converts from a floating complex to an integral complex. + /// _Complex float -> _Complex int + CK_FloatingComplexToIntegralComplex, + + /// \brief Converts from an integral real to an integral complex + /// whose element type matches the source. Injects the value as + /// the real component with a zero imaginary component. + /// long -> _Complex long + CK_IntegralRealToComplex, + + /// \brief Converts an integral complex to an integral real of the + /// source's element type by discarding the imaginary component. + /// _Complex short -> short + CK_IntegralComplexToReal, + + /// \brief Converts an integral complex to bool by comparing against + /// 0+0i. + CK_IntegralComplexToBoolean, + + /// \brief Converts between different integral complex types. + /// _Complex char -> _Complex long long + /// _Complex unsigned int -> _Complex signed int + CK_IntegralComplexCast, + + /// \brief Converts from an integral complex to a floating complex. + /// _Complex unsigned -> _Complex float + CK_IntegralComplexToFloatingComplex }; +#define CK_Invalid ((CastKind) -1) enum BinaryOperatorKind { // Operators listed in order of precedence. diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h index f826e1117b66..9ea5a0930d32 100644 --- a/include/clang/AST/ParentMap.h +++ b/include/clang/AST/ParentMap.h @@ -24,8 +24,14 @@ public: ParentMap(Stmt* ASTRoot); ~ParentMap(); + /// \brief Adds and/or updates the parent/child-relations of the complete + /// stmt tree of S. All children of S including indirect descendants are + /// visited and updated or inserted but not the parents of S. + void addStmt(Stmt* S); + Stmt *getParent(Stmt*) const; Stmt *getParentIgnoreParens(Stmt *) const; + Stmt *getParentIgnoreParenCasts(Stmt *) const; const Stmt *getParent(const Stmt* S) const { return getParent(const_cast<Stmt*>(S)); @@ -35,6 +41,10 @@ public: return getParentIgnoreParens(const_cast<Stmt*>(S)); } + const Stmt *getParentIgnoreParenCasts(const Stmt *S) const { + return getParentIgnoreParenCasts(const_cast<Stmt*>(S)); + } + bool hasParent(Stmt* S) const { return getParent(S) != 0; } diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index 70d65d35fef8..a59c302ffc1e 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -14,6 +14,8 @@ #ifndef LLVM_CLANG_AST_PRETTY_PRINTER_H #define LLVM_CLANG_AST_PRETTY_PRINTER_H +#include "clang/Basic/LangOptions.h" + namespace llvm { class raw_ostream; } @@ -44,7 +46,7 @@ struct PrintingPolicy { unsigned Indentation : 8; /// \brief What language we're printing. - const LangOptions &LangOpts; + const LangOptions LangOpts; /// \brief Whether we should suppress printing of the actual specifiers for /// the given type or declaration. diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 2b3229e8fae9..d7bab80afc5e 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -14,8 +14,9 @@ #ifndef LLVM_CLANG_AST_LAYOUTINFO_H #define LLVM_CLANG_AST_LAYOUTINFO_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/ADT/DenseMap.h" +#include "clang/AST/CharUnits.h" #include "clang/AST/DeclCXX.h" namespace clang { @@ -32,93 +33,41 @@ namespace clang { /// ObjCInterfaceDecl. FIXME - Find appropriate name. /// These objects are managed by ASTContext. class ASTRecordLayout { - /// Size - Size of record in bits. - uint64_t Size; + /// Size - Size of record in characters. + CharUnits Size; - /// DataSize - Size of record in bits without tail padding. - uint64_t DataSize; + /// DataSize - Size of record in characters without tail padding. + CharUnits DataSize; /// FieldOffsets - Array of field offsets in bits. uint64_t *FieldOffsets; - // Alignment - Alignment of record in bits. - unsigned Alignment; + // Alignment - Alignment of record in characters. + CharUnits Alignment; // FieldCount - Number of fields. unsigned FieldCount; -public: - /// PrimaryBaseInfo - Contains info about a primary base. - struct PrimaryBaseInfo { - PrimaryBaseInfo() {} - - PrimaryBaseInfo(const CXXRecordDecl *Base, bool IsVirtual) - : Value(Base, Base && IsVirtual) {} - - /// Value - Points to the primary base. The single-bit value - /// will be non-zero when the primary base is virtual. - llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Value; - - /// getBase - Returns the primary base. - const CXXRecordDecl *getBase() const { return Value.getPointer(); } - - /// isVirtual - Returns whether the primary base is virtual or not. - bool isVirtual() const { return Value.getInt(); } - - friend bool operator==(const PrimaryBaseInfo &X, const PrimaryBaseInfo &Y) { - return X.Value == Y.Value; - } - }; - - /// primary_base_info_iterator - An iterator for iterating the primary base - /// class chain. - class primary_base_info_iterator { - /// Current - The current base class info. - PrimaryBaseInfo Current; - - public: - primary_base_info_iterator() {} - primary_base_info_iterator(PrimaryBaseInfo Info) : Current(Info) {} - - const PrimaryBaseInfo &operator*() const { return Current; } - - primary_base_info_iterator& operator++() { - const CXXRecordDecl *RD = Current.getBase(); - Current = RD->getASTContext().getASTRecordLayout(RD).getPrimaryBaseInfo(); - return *this; - } - - friend bool operator==(const primary_base_info_iterator &X, - const primary_base_info_iterator &Y) { - return X.Current == Y.Current; - } - friend bool operator!=(const primary_base_info_iterator &X, - const primary_base_info_iterator &Y) { - return !(X == Y); - } - }; - -private: /// CXXRecordLayoutInfo - Contains C++ specific layout information. struct CXXRecordLayoutInfo { - /// NonVirtualSize - The non-virtual size (in bits) of an object, which is + /// NonVirtualSize - The non-virtual size (in chars) of an object, which is /// the size of the object without virtual bases. - uint64_t NonVirtualSize; + CharUnits NonVirtualSize; - /// NonVirtualAlign - The non-virtual alignment (in bits) of an object, + /// NonVirtualAlign - The non-virtual alignment (in chars) of an object, /// which is the alignment of the object without virtual bases. - uint64_t NonVirtualAlign; + CharUnits NonVirtualAlign; /// SizeOfLargestEmptySubobject - The size of the largest empty subobject /// (either a base or a member). Will be zero if the class doesn't contain /// any empty subobjects. - uint64_t SizeOfLargestEmptySubobject; + CharUnits SizeOfLargestEmptySubobject; /// PrimaryBase - The primary base info for this record. - PrimaryBaseInfo PrimaryBase; + llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase; /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) - typedef llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsetsMapTy; + typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy; /// BaseOffsets - Contains a map from base classes to their offset. BaseOffsetsMapTy BaseOffsets; @@ -133,35 +82,35 @@ private: friend class ASTContext; - ASTRecordLayout(ASTContext &Ctx, uint64_t size, unsigned alignment, - unsigned datasize, const uint64_t *fieldoffsets, + ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, + CharUnits datasize, const uint64_t *fieldoffsets, unsigned fieldcount); // Constructor for C++ records. typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy; - ASTRecordLayout(ASTContext &Ctx, - uint64_t size, unsigned alignment, uint64_t datasize, + ASTRecordLayout(const ASTContext &Ctx, + CharUnits size, CharUnits alignment, CharUnits datasize, const uint64_t *fieldoffsets, unsigned fieldcount, - uint64_t nonvirtualsize, unsigned nonvirtualalign, - uint64_t SizeOfLargestEmptySubobject, + CharUnits nonvirtualsize, CharUnits nonvirtualalign, + CharUnits SizeOfLargestEmptySubobject, const CXXRecordDecl *PrimaryBase, - bool PrimaryBaseIsVirtual, + bool IsPrimaryBaseVirtual, const BaseOffsetsMapTy& BaseOffsets, const BaseOffsetsMapTy& VBaseOffsets); ~ASTRecordLayout() {} void Destroy(ASTContext &Ctx); - + 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; } + /// getAlignment - Get the record alignment in characters. + CharUnits getAlignment() const { return Alignment; } - /// getSize - Get the record size in bits. - uint64_t getSize() const { return Size; } + /// getSize - Get the record size in characters. + CharUnits getSize() const { return Size; } /// getFieldCount - Get the number of fields in the layout. unsigned getFieldCount() const { return FieldCount; } @@ -174,75 +123,81 @@ public: } /// getDataSize() - Get the record data size, which is the record size - /// without tail padding, in bits. - uint64_t getDataSize() const { + /// without tail padding, in characters. + CharUnits getDataSize() const { return DataSize; } - /// getNonVirtualSize - Get the non-virtual size (in bits) of an object, + /// getNonVirtualSize - Get the non-virtual size (in chars) of an object, /// which is the size of the object without virtual bases. - uint64_t getNonVirtualSize() const { + CharUnits getNonVirtualSize() const { assert(CXXInfo && "Record layout does not have C++ specific info!"); return CXXInfo->NonVirtualSize; } - /// getNonVirtualSize - Get the non-virtual alignment (in bits) of an object, + /// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object, /// which is the alignment of the object without virtual bases. - unsigned getNonVirtualAlign() const { + CharUnits getNonVirtualAlign() const { assert(CXXInfo && "Record layout does not have C++ specific info!"); return CXXInfo->NonVirtualAlign; } - /// getPrimaryBaseInfo - Get the primary base info. - const PrimaryBaseInfo &getPrimaryBaseInfo() const { + /// getPrimaryBase - Get the primary base for this record. + const CXXRecordDecl *getPrimaryBase() const { assert(CXXInfo && "Record layout does not have C++ specific info!"); - return CXXInfo->PrimaryBase; + return CXXInfo->PrimaryBase.getPointer(); } - // FIXME: Migrate off of this function and use getPrimaryBaseInfo directly. - const CXXRecordDecl *getPrimaryBase() const { - return getPrimaryBaseInfo().getBase(); - } + /// isPrimaryBaseVirtual - Get whether the primary base for this record + /// is virtual or not. + bool isPrimaryBaseVirtual() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); - // FIXME: Migrate off of this function and use getPrimaryBaseInfo directly. - bool getPrimaryBaseWasVirtual() const { - return getPrimaryBaseInfo().isVirtual(); + return CXXInfo->PrimaryBase.getInt(); } - /// getBaseClassOffset - Get the offset, in bits, for the given base class. - uint64_t getBaseClassOffset(const CXXRecordDecl *Base) const { + /// getBaseClassOffset - Get the offset, in chars, for the given base class. + CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const { assert(CXXInfo && "Record layout does not have C++ specific info!"); assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!"); return CXXInfo->BaseOffsets[Base]; } - /// getVBaseClassOffset - Get the offset, in bits, for the given base class. - uint64_t getVBaseClassOffset(const CXXRecordDecl *VBase) const { + /// getVBaseClassOffset - Get the offset, in chars, for the given base class. + CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const { assert(CXXInfo && "Record layout does not have C++ specific info!"); assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!"); return CXXInfo->VBaseOffsets[VBase]; } - - uint64_t getSizeOfLargestEmptySubobject() const { + + /// getBaseClassOffsetInBits - Get the offset, in bits, for the given + /// base class. + uint64_t getBaseClassOffsetInBits(const CXXRecordDecl *Base) const { assert(CXXInfo && "Record layout does not have C++ specific info!"); - return CXXInfo->SizeOfLargestEmptySubobject; + assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!"); + + return getBaseClassOffset(Base).getQuantity() * + Base->getASTContext().getCharWidth(); } - primary_base_info_iterator primary_base_begin() const { + /// getVBaseClassOffsetInBits - Get the offset, in bits, for the given + /// base class. + uint64_t getVBaseClassOffsetInBits(const CXXRecordDecl *VBase) const { assert(CXXInfo && "Record layout does not have C++ specific info!"); - - return primary_base_info_iterator(getPrimaryBaseInfo()); + assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!"); + + return getVBaseClassOffset(VBase).getQuantity() * + VBase->getASTContext().getCharWidth(); } - primary_base_info_iterator primary_base_end() const { + CharUnits getSizeOfLargestEmptySubobject() const { assert(CXXInfo && "Record layout does not have C++ specific info!"); - - return primary_base_info_iterator(); + return CXXInfo->SizeOfLargestEmptySubobject; } }; diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 232e47b03ae5..921b799b94b5 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -143,6 +143,10 @@ public: /// \brief Return whether this visitor should recurse into /// template instantiations. bool shouldVisitTemplateInstantiations() const { return false; } + + /// \brief Return whether this visitor should recurse into the types of + /// TypeLocs. + bool shouldWalkTypesOfTypeLocs() const { return true; } /// \brief Recursively visit a statement or expression, by /// dispatching to Traverse*() based on the argument's dynamic type. @@ -211,7 +215,7 @@ public: /// be overridden for clients that need access to the name. /// /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseConstructorInitializer(CXXBaseOrMemberInitializer *Init); + bool TraverseConstructorInitializer(CXXCtorInitializer *Init); // ---- Methods on Stmts ---- @@ -368,7 +372,7 @@ private: bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); bool TraverseClassInstantiations(ClassTemplateDecl* D, Decl *Pattern); bool TraverseFunctionInstantiations(FunctionTemplateDecl* D) ; - bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, + bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, unsigned Count); bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); bool TraverseRecordHelper(RecordDecl *D); @@ -393,7 +397,7 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) { if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { switch (BinOp->getOpcode()) { #define OPERATOR(NAME) \ - case BO_##NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S); + case BO_##NAME: DISPATCH(Bin##NAME, BinaryOperator, S); BINOP_LIST() #undef OPERATOR @@ -438,7 +442,8 @@ bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) { switch (T->getTypeClass()) { #define ABSTRACT_TYPE(CLASS, BASE) #define TYPE(CLASS, BASE) \ - case Type::CLASS: DISPATCH(CLASS##Type, CLASS##Type, T.getTypePtr()); + case Type::CLASS: DISPATCH(CLASS##Type, CLASS##Type, \ + const_cast<Type*>(T.getTypePtr())); #include "clang/AST/TypeNodes.def" } @@ -531,7 +536,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument( return getDerived().TraverseType(Arg.getAsType()); case TemplateArgument::Template: - return getDerived().TraverseTemplateName(Arg.getAsTemplate()); + case TemplateArgument::TemplateExpansion: + return getDerived().TraverseTemplateName( + Arg.getAsTemplateOrTemplatePattern()); case TemplateArgument::Expression: return getDerived().TraverseStmt(Arg.getAsExpr()); @@ -566,7 +573,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( } case TemplateArgument::Template: - return getDerived().TraverseTemplateName(Arg.getAsTemplate()); + case TemplateArgument::TemplateExpansion: + return getDerived().TraverseTemplateName( + Arg.getAsTemplateOrTemplatePattern()); case TemplateArgument::Expression: return getDerived().TraverseStmt(ArgLoc.getSourceExpression()); @@ -592,7 +601,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments( template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer( - CXXBaseOrMemberInitializer *Init) { + CXXCtorInitializer *Init) { // FIXME: recurse on TypeLoc of the base initializer if isBaseInitializer()? if (Init->isWritten()) TRY_TO(TraverseStmt(Init->getInit())); @@ -706,10 +715,15 @@ DEF_TRAVERSE_TYPE(DecltypeType, { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) +DEF_TRAVERSE_TYPE(AutoType, { + TRY_TO(TraverseType(T->getDeducedType())); + }) + DEF_TRAVERSE_TYPE(RecordType, { }) DEF_TRAVERSE_TYPE(EnumType, { }) DEF_TRAVERSE_TYPE(TemplateTypeParmType, { }) DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, { }) +DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, { }) DEF_TRAVERSE_TYPE(TemplateSpecializationType, { TRY_TO(TraverseTemplateName(T->getTemplateName())); @@ -718,6 +732,14 @@ DEF_TRAVERSE_TYPE(TemplateSpecializationType, { DEF_TRAVERSE_TYPE(InjectedClassNameType, { }) +DEF_TRAVERSE_TYPE(AttributedType, { + TRY_TO(TraverseType(T->getModifiedType())); + }) + +DEF_TRAVERSE_TYPE(ParenType, { + TRY_TO(TraverseType(T->getInnerType())); + }) + DEF_TRAVERSE_TYPE(ElaboratedType, { if (T->getQualifier()) { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); @@ -734,6 +756,10 @@ DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, { TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); }) +DEF_TRAVERSE_TYPE(PackExpansionType, { + TRY_TO(TraverseType(T->getPattern())); + }) + DEF_TRAVERSE_TYPE(ObjCInterfaceType, { }) DEF_TRAVERSE_TYPE(ObjCObjectType, { @@ -752,14 +778,15 @@ DEF_TRAVERSE_TYPE(ObjCObjectPointerType, { // ----------------- TypeLoc traversal ----------------- // This macro makes available a variable TL, the passed-in TypeLoc. -// It calls WalkUpFrom* for the Type in the given TypeLoc, in addition -// to WalkUpFrom* for the TypeLoc itself, such that existing clients -// that override the WalkUpFrom*Type() and/or Visit*Type() methods +// If requested, it calls WalkUpFrom* for the Type in the given TypeLoc, +// in addition to WalkUpFrom* for the TypeLoc itself, such that existing +// clients that override the WalkUpFrom*Type() and/or Visit*Type() methods // continue to work. #define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \ template<typename Derived> \ bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \ - TRY_TO(WalkUpFrom##TYPE(TL.getTypePtr())); \ + if (getDerived().shouldWalkTypesOfTypeLocs()) \ + TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE*>(TL.getTypePtr()))); \ TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ { CODE; } \ return true; \ @@ -867,22 +894,16 @@ DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, { TRY_TO(TraverseTypeLoc(TL.getResultLoc())); }) -// FIXME: location of arguments, exception specifications (attributes?) -// Note that we have the ParmVarDecl's here. Do we want to use them? +// FIXME: location of exception specifications (attributes?) DEF_TRAVERSE_TYPELOC(FunctionProtoType, { TRY_TO(TraverseTypeLoc(TL.getResultLoc())); - FunctionProtoType *T = TL.getTypePtr(); -/* + const FunctionProtoType *T = TL.getTypePtr(); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { TRY_TO(TraverseDecl(TL.getArg(I))); } -*/ - for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(), - AEnd = T->arg_type_end(); - A != AEnd; ++A) { - TRY_TO(TraverseType(*A)); - } + for (FunctionProtoType::exception_iterator E = T->exception_begin(), EEnd = T->exception_end(); E != EEnd; ++E) { @@ -906,10 +927,15 @@ DEF_TRAVERSE_TYPELOC(DecltypeType, { TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr())); }) +DEF_TRAVERSE_TYPELOC(AutoType, { + TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); + }) + DEF_TRAVERSE_TYPELOC(RecordType, { }) DEF_TRAVERSE_TYPELOC(EnumType, { }) DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, { }) DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, { }) +DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, { }) // FIXME: use the loc for the template name? DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, { @@ -921,6 +947,14 @@ DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, { DEF_TRAVERSE_TYPELOC(InjectedClassNameType, { }) +DEF_TRAVERSE_TYPELOC(ParenType, { + TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); + }) + +DEF_TRAVERSE_TYPELOC(AttributedType, { + TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); + }) + // FIXME: use the sourceloc on qualifier? DEF_TRAVERSE_TYPELOC(ElaboratedType, { if (TL.getTypePtr()->getQualifier()) { @@ -941,6 +975,10 @@ DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { } }) +DEF_TRAVERSE_TYPELOC(PackExpansionType, { + TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); + }) + DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, { }) DEF_TRAVERSE_TYPELOC(ObjCObjectType, { @@ -1001,11 +1039,18 @@ DEF_TRAVERSE_DECL(FileScopeAsmDecl, { }) DEF_TRAVERSE_DECL(FriendDecl, { - TRY_TO(TraverseDecl(D->getFriendDecl())); + // Friend is either decl or a type. + if (D->getFriendType()) + TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); + else + TRY_TO(TraverseDecl(D->getFriendDecl())); }) DEF_TRAVERSE_DECL(FriendTemplateDecl, { - TRY_TO(TraverseDecl(D->getFriendDecl())); + if (D->getFriendType()) + TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); + else + TRY_TO(TraverseDecl(D->getFriendDecl())); for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) { TemplateParameterList *TPL = D->getTemplateParameterList(I); for (TemplateParameterList::iterator ITPL = TPL->begin(), @@ -1051,6 +1096,11 @@ DEF_TRAVERSE_DECL(NamespaceAliasDecl, { return true; }) +DEF_TRAVERSE_DECL(LabelDecl, { + // There is no code in a LabelDecl. +}) + + DEF_TRAVERSE_DECL(NamespaceDecl, { // Code in an unnamed namespace shows up automatically in // decls_begin()/decls_end(). Thus we don't need to recurse on @@ -1082,7 +1132,9 @@ DEF_TRAVERSE_DECL(ObjCProtocolDecl, { }) DEF_TRAVERSE_DECL(ObjCMethodDecl, { - // FIXME: implement + // We don't traverse nodes in param_begin()/param_end(), as they + // appear in decls_begin()/decls_end() and thus are handled. + TRY_TO(TraverseStmt(D->getBody())); }) DEF_TRAVERSE_DECL(ObjCPropertyDecl, { @@ -1175,7 +1227,7 @@ DEF_TRAVERSE_DECL(ClassTemplateDecl, { if (D->isThisDeclarationADefinition()) TRY_TO(TraverseClassInstantiations(D, D)); } - + // Note that getInstantiatedFromMemberTemplate() is just a link // from a template instantiation back to the template from which // it was instantiated, and thus should not be traversed. @@ -1208,10 +1260,10 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations( assert(false && "Unknown specialization kind."); } } - + return true; } - + DEF_TRAVERSE_DECL(FunctionTemplateDecl, { TRY_TO(TraverseDecl(D->getTemplatedDecl())); TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); @@ -1251,7 +1303,7 @@ DEF_TRAVERSE_DECL(TemplateTypeParmDecl, { }) DEF_TRAVERSE_DECL(TypedefDecl, { - TRY_TO(TraverseType(D->getUnderlyingType())); + TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); // We shouldn't traverse D->getTypeForDecl(); it's a result of // declaring the typedef, not something that was written in the // source. @@ -1282,11 +1334,7 @@ bool RecursiveASTVisitor<Derived>::TraverseRecordHelper( RecordDecl *D) { // We shouldn't traverse D->getTypeForDecl(); it's a result of // declaring the type, not something that was written in the source. - // - // The anonymous struct or union object is the variable or field - // whose type is the anonymous struct or union. We shouldn't - // traverse D->getAnonymousStructOrUnionObject(), as it's not - // something that is explicitly written in the source. + TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); return true; } @@ -1380,6 +1428,8 @@ DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, { TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier())); }) +DEF_TRAVERSE_DECL(IndirectFieldDecl, {}) + template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) { TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); @@ -1412,47 +1462,11 @@ template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); - // Visit the function type itself, which can be either - // FunctionNoProtoType or FunctionProtoType, or a typedef. If it's - // not a Function*ProtoType, then it can't have a body or arguments, - // so we have to do less work. - Type *FuncType = D->getType().getTypePtr(); - if (FunctionProtoType *FuncProto = dyn_cast<FunctionProtoType>(FuncType)) { - if (D->isThisDeclarationADefinition()) { - // Don't call Traverse*, or the result type and parameter types - // will be double counted. - TRY_TO(WalkUpFromFunctionProtoType(FuncProto)); - } else { - // This works around a bug in Clang that does not add the parameters - // to decls_begin/end for function declarations (as opposed to - // definitions): - // http://llvm.org/PR7442 - // We work around this here by traversing the function type. - // This isn't perfect because we don't traverse the default - // values, if any. It also may not interact great with - // templates. But it's the best we can do until the bug is - // fixed. - // FIXME: replace the entire 'if' statement with - // TRY_TO(WalkUpFromFunctionProtoType(FuncProto)); - // when the bug is fixed. - TRY_TO(TraverseFunctionProtoType(FuncProto)); - return true; - } - } else if (FunctionNoProtoType *FuncNoProto = - dyn_cast<FunctionNoProtoType>(FuncType)) { - // Don't call Traverse*, or the result type will be double - // counted. - TRY_TO(WalkUpFromFunctionNoProtoType(FuncNoProto)); - } else { // a typedef type, or who knows what - assert(!D->isThisDeclarationADefinition() && "Unexpected function type"); - TRY_TO(TraverseType(D->getType())); - return true; - } - - TRY_TO(TraverseType(D->getResultType())); - // If we're an explicit template specialization, iterate over the - // template args that were explicitly specified. + // template args that were explicitly specified. If we were doing + // this in typing order, we'd do it between the return type and + // the function args, but both are handled by the FunctionTypeLoc + // above, so we have to choose one side. I've decided to do before. if (const FunctionTemplateSpecializationInfo *FTSI = D->getTemplateSpecializationInfo()) { if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared && @@ -1467,28 +1481,11 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { } } - for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end(); - I != E; ++I) { - TRY_TO(TraverseDecl(*I)); - } - - if (FunctionProtoType *FuncProto = dyn_cast<FunctionProtoType>(FuncType)) { - if (D->isThisDeclarationADefinition()) { - // This would be visited if we called TraverseType(D->getType()) - // above, but we don't (at least, not in the - // declaration-is-a-definition case), in order to avoid duplicate - // visiting for parameters. (We need to check parameters here, - // rather than letting D->getType() do it, so we visit default - // parameter values). So we need to re-do some of the work the - // type would do. - for (FunctionProtoType::exception_iterator - E = FuncProto->exception_begin(), - EEnd = FuncProto->exception_end(); - E != EEnd; ++E) { - TRY_TO(TraverseType(*E)); - } - } - } + // Visit the function type itself, which can be either + // FunctionNoProtoType or FunctionProtoType, or a typedef. This + // also covers the return type and the function parameters, + // including exception specifications. + TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { // Constructor initializers. @@ -1554,7 +1551,7 @@ DEF_TRAVERSE_DECL(ImplicitParamDecl, { DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, { // A non-type template parameter, e.g. "S" in template<int S> class Foo ... - TRY_TO(TraverseVarHelper(D)); + TRY_TO(TraverseDeclaratorHelper(D)); TRY_TO(TraverseStmt(D->getDefaultArgument())); }) @@ -1577,12 +1574,11 @@ DEF_TRAVERSE_DECL(ParmVarDecl, { // ----------------- Stmt traversal ----------------- // // For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating -// over the children defined in child_begin/child_end (every stmt -// defines these, though sometimes the range is empty). Each -// individual Traverse* method only needs to worry about children -// other than those. To see what child_begin()/end() does for a given -// class, see, e.g., -// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html +// over the children defined in children() (every stmt defines these, +// though sometimes the range is empty). Each individual Traverse* +// method only needs to worry about children other than those. To see +// what children() does for a given class, see, e.g., +// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html // This macro makes available a variable S, the passed-in stmt. #define DEF_TRAVERSE_STMT(STMT, CODE) \ @@ -1590,9 +1586,8 @@ template<typename Derived> \ bool RecursiveASTVisitor<Derived>::Traverse##STMT (STMT *S) { \ TRY_TO(WalkUpFrom##STMT(S)); \ { CODE; } \ - for (Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end(); \ - C != CEnd; ++C) { \ - TRY_TO(TraverseStmt(*C)); \ + for (Stmt::child_range range = S->children(); range; ++range) { \ + TRY_TO(TraverseStmt(*range)); \ } \ return true; \ } @@ -1608,12 +1603,12 @@ DEF_TRAVERSE_STMT(AsmStmt, { for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) { TRY_TO(TraverseStmt(S->getClobber(I))); } - // child_begin()/end() iterates over inputExpr and outputExpr. + // children() iterates over inputExpr and outputExpr. }) DEF_TRAVERSE_STMT(CXXCatchStmt, { TRY_TO(TraverseDecl(S->getExceptionDecl())); - // child_begin()/end() iterates over the handler block. + // children() iterates over the handler block. }) DEF_TRAVERSE_STMT(DeclStmt, { @@ -1621,11 +1616,11 @@ DEF_TRAVERSE_STMT(DeclStmt, { I != E; ++I) { TRY_TO(TraverseDecl(*I)); } - // Suppress the default iteration over child_begin/end by + // Suppress the default iteration over children() by // returning. Here's why: A DeclStmt looks like 'type var [= // initializer]'. The decls above already traverse over the // initializers, so we don't have to do it again (which - // child_begin/end would do). + // children() would do). return true; }) @@ -1652,17 +1647,16 @@ DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { }) DEF_TRAVERSE_STMT(ObjCAtTryStmt, { }) DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { }) DEF_TRAVERSE_STMT(ReturnStmt, { }) -DEF_TRAVERSE_STMT(SwitchCase, { }) DEF_TRAVERSE_STMT(SwitchStmt, { }) DEF_TRAVERSE_STMT(WhileStmt, { }) DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { + TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); if (S->hasExplicitTemplateArgs()) { TRY_TO(TraverseTemplateArgumentLocsHelper( S->getTemplateArgs(), S->getNumTemplateArgs())); } - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); }) DEF_TRAVERSE_STMT(DeclRefExpr, { @@ -1695,27 +1689,27 @@ DEF_TRAVERSE_STMT(ImplicitCastExpr, { }) DEF_TRAVERSE_STMT(CStyleCastExpr, { - TRY_TO(TraverseType(S->getTypeAsWritten())); + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); }) DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, { - TRY_TO(TraverseType(S->getTypeAsWritten())); + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); }) DEF_TRAVERSE_STMT(CXXConstCastExpr, { - TRY_TO(TraverseType(S->getTypeAsWritten())); + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); }) DEF_TRAVERSE_STMT(CXXDynamicCastExpr, { - TRY_TO(TraverseType(S->getTypeAsWritten())); + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); }) DEF_TRAVERSE_STMT(CXXReinterpretCastExpr, { - TRY_TO(TraverseType(S->getTypeAsWritten())); + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); }) DEF_TRAVERSE_STMT(CXXStaticCastExpr, { - TRY_TO(TraverseType(S->getTypeAsWritten())); + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); }) // InitListExpr is a tricky one, because we want to do all our work on @@ -1729,9 +1723,8 @@ bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) { S = Syn; TRY_TO(WalkUpFromInitListExpr(S)); // All we need are the default actions. FIXME: use a helper function. - for (Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end(); - C != CEnd; ++C) { - TRY_TO(TraverseStmt(*C)); + for (Stmt::child_range range = S->children(); range; ++range) { + TRY_TO(TraverseStmt(*range)); } return true; } @@ -1739,12 +1732,12 @@ bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) { DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, { // This is called for code like 'return T()' where T is a built-in // (i.e. non-class) type. - if (!S->isImplicit()) - TRY_TO(TraverseType(S->getType())); + TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); }) DEF_TRAVERSE_STMT(CXXNewExpr, { - TRY_TO(TraverseType(S->getAllocatedType())); + // The child-iterator will pick up the other arguments. + TRY_TO(TraverseTypeLoc(S->getAllocatedTypeSourceInfo()->getTypeLoc())); }) DEF_TRAVERSE_STMT(OffsetOfExpr, { @@ -1769,15 +1762,43 @@ DEF_TRAVERSE_STMT(CXXTypeidExpr, { TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc())); }) -DEF_TRAVERSE_STMT(TypesCompatibleExpr, { - TRY_TO(TraverseTypeLoc(S->getArgTInfo1()->getTypeLoc())); - TRY_TO(TraverseTypeLoc(S->getArgTInfo2()->getTypeLoc())); +DEF_TRAVERSE_STMT(CXXUuidofExpr, { + // The child-iterator will pick up the arg if it's an expression, + // but not if it's a type. + if (S->isTypeOperand()) + TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc())); }) DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, { - TRY_TO(TraverseType(S->getQueriedType())); + TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc())); + }) + +DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, { + TRY_TO(TraverseTypeLoc(S->getLhsTypeSourceInfo()->getTypeLoc())); + TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc())); + }) + +DEF_TRAVERSE_STMT(VAArgExpr, { + // The child-iterator will pick up the expression argument. + TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc())); }) +DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { + // This is called for code like 'return T()' where T is a class type. + TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); + }) + +DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { + // This is called for code like 'T()', where T is a template argument. + TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); + }) + +// These expressions all might take explicit template arguments. +// We traverse those if so. FIXME: implement these. +DEF_TRAVERSE_STMT(CXXConstructExpr, { }) +DEF_TRAVERSE_STMT(CallExpr, { }) +DEF_TRAVERSE_STMT(CXXMemberCallExpr, { }) + // These exprs (most of them), do not need any action except iterating // over the children. DEF_TRAVERSE_STMT(AddrLabelExpr, { }) @@ -1790,53 +1811,64 @@ DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { }) DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { }) DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { }) DEF_TRAVERSE_STMT(CXXDeleteExpr, { }) -DEF_TRAVERSE_STMT(CXXExprWithTemporaries, { }) +DEF_TRAVERSE_STMT(ExprWithCleanups, { }) DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { }) -DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { }) +DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { + TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo()) + TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc())); + if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo()) + TRY_TO(TraverseTypeLoc(DestroyedTypeInfo->getTypeLoc())); +}) DEF_TRAVERSE_STMT(CXXThisExpr, { }) DEF_TRAVERSE_STMT(CXXThrowExpr, { }) -DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { }) DEF_TRAVERSE_STMT(DesignatedInitExpr, { }) DEF_TRAVERSE_STMT(ExtVectorElementExpr, { }) DEF_TRAVERSE_STMT(GNUNullExpr, { }) DEF_TRAVERSE_STMT(ImplicitValueInitExpr, { }) DEF_TRAVERSE_STMT(ObjCEncodeExpr, { }) -DEF_TRAVERSE_STMT(ObjCImplicitSetterGetterRefExpr, { }) DEF_TRAVERSE_STMT(ObjCIsaExpr, { }) DEF_TRAVERSE_STMT(ObjCIvarRefExpr, { }) DEF_TRAVERSE_STMT(ObjCMessageExpr, { }) DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { }) DEF_TRAVERSE_STMT(ObjCProtocolExpr, { }) DEF_TRAVERSE_STMT(ObjCSelectorExpr, { }) -DEF_TRAVERSE_STMT(ObjCSuperExpr, { }) DEF_TRAVERSE_STMT(ParenExpr, { }) DEF_TRAVERSE_STMT(ParenListExpr, { }) DEF_TRAVERSE_STMT(PredefinedExpr, { }) DEF_TRAVERSE_STMT(ShuffleVectorExpr, { }) DEF_TRAVERSE_STMT(StmtExpr, { }) -DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { }) -DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { }) -DEF_TRAVERSE_STMT(VAArgExpr, { - // The child-iterator will pick up the expression argument. - TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc())); - }) -DEF_TRAVERSE_STMT(CXXConstructExpr, { }) - -DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { - // This is called for code like 'return T()' where T is a class type. - TRY_TO(TraverseType(S->getType())); - }) +DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { + TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + if (S->hasExplicitTemplateArgs()) { + TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), + S->getNumTemplateArgs())); + } +}) + +DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { + TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + if (S->hasExplicitTemplateArgs()) { + TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), + S->getNumTemplateArgs())); + } +}) -DEF_TRAVERSE_STMT(CallExpr, { }) -DEF_TRAVERSE_STMT(CXXMemberCallExpr, { }) DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { }) +DEF_TRAVERSE_STMT(OpaqueValueExpr, { }) +DEF_TRAVERSE_STMT(CUDAKernelCallExpr, { }) // These operators (all of them) do not need any action except // iterating over the children. +DEF_TRAVERSE_STMT(BinaryConditionalOperator, { }) DEF_TRAVERSE_STMT(ConditionalOperator, { }) DEF_TRAVERSE_STMT(UnaryOperator, { }) DEF_TRAVERSE_STMT(BinaryOperator, { }) DEF_TRAVERSE_STMT(CompoundAssignOperator, { }) +DEF_TRAVERSE_STMT(CXXNoexceptExpr, { }) +DEF_TRAVERSE_STMT(PackExpansionExpr, { }) +DEF_TRAVERSE_STMT(SizeOfPackExpr, { }) +DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { }) // These literals (all of them) do not need any action. DEF_TRAVERSE_STMT(IntegerLiteral, { }) @@ -1861,7 +1893,6 @@ DEF_TRAVERSE_STMT(ObjCStringLiteral, { }) // http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html // http://clang.llvm.org/doxygen/classclang_1_1SizeOfAlignOfExpr.html // http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html -// http://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html // Every class that has getQualifier. #undef DEF_TRAVERSE_STMT diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index ba778293ba2d..e87ca78d635a 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -109,25 +109,7 @@ public: /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the /// first and only declaration. - void setPreviousDeclaration(decl_type *PrevDecl) { - decl_type *First; - - if (PrevDecl) { - // Point to previous. Make sure that this is actually the most recent - // redeclaration, or we can build invalid chains. If the most recent - // redeclaration is invalid, it won't be PrevDecl, but we want it anyway. - RedeclLink = PreviousDeclLink(llvm::cast<decl_type>( - PrevDecl->getMostRecentDeclaration())); - First = PrevDecl->getFirstDeclaration(); - assert(First->RedeclLink.NextIsLatest() && "Expected first"); - } else { - // Make this first. - First = static_cast<decl_type*>(this); - } - - // First one will point to this one as latest. - First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this)); - } + void setPreviousDeclaration(decl_type *PrevDecl); /// \brief Iterates through all the redeclarations of the same decl. class redecl_iterator { diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 62a6b6463df5..7ede9ce323f4 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -20,7 +20,6 @@ #include "clang/AST/PrettyPrinter.h" #include "clang/AST/StmtIterator.h" #include "clang/AST/DeclGroup.h" -#include "clang/AST/FullExpr.h" #include "llvm/ADT/SmallVector.h" #include "clang/AST/ASTContext.h" #include <string> @@ -104,13 +103,7 @@ public: first##BASE##Constant=FIRST##Class, last##BASE##Constant=LAST##Class #define ABSTRACT_STMT(STMT) #include "clang/AST/StmtNodes.inc" -}; -private: - /// \brief The statement class. - const unsigned sClass : 8; - - /// \brief The reference count for this statement. - unsigned RefCount : 24; + }; // Make vanilla 'new' and 'delete' illegal for Stmts. protected: @@ -122,6 +115,77 @@ protected: assert(0 && "Stmts cannot be released with regular 'delete'."); } + class StmtBitfields { + friend class Stmt; + + /// \brief The statement class. + unsigned sClass : 8; + }; + enum { NumStmtBits = 8 }; + + class CompoundStmtBitfields { + friend class CompoundStmt; + unsigned : NumStmtBits; + + unsigned NumStmts : 32 - NumStmtBits; + }; + + class ExprBitfields { + friend class Expr; + friend class DeclRefExpr; // computeDependence + friend class InitListExpr; // ctor + friend class DesignatedInitExpr; // ctor + friend class BlockDeclRefExpr; // ctor + friend class ASTStmtReader; // deserialization + friend class CXXNewExpr; // ctor + friend class DependentScopeDeclRefExpr; // ctor + friend class CXXConstructExpr; // ctor + friend class CallExpr; // ctor + friend class OffsetOfExpr; // ctor + friend class ObjCMessageExpr; // ctor + friend class ShuffleVectorExpr; // ctor + friend class ParenListExpr; // ctor + friend class CXXUnresolvedConstructExpr; // ctor + friend class CXXDependentScopeMemberExpr; // ctor + friend class OverloadExpr; // ctor + unsigned : NumStmtBits; + + unsigned ValueKind : 2; + unsigned ObjectKind : 2; + unsigned TypeDependent : 1; + unsigned ValueDependent : 1; + unsigned ContainsUnexpandedParameterPack : 1; + }; + enum { NumExprBits = 15 }; + + class CastExprBitfields { + friend class CastExpr; + unsigned : NumExprBits; + + unsigned Kind : 6; + unsigned BasePathSize : 32 - 6 - NumExprBits; + }; + + class CallExprBitfields { + friend class CallExpr; + unsigned : NumExprBits; + + unsigned NumPreArgs : 1; + }; + + union { + // FIXME: this is wasteful on 64-bit platforms. + void *Aligner; + + StmtBitfields StmtBits; + CompoundStmtBitfields CompoundStmtBits; + ExprBitfields ExprBits; + CastExprBitfields CastExprBits; + CallExprBitfields CallExprBits; + }; + + friend class ASTStmtReader; + public: // Only allow allocation of Stmts using the allocator in ASTContext // or by doing a placement new. @@ -152,44 +216,27 @@ public: protected: /// \brief Construct an empty statement. - explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC), RefCount(1) { + explicit Stmt(StmtClass SC, EmptyShell) { + StmtBits.sClass = SC; if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); } public: - Stmt(StmtClass SC) : sClass(SC), RefCount(1) { + Stmt(StmtClass SC) { + StmtBits.sClass = SC; if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); } - virtual ~Stmt() {} - -#ifndef NDEBUG - /// \brief True if this statement's refcount is in a valid state. - /// Should be used only in assertions. - bool isRetained() const { - return (RefCount >= 1); - } -#endif - - /// \brief Increases the reference count for this statement. - /// - /// Invoke the Retain() operation when this statement or expression - /// is being shared by another owner. - Stmt *Retain() { - assert(RefCount >= 1); - ++RefCount; - return this; - } StmtClass getStmtClass() const { - assert(RefCount >= 1 && "Referencing already-destroyed statement!"); - return (StmtClass)sClass; + return static_cast<StmtClass>(StmtBits.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; + SourceRange getSourceRange() const; + SourceLocation getLocStart() const { return getSourceRange().getBegin(); } SourceLocation getLocEnd() const { return getSourceRange().getEnd(); } @@ -236,22 +283,25 @@ public: /// 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. + /// Child Iterators: All subclasses must implement 'children' + /// 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; + typedef StmtRange child_range; + typedef ConstStmtRange const_child_range; - const_child_iterator child_begin() const { - return const_child_iterator(const_cast<Stmt*>(this)->child_begin()); + child_range children(); + const_child_range children() const { + return const_cast<Stmt*>(this)->children(); } - const_child_iterator child_end() const { - return const_child_iterator(const_cast<Stmt*>(this)->child_end()); - } + child_iterator child_begin() { return children().first; } + child_iterator child_end() { return children().second; } + + const_child_iterator child_begin() const { return children().first; } + const_child_iterator child_end() const { return children().second; } /// \brief Produce a unique representation of the given statement. /// @@ -265,7 +315,7 @@ public: /// parameters are identified by index/level rather than their /// declaration pointers) or the exact representation of the statement as /// written in the source. - void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical); }; @@ -314,8 +364,10 @@ public: static bool classof(const DeclStmt *) { return true; } // Iterators over subexpressions. - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(child_iterator(DG.begin(), DG.end()), + child_iterator(DG.end(), DG.end())); + } typedef DeclGroupRef::iterator decl_iterator; typedef DeclGroupRef::const_iterator const_decl_iterator; @@ -330,8 +382,16 @@ public: /// class NullStmt : public Stmt { SourceLocation SemiLoc; + + /// \brief Whether the null statement was preceded by an empty macro, e.g: + /// @code + /// #define CALL(x) + /// CALL(0); + /// @endcode + bool LeadingEmptyMacro; public: - NullStmt(SourceLocation L) : Stmt(NullStmtClass), SemiLoc(L) {} + NullStmt(SourceLocation L, bool LeadingEmptyMacro = false) + : Stmt(NullStmtClass), SemiLoc(L), LeadingEmptyMacro(LeadingEmptyMacro) {} /// \brief Build an empty null statement. explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) { } @@ -339,55 +399,66 @@ public: SourceLocation getSemiLoc() const { return SemiLoc; } void setSemiLoc(SourceLocation L) { SemiLoc = L; } - virtual SourceRange getSourceRange() const { return SourceRange(SemiLoc); } + bool hasLeadingEmptyMacro() const { return LeadingEmptyMacro; } + + 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(); + child_range children() { return child_range(); } + + friend class ASTStmtReader; + friend class ASTStmtWriter; }; /// 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) { + CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned NumStmts, + SourceLocation LB, SourceLocation RB) + : Stmt(CompoundStmtClass), LBracLoc(LB), RBracLoc(RB) { + CompoundStmtBits.NumStmts = NumStmts; + if (NumStmts == 0) { Body = 0; return; } Body = new (C) Stmt*[NumStmts]; - memcpy(Body, StmtStart, numStmts * sizeof(*Body)); + memcpy(Body, StmtStart, NumStmts * sizeof(*Body)); } // \brief Build an empty compound statement. explicit CompoundStmt(EmptyShell Empty) - : Stmt(CompoundStmtClass, Empty), Body(0), NumStmts(0) { } + : Stmt(CompoundStmtClass, Empty), Body(0) { + CompoundStmtBits.NumStmts = 0; + } void setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts); - bool body_empty() const { return NumStmts == 0; } - unsigned size() const { return NumStmts; } + bool body_empty() const { return CompoundStmtBits.NumStmts == 0; } + unsigned size() const { return CompoundStmtBits.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; } + body_iterator body_end() { return Body + size(); } + Stmt *body_back() { return !body_empty() ? Body[size()-1] : 0; } + + void setLastStmt(Stmt *S) { + assert(!body_empty() && "setLastStmt"); + Body[size()-1] = S; + } 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; } + const_body_iterator body_end() const { return Body + size(); } + const Stmt *body_back() const { return !body_empty() ? Body[size()-1] : 0; } typedef std::reverse_iterator<body_iterator> reverse_body_iterator; reverse_body_iterator body_rbegin() { @@ -408,7 +479,7 @@ public: return const_reverse_body_iterator(body_begin()); } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(LBracLoc, RBracLoc); } @@ -423,8 +494,9 @@ public: static bool classof(const CompoundStmt *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&Body[0], &Body[0]+CompoundStmtBits.NumStmts); + } }; // SwitchCase is the base class for CaseStmt and DefaultStmt, @@ -443,17 +515,15 @@ public: void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; } - Stmt *getSubStmt() { return v_getSubStmt(); } + Stmt *getSubStmt(); - virtual SourceRange getSourceRange() const { return SourceRange(); } + SourceRange getSourceRange() const { return SourceRange(); } static bool classof(const Stmt *T) { return T->getStmtClass() == CaseStmtClass || - T->getStmtClass() == DefaultStmtClass; + T->getStmtClass() == DefaultStmtClass; } static bool classof(const SwitchCase *) { return true; } -protected: - virtual Stmt* v_getSubStmt() = 0; }; class CaseStmt : public SwitchCase { @@ -463,8 +533,6 @@ class CaseStmt : public SwitchCase { SourceLocation CaseLoc; SourceLocation EllipsisLoc; SourceLocation ColonLoc; - - virtual Stmt* v_getSubStmt() { return getSubStmt(); } public: CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc, SourceLocation ellipsisLoc, SourceLocation colonLoc) @@ -504,7 +572,7 @@ public: void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); } - virtual SourceRange getSourceRange() const { + 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())) @@ -518,15 +586,15 @@ public: static bool classof(const CaseStmt *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&SubExprs[0], &SubExprs[END_EXPR]); + } }; 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), @@ -544,7 +612,7 @@ public: SourceLocation getColonLoc() const { return ColonLoc; } void setColonLoc(SourceLocation L) { ColonLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(DefaultLoc, SubStmt->getLocEnd()); } static bool classof(const Stmt *T) { @@ -553,42 +621,43 @@ public: static bool classof(const DefaultStmt *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&SubStmt, &SubStmt+1); } }; + +/// LabelStmt - Represents a label, which has a substatement. For example: +/// foo: return; +/// class LabelStmt : public Stmt { - IdentifierInfo *Label; + LabelDecl *TheDecl; Stmt *SubStmt; SourceLocation IdentLoc; public: - LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt) - : Stmt(LabelStmtClass), Label(label), - SubStmt(substmt), IdentLoc(IL) {} + LabelStmt(SourceLocation IL, LabelDecl *D, Stmt *substmt) + : Stmt(LabelStmtClass), TheDecl(D), 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; } + LabelDecl *getDecl() const { return TheDecl; } + void setDecl(LabelDecl *D) { TheDecl = D; } 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 { + SourceRange getSourceRange() const { return SourceRange(IdentLoc, SubStmt->getLocEnd()); } + child_range children() { return child_range(&SubStmt, &SubStmt+1); } + 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(); }; @@ -635,22 +704,23 @@ public: SourceLocation getElseLoc() const { return ElseLoc; } void setElseLoc(SourceLocation L) { ElseLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { if (SubExprs[ELSE]) return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd()); else return SourceRange(IfLoc, SubExprs[THEN]->getLocEnd()); } + // Iterators over subexpressions. The iterators will include iterating + // over the initialization expression referenced by the condition variable. + child_range children() { + return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == IfStmtClass; } static bool classof(const IfStmt *) { return true; } - - // Iterators over subexpressions. The iterators will include iterating - // over the initialization expression referenced by the condition variable. - virtual child_iterator child_begin(); - virtual child_iterator child_end(); }; /// SwitchStmt - This represents a 'switch' stmt. @@ -662,6 +732,11 @@ class SwitchStmt : public Stmt { SwitchCase *FirstCase; SourceLocation SwitchLoc; + /// If the SwitchStmt is a switch on an enum value, this records whether + /// all the enum values were covered by CaseStmts. This value is meant to + /// be a hint for possible clients. + unsigned AllEnumCasesCovered : 1; + public: SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond); @@ -705,21 +780,34 @@ public: } void addSwitchCase(SwitchCase *SC) { assert(!SC->getNextSwitchCase() && "case/default already added to a switch"); - SC->Retain(); SC->setNextSwitchCase(FirstCase); FirstCase = SC; } - virtual SourceRange getSourceRange() const { + + /// Set a flag in the SwitchStmt indicating that if the 'switch (X)' is a + /// switch over an enum value then all cases have been explicitly covered. + void setAllEnumCasesCovered() { + AllEnumCasesCovered = 1; + } + + /// Returns true if the SwitchStmt is a switch of an enum value and all cases + /// have been explicitly covered. + bool isAllEnumCasesCovered() const { + return (bool) AllEnumCasesCovered; + } + + SourceRange getSourceRange() const { return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd()); } + // Iterators + child_range children() { + return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); + } + 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(); }; @@ -757,7 +845,7 @@ public: SourceLocation getWhileLoc() const { return WhileLoc; } void setWhileLoc(SourceLocation L) { WhileLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd()); } static bool classof(const Stmt *T) { @@ -766,14 +854,15 @@ public: static bool classof(const WhileStmt *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); + } }; /// DoStmt - This represents a 'do/while' stmt. /// class DoStmt : public Stmt { - enum { COND, BODY, END_EXPR }; + enum { BODY, COND, END_EXPR }; Stmt* SubExprs[END_EXPR]; SourceLocation DoLoc; SourceLocation WhileLoc; @@ -805,7 +894,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(DoLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -814,8 +903,9 @@ public: static bool classof(const DoStmt *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); + } }; @@ -870,7 +960,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); } static bool classof(const Stmt *T) { @@ -879,32 +969,33 @@ public: static bool classof(const ForStmt *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); + } }; /// GotoStmt - This represents a direct goto. /// class GotoStmt : public Stmt { - LabelStmt *Label; + LabelDecl *Label; SourceLocation GotoLoc; SourceLocation LabelLoc; public: - GotoStmt(LabelStmt *label, SourceLocation GL, SourceLocation LL) + GotoStmt(LabelDecl *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; } + LabelDecl *getLabel() const { return Label; } + void setLabel(LabelDecl *D) { Label = D; } 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 { + SourceRange getSourceRange() const { return SourceRange(GotoLoc, LabelLoc); } static bool classof(const Stmt *T) { @@ -913,8 +1004,7 @@ public: static bool classof(const GotoStmt *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; /// IndirectGotoStmt - This represents an indirect goto. @@ -938,11 +1028,18 @@ public: void setStarLoc(SourceLocation L) { StarLoc = L; } SourceLocation getStarLoc() const { return StarLoc; } - Expr *getTarget(); - const Expr *getTarget() const; + Expr *getTarget() { return reinterpret_cast<Expr*>(Target); } + const Expr *getTarget() const {return reinterpret_cast<const Expr*>(Target);} void setTarget(Expr *E) { Target = reinterpret_cast<Stmt*>(E); } - virtual SourceRange getSourceRange() const { + /// getConstantTarget - Returns the fixed target of this indirect + /// goto, if one exists. + LabelDecl *getConstantTarget(); + const LabelDecl *getConstantTarget() const { + return const_cast<IndirectGotoStmt*>(this)->getConstantTarget(); + } + + SourceRange getSourceRange() const { return SourceRange(GotoLoc, Target->getLocEnd()); } @@ -952,8 +1049,7 @@ public: static bool classof(const IndirectGotoStmt *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&Target, &Target+1); } }; @@ -970,7 +1066,7 @@ public: SourceLocation getContinueLoc() const { return ContinueLoc; } void setContinueLoc(SourceLocation L) { ContinueLoc = L; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(ContinueLoc); } @@ -980,8 +1076,7 @@ public: static bool classof(const ContinueStmt *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; /// BreakStmt - This represents a break. @@ -997,7 +1092,7 @@ public: SourceLocation getBreakLoc() const { return BreakLoc; } void setBreakLoc(SourceLocation L) { BreakLoc = L; } - virtual SourceRange getSourceRange() const { return SourceRange(BreakLoc); } + SourceRange getSourceRange() const { return SourceRange(BreakLoc); } static bool classof(const Stmt *T) { return T->getStmtClass() == BreakStmtClass; @@ -1005,8 +1100,7 @@ public: static bool classof(const BreakStmt *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(); } }; @@ -1050,7 +1144,7 @@ public: const VarDecl *getNRVOCandidate() const { return NRVOCandidate; } void setNRVOCandidate(const VarDecl *Var) { NRVOCandidate = Var; } - virtual SourceRange getSourceRange() const; + SourceRange getSourceRange() const; static bool classof(const Stmt *T) { return T->getStmtClass() == ReturnStmtClass; @@ -1058,8 +1152,10 @@ public: static bool classof(const ReturnStmt *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + if (RetExpr) return child_range(&RetExpr, &RetExpr+1); + return child_range(); + } }; /// AsmStmt - This represents a GNU inline-assembly statement extension. @@ -1257,7 +1353,7 @@ public: StringLiteral *getClobber(unsigned i) { return Clobbers[i]; } const StringLiteral *getClobber(unsigned i) const { return Clobbers[i]; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(AsmLoc, RParenLoc); } @@ -1304,10 +1400,9 @@ public: return &Exprs[0] + NumOutputs; } - // Child iterators - - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&Exprs[0], &Exprs[0] + NumOutputs + NumInputs); + } }; } // end namespace clang diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index 0508f35e48e8..f08815fd562d 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -37,7 +37,7 @@ public: CXXCatchStmt(EmptyShell Empty) : Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {} - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(CatchLoc, HandlerBlock->getLocEnd()); } @@ -51,8 +51,7 @@ public: } static bool classof(const CXXCatchStmt *) { return true; } - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&HandlerBlock, &HandlerBlock+1); } friend class ASTStmtReader; }; @@ -84,7 +83,7 @@ public: static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty, unsigned numHandlers); - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(getTryLoc(), getEndLoc()); } @@ -113,8 +112,9 @@ public: } static bool classof(const CXXTryStmt *) { return true; } - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(getStmts(), getStmts() + getNumHandlers() + 1); + } friend class ASTStmtReader; }; diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h index 4da2e3474b1c..851c001adc54 100644 --- a/include/clang/AST/StmtIterator.h +++ b/include/clang/AST/StmtIterator.h @@ -1,4 +1,4 @@ -//===--- StmtIterator.h - Iterators for Statements ------------------------===// +//===--- StmtIterator.h - Iterators for Statements --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,7 +14,7 @@ #ifndef LLVM_CLANG_AST_STMT_ITR_H #define LLVM_CLANG_AST_STMT_ITR_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> #include <cstddef> #include <iterator> @@ -51,11 +51,11 @@ protected: return (RawVAPtr & Flags) == 0; } - VariableArrayType* getVAPtr() const { - return reinterpret_cast<VariableArrayType*>(RawVAPtr & ~Flags); + const VariableArrayType *getVAPtr() const { + return reinterpret_cast<const VariableArrayType*>(RawVAPtr & ~Flags); } - void setVAPtr(VariableArrayType* P) { + void setVAPtr(const VariableArrayType *P) { assert (inDecl() || inDeclGroup() || inSizeOfTypeVA()); RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags); } @@ -68,7 +68,7 @@ protected: StmtIteratorBase(Stmt **s) : stmt(s), decl(0), RawVAPtr(0) {} StmtIteratorBase(Decl *d, Stmt **s); - StmtIteratorBase(VariableArrayType *t); + StmtIteratorBase(const VariableArrayType *t); StmtIteratorBase(Decl **dgi, Decl **dge); StmtIteratorBase() : stmt(0), decl(0), RawVAPtr(0) {} }; @@ -86,7 +86,7 @@ public: StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {} StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {} StmtIteratorImpl(Decl *d, Stmt **s) : StmtIteratorBase(d, s) {} - StmtIteratorImpl(VariableArrayType* t) : StmtIteratorBase(t) {} + StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {} DERIVED& operator++() { if (inDecl() || inDeclGroup()) { @@ -130,7 +130,7 @@ struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> { StmtIterator(Decl** dgi, Decl** dge) : StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {} - StmtIterator(VariableArrayType* t) + StmtIterator(const VariableArrayType *t) : StmtIteratorImpl<StmtIterator,Stmt*&>(t) {} StmtIterator(Decl* D, Stmt **s = 0) @@ -146,6 +146,86 @@ struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator, StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {} }; +/// A range of statement iterators. +/// +/// This class provides some extra functionality beyond std::pair +/// in order to allow the following idiom: +/// for (StmtRange range = stmt->children(); range; ++range) +struct StmtRange : std::pair<StmtIterator,StmtIterator> { + StmtRange() {} + StmtRange(const StmtIterator &begin, const StmtIterator &end) + : std::pair<StmtIterator,StmtIterator>(begin, end) {} + + bool empty() const { return first == second; } + operator bool() const { return !empty(); } + + Stmt *operator->() const { return first.operator->(); } + Stmt *&operator*() const { return first.operator*(); } + + StmtRange &operator++() { + assert(!empty() && "incrementing on empty range"); + ++first; + return *this; + } + + StmtRange operator++(int) { + assert(!empty() && "incrementing on empty range"); + StmtRange copy = *this; + ++first; + return copy; + } + + friend const StmtIterator &begin(const StmtRange &range) { + return range.first; + } + friend const StmtIterator &end(const StmtRange &range) { + return range.second; + } +}; + +/// A range of const statement iterators. +/// +/// This class provides some extra functionality beyond std::pair +/// in order to allow the following idiom: +/// for (ConstStmtRange range = stmt->children(); range; ++range) +struct ConstStmtRange : std::pair<ConstStmtIterator,ConstStmtIterator> { + ConstStmtRange() {} + ConstStmtRange(const ConstStmtIterator &begin, + const ConstStmtIterator &end) + : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {} + ConstStmtRange(const StmtRange &range) + : std::pair<ConstStmtIterator,ConstStmtIterator>(range.first, range.second) + {} + ConstStmtRange(const StmtIterator &begin, const StmtIterator &end) + : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {} + + bool empty() const { return first == second; } + operator bool() const { return !empty(); } + + const Stmt *operator->() const { return first.operator->(); } + const Stmt *operator*() const { return first.operator*(); } + + ConstStmtRange &operator++() { + assert(!empty() && "incrementing on empty range"); + ++first; + return *this; + } + + ConstStmtRange operator++(int) { + assert(!empty() && "incrementing on empty range"); + ConstStmtRange copy = *this; + ++first; + return copy; + } + + friend const ConstStmtIterator &begin(const ConstStmtRange &range) { + return range.first; + } + friend const ConstStmtIterator &end(const ConstStmtRange &range) { + return range.second; + } +}; + } // end namespace clang #endif diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h index 269aa4c6dab2..1800a71f9154 100644 --- a/include/clang/AST/StmtObjC.h +++ b/include/clang/AST/StmtObjC.h @@ -55,7 +55,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); } static bool classof(const Stmt *T) { @@ -64,8 +64,9 @@ public: static bool classof(const ObjCForCollectionStmt *) { return true; } // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&SubExprs[0], &SubExprs[END_EXPR]); + } }; /// ObjCAtCatchStmt - This represents objective-c's @catch statement. @@ -102,7 +103,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(AtCatchLoc, Body->getLocEnd()); } @@ -113,8 +114,7 @@ public: } static bool classof(const ObjCAtCatchStmt *) { return true; } - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&Body, &Body + 1); } }; /// ObjCAtFinallyStmt - This represent objective-c's @finally Statement @@ -133,7 +133,7 @@ public: Stmt *getFinallyBody() { return AtFinallyStmt; } void setFinallyBody(Stmt *S) { AtFinallyStmt = S; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(AtFinallyLoc, AtFinallyStmt->getLocEnd()); } @@ -145,8 +145,9 @@ public: } static bool classof(const ObjCAtFinallyStmt *) { return true; } - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&AtFinallyStmt, &AtFinallyStmt+1); + } }; /// ObjCAtTryStmt - This represent objective-c's over-all @@ -239,15 +240,17 @@ public: getStmts()[1 + NumCatchStmts] = S; } - virtual SourceRange getSourceRange() const; + SourceRange getSourceRange() const; 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(); + child_range children() { + return child_range(getStmts(), + getStmts() + 1 + NumCatchStmts + HasFinally); + } }; /// ObjCAtSynchronizedStmt - This is for objective-c's @synchronized statement. @@ -291,7 +294,7 @@ public: } void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { return SourceRange(AtSynchronizedLoc, getSynchBody()->getLocEnd()); } @@ -300,8 +303,9 @@ public: } static bool classof(const ObjCAtSynchronizedStmt *) { return true; } - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { + return child_range(&SubStmts[0], &SubStmts[0]+END_EXPR); + } }; /// ObjCAtThrowStmt - This represents objective-c's @throw statement. @@ -323,7 +327,7 @@ public: SourceLocation getThrowLoc() { return AtThrowLoc; } void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; } - virtual SourceRange getSourceRange() const { + SourceRange getSourceRange() const { if (Throw) return SourceRange(AtThrowLoc, Throw->getLocEnd()); else @@ -335,8 +339,7 @@ public: } static bool classof(const ObjCAtThrowStmt *) { return true; } - virtual child_iterator child_begin(); - virtual child_iterator child_end(); + child_range children() { return child_range(&Throw, &Throw+1); } }; } // end namespace clang diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 7d5123fb0449..a4e074e083f6 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -23,6 +23,7 @@ namespace llvm { class FoldingSetNodeID; + class raw_ostream; } namespace clang { @@ -30,26 +31,14 @@ namespace clang { class Decl; class DiagnosticBuilder; class Expr; +struct PrintingPolicy; class TypeSourceInfo; /// \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; - struct { - TemplateArgument *Args; - unsigned NumArgs; - bool CopyArgs; - } Args; - }; - public: - /// \brief The type of template argument we're storing. + /// \brief The kind of template argument we're storing. enum ArgKind { /// \brief Represents an empty template argument, e.g., one that has not /// been deduced. @@ -66,16 +55,42 @@ public: /// The template argument is a template name that was provided for a /// template template parameter. Template, + /// The template argument is a pack expansion of a template name that was + /// provided for a template template parameter. + TemplateExpansion, /// The template argument is a value- or type-dependent expression /// stored in an Expr*. Expression, /// The template argument is actually a parameter pack. Arguments are stored /// in the Args struct. Pack - } Kind; + }; + +private: + /// \brief The kind of template argument we're storing. + unsigned Kind; + union { + uintptr_t TypeOrValue; + struct { + char Value[sizeof(llvm::APSInt)]; + void *Type; + } Integer; + struct { + const TemplateArgument *Args; + unsigned NumArgs; + } Args; + struct { + void *Name; + unsigned NumExpansions; + } TemplateArg; + }; + + TemplateArgument(TemplateName, bool); // DO NOT USE + +public: /// \brief Construct an empty, invalid template argument. - TemplateArgument() : TypeOrValue(0), Kind(Null) { } + TemplateArgument() : Kind(Null), TypeOrValue(0) { } /// \brief Construct a template type argument. TemplateArgument(QualType T) : Kind(Type) { @@ -92,6 +107,8 @@ public: /// \brief Construct an integral constant template argument. TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) { + // FIXME: Large integral values will get leaked. Do something + // similar to what we did with IntegerLiteral. new (Integer.Value) llvm::APSInt(Value); Integer.Type = Type.getAsOpaquePtr(); } @@ -102,10 +119,35 @@ public: /// parameters. However, the template name could be a dependent template /// name that ends up being instantiated to a function template whose address /// is taken. - TemplateArgument(TemplateName Name) : Kind(Template) { - TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer()); + /// + /// \param Name The template name. + TemplateArgument(TemplateName Name) : Kind(Template) + { + TemplateArg.Name = Name.getAsVoidPointer(); + TemplateArg.NumExpansions = 0; } - + + /// \brief Construct a template argument that is a template pack expansion. + /// + /// This form of template argument is generally used for template template + /// parameters. However, the template name could be a dependent template + /// name that ends up being instantiated to a function template whose address + /// is taken. + /// + /// \param Name The template name. + /// + /// \param NumExpansions The number of expansions that will be generated by + /// instantiating + TemplateArgument(TemplateName Name, llvm::Optional<unsigned> NumExpansions) + : Kind(TemplateExpansion) + { + TemplateArg.Name = Name.getAsVoidPointer(); + if (NumExpansions) + TemplateArg.NumExpansions = *NumExpansions + 1; + else + TemplateArg.NumExpansions = 0; + } + /// \brief Construct a template argument that is an expression. /// /// This form of template argument only occurs in template argument @@ -115,46 +157,59 @@ public: TypeOrValue = reinterpret_cast<uintptr_t>(E); } + /// \brief Construct a template argument that is a template argument pack. + /// + /// We assume that storage for the template arguments provided + /// outlives the TemplateArgument itself. + TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) : Kind(Pack){ + this->Args.Args = Args; + this->Args.NumArgs = NumArgs; + } + /// \brief Copy constructor for a template argument. TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) { + // FIXME: Large integral values will get leaked. Do something + // similar to what we did with IntegerLiteral. if (Kind == Integral) { new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); Integer.Type = Other.Integer.Type; } else if (Kind == Pack) { Args.NumArgs = Other.Args.NumArgs; - Args.Args = new TemplateArgument[Args.NumArgs]; - for (unsigned I = 0; I != Args.NumArgs; ++I) - Args.Args[I] = Other.Args.Args[I]; - } - else + Args.Args = Other.Args.Args; + } else if (Kind == Template || Kind == TemplateExpansion) { + TemplateArg.Name = Other.TemplateArg.Name; + TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions; + } else TypeOrValue = Other.TypeOrValue; } TemplateArgument& operator=(const TemplateArgument& Other) { - // FIXME: Does not provide the strong guarantee for exception - // safety. using llvm::APSInt; - // FIXME: Handle Packs - assert(Kind != Pack && "FIXME: Handle packs"); - assert(Other.Kind != Pack && "FIXME: Handle packs"); - if (Kind == Other.Kind && Kind == Integral) { // Copy integral values. *this->getAsIntegral() = *Other.getAsIntegral(); Integer.Type = Other.Integer.Type; - } else { - // Destroy the current integral value, if that's what we're holding. - if (Kind == Integral) - getAsIntegral()->~APSInt(); + return *this; + } + + // Destroy the current integral value, if that's what we're holding. + if (Kind == Integral) + getAsIntegral()->~APSInt(); - Kind = Other.Kind; + Kind = Other.Kind; - if (Other.Kind == Integral) { - new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); - Integer.Type = Other.Integer.Type; - } else - TypeOrValue = Other.TypeOrValue; + if (Other.Kind == Integral) { + new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); + Integer.Type = Other.Integer.Type; + } else if (Other.Kind == Pack) { + Args.NumArgs = Other.Args.NumArgs; + Args.Args = Other.Args.Args; + } else if (Kind == Template || Kind == TemplateExpansion) { + TemplateArg.Name = Other.TemplateArg.Name; + TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions; + } else { + TypeOrValue = Other.TypeOrValue; } return *this; @@ -165,16 +220,31 @@ public: if (Kind == Integral) getAsIntegral()->~APSInt(); - else if (Kind == Pack && Args.CopyArgs) - delete[] Args.Args; } + /// \brief Create a new template argument pack by copying the given set of + /// template arguments. + static TemplateArgument CreatePackCopy(ASTContext &Context, + const TemplateArgument *Args, + unsigned NumArgs); + /// \brief Return the kind of stored template argument. - ArgKind getKind() const { return Kind; } + ArgKind getKind() const { return (ArgKind)Kind; } /// \brief Determine whether this template argument has no value. bool isNull() const { return Kind == Null; } + /// \brief Whether this template argument is dependent on a template + /// parameter. + bool isDependent() const; + + /// \brief Whether this template argument contains an unexpanded + /// parameter pack. + bool containsUnexpandedParameterPack() const; + + /// \brief Determine whether this template argument is a pack expansion. + bool isPackExpansion() const; + /// \brief Retrieve the template argument as a type. QualType getAsType() const { if (Kind != Type) @@ -195,9 +265,21 @@ public: if (Kind != Template) return TemplateName(); - return TemplateName::getFromVoidPointer( - reinterpret_cast<void *> (TypeOrValue)); + return TemplateName::getFromVoidPointer(TemplateArg.Name); + } + + /// \brief Retrieve the template argument as a template name; if the argument + /// is a pack expansion, return the pattern as a template name. + TemplateName getAsTemplateOrTemplatePattern() const { + if (Kind != Template && Kind != TemplateExpansion) + return TemplateName(); + + return TemplateName::getFromVoidPointer(TemplateArg.Name); } + + /// \brief Retrieve the number of expansions that a template template argument + /// expansion will produce, if known. + llvm::Optional<unsigned> getNumTemplateExpansions() const; /// \brief Retrieve the template argument as an integral value. llvm::APSInt *getAsIntegral() { @@ -260,11 +342,17 @@ public: /// same. bool structurallyEquals(const TemplateArgument &Other) const; - /// \brief Construct a template argument pack. - void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs); + /// \brief When the template argument is a pack expansion, returns + /// the pattern of the pack expansion. + /// + /// \param Ellipsis Will be set to the location of the ellipsis. + TemplateArgument getPackExpansionPattern() const; + /// \brief Print this template argument to the given output stream. + void print(const PrintingPolicy &Policy, llvm::raw_ostream &Out) const; + /// \brief Used to insert TemplateArguments into FoldingSets. - void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const; + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const; }; /// Location information for a TemplateArgument. @@ -276,95 +364,48 @@ private: struct { unsigned QualifierRange[2]; unsigned TemplateNameLoc; + unsigned EllipsisLoc; } Template; }; -#ifndef NDEBUG - enum Kind { - K_None, - K_TypeSourceInfo, - K_Expression, - K_Template - } Kind; -#endif - public: - TemplateArgumentLocInfo() - : Expression(0) -#ifndef NDEBUG - , Kind(K_None) -#endif - {} + TemplateArgumentLocInfo(); - TemplateArgumentLocInfo(TypeSourceInfo *TInfo) - : Declarator(TInfo) -#ifndef NDEBUG - , Kind(K_TypeSourceInfo) -#endif - {} + TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {} - TemplateArgumentLocInfo(Expr *E) - : Expression(E) -#ifndef NDEBUG - , Kind(K_Expression) -#endif - {} + TemplateArgumentLocInfo(Expr *E) : Expression(E) {} TemplateArgumentLocInfo(SourceRange QualifierRange, - SourceLocation TemplateNameLoc) -#ifndef NDEBUG - : Kind(K_Template) -#endif + SourceLocation TemplateNameLoc, + SourceLocation EllipsisLoc) { Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding(); Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding(); Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); + Template.EllipsisLoc = EllipsisLoc.getRawEncoding(); } TypeSourceInfo *getAsTypeSourceInfo() const { - assert(Kind == K_TypeSourceInfo); return Declarator; } Expr *getAsExpr() const { - assert(Kind == K_Expression); return Expression; } SourceRange getTemplateQualifierRange() const { - assert(Kind == K_Template); return SourceRange( SourceLocation::getFromRawEncoding(Template.QualifierRange[0]), SourceLocation::getFromRawEncoding(Template.QualifierRange[1])); } SourceLocation getTemplateNameLoc() const { - assert(Kind == K_Template); return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); } -#ifndef NDEBUG - void validateForArgument(const TemplateArgument &Arg) { - switch (Arg.getKind()) { - case TemplateArgument::Type: - assert(Kind == K_TypeSourceInfo); - break; - case TemplateArgument::Expression: - case TemplateArgument::Declaration: - assert(Kind == K_Expression); - break; - case TemplateArgument::Template: - assert(Kind == K_Template); - break; - case TemplateArgument::Integral: - case TemplateArgument::Pack: - assert(Kind == K_None); - break; - case TemplateArgument::Null: - llvm_unreachable("source info for null template argument?"); - } + SourceLocation getTemplateEllipsisLoc() const { + return SourceLocation::getFromRawEncoding(Template.EllipsisLoc); } -#endif }; /// Location wrapper for a TemplateArgument. TemplateArgument is to @@ -393,14 +434,18 @@ public: TemplateArgumentLoc(const TemplateArgument &Argument, SourceRange QualifierRange, - SourceLocation TemplateNameLoc) - : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) { - assert(Argument.getKind() == TemplateArgument::Template); + SourceLocation TemplateNameLoc, + SourceLocation EllipsisLoc = SourceLocation()) + : Argument(Argument), + LocInfo(QualifierRange, TemplateNameLoc, EllipsisLoc) { + assert(Argument.getKind() == TemplateArgument::Template || + Argument.getKind() == TemplateArgument::TemplateExpansion); } /// \brief - Fetches the primary location of the argument. SourceLocation getLocation() const { - if (Argument.getKind() == TemplateArgument::Template) + if (Argument.getKind() == TemplateArgument::Template || + Argument.getKind() == TemplateArgument::TemplateExpansion) return getTemplateNameLoc(); return getSourceRange().getBegin(); @@ -433,14 +478,32 @@ public: } SourceRange getTemplateQualifierRange() const { - assert(Argument.getKind() == TemplateArgument::Template); + assert(Argument.getKind() == TemplateArgument::Template || + Argument.getKind() == TemplateArgument::TemplateExpansion); return LocInfo.getTemplateQualifierRange(); } SourceLocation getTemplateNameLoc() const { - assert(Argument.getKind() == TemplateArgument::Template); + assert(Argument.getKind() == TemplateArgument::Template || + Argument.getKind() == TemplateArgument::TemplateExpansion); return LocInfo.getTemplateNameLoc(); } + + SourceLocation getTemplateEllipsisLoc() const { + assert(Argument.getKind() == TemplateArgument::TemplateExpansion); + return LocInfo.getTemplateEllipsisLoc(); + } + + /// \brief When the template argument is a pack expansion, returns + /// the pattern of the pack expansion. + /// + /// \param Ellipsis Will be set to the location of the ellipsis. + /// + /// \param NumExpansions Will be set to the number of expansions that will + /// be generated from this pack expansion, if known a priori. + TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis, + llvm::Optional<unsigned> &NumExpansions, + ASTContext &Context) const; }; /// A convenient class for passing around template argument diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index ddfac712734b..1721973e8229 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -23,43 +23,119 @@ namespace llvm { } namespace clang { - + +class ASTContext; class DependentTemplateName; class DiagnosticBuilder; class IdentifierInfo; class NestedNameSpecifier; +class OverloadedTemplateStorage; struct PrintingPolicy; class QualifiedTemplateName; class NamedDecl; +class SubstTemplateTemplateParmPackStorage; +class TemplateArgument; class TemplateDecl; - -/// \brief A structure for storing the information associated with an -/// overloaded template name. -class OverloadedTemplateStorage { +class TemplateTemplateParmDecl; + +/// \brief Implementation class used to describe either a set of overloaded +/// template names or an already-substituted template template parameter pack. +class UncommonTemplateNameStorage { +protected: union { - unsigned Size; - NamedDecl *Storage[1]; + struct { + /// \brief If true, this is an OverloadedTemplateStorage instance; + /// otherwise, it's a SubstTemplateTemplateParmPackStorage instance. + unsigned IsOverloadedStorage : 1; + + /// \brief The number of stored templates or template arguments, + /// depending on which subclass we have. + unsigned Size : 31; + } Bits; + + void *PointerAlignment; }; - + + UncommonTemplateNameStorage(unsigned Size, bool OverloadedStorage) { + Bits.IsOverloadedStorage = OverloadedStorage; + Bits.Size = Size; + } + +public: + unsigned size() const { return Bits.Size; } + + OverloadedTemplateStorage *getAsOverloadedStorage() { + return Bits.IsOverloadedStorage + ? reinterpret_cast<OverloadedTemplateStorage *>(this) + : 0; + } + + SubstTemplateTemplateParmPackStorage *getAsSubstTemplateTemplateParmPack() { + return Bits.IsOverloadedStorage + ? 0 + : reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this) ; + } +}; + +/// \brief A structure for storing the information associated with an +/// overloaded template name. +class OverloadedTemplateStorage : public UncommonTemplateNameStorage { friend class ASTContext; - OverloadedTemplateStorage(unsigned Size) : Size(Size) {} + OverloadedTemplateStorage(unsigned Size) + : UncommonTemplateNameStorage(Size, true) { } NamedDecl **getStorage() { - return &Storage[1]; + return reinterpret_cast<NamedDecl **>(this + 1); } NamedDecl * const *getStorage() const { - return &Storage[1]; + return reinterpret_cast<NamedDecl *const *>(this + 1); } public: typedef NamedDecl *const *iterator; - unsigned size() const { return Size; } - iterator begin() const { return getStorage(); } iterator end() const { return getStorage() + size(); } }; + + +/// \brief A structure for storing an already-substituted template template +/// parameter pack. +/// +/// This kind of template names occurs when the parameter pack has been +/// provided with a template template argument pack in a context where its +/// enclosing pack expansion could not be fully expanded. +class SubstTemplateTemplateParmPackStorage + : public UncommonTemplateNameStorage, public llvm::FoldingSetNode +{ + ASTContext &Context; + TemplateTemplateParmDecl *Parameter; + const TemplateArgument *Arguments; + +public: + SubstTemplateTemplateParmPackStorage(ASTContext &Context, + TemplateTemplateParmDecl *Parameter, + unsigned Size, + const TemplateArgument *Arguments) + : UncommonTemplateNameStorage(Size, false), Context(Context), + Parameter(Parameter), Arguments(Arguments) { } + + /// \brief Retrieve the template template parameter pack being substituted. + TemplateTemplateParmDecl *getParameterPack() const { + return Parameter; + } + + /// \brief Retrieve the template template argument pack with which this + /// parameter was substituted. + TemplateArgument getArgumentPack() const; + + void Profile(llvm::FoldingSetNodeID &ID); + + static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, + TemplateTemplateParmDecl *Parameter, + const TemplateArgument &ArgPack); +}; /// \brief Represents a C++ template name within the type system. /// @@ -90,7 +166,7 @@ public: /// only be understood in the context of class TemplateName { typedef llvm::PointerUnion4<TemplateDecl *, - OverloadedTemplateStorage *, + UncommonTemplateNameStorage *, QualifiedTemplateName *, DependentTemplateName *> StorageType; @@ -103,16 +179,28 @@ class TemplateName { public: // \brief Kind of name that is actually stored. enum NameKind { + /// \brief A single template declaration. Template, + /// \brief A set of overloaded template declarations. OverloadedTemplate, + /// \brief A qualified template name, where the qualification is kept + /// to describe the source code as written. QualifiedTemplate, - DependentTemplate + /// \brief A dependent template name that has not been resolved to a + /// template (or set of templates). + DependentTemplate, + /// \brief A template template parameter pack that has been substituted for + /// a template template argument pack, but has not yet been expanded into + /// individual arguments. + SubstTemplateTemplateParmPack }; TemplateName() : Storage() { } explicit TemplateName(TemplateDecl *Template) : Storage(Template) { } explicit TemplateName(OverloadedTemplateStorage *Storage) : Storage(Storage) { } + explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage) + : Storage(Storage) { } explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { } explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { } @@ -122,7 +210,7 @@ public: // \brief Get the kind of name that is actually stored. NameKind getKind() const; - /// \brief Retrieve the the underlying template declaration that + /// \brief Retrieve the underlying template declaration that /// this template name refers to, if known. /// /// \returns The template declaration that this template name refers @@ -131,7 +219,7 @@ public: /// set of function templates, returns NULL. TemplateDecl *getAsTemplateDecl() const; - /// \brief Retrieve the the underlying, overloaded function template + /// \brief Retrieve the underlying, overloaded function template // declarations that this template name refers to, if known. /// /// \returns The set of overloaded function templates that this template @@ -139,7 +227,25 @@ public: /// specific set of function templates because it is a dependent name or /// refers to a single template, returns NULL. OverloadedTemplateStorage *getAsOverloadedTemplate() const { - return Storage.dyn_cast<OverloadedTemplateStorage *>(); + if (UncommonTemplateNameStorage *Uncommon = + Storage.dyn_cast<UncommonTemplateNameStorage *>()) + return Uncommon->getAsOverloadedStorage(); + + return 0; + } + + /// \brief Retrieve the substituted template template parameter pack, if + /// known. + /// + /// \returns The storage for the substituted template template parameter pack, + /// if known. Otherwise, returns NULL. + SubstTemplateTemplateParmPackStorage * + getAsSubstTemplateTemplateParmPack() const { + if (UncommonTemplateNameStorage *Uncommon = + Storage.dyn_cast<UncommonTemplateNameStorage *>()) + return Uncommon->getAsSubstTemplateTemplateParmPack(); + + return 0; } /// \brief Retrieve the underlying qualified template name @@ -157,6 +263,10 @@ public: /// \brief Determines whether this is a dependent template name. bool isDependent() const; + /// \brief Determines whether this template name contains an + /// unexpanded parameter pack (for C++0x variadic templates). + bool containsUnexpandedParameterPack() const; + /// \brief Print the template name. /// /// \param OS the output stream to which the template name will be diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 92e62a58d42c..9b177cceed96 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -18,12 +18,14 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Linkage.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/Visibility.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateName.h" #include "llvm/Support/Casting.h" #include "llvm/Support/type_traits.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" @@ -34,7 +36,7 @@ using llvm::dyn_cast; using llvm::dyn_cast_or_null; namespace clang { enum { - TypeAlignmentInBits = 3, + TypeAlignmentInBits = 4, TypeAlignment = 1 << TypeAlignmentInBits }; class Type; @@ -91,8 +93,9 @@ namespace clang { class TemplateArgument; class TemplateArgumentLoc; class TemplateArgumentListInfo; - class Type; class ElaboratedType; + class ExtQuals; + class ExtQualsTypeCommonBase; struct PrintingPolicy; template <typename> class CanQual; @@ -128,7 +131,7 @@ public: MaxAddressSpace = 0xffffffu, /// The width of the "fast" qualifier mask. - FastWidth = 2, + FastWidth = 3, /// The fast qualifier mask. FastMask = (1 << FastWidth) - 1 @@ -271,6 +274,25 @@ public: } } + /// \brief Add the qualifiers from the given set to this set, given that + /// they don't conflict. + void addConsistentQualifiers(Qualifiers qs) { + assert(getAddressSpace() == qs.getAddressSpace() || + !hasAddressSpace() || !qs.hasAddressSpace()); + assert(getObjCGCAttr() == qs.getObjCGCAttr() || + !hasObjCGCAttr() || !qs.hasObjCGCAttr()); + Mask |= qs.Mask; + } + + /// \brief Determines if these qualifiers compatibly include another set. + /// Generally this answers the question of whether an object with the other + /// qualifiers can be safely used as an object with these qualifiers. + bool compatiblyIncludes(Qualifiers other) const { + // Non-CVR qualifiers must match exactly. CVR qualifiers may subset. + return ((Mask & ~CVRMask) == (other.Mask & ~CVRMask)) && + (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask)); + } + bool isSupersetOf(Qualifiers Other) const; bool operator==(Qualifiers Other) const { return Mask == Other.Mask; } @@ -325,85 +347,6 @@ private: static const uint32_t AddressSpaceShift = 5; }; - -/// ExtQuals - We can encode up to three bits in the low bits of a -/// type pointer, but there are many more type qualifiers that we want -/// to be able to apply to an arbitrary type. Therefore we have this -/// struct, intended to be heap-allocated and used by QualType to -/// store qualifiers. -/// -/// The current design tags the 'const' and 'restrict' qualifiers in -/// two low bits on the QualType pointer; a third bit records whether -/// the pointer is an ExtQuals node. 'const' was chosen because it is -/// orders of magnitude more common than the other two qualifiers, in -/// both library and user code. It's relatively rare to see -/// 'restrict' in user code, but many standard C headers are saturated -/// with 'restrict' declarations, so that representing them efficiently -/// is a critical goal of this representation. -class ExtQuals : public llvm::FoldingSetNode { - // NOTE: changing the fast qualifiers should be straightforward as - // long as you don't make 'const' non-fast. - // 1. Qualifiers: - // a) Modify the bitmasks (Qualifiers::TQ and DeclSpec::TQ). - // Fast qualifiers must occupy the low-order bits. - // b) Update Qualifiers::FastWidth and FastMask. - // 2. QualType: - // a) Update is{Volatile,Restrict}Qualified(), defined inline. - // b) Update remove{Volatile,Restrict}, defined near the end of - // this header. - // 3. ASTContext: - // a) Update get{Volatile,Restrict}Type. - - /// Context - the context to which this set belongs. We save this - /// here so that QualifierCollector can use it to reapply extended - /// qualifiers to an arbitrary type without requiring a context to - /// be pushed through every single API dealing with qualifiers. - ASTContext& Context; - - /// BaseType - the underlying type that this qualifies - const Type *BaseType; - - /// Quals - the immutable set of qualifiers applied by this - /// node; always contains extended qualifiers. - Qualifiers Quals; - -public: - ExtQuals(ASTContext& Context, const Type *Base, Qualifiers Quals) - : Context(Context), BaseType(Base), Quals(Quals) - { - assert(Quals.hasNonFastQualifiers() - && "ExtQuals created with no fast qualifiers"); - assert(!Quals.hasFastQualifiers() - && "ExtQuals created with fast qualifiers"); - } - - Qualifiers getQualifiers() const { return Quals; } - - bool hasVolatile() const { return Quals.hasVolatile(); } - - bool hasObjCGCAttr() const { return Quals.hasObjCGCAttr(); } - Qualifiers::GC getObjCGCAttr() const { return Quals.getObjCGCAttr(); } - - bool hasAddressSpace() const { return Quals.hasAddressSpace(); } - unsigned getAddressSpace() const { return Quals.getAddressSpace(); } - - const Type *getBaseType() const { return BaseType; } - - ASTContext &getContext() const { return Context; } - -public: - void Profile(llvm::FoldingSetNodeID &ID) const { - Profile(ID, getBaseType(), Quals); - } - static void Profile(llvm::FoldingSetNodeID &ID, - const Type *BaseType, - Qualifiers Quals) { - assert(!Quals.hasFastQualifiers() && "fast qualifiers in ExtQuals hash!"); - ID.AddPointer(BaseType); - Quals.Profile(ID); - } -}; - /// CallingConv - Specifies the calling convention that a function uses. enum CallingConv { CC_Default, @@ -414,6 +357,7 @@ enum CallingConv { CC_X86Pascal // __attribute__((pascal)) }; +typedef std::pair<const Type*, Qualifiers> SplitQualType; /// QualType - For efficiency, we don't store CV-qualified types as nodes on /// their own: instead each reference to a type stores the qualifiers. This @@ -440,8 +384,14 @@ class QualType { return Value.getPointer().get<const Type*>(); } - QualType getUnqualifiedTypeSlow() const; - + const ExtQualsTypeCommonBase *getCommonPtr() const { + assert(!isNull() && "Cannot retrieve a NULL type pointer"); + uintptr_t CommonPtrVal + = reinterpret_cast<uintptr_t>(Value.getOpaqueValue()); + CommonPtrVal &= ~(uintptr_t)((1 << TypeAlignmentInBits) - 1); + return reinterpret_cast<ExtQualsTypeCommonBase*>(CommonPtrVal); + } + friend class QualifierCollector; public: QualType() {} @@ -457,24 +407,29 @@ public: /// Retrieves a pointer to the underlying (unqualified) type. /// This should really return a const Type, but it's not worth /// changing all the users right now. - Type *getTypePtr() const { - if (hasLocalNonFastQualifiers()) - return const_cast<Type*>(getExtQualsUnsafe()->getBaseType()); - return const_cast<Type*>(getTypePtrUnsafe()); - } + /// + /// This function requires that the type not be NULL. If the type might be + /// NULL, use the (slightly less efficient) \c getTypePtrOrNull(). + const Type *getTypePtr() const; + + const Type *getTypePtrOrNull() const; + + /// Divides a QualType into its unqualified type and a set of local + /// qualifiers. + SplitQualType split() const; void *getAsOpaquePtr() const { return Value.getOpaqueValue(); } - static QualType getFromOpaquePtr(void *Ptr) { + static QualType getFromOpaquePtr(const void *Ptr) { QualType T; - T.Value.setFromOpaqueValue(Ptr); + T.Value.setFromOpaqueValue(const_cast<void*>(Ptr)); return T; } - Type &operator*() const { + const Type &operator*() const { return *getTypePtr(); } - Type *operator->() const { + const Type *operator->() const { return getTypePtr(); } @@ -510,7 +465,7 @@ public: /// "volatile" qualifier set, without looking through typedefs that may have /// added "volatile" at a different level. bool isLocalVolatileQualified() const { - return (hasLocalNonFastQualifiers() && getExtQualsUnsafe()->hasVolatile()); + return (getLocalFastQualifiers() & Qualifiers::Volatile); } /// \brief Determine whether this type is volatile-qualified. @@ -536,13 +491,7 @@ public: /// \brief Retrieve the set of qualifiers local to this particular QualType /// instance, not including any qualifiers acquired through typedefs or /// other sugar. - Qualifiers getLocalQualifiers() const { - Qualifiers Quals; - if (hasLocalNonFastQualifiers()) - Quals = getExtQualsUnsafe()->getQualifiers(); - Quals.addFastQualifiers(getLocalFastQualifiers()); - return Quals; - } + Qualifiers getLocalQualifiers() const; /// \brief Retrieve the set of qualifiers applied to this type. Qualifiers getQualifiers() const; @@ -551,21 +500,13 @@ public: /// local to this particular QualType instance, not including any qualifiers /// acquired through typedefs or other sugar. unsigned getLocalCVRQualifiers() const { - unsigned CVR = getLocalFastQualifiers(); - if (isLocalVolatileQualified()) - CVR |= Qualifiers::Volatile; - return CVR; + return getLocalFastQualifiers(); } /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers /// applied to this type. unsigned getCVRQualifiers() const; - /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers - /// applied to this type, looking through any number of unqualified array - /// types to their element types' qualifiers. - unsigned getCVRQualifiersThroughArrayTypes() const; - bool isConstant(ASTContext& Ctx) const { return QualType::isConstant(*this, Ctx); } @@ -587,16 +528,13 @@ public: Value.setInt(Value.getInt() | TQs); } - // FIXME: The remove* functions are semantically broken, because they might - // not remove a qualifier stored on a typedef. Most of the with* functions - // have the same problem. - void removeConst(); - void removeVolatile(); - void removeRestrict(); - void removeCVRQualifiers(unsigned Mask); + void removeLocalConst(); + void removeLocalVolatile(); + void removeLocalRestrict(); + void removeLocalCVRQualifiers(unsigned Mask); - void removeFastQualifiers() { Value.setInt(0); } - void removeFastQualifiers(unsigned Mask) { + void removeLocalFastQualifiers() { Value.setInt(0); } + void removeLocalFastQualifiers(unsigned Mask) { assert(!(Mask & ~Qualifiers::FastMask) && "mask has non-fast qualifiers"); Value.setInt(Value.getInt() & ~Mask); } @@ -611,31 +549,54 @@ public: // Creates a type with exactly the given fast qualifiers, removing // any existing fast qualifiers. - QualType withExactFastQualifiers(unsigned TQs) const { - return withoutFastQualifiers().withFastQualifiers(TQs); + QualType withExactLocalFastQualifiers(unsigned TQs) const { + return withoutLocalFastQualifiers().withFastQualifiers(TQs); } // Removes fast qualifiers, but leaves any extended qualifiers in place. - QualType withoutFastQualifiers() const { + QualType withoutLocalFastQualifiers() const { QualType T = *this; - T.removeFastQualifiers(); + T.removeLocalFastQualifiers(); return T; } + QualType getCanonicalType() const; + /// \brief Return this type with all of the instance-specific qualifiers /// removed, but without removing any qualifiers that may have been applied /// through typedefs. QualType getLocalUnqualifiedType() const { return QualType(getTypePtr(), 0); } - /// \brief Return the unqualified form of the given type, which might be - /// desugared to eliminate qualifiers introduced via typedefs. - QualType getUnqualifiedType() const { - QualType T = getLocalUnqualifiedType(); - if (!T.hasQualifiers()) - return T; - - return getUnqualifiedTypeSlow(); - } + /// \brief Retrieve the unqualified variant of the given type, + /// removing as little sugar as possible. + /// + /// This routine looks through various kinds of sugar to find the + /// least-desugared type that is unqualified. For example, given: + /// + /// \code + /// typedef int Integer; + /// typedef const Integer CInteger; + /// typedef CInteger DifferenceType; + /// \endcode + /// + /// Executing \c getUnqualifiedType() on the type \c DifferenceType will + /// desugar until we hit the type \c Integer, which has no qualifiers on it. + /// + /// The resulting type might still be qualified if it's an array + /// type. To strip qualifiers even from within an array type, use + /// ASTContext::getUnqualifiedArrayType. + inline QualType getUnqualifiedType() const; + + /// getSplitUnqualifiedType - Retrieve the unqualified variant of the + /// given type, removing as little sugar as possible. + /// + /// Like getUnqualifiedType(), but also returns the set of + /// qualifiers that were built up. + /// + /// The resulting type might still be qualified if it's an array + /// type. To strip qualifiers even from within an array type, use + /// ASTContext::getUnqualifiedArrayType. + inline SplitQualType getSplitUnqualifiedType() const; bool isMoreQualifiedThan(QualType Other) const; bool isAtLeastAsQualifiedAs(QualType Other) const; @@ -659,8 +620,20 @@ public: /// concrete. /// /// Qualifiers are left in place. - QualType getDesugaredType() const { - return QualType::getDesugaredType(*this); + QualType getDesugaredType(const ASTContext &Context) const { + return getDesugaredType(*this, Context); + } + + SplitQualType getSplitDesugaredType() const { + return getSplitDesugaredType(*this); + } + + /// IgnoreParens - Returns the specified type after dropping any + /// outer-level parentheses. + QualType IgnoreParens() const { + if (isa<ParenType>(*this)) + return QualType::IgnoreParens(*this); + return *this; } /// operator==/!= - Indicate whether the specified types and qualifiers are @@ -671,7 +644,13 @@ public: friend bool operator!=(const QualType &LHS, const QualType &RHS) { return LHS.Value != RHS.Value; } - std::string getAsString() const; + std::string getAsString() const { + return getAsString(split()); + } + static std::string getAsString(SplitQualType split) { + return getAsString(split.first, split.second); + } + static std::string getAsString(const Type *ty, Qualifiers qs); std::string getAsString(const PrintingPolicy &Policy) const { std::string S; @@ -679,7 +658,16 @@ public: return S; } void getAsStringInternal(std::string &Str, - const PrintingPolicy &Policy) const; + const PrintingPolicy &Policy) const { + return getAsStringInternal(split(), Str, Policy); + } + static void getAsStringInternal(SplitQualType split, std::string &out, + const PrintingPolicy &policy) { + return getAsStringInternal(split.first, split.second, out, policy); + } + static void getAsStringInternal(const Type *ty, Qualifiers qs, + std::string &out, + const PrintingPolicy &policy); void dump(const char *s) const; void dump() const; @@ -704,12 +692,29 @@ public: return getObjCGCAttr() == Qualifiers::Strong; } + enum DestructionKind { + DK_none, + DK_cxx_destructor + }; + + /// isDestructedType - nonzero if objects of this type require + /// non-trivial work to clean up after. Non-zero because it's + /// conceivable that qualifiers (objc_gc(weak)?) could make + /// something require destruction. + DestructionKind isDestructedType() const { + return isDestructedTypeImpl(*this); + } + private: // These methods are implemented in a separate translation unit; // "static"-ize them to avoid creating temporary QualTypes in the // caller. static bool isConstant(QualType T, ASTContext& Ctx); - static QualType getDesugaredType(QualType T); + static QualType getDesugaredType(QualType T, const ASTContext &Context); + static SplitQualType getSplitDesugaredType(QualType T); + static SplitQualType getSplitUnqualifiedTypeImpl(QualType type); + static QualType IgnoreParens(QualType T); + static DestructionKind isDestructedTypeImpl(QualType type); }; } // end clang. @@ -718,7 +723,7 @@ 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; + typedef const ::clang::Type *SimpleType; static SimpleType getSimplifiedValue(const ::clang::QualType &Val) { return Val.getTypePtr(); } @@ -744,6 +749,106 @@ public: namespace clang { +/// \brief Base class that is common to both the \c ExtQuals and \c Type +/// classes, which allows \c QualType to access the common fields between the +/// two. +/// +class ExtQualsTypeCommonBase { + ExtQualsTypeCommonBase(const Type *baseType, QualType canon) + : BaseType(baseType), CanonicalType(canon) {} + + /// \brief The "base" type of an extended qualifiers type (\c ExtQuals) or + /// a self-referential pointer (for \c Type). + /// + /// This pointer allows an efficient mapping from a QualType to its + /// underlying type pointer. + const Type *const BaseType; + + /// \brief The canonical type of this type. A QualType. + QualType CanonicalType; + + friend class QualType; + friend class Type; + friend class ExtQuals; +}; + +/// ExtQuals - We can encode up to four bits in the low bits of a +/// type pointer, but there are many more type qualifiers that we want +/// to be able to apply to an arbitrary type. Therefore we have this +/// struct, intended to be heap-allocated and used by QualType to +/// store qualifiers. +/// +/// The current design tags the 'const', 'restrict', and 'volatile' qualifiers +/// in three low bits on the QualType pointer; a fourth bit records whether +/// the pointer is an ExtQuals node. The extended qualifiers (address spaces, +/// Objective-C GC attributes) are much more rare. +class ExtQuals : public ExtQualsTypeCommonBase, public llvm::FoldingSetNode { + // NOTE: changing the fast qualifiers should be straightforward as + // long as you don't make 'const' non-fast. + // 1. Qualifiers: + // a) Modify the bitmasks (Qualifiers::TQ and DeclSpec::TQ). + // Fast qualifiers must occupy the low-order bits. + // b) Update Qualifiers::FastWidth and FastMask. + // 2. QualType: + // a) Update is{Volatile,Restrict}Qualified(), defined inline. + // b) Update remove{Volatile,Restrict}, defined near the end of + // this header. + // 3. ASTContext: + // a) Update get{Volatile,Restrict}Type. + + /// Quals - the immutable set of qualifiers applied by this + /// node; always contains extended qualifiers. + Qualifiers Quals; + + ExtQuals *this_() { return this; } + +public: + ExtQuals(const Type *baseType, QualType canon, Qualifiers quals) + : ExtQualsTypeCommonBase(baseType, + canon.isNull() ? QualType(this_(), 0) : canon), + Quals(quals) + { + assert(Quals.hasNonFastQualifiers() + && "ExtQuals created with no fast qualifiers"); + assert(!Quals.hasFastQualifiers() + && "ExtQuals created with fast qualifiers"); + } + + Qualifiers getQualifiers() const { return Quals; } + + bool hasObjCGCAttr() const { return Quals.hasObjCGCAttr(); } + Qualifiers::GC getObjCGCAttr() const { return Quals.getObjCGCAttr(); } + + bool hasAddressSpace() const { return Quals.hasAddressSpace(); } + unsigned getAddressSpace() const { return Quals.getAddressSpace(); } + + const Type *getBaseType() const { return BaseType; } + +public: + void Profile(llvm::FoldingSetNodeID &ID) const { + Profile(ID, getBaseType(), Quals); + } + static void Profile(llvm::FoldingSetNodeID &ID, + const Type *BaseType, + Qualifiers Quals) { + assert(!Quals.hasFastQualifiers() && "fast qualifiers in ExtQuals hash!"); + ID.AddPointer(BaseType); + Quals.Profile(ID); + } +}; + +/// \brief The kind of C++0x ref-qualifier associated with a function type, +/// which determines whether a member function's "this" object can be an +/// lvalue, rvalue, or neither. +enum RefQualifierKind { + /// \brief No ref-qualifier was provided. + RQ_None = 0, + /// \brief An lvalue ref-qualifier was provided (\c &). + RQ_LValue, + /// \brief An rvalue ref-qualifier was provided (\c &&). + RQ_RValue +}; + /// 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 @@ -769,7 +874,7 @@ namespace clang { /// /// Types, once created, are immutable. /// -class Type { +class Type : public ExtQualsTypeCommonBase { public: enum TypeClass { #define TYPE(Class, Base) Class, @@ -783,53 +888,249 @@ private: Type(const Type&); // DO NOT IMPLEMENT. void operator=(const Type&); // DO NOT IMPLEMENT. - QualType CanonicalType; + /// Bitfields required by the Type class. + class TypeBitfields { + friend class Type; + template <class T> friend class TypePropertyCache; - /// TypeClass bitfield - Enum that specifies what subclass this belongs to. - unsigned TC : 8; + /// TypeClass bitfield - Enum that specifies what subclass this belongs to. + unsigned TC : 8; - /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]). - /// Note that this should stay at the end of the ivars for Type so that - /// subclasses can pack their bitfields into the same word. - bool Dependent : 1; + /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]). + /// 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 Dependent : 1; - /// \brief Whether the linkage of this type is already known. - mutable bool LinkageKnown : 1; + /// \brief Whether this type is a variably-modified type (C99 6.7.5). + unsigned VariablyModified : 1; + + /// \brief Whether this type contains an unexpanded parameter pack + /// (for C++0x variadic templates). + unsigned ContainsUnexpandedParameterPack : 1; + + /// \brief Nonzero if the cache (i.e. the bitfields here starting + /// with 'Cache') is valid. If so, then this is a + /// LangOptions::VisibilityMode+1. + mutable unsigned CacheValidAndVisibility : 2; + + /// \brief Linkage of this type. + mutable unsigned CachedLinkage : 2; + + /// \brief Whether this type involves and local or unnamed types. + mutable unsigned CachedLocalOrUnnamed : 1; - /// \brief Linkage of this type. - mutable unsigned CachedLinkage : 2; + /// \brief FromAST - Whether this type comes from an AST file. + mutable unsigned FromAST : 1; + + bool isCacheValid() const { + return (CacheValidAndVisibility != 0); + } + Visibility getVisibility() const { + assert(isCacheValid() && "getting linkage from invalid cache"); + return static_cast<Visibility>(CacheValidAndVisibility-1); + } + Linkage getLinkage() const { + assert(isCacheValid() && "getting linkage from invalid cache"); + return static_cast<Linkage>(CachedLinkage); + } + bool hasLocalOrUnnamedType() const { + assert(isCacheValid() && "getting linkage from invalid cache"); + return CachedLocalOrUnnamed; + } + }; + enum { NumTypeBits = 17 }; + +protected: + // These classes allow subclasses to somewhat cleanly pack bitfields + // into Type. + + class ArrayTypeBitfields { + friend class ArrayType; + + unsigned : NumTypeBits; + + /// IndexTypeQuals - CVR qualifiers from declarations like + /// 'int X[static restrict 4]'. For function parameters only. + unsigned IndexTypeQuals : 3; + + /// SizeModifier - storage class qualifiers from declarations like + /// 'int X[static restrict 4]'. For function parameters only. + /// Actually an ArrayType::ArraySizeModifier. + unsigned SizeModifier : 3; + }; + + class BuiltinTypeBitfields { + friend class BuiltinType; + + unsigned : NumTypeBits; + + /// The kind (BuiltinType::Kind) of builtin type this is. + unsigned Kind : 8; + }; + + class FunctionTypeBitfields { + friend class FunctionType; + + unsigned : NumTypeBits; + + /// Extra information which affects how the function is called, like + /// regparm and the calling convention. + unsigned ExtInfo : 8; + + /// Whether the function is variadic. Only used by FunctionProtoType. + unsigned Variadic : 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; + + /// \brief The ref-qualifier associated with a \c FunctionProtoType. + /// + /// This is a value of type \c RefQualifierKind. + unsigned RefQualifier : 2; + }; + + class ObjCObjectTypeBitfields { + friend class ObjCObjectType; + + unsigned : NumTypeBits; + + /// NumProtocols - The number of protocols stored directly on this + /// object type. + unsigned NumProtocols : 32 - NumTypeBits; + }; + + class ReferenceTypeBitfields { + friend class ReferenceType; + + unsigned : NumTypeBits; + + /// True if the type was originally spelled with an lvalue sigil. + /// This is never true of rvalue references but can also be false + /// on lvalue references because of C++0x [dcl.typedef]p9, + /// as follows: + /// + /// typedef int &ref; // lvalue, spelled lvalue + /// typedef int &&rvref; // rvalue + /// ref &a; // lvalue, inner ref, spelled lvalue + /// ref &&a; // lvalue, inner ref + /// rvref &a; // lvalue, inner ref, spelled lvalue + /// rvref &&a; // rvalue, inner ref + unsigned SpelledAsLValue : 1; + + /// True if the inner type is a reference type. This only happens + /// in non-canonical forms. + unsigned InnerRef : 1; + }; + + class TypeWithKeywordBitfields { + friend class TypeWithKeyword; + + unsigned : NumTypeBits; + + /// An ElaboratedTypeKeyword. 8 bits for efficient access. + unsigned Keyword : 8; + }; + + class VectorTypeBitfields { + friend class VectorType; + + unsigned : NumTypeBits; + + /// VecKind - The kind of vector, either a generic vector type or some + /// target-specific vector type such as for AltiVec or Neon. + unsigned VecKind : 3; + + /// NumElements - The number of elements in the vector. + unsigned NumElements : 29 - NumTypeBits; + }; + + class AttributedTypeBitfields { + friend class AttributedType; - /// \brief FromAST - Whether this type comes from an AST file. - mutable bool FromAST : 1; + unsigned : NumTypeBits; + /// AttrKind - an AttributedType::Kind + unsigned AttrKind : 32 - NumTypeBits; + }; + + union { + TypeBitfields TypeBits; + ArrayTypeBitfields ArrayTypeBits; + AttributedTypeBitfields AttributedTypeBits; + BuiltinTypeBitfields BuiltinTypeBits; + FunctionTypeBitfields FunctionTypeBits; + ObjCObjectTypeBitfields ObjCObjectTypeBits; + ReferenceTypeBitfields ReferenceTypeBits; + TypeWithKeywordBitfields TypeWithKeywordBits; + VectorTypeBitfields VectorTypeBits; + }; + +private: /// \brief Set whether this type comes from an AST file. void setFromAST(bool V = true) const { - FromAST = V; + TypeBits.FromAST = V; } -protected: - /// \brief Compute the linkage of this type. - virtual Linkage getLinkageImpl() const; - - enum { BitsRemainingInType = 19 }; + template <class T> friend class TypePropertyCache; +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), - TC(tc), Dependent(dependent), LinkageKnown(false), - CachedLinkage(NoLinkage), FromAST(false) {} - virtual ~Type(); + Type(TypeClass tc, QualType canon, bool Dependent, bool VariablyModified, + bool ContainsUnexpandedParameterPack) + : ExtQualsTypeCommonBase(this, + canon.isNull() ? QualType(this_(), 0) : canon) { + TypeBits.TC = tc; + TypeBits.Dependent = Dependent; + TypeBits.VariablyModified = VariablyModified; + TypeBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; + TypeBits.CacheValidAndVisibility = 0; + TypeBits.CachedLocalOrUnnamed = false; + TypeBits.CachedLinkage = NoLinkage; + TypeBits.FromAST = false; + } friend class ASTContext; + void setDependent(bool D = true) { TypeBits.Dependent = D; } + void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM; } + void setContainsUnexpandedParameterPack(bool PP = true) { + TypeBits.ContainsUnexpandedParameterPack = PP; + } + public: - TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); } + TypeClass getTypeClass() const { return static_cast<TypeClass>(TypeBits.TC); } /// \brief Whether this type comes from an AST file. - bool isFromAST() const { return FromAST; } + bool isFromAST() const { return TypeBits.FromAST; } + + /// \brief Whether this type is or contains an unexpanded parameter + /// pack, used to support C++0x variadic templates. + /// + /// A type that contains a parameter pack shall be expanded by the + /// ellipsis operator at some point. For example, the typedef in the + /// following example contains an unexpanded parameter pack 'T': + /// + /// \code + /// template<typename ...T> + /// struct X { + /// typedef T* pointer_types; // ill-formed; T is a parameter pack. + /// }; + /// \endcode + /// + /// Note that this routine does not specify which + bool containsUnexpandedParameterPack() const { + return TypeBits.ContainsUnexpandedParameterPack; + } + /// Determines if this type would be canonical if it had no further + /// qualification. bool isCanonicalUnqualified() const { - return CanonicalType.getTypePtr() == this; + return CanonicalType == QualType(this, 0); } /// Types are partitioned into 3 broad categories (C99 6.2.5p1): @@ -846,6 +1147,14 @@ public: bool isIncompleteOrObjectType() const { return !isFunctionType(); } + + /// \brief Determine whether this type is an object type. + bool isObjectType() const { + // C++ [basic.types]p8: + // An object type is a (possibly cv-qualified) type that is not a + // function type, not a reference type, and not a void type. + return !isReferenceType() && !isFunctionType() && !isVoidType(); + } /// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10). bool isPODType() const; @@ -854,10 +1163,6 @@ public: /// (C++0x [basic.types]p10) bool isLiteralType() 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. @@ -867,6 +1172,12 @@ public: /// isSpecificBuiltinType - Test for a particular builtin type. bool isSpecificBuiltinType(unsigned K) const; + /// isPlaceholderType - Test for a type which does not represent an + /// actual type-system type but is instead used as a placeholder for + /// various convenient purposes within Clang. All such types are + /// BuiltinTypes. + bool isPlaceholderType() 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) @@ -879,6 +1190,9 @@ public: /// \brief Determine whether this type is an integral or enumeration type. bool isIntegralOrEnumerationType() const; + /// \brief Determine whether this type is an integral or unscoped enumeration + /// type. + bool isIntegralOrUnscopedEnumerationType() const; /// Floating point categories. bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double) @@ -938,10 +1252,33 @@ public: bool isTemplateTypeParmType() const; // C++ template type parameter bool isNullPtrType() const; // C++0x nullptr_t + enum ScalarTypeKind { + STK_Pointer, + STK_MemberPointer, + STK_Bool, + STK_Integral, + STK_Floating, + STK_IntegralComplex, + STK_FloatingComplex + }; + /// getScalarTypeKind - Given that this is a scalar type, classify it. + ScalarTypeKind getScalarTypeKind() const; + /// 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 isDependentType() const { return TypeBits.Dependent; } + + /// \brief Whether this type is a variably-modified type (C99 6.7.5). + bool isVariablyModifiedType() const { return TypeBits.VariablyModified; } + + /// \brief Whether this type involves a variable-length array type + /// with a definite size. + bool hasSizedVLAType() const; + + /// \brief Whether this type is or contains a local or unnamed type. + bool hasUnnamedOrLocalType() const; + bool isOverloadableType() const; /// \brief Determine wither this type is a C++ elaborated-type-specifier. @@ -991,15 +1328,41 @@ public: /// because the type is a RecordType or because it is the injected-class-name /// type of a class template or class template partial specialization. CXXRecordDecl *getAsCXXRecordDecl() const; + + /// \brief Get the AutoType whose type will be deduced for a variable with + /// an initializer of this type. This looks through declarators like pointer + /// types, but not through decltype or typedefs. + AutoType *getContainedAutoType() const; - // Member-template getAs<specific type>'. Look through sugar for - // an instance of <specific type>. This scheme will eventually - // replace the specific getAsXXXX methods above. - // - // There are some specializations of this member template listed - // immediately following this class. + /// Member-template getAs<specific type>'. Look through sugar for + /// an instance of <specific type>. This scheme will eventually + /// replace the specific getAsXXXX methods above. + /// + /// There are some specializations of this member template listed + /// immediately following this class. template <typename T> const T *getAs() const; + /// A variant of getAs<> for array types which silently discards + /// qualifiers from the outermost type. + const ArrayType *getAsArrayTypeUnsafe() const; + + /// Member-template castAs<specific type>. Look through sugar for + /// the underlying instance of <specific type>. + /// + /// This method has the same relationship to getAs<T> as cast<T> has + /// to dyn_cast<T>; which is to say, the underlying type *must* + /// have the intended type, and this method will never return null. + template <typename T> const T *castAs() const; + + /// A variant of castAs<> for array type which silently discards + /// qualifiers from the outermost type. + const ArrayType *castAsArrayTypeUnsafe() const; + + /// getBaseElementTypeUnsafe - Get the base element type of this + /// type, potentially discarding type qualifiers. This method + /// should never be used when type qualifiers are meaningful. + const Type *getBaseElementTypeUnsafe() 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. @@ -1040,6 +1403,12 @@ public: /// \brief Determine the linkage of this type. Linkage getLinkage() const; + + /// \brief Determine the visibility of this type. + Visibility getVisibility() const; + + /// \brief Determine the linkage and visibility of this type. + std::pair<Linkage,Visibility> getLinkageAndVisibility() const; /// \brief Note that the linkage is no longer known. void ClearLinkageCache(); @@ -1067,6 +1436,9 @@ template <> inline const TypedefType *Type::getAs() const { #define LEAF_TYPE(Class) \ template <> inline const Class##Type *Type::getAs() const { \ return dyn_cast<Class##Type>(CanonicalType); \ +} \ +template <> inline const Class##Type *Type::castAs() const { \ + return cast<Class##Type>(CanonicalType); \ } #include "clang/AST/TypeNodes.def" @@ -1081,6 +1453,7 @@ public: 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. + WChar_U, // This is 'wchar_t' for C++, when unsigned. Char16, // This is 'char16_t' for C++. Char32, // This is 'char32_t' for C++. UShort, @@ -1091,7 +1464,7 @@ public: 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++. + WChar_S, // This is 'wchar_t' for C++, when signed. Short, Int, Long, @@ -1102,11 +1475,13 @@ public: 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. + /// This represents the type of an expression whose type is + /// totally unknown, e.g. 'T::foo'. It is permitted for this to + /// appear in situations where the structure of the type is + /// theoretically deducible. + Dependent, - UndeducedAuto, // In C++0x, this represents the type of an auto variable - // that has not been deduced yet. + Overload, // This represents the type of an overloaded function declaration. /// The primitive Objective C 'id' type. The type pointed to by the /// user-visible 'id' type. Only ever shows up in an AST as the base @@ -1120,37 +1495,42 @@ public: ObjCSel // This represents the ObjC 'SEL' type. }; -private: - Kind TypeKind; - -protected: - virtual Linkage getLinkageImpl() const; - + public: BuiltinType(Kind K) - : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent)), - TypeKind(K) {} + : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent), + /*VariablyModified=*/false, + /*Unexpanded paramter pack=*/false) { + BuiltinTypeBits.Kind = K; + } - Kind getKind() const { return TypeKind; } + Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); } const char *getName(const LangOptions &LO) const; bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } bool isInteger() const { - return TypeKind >= Bool && TypeKind <= Int128; + return getKind() >= Bool && getKind() <= Int128; } bool isSignedInteger() const { - return TypeKind >= Char_S && TypeKind <= Int128; + return getKind() >= Char_S && getKind() <= Int128; } bool isUnsignedInteger() const { - return TypeKind >= Bool && TypeKind <= UInt128; + return getKind() >= Bool && getKind() <= UInt128; } bool isFloatingPoint() const { - return TypeKind >= Float && TypeKind <= LongDouble; + return getKind() >= Float && getKind() <= LongDouble; + } + + /// Determines whether this type is a "forbidden" placeholder type, + /// i.e. a type which cannot appear in arbitrary positions in a + /// fully-formed expression. + bool isPlaceholderType() const { + return getKind() == Overload; } static bool classof(const Type *T) { return T->getTypeClass() == Builtin; } @@ -1163,14 +1543,13 @@ public: class ComplexType : public Type, public llvm::FoldingSetNode { QualType ElementType; ComplexType(QualType Element, QualType CanonicalPtr) : - Type(Complex, CanonicalPtr, Element->isDependentType()), + Type(Complex, CanonicalPtr, Element->isDependentType(), + Element->isVariablyModifiedType(), + Element->containsUnexpandedParameterPack()), ElementType(Element) { } friend class ASTContext; // ASTContext creates these. -protected: - virtual Linkage getLinkageImpl() const; - public: QualType getElementType() const { return ElementType; } @@ -1188,19 +1567,50 @@ public: static bool classof(const ComplexType *) { return true; } }; +/// ParenType - Sugar for parentheses used when specifying types. +/// +class ParenType : public Type, public llvm::FoldingSetNode { + QualType Inner; + + ParenType(QualType InnerType, QualType CanonType) : + Type(Paren, CanonType, InnerType->isDependentType(), + InnerType->isVariablyModifiedType(), + InnerType->containsUnexpandedParameterPack()), + Inner(InnerType) { + } + friend class ASTContext; // ASTContext creates these. + +public: + + QualType getInnerType() const { return Inner; } + + bool isSugared() const { return true; } + QualType desugar() const { return getInnerType(); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getInnerType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Inner) { + Inner.Profile(ID); + } + + static bool classof(const Type *T) { return T->getTypeClass() == Paren; } + static bool classof(const ParenType *) { 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) { + Type(Pointer, CanonicalPtr, Pointee->isDependentType(), + Pointee->isVariablyModifiedType(), + Pointee->containsUnexpandedParameterPack()), + PointeeType(Pointee) { } friend class ASTContext; // ASTContext creates these. -protected: - virtual Linkage getLinkageImpl() const; - public: QualType getPointeeType() const { return PointeeType; } @@ -1226,14 +1636,13 @@ public: 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()), + Type(BlockPointer, CanonicalCls, Pointee->isDependentType(), + Pointee->isVariablyModifiedType(), + Pointee->containsUnexpandedParameterPack()), PointeeType(Pointee) { } friend class ASTContext; // ASTContext creates these. -protected: - virtual Linkage getLinkageImpl() const; - public: // Get the pointee type. Pointee is required to always be a function type. @@ -1260,48 +1669,33 @@ public: class ReferenceType : public Type, public llvm::FoldingSetNode { QualType PointeeType; - /// True if the type was originally spelled with an lvalue sigil. - /// This is never true of rvalue references but can also be false - /// on lvalue references because of C++0x [dcl.typedef]p9, - /// as follows: - /// - /// typedef int &ref; // lvalue, spelled lvalue - /// typedef int &&rvref; // rvalue - /// ref &a; // lvalue, inner ref, spelled lvalue - /// ref &&a; // lvalue, inner ref - /// rvref &a; // lvalue, inner ref, spelled lvalue - /// rvref &&a; // rvalue, inner ref - bool SpelledAsLValue; - - /// True if the inner type is a reference type. This only happens - /// in non-canonical forms. - bool InnerRef; - protected: ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef, bool SpelledAsLValue) : - Type(tc, CanonicalRef, Referencee->isDependentType()), - PointeeType(Referencee), SpelledAsLValue(SpelledAsLValue), - InnerRef(Referencee->isReferenceType()) { + Type(tc, CanonicalRef, Referencee->isDependentType(), + Referencee->isVariablyModifiedType(), + Referencee->containsUnexpandedParameterPack()), + PointeeType(Referencee) + { + ReferenceTypeBits.SpelledAsLValue = SpelledAsLValue; + ReferenceTypeBits.InnerRef = Referencee->isReferenceType(); } - virtual Linkage getLinkageImpl() const; - public: - bool isSpelledAsLValue() const { return SpelledAsLValue; } - bool isInnerRef() const { return InnerRef; } + bool isSpelledAsLValue() const { return ReferenceTypeBits.SpelledAsLValue; } + bool isInnerRef() const { return ReferenceTypeBits.InnerRef; } QualType getPointeeTypeAsWritten() const { return PointeeType; } QualType getPointeeType() const { // FIXME: this might strip inner qualifiers; okay? const ReferenceType *T = this; - while (T->InnerRef) - T = T->PointeeType->getAs<ReferenceType>(); + while (T->isInnerRef()) + T = T->PointeeType->castAs<ReferenceType>(); return T->PointeeType; } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, PointeeType, SpelledAsLValue); + Profile(ID, PointeeType, isSpelledAsLValue()); } static void Profile(llvm::FoldingSetNodeID &ID, QualType Referencee, @@ -1362,14 +1756,14 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode { MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) : Type(MemberPointer, CanonicalPtr, - Cls->isDependentType() || Pointee->isDependentType()), + Cls->isDependentType() || Pointee->isDependentType(), + Pointee->isVariablyModifiedType(), + (Cls->containsUnexpandedParameterPack() || + Pointee->containsUnexpandedParameterPack())), PointeeType(Pointee), Class(Cls) { } friend class ASTContext; // ASTContext creates these. -protected: - virtual Linkage getLinkageImpl() const; - public: QualType getPointeeType() const { return PointeeType; } @@ -1420,14 +1814,6 @@ 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... @@ -1435,23 +1821,29 @@ protected: // 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) {} + ArraySizeModifier sm, unsigned tq, + bool ContainsUnexpandedParameterPack) + : Type(tc, can, et->isDependentType() || tc == DependentSizedArray, + (tc == VariableArray || et->isVariablyModifiedType()), + ContainsUnexpandedParameterPack), + ElementType(et) { + ArrayTypeBits.IndexTypeQuals = tq; + ArrayTypeBits.SizeModifier = sm; + } friend class ASTContext; // ASTContext creates these. - virtual Linkage getLinkageImpl() const; - public: QualType getElementType() const { return ElementType; } ArraySizeModifier getSizeModifier() const { - return ArraySizeModifier(SizeModifier); + return ArraySizeModifier(ArrayTypeBits.SizeModifier); } Qualifiers getIndexTypeQualifiers() const { - return Qualifiers::fromCVRMask(IndexTypeQuals); + return Qualifiers::fromCVRMask(getIndexTypeCVRQualifiers()); + } + unsigned getIndexTypeCVRQualifiers() const { + return ArrayTypeBits.IndexTypeQuals; } - unsigned getIndexTypeCVRQualifiers() const { return IndexTypeQuals; } static bool classof(const Type *T) { return T->getTypeClass() == ConstantArray || @@ -1471,12 +1863,14 @@ class ConstantArrayType : public ArrayType { ConstantArrayType(QualType et, QualType can, const llvm::APInt &size, ArraySizeModifier sm, unsigned tq) - : ArrayType(ConstantArray, et, can, sm, tq), + : ArrayType(ConstantArray, et, can, sm, tq, + et->containsUnexpandedParameterPack()), Size(size) {} protected: ConstantArrayType(TypeClass tc, QualType et, QualType can, const llvm::APInt &size, ArraySizeModifier sm, unsigned tq) - : ArrayType(tc, et, can, sm, tq), Size(size) {} + : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()), + Size(size) {} friend class ASTContext; // ASTContext creates these. public: const llvm::APInt &getSize() const { return Size; } @@ -1519,7 +1913,8 @@ class IncompleteArrayType : public ArrayType { IncompleteArrayType(QualType et, QualType can, ArraySizeModifier sm, unsigned tq) - : ArrayType(IncompleteArray, et, can, sm, tq) {} + : ArrayType(IncompleteArray, et, can, sm, tq, + et->containsUnexpandedParameterPack()) {} friend class ASTContext; // ASTContext creates these. public: bool isSugared() const { return false; } @@ -1570,7 +1965,8 @@ class VariableArrayType : public ArrayType { VariableArrayType(QualType et, QualType can, Expr *e, ArraySizeModifier sm, unsigned tq, SourceRange brackets) - : ArrayType(VariableArray, et, can, sm, tq), + : ArrayType(VariableArray, et, can, sm, tq, + et->containsUnexpandedParameterPack()), SizeExpr((Stmt*) e), Brackets(brackets) {} friend class ASTContext; // ASTContext creates these. @@ -1613,7 +2009,7 @@ public: /// until template instantiation occurs, at which point this will /// become either a ConstantArrayType or a VariableArrayType. class DependentSizedArrayType : public ArrayType { - ASTContext &Context; + const ASTContext &Context; /// \brief An assignment expression that will instantiate to the /// size of the array. @@ -1625,11 +2021,10 @@ class DependentSizedArrayType : public ArrayType { /// Brackets - The left and right array brackets. SourceRange Brackets; - DependentSizedArrayType(ASTContext &Context, QualType et, QualType can, + DependentSizedArrayType(const ASTContext &Context, QualType et, QualType can, Expr *e, ArraySizeModifier sm, unsigned tq, - SourceRange brackets) - : ArrayType(DependentSizedArray, et, can, sm, tq), - Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {} + SourceRange brackets); + friend class ASTContext; // ASTContext creates these. public: @@ -1658,7 +2053,7 @@ public: getSizeModifier(), getIndexTypeCVRQualifiers(), getSizeExpr()); } - static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, QualType ET, ArraySizeModifier SizeMod, unsigned TypeQuals, Expr *E); }; @@ -1672,17 +2067,15 @@ public: /// } /// @endcode class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { - ASTContext &Context; + const ASTContext &Context; Expr *SizeExpr; /// ElementType - The element type of the array. QualType ElementType; SourceLocation loc; - DependentSizedExtVectorType(ASTContext &Context, QualType ElementType, - QualType can, Expr *SizeExpr, SourceLocation loc) - : Type (DependentSizedExtVector, can, true), - Context(Context), SizeExpr(SizeExpr), ElementType(ElementType), - loc(loc) {} + DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType, + QualType can, Expr *SizeExpr, SourceLocation loc); + friend class ASTContext; public: @@ -1702,7 +2095,7 @@ public: Profile(ID, Context, getElementType(), getSizeExpr()); } - static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, QualType ElementType, Expr *SizeExpr); }; @@ -1714,53 +2107,49 @@ public: /// client is responsible for converting the size into the number of elements. class VectorType : public Type, public llvm::FoldingSetNode { public: - enum AltiVecSpecific { - NotAltiVec, // is not AltiVec vector - AltiVec, // is AltiVec vector - Pixel, // is AltiVec 'vector Pixel' - Bool // is AltiVec 'vector bool ...' + enum VectorKind { + GenericVector, // not a target-specific vector type + AltiVecVector, // is AltiVec vector + AltiVecPixel, // is AltiVec 'vector Pixel' + AltiVecBool, // is AltiVec 'vector bool ...' + NeonVector, // is ARM Neon vector + NeonPolyVector // is ARM Neon polynomial vector }; protected: /// ElementType - The element type of the vector. QualType ElementType; - /// NumElements - The number of elements in the vector. - unsigned NumElements; - - AltiVecSpecific AltiVecSpec; - VectorType(QualType vecType, unsigned nElements, QualType canonType, - AltiVecSpecific altiVecSpec) : - Type(Vector, canonType, vecType->isDependentType()), - ElementType(vecType), NumElements(nElements), AltiVecSpec(altiVecSpec) {} + VectorKind vecKind); + VectorType(TypeClass tc, QualType vecType, unsigned nElements, - QualType canonType, AltiVecSpecific altiVecSpec) - : Type(tc, canonType, vecType->isDependentType()), ElementType(vecType), - NumElements(nElements), AltiVecSpec(altiVecSpec) {} + QualType canonType, VectorKind vecKind); + friend class ASTContext; // ASTContext creates these. - virtual Linkage getLinkageImpl() const; - public: QualType getElementType() const { return ElementType; } - unsigned getNumElements() const { return NumElements; } + unsigned getNumElements() const { return VectorTypeBits.NumElements; } bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - AltiVecSpecific getAltiVecSpecific() const { return AltiVecSpec; } + VectorKind getVectorKind() const { + return VectorKind(VectorTypeBits.VecKind); + } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getElementType(), getNumElements(), getTypeClass(), AltiVecSpec); + Profile(ID, getElementType(), getNumElements(), + getTypeClass(), getVectorKind()); } static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType, unsigned NumElements, TypeClass TypeClass, - unsigned AltiVecSpec) { + VectorKind VecKind) { ID.AddPointer(ElementType.getAsOpaquePtr()); ID.AddInteger(NumElements); ID.AddInteger(TypeClass); - ID.AddInteger(AltiVecSpec); + ID.AddInteger(VecKind); } static bool classof(const Type *T) { @@ -1776,7 +2165,7 @@ public: /// 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, NotAltiVec) {} + VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {} friend class ASTContext; // ASTContext creates these. public: static int getPointAccessorIdx(char c) { @@ -1823,7 +2212,7 @@ public: bool isAccessorWithinNumElements(char c) const { if (int idx = getAccessorIdx(c)+1) - return unsigned(idx-1) < NumElements; + return unsigned(idx-1) < getNumElements(); return false; } bool isSugared() const { return false; } @@ -1839,40 +2228,20 @@ public: /// class of FunctionNoProtoType and FunctionProtoType. /// class FunctionType : public Type { - virtual void ANCHOR(); // Key function for FunctionType. - - /// 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; - - /// NoReturn - Indicates if the function type is attribute noreturn. - unsigned NoReturn : 1; - - /// RegParm - How many arguments to pass inreg. - unsigned RegParm : 3; - - /// CallConv - The calling convention used by the function. - unsigned CallConv : 3; - // The type returned by the function. QualType ResultType; public: - // This class is used for passing arround the information needed to - // construct a call. It is not actually used for storage, just for - // factoring together common arguments. - // If you add a field (say Foo), other than the obvious places (both, constructors, - // compile failures), what you need to update is - // * Operetor== + /// ExtInfo - A class which abstracts out some details necessary for + /// making a call. + /// + /// It is not actually used directly for storing this information in + /// a FunctionType, although FunctionType does currently use the + /// same bit-pattern. + /// + // If you add a field (say Foo), other than the obvious places (both, + // constructors, compile failures), what you need to update is + // * Operator== // * getFoo // * withFoo // * functionType. Add Foo, getFoo. @@ -1883,76 +2252,100 @@ class FunctionType : public Type { // * TypePrinter::PrintFunctionProto // * AST read and write // * Codegen - class ExtInfo { + // Feel free to rearrange or add bits, but if you go over 8, + // you'll need to adjust both the Bits field below and + // Type::FunctionTypeBitfields. + + // | CC |noreturn|regparm + // |0 .. 2| 3 |4 .. 6 + enum { CallConvMask = 0x7 }; + enum { NoReturnMask = 0x8 }; + enum { RegParmMask = ~(CallConvMask | NoReturnMask), + RegParmOffset = 4 }; + + unsigned char Bits; + + ExtInfo(unsigned Bits) : Bits(static_cast<unsigned char>(Bits)) {} + + friend class FunctionType; + public: // Constructor with no defaults. Use this when you know that you // have all the elements (when reading an AST file for example). - ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) : - NoReturn(noReturn), RegParm(regParm), CC(cc) {} + ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) { + Bits = ((unsigned) cc) | + (noReturn ? NoReturnMask : 0) | + (regParm << RegParmOffset); + } // Constructor with all defaults. Use when for example creating a // function know to use defaults. - ExtInfo() : NoReturn(false), RegParm(0), CC(CC_Default) {} + ExtInfo() : Bits(0) {} - bool getNoReturn() const { return NoReturn; } - unsigned getRegParm() const { return RegParm; } - CallingConv getCC() const { return CC; } + bool getNoReturn() const { return Bits & NoReturnMask; } + unsigned getRegParm() const { return Bits >> RegParmOffset; } + CallingConv getCC() const { return CallingConv(Bits & CallConvMask); } - bool operator==(const ExtInfo &Other) const { - return getNoReturn() == Other.getNoReturn() && - getRegParm() == Other.getRegParm() && - getCC() == Other.getCC(); + bool operator==(ExtInfo Other) const { + return Bits == Other.Bits; } - bool operator!=(const ExtInfo &Other) const { - return !(*this == Other); + bool operator!=(ExtInfo Other) const { + return Bits != Other.Bits; } // Note that we don't have setters. That is by design, use // the following with methods instead of mutating these objects. ExtInfo withNoReturn(bool noReturn) const { - return ExtInfo(noReturn, getRegParm(), getCC()); + if (noReturn) + return ExtInfo(Bits | NoReturnMask); + else + return ExtInfo(Bits & ~NoReturnMask); } ExtInfo withRegParm(unsigned RegParm) const { - return ExtInfo(getNoReturn(), RegParm, getCC()); + return ExtInfo((Bits & ~RegParmMask) | (RegParm << RegParmOffset)); } ExtInfo withCallingConv(CallingConv cc) const { - return ExtInfo(getNoReturn(), getRegParm(), cc); + return ExtInfo((Bits & ~CallConvMask) | (unsigned) cc); } - private: - // True if we have __attribute__((noreturn)) - bool NoReturn; - // The value passed to __attribute__((regparm(x))) - unsigned RegParm; - // The calling convention as specified via - // __attribute__((cdecl|stdcall|fastcall|thiscall|pascal)) - CallingConv CC; + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddInteger(Bits); + } }; protected: - FunctionType(TypeClass tc, QualType res, bool SubclassInfo, - unsigned typeQuals, QualType Canonical, bool Dependent, - const ExtInfo &Info) - : Type(tc, Canonical, Dependent), - SubClassData(SubclassInfo), TypeQuals(typeQuals), - NoReturn(Info.getNoReturn()), - RegParm(Info.getRegParm()), CallConv(Info.getCC()), ResultType(res) {} - bool getSubClassData() const { return SubClassData; } - unsigned getTypeQuals() const { return TypeQuals; } + FunctionType(TypeClass tc, QualType res, bool variadic, + unsigned typeQuals, RefQualifierKind RefQualifier, + QualType Canonical, bool Dependent, + bool VariablyModified, bool ContainsUnexpandedParameterPack, + ExtInfo Info) + : Type(tc, Canonical, Dependent, VariablyModified, + ContainsUnexpandedParameterPack), + ResultType(res) { + FunctionTypeBits.ExtInfo = Info.Bits; + FunctionTypeBits.Variadic = variadic; + FunctionTypeBits.TypeQuals = typeQuals; + FunctionTypeBits.RefQualifier = static_cast<unsigned>(RefQualifier); + } + bool isVariadic() const { return FunctionTypeBits.Variadic; } + unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; } + + RefQualifierKind getRefQualifier() const { + return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier); + } + public: QualType getResultType() const { return ResultType; } - unsigned getRegParmType() const { return RegParm; } - bool getNoReturnAttr() const { return NoReturn; } - CallingConv getCallConv() const { return (CallingConv)CallConv; } - ExtInfo getExtInfo() const { - return ExtInfo(NoReturn, RegParm, (CallingConv)CallConv); - } + unsigned getRegParmType() const { return getExtInfo().getRegParm(); } + bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); } + CallingConv getCallConv() const { return getExtInfo().getCC(); } + ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); } /// \brief Determine the type of an expression that calls a function of /// this type. @@ -1972,15 +2365,13 @@ public: /// 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, - const ExtInfo &Info) - : FunctionType(FunctionNoProto, Result, false, 0, Canonical, - /*Dependent=*/false, Info) {} + FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info) + : FunctionType(FunctionNoProto, Result, false, 0, RQ_None, Canonical, + /*Dependent=*/false, Result->isVariablyModifiedType(), + /*ContainsUnexpandedParameterPack=*/false, Info) {} + friend class ASTContext; // ASTContext creates these. -protected: - virtual Linkage getLinkageImpl() const; - public: // No additional state past what FunctionType provides. @@ -1991,10 +2382,8 @@ public: Profile(ID, getResultType(), getExtInfo()); } static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType, - const ExtInfo &Info) { - ID.AddInteger(Info.getCC()); - ID.AddInteger(Info.getRegParm()); - ID.AddInteger(Info.getNoReturn()); + ExtInfo Info) { + Info.Profile(ID); ID.AddPointer(ResultType.getAsOpaquePtr()); } @@ -2010,36 +2399,37 @@ public: /// 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) { +public: + /// ExtProtoInfo - Extra information about a function prototype. + struct ExtProtoInfo { + ExtProtoInfo() : + Variadic(false), HasExceptionSpec(false), HasAnyExceptionSpec(false), + TypeQuals(0), RefQualifier(RQ_None), NumExceptions(0), Exceptions(0) {} + + FunctionType::ExtInfo ExtInfo; + bool Variadic; + bool HasExceptionSpec; + bool HasAnyExceptionSpec; + unsigned char TypeQuals; + RefQualifierKind RefQualifier; + unsigned NumExceptions; + const QualType *Exceptions; + }; + +private: + /// \brief Determine whether there are any argument types that + /// contain an unexpanded parameter pack. + static bool containsAnyUnexpandedParameterPack(const QualType *ArgArray, + unsigned numArgs) { for (unsigned Idx = 0; Idx < numArgs; ++Idx) - if (ArgArray[Idx]->isDependentType()) - return true; + if (ArgArray[Idx]->containsUnexpandedParameterPack()) + 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, - const ExtInfo &Info) - : FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical, - (Result->isDependentType() || - hasAnyDependentType(ArgArray, numArgs)), - Info), - 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]; - } + FunctionProtoType(QualType result, const QualType *args, unsigned numArgs, + QualType canonical, const ExtProtoInfo &epi); /// NumArgs - The number of arguments this function has, not counting '...'. unsigned NumArgs : 20; @@ -2048,10 +2438,10 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { unsigned NumExceptions : 10; /// HasExceptionSpec - Whether this function has an exception spec at all. - bool HasExceptionSpec : 1; + unsigned HasExceptionSpec : 1; - /// AnyExceptionSpec - Whether this function has a throw(...) spec. - bool AnyExceptionSpec : 1; + /// HasAnyExceptionSpec - Whether this function has a throw(...) spec. + unsigned HasAnyExceptionSpec : 1; /// ArgInfo - There is an variable size array after the class in memory that /// holds the argument types. @@ -2061,9 +2451,6 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these. -protected: - virtual Linkage getLinkageImpl() const; - public: unsigned getNumArgs() const { return NumArgs; } QualType getArgType(unsigned i) const { @@ -2071,8 +2458,21 @@ public: return arg_type_begin()[i]; } + ExtProtoInfo getExtProtoInfo() const { + ExtProtoInfo EPI; + EPI.ExtInfo = getExtInfo(); + EPI.Variadic = isVariadic(); + EPI.HasExceptionSpec = hasExceptionSpec(); + EPI.HasAnyExceptionSpec = hasAnyExceptionSpec(); + EPI.TypeQuals = static_cast<unsigned char>(getTypeQuals()); + EPI.RefQualifier = getRefQualifier(); + EPI.NumExceptions = NumExceptions; + EPI.Exceptions = exception_begin(); + return EPI; + } + bool hasExceptionSpec() const { return HasExceptionSpec; } - bool hasAnyExceptionSpec() const { return AnyExceptionSpec; } + bool hasAnyExceptionSpec() const { return HasAnyExceptionSpec; } unsigned getNumExceptions() const { return NumExceptions; } QualType getExceptionType(unsigned i) const { assert(i < NumExceptions && "Invalid exception number!"); @@ -2083,9 +2483,24 @@ public: getNumExceptions() == 0; } - bool isVariadic() const { return getSubClassData(); } + using FunctionType::isVariadic; + + /// \brief Determines whether this function prototype contains a + /// parameter pack at the end. + /// + /// A function template whose last parameter is a parameter pack can be + /// called with an arbitrary number of arguments, much like a variadic + /// function. However, + bool isTemplateVariadic() const; + unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); } + + /// \brief Retrieve the ref-qualifier associated with this function type. + RefQualifierKind getRefQualifier() const { + return FunctionType::getRefQualifier(); + } + typedef const QualType *arg_type_iterator; arg_type_iterator arg_type_begin() const { return reinterpret_cast<const QualType *>(this+1); @@ -2112,10 +2527,7 @@ public: 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, - const ExtInfo &ExtInfo); + const ExtProtoInfo &EPI); }; @@ -2127,7 +2539,8 @@ class UnresolvedUsingType : public Type { UnresolvedUsingTypenameDecl *Decl; UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D) - : Type(UnresolvedUsing, QualType(), true), + : Type(UnresolvedUsing, QualType(), true, false, + /*ContainsUnexpandedParameterPack=*/false), Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {} friend class ASTContext; // ASTContext creates these. public: @@ -2156,7 +2569,8 @@ class TypedefType : public Type { TypedefDecl *Decl; protected: TypedefType(TypeClass tc, const TypedefDecl *D, QualType can) - : Type(tc, can, can->isDependentType()), + : Type(tc, can, can->isDependentType(), can->isVariablyModifiedType(), + /*ContainsUnexpandedParameterPack=*/false), Decl(const_cast<TypedefDecl*>(D)) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); } @@ -2165,14 +2579,6 @@ 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; - bool isSugared() const { return true; } QualType desugar() const; @@ -2208,10 +2614,10 @@ public: /// of this class via TypeOfExprType nodes. class DependentTypeOfExprType : public TypeOfExprType, public llvm::FoldingSetNode { - ASTContext &Context; + const ASTContext &Context; public: - DependentTypeOfExprType(ASTContext &Context, Expr *E) + DependentTypeOfExprType(const ASTContext &Context, Expr *E) : TypeOfExprType(E), Context(Context) { } bool isSugared() const { return false; } @@ -2221,7 +2627,7 @@ public: Profile(ID, Context, getUnderlyingExpr()); } - static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, Expr *E); }; @@ -2229,7 +2635,9 @@ public: class TypeOfType : public Type { QualType TOType; TypeOfType(QualType T, QualType can) - : Type(TypeOf, can, T->isDependentType()), TOType(T) { + : Type(TypeOf, can, T->isDependentType(), T->isVariablyModifiedType(), + T->containsUnexpandedParameterPack()), + TOType(T) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); } friend class ASTContext; // ASTContext creates these. @@ -2279,10 +2687,10 @@ public: /// canonical, dependent types, only. Clients will only see instances /// of this class via DecltypeType nodes. class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode { - ASTContext &Context; + const ASTContext &Context; public: - DependentDecltypeType(ASTContext &Context, Expr *E); + DependentDecltypeType(const ASTContext &Context, Expr *E); bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2291,7 +2699,7 @@ public: Profile(ID, Context, getUnderlyingExpr()); } - static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, Expr *E); }; @@ -2303,8 +2711,6 @@ class TagType : public Type { protected: TagType(TypeClass TC, const TagDecl *D, QualType can); - virtual Linkage getLinkageImpl() const; - public: TagDecl *getDecl() const; @@ -2340,10 +2746,6 @@ public: // 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; } - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2376,20 +2778,107 @@ public: static bool classof(const EnumType *) { return true; } }; +/// AttributedType - An attributed type is a type to which a type +/// attribute has been applied. The "modified type" is the +/// fully-sugared type to which the attributed type was applied; +/// generally it is not canonically equivalent to the attributed type. +/// The "equivalent type" is the minimally-desugared type which the +/// type is canonically equivalent to. +/// +/// For example, in the following attributed type: +/// int32_t __attribute__((vector_size(16))) +/// - the modified type is the TypedefType for int32_t +/// - the equivalent type is VectorType(16, int32_t) +/// - the canonical type is VectorType(16, int) +class AttributedType : public Type, public llvm::FoldingSetNode { +public: + // It is really silly to have yet another attribute-kind enum, but + // clang::attr::Kind doesn't currently cover the pure type attrs. + enum Kind { + // Expression operand. + attr_address_space, + attr_regparm, + attr_vector_size, + attr_neon_vector_type, + attr_neon_polyvector_type, + + FirstExprOperandKind = attr_address_space, + LastExprOperandKind = attr_neon_polyvector_type, + + // Enumerated operand (string or keyword). + attr_objc_gc, + + FirstEnumOperandKind = attr_objc_gc, + LastEnumOperandKind = attr_objc_gc, + + // No operand. + attr_noreturn, + attr_cdecl, + attr_fastcall, + attr_stdcall, + attr_thiscall, + attr_pascal + }; + +private: + QualType ModifiedType; + QualType EquivalentType; + + friend class ASTContext; // creates these + + AttributedType(QualType canon, Kind attrKind, + QualType modified, QualType equivalent) + : Type(Attributed, canon, canon->isDependentType(), + canon->isVariablyModifiedType(), + canon->containsUnexpandedParameterPack()), + ModifiedType(modified), EquivalentType(equivalent) { + AttributedTypeBits.AttrKind = attrKind; + } + +public: + Kind getAttrKind() const { + return static_cast<Kind>(AttributedTypeBits.AttrKind); + } + + QualType getModifiedType() const { return ModifiedType; } + QualType getEquivalentType() const { return EquivalentType; } + + bool isSugared() const { return true; } + QualType desugar() const { return getEquivalentType(); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getAttrKind(), ModifiedType, EquivalentType); + } + + static void Profile(llvm::FoldingSetNodeID &ID, Kind attrKind, + QualType modified, QualType equivalent) { + ID.AddInteger(attrKind); + ID.AddPointer(modified.getAsOpaquePtr()); + ID.AddPointer(equivalent.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == Attributed; + } + static bool classof(const AttributedType *T) { return true; } +}; + class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { unsigned Depth : 15; - unsigned Index : 16; unsigned ParameterPack : 1; + unsigned Index : 16; IdentifierInfo *Name; TemplateTypeParmType(unsigned D, unsigned I, bool PP, IdentifierInfo *N, QualType Canon) - : Type(TemplateTypeParm, Canon, /*Dependent=*/true), - Depth(D), Index(I), ParameterPack(PP), Name(N) { } + : Type(TemplateTypeParm, Canon, /*Dependent=*/true, + /*VariablyModified=*/false, PP), + Depth(D), ParameterPack(PP), Index(I), Name(N) { } TemplateTypeParmType(unsigned D, unsigned I, bool PP) - : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true), - Depth(D), Index(I), ParameterPack(PP), Name(0) { } + : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true, + /*VariablyModified=*/false, PP), + Depth(D), ParameterPack(PP), Index(I), Name(0) { } friend class ASTContext; // ASTContext creates these @@ -2433,7 +2922,9 @@ class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { const TemplateTypeParmType *Replaced; SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon) - : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType()), + : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(), + Canon->isVariablyModifiedType(), + Canon->containsUnexpandedParameterPack()), Replaced(Param) { } friend class ASTContext; @@ -2471,6 +2962,101 @@ public: static bool classof(const SubstTemplateTypeParmType *T) { return true; } }; +/// \brief Represents the result of substituting a set of types for a template +/// type parameter pack. +/// +/// When a pack expansion in the source code contains multiple parameter packs +/// and those parameter packs correspond to different levels of template +/// parameter lists, this type node is used to represent a template type +/// parameter pack from an outer level, which has already had its argument pack +/// substituted but that still lives within a pack expansion that itself +/// could not be instantiated. When actually performing a substitution into +/// that pack expansion (e.g., when all template parameters have corresponding +/// arguments), this type will be replaced with the \c SubstTemplateTypeParmType +/// at the current pack substitution index. +class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { + /// \brief The original type parameter. + const TemplateTypeParmType *Replaced; + + /// \brief A pointer to the set of template arguments that this + /// parameter pack is instantiated with. + const TemplateArgument *Arguments; + + /// \brief The number of template arguments in \c Arguments. + unsigned NumArguments; + + SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, + QualType Canon, + const TemplateArgument &ArgPack); + + friend class ASTContext; + +public: + IdentifierInfo *getName() const { return Replaced->getName(); } + + /// Gets the template parameter that was substituted for. + const TemplateTypeParmType *getReplacedParameter() const { + return Replaced; + } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + TemplateArgument getArgumentPack() const; + + void Profile(llvm::FoldingSetNodeID &ID); + static void Profile(llvm::FoldingSetNodeID &ID, + const TemplateTypeParmType *Replaced, + const TemplateArgument &ArgPack); + + static bool classof(const Type *T) { + return T->getTypeClass() == SubstTemplateTypeParmPack; + } + static bool classof(const SubstTemplateTypeParmPackType *T) { return true; } +}; + +/// \brief Represents a C++0x auto type. +/// +/// These types are usually a placeholder for a deduced type. However, within +/// templates and before the initializer is attached, there is no deduced type +/// and an auto type is type-dependent and canonical. +class AutoType : public Type, public llvm::FoldingSetNode { + AutoType(QualType DeducedType) + : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType, + /*Dependent=*/DeducedType.isNull(), + /*VariablyModified=*/false, /*ContainsParameterPack=*/false) { + assert((DeducedType.isNull() || !DeducedType->isDependentType()) && + "deduced a dependent type for auto"); + } + + friend class ASTContext; // ASTContext creates these + +public: + bool isSugared() const { return isDeduced(); } + QualType desugar() const { return getCanonicalTypeInternal(); } + + QualType getDeducedType() const { + return isDeduced() ? getCanonicalTypeInternal() : QualType(); + } + bool isDeduced() const { + return !isDependentType(); + } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getDeducedType()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, + QualType Deduced) { + ID.AddPointer(Deduced.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == Auto; + } + static bool classof(const AutoType *T) { return true; } +}; + /// \brief Represents the type of a template specialization as written /// in the source code. /// @@ -2516,7 +3102,8 @@ public: /// enclosing the template arguments. static std::string PrintTemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs, - const PrintingPolicy &Policy); + const PrintingPolicy &Policy, + bool SkipBrackets = false); static std::string PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs, @@ -2556,14 +3143,14 @@ public: } QualType desugar() const { return getCanonicalTypeInternal(); } - void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Ctx) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { Profile(ID, Template, getArgs(), NumArgs, Ctx); } static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T, const TemplateArgument *Args, unsigned NumArgs, - ASTContext &Context); + const ASTContext &Context); static bool classof(const Type *T) { return T->getTypeClass() == TemplateSpecialization; @@ -2607,7 +3194,9 @@ class InjectedClassNameType : public Type { // currently suitable for AST reading, too much // interdependencies. InjectedClassNameType(CXXRecordDecl *D, QualType TST) - : Type(InjectedClassName, QualType(), true), + : Type(InjectedClassName, QualType(), /*Dependent=*/true, + /*VariablyModified=*/false, + /*ContainsUnexpandedParameterPack=*/false), Decl(D), InjectedType(TST) { assert(isa<TemplateSpecializationType>(TST)); assert(!TST.hasQualifiers()); @@ -2666,19 +3255,18 @@ enum ElaboratedTypeKeyword { /// Also provides a few static helpers for converting and printing /// elaborated type keyword and tag type kind enumerations. class TypeWithKeyword : public Type { - /// Keyword - Encodes an ElaboratedTypeKeyword enumeration constant. - unsigned Keyword : 3; - protected: TypeWithKeyword(ElaboratedTypeKeyword Keyword, TypeClass tc, - QualType Canonical, bool dependent) - : Type(tc, Canonical, dependent), Keyword(Keyword) {} + QualType Canonical, bool Dependent, bool VariablyModified, + bool ContainsUnexpandedParameterPack) + : Type(tc, Canonical, Dependent, VariablyModified, + ContainsUnexpandedParameterPack) { + TypeWithKeywordBits.Keyword = Keyword; + } public: - virtual ~TypeWithKeyword(); // pin vtable to Type.cpp - ElaboratedTypeKeyword getKeyword() const { - return static_cast<ElaboratedTypeKeyword>(Keyword); + return static_cast<ElaboratedTypeKeyword>(TypeWithKeywordBits.Keyword); } /// getKeywordForTypeSpec - Converts a type specifier (DeclSpec::TST) @@ -2730,7 +3318,9 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, QualType NamedType, QualType CanonType) : TypeWithKeyword(Keyword, Elaborated, CanonType, - NamedType->isDependentType()), + NamedType->isDependentType(), + NamedType->isVariablyModifiedType(), + NamedType->containsUnexpandedParameterPack()), NNS(NNS), NamedType(NamedType) { assert(!(Keyword == ETK_None && NNS == 0) && "ElaboratedType cannot have elaborated type keyword " @@ -2790,7 +3380,9 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, QualType CanonType) - : TypeWithKeyword(Keyword, DependentName, CanonType, true), + : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true, + /*VariablyModified=*/false, + NNS->containsUnexpandedParameterPack()), NNS(NNS), Name(Name) { assert(NNS->isDependent() && "DependentNameType requires a dependent nested-name-specifier"); @@ -2799,8 +3391,6 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these public: - virtual ~DependentNameType(); - /// \brief Retrieve the qualification on this type. NestedNameSpecifier *getQualifier() const { return NNS; } @@ -2867,8 +3457,6 @@ class DependentTemplateSpecializationType : friend class ASTContext; // ASTContext creates these public: - virtual ~DependentTemplateSpecializationType(); - NestedNameSpecifier *getQualifier() const { return NNS; } const IdentifierInfo *getIdentifier() const { return Name; } @@ -2889,12 +3477,12 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getKeyword(), NNS, Name, NumArgs, getArgs()); } static void Profile(llvm::FoldingSetNodeID &ID, - ASTContext &Context, + const ASTContext &Context, ElaboratedTypeKeyword Keyword, NestedNameSpecifier *Qualifier, const IdentifierInfo *Name, @@ -2909,6 +3497,88 @@ public: } }; +/// \brief Represents a pack expansion of types. +/// +/// Pack expansions are part of C++0x variadic templates. A pack +/// expansion contains a pattern, which itself contains one or more +/// "unexpanded" parameter packs. When instantiated, a pack expansion +/// produces a series of types, each instantiated from the pattern of +/// the expansion, where the Ith instantiation of the pattern uses the +/// Ith arguments bound to each of the unexpanded parameter packs. The +/// pack expansion is considered to "expand" these unexpanded +/// parameter packs. +/// +/// \code +/// template<typename ...Types> struct tuple; +/// +/// template<typename ...Types> +/// struct tuple_of_references { +/// typedef tuple<Types&...> type; +/// }; +/// \endcode +/// +/// Here, the pack expansion \c Types&... is represented via a +/// PackExpansionType whose pattern is Types&. +class PackExpansionType : public Type, public llvm::FoldingSetNode { + /// \brief The pattern of the pack expansion. + QualType Pattern; + + /// \brief The number of expansions that this pack expansion will + /// generate when substituted (+1), or indicates that + /// + /// This field will only have a non-zero value when some of the parameter + /// packs that occur within the pattern have been substituted but others have + /// not. + unsigned NumExpansions; + + PackExpansionType(QualType Pattern, QualType Canon, + llvm::Optional<unsigned> NumExpansions) + : Type(PackExpansion, Canon, /*Dependent=*/true, + /*VariableModified=*/Pattern->isVariablyModifiedType(), + /*ContainsUnexpandedParameterPack=*/false), + Pattern(Pattern), + NumExpansions(NumExpansions? *NumExpansions + 1: 0) { } + + friend class ASTContext; // ASTContext creates these + +public: + /// \brief Retrieve the pattern of this pack expansion, which is the + /// type that will be repeatedly instantiated when instantiating the + /// pack expansion itself. + QualType getPattern() const { return Pattern; } + + /// \brief Retrieve the number of expansions that this pack expansion will + /// generate, if known. + llvm::Optional<unsigned> getNumExpansions() const { + if (NumExpansions) + return NumExpansions - 1; + + return llvm::Optional<unsigned>(); + } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getPattern(), getNumExpansions()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pattern, + llvm::Optional<unsigned> NumExpansions) { + ID.AddPointer(Pattern.getAsOpaquePtr()); + ID.AddBoolean(NumExpansions); + if (NumExpansions) + ID.AddInteger(*NumExpansions); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == PackExpansion; + } + static bool classof(const PackExpansionType *T) { + return true; + } +}; + /// ObjCObjectType - Represents a class type in Objective C. /// Every Objective C type is a combination of a base type and a /// list of protocols. @@ -2930,19 +3600,15 @@ public: /// with base BuiltinType::ObjCIdType and protocol list [P]. Eventually /// this should get its own sugar class to better represent the source. class ObjCObjectType : public Type { - // Pad the bit count up so that NumProtocols is 2-byte aligned - unsigned : BitsRemainingInType - 16; - - /// \brief The number of protocols stored after the - /// ObjCObjectPointerType node. - /// - /// These protocols are those written directly on the type. If - /// protocol qualifiers ever become additive, the iterators will - /// get kindof complicated. - /// - /// In the canonical object type, these are sorted alphabetically - /// and uniqued. - unsigned NumProtocols : 16; + // ObjCObjectType.NumProtocols - the number of protocols stored + // after the ObjCObjectPointerType node. + // + // These protocols are those written directly on the type. If + // protocol qualifiers ever become additive, the iterators will need + // to get kindof complicated. + // + // In the canonical object type, these are sorted alphabetically + // and uniqued. /// Either a BuiltinType or an InterfaceType or sugar for either. QualType BaseType; @@ -2959,13 +3625,11 @@ protected: enum Nonce_ObjCInterface { Nonce_ObjCInterface }; ObjCObjectType(enum Nonce_ObjCInterface) - : Type(ObjCInterface, QualType(), false), - NumProtocols(0), - BaseType(QualType(this_(), 0)) {} + : Type(ObjCInterface, QualType(), false, false, false), + BaseType(QualType(this_(), 0)) { + ObjCObjectTypeBits.NumProtocols = 0; + } -protected: - Linkage getLinkageImpl() const; // key function - public: /// getBaseType - Gets the base type of this object type. This is /// always (possibly sugar for) one of: @@ -3006,7 +3670,7 @@ public: /// getNumProtocols - Return the number of qualifying protocols in this /// interface type, or 0 if there are none. - unsigned getNumProtocols() const { return NumProtocols; } + unsigned getNumProtocols() const { return ObjCObjectTypeBits.NumProtocols; } /// \brief Fetch a protocol by index. ObjCProtocolDecl *getProtocol(unsigned I) const { @@ -3072,6 +3736,7 @@ class ObjCInterfaceType : public ObjCObjectType { : ObjCObjectType(Nonce_ObjCInterface), Decl(const_cast<ObjCInterfaceDecl*>(D)) {} friend class ASTContext; // ASTContext creates these. + public: /// getDecl - Get the declaration of this interface. ObjCInterfaceDecl *getDecl() const { return Decl; } @@ -3117,13 +3782,10 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { QualType PointeeType; ObjCObjectPointerType(QualType Canonical, QualType Pointee) - : Type(ObjCObjectPointer, Canonical, false), + : Type(ObjCObjectPointer, Canonical, false, false, false), PointeeType(Pointee) {} friend class ASTContext; // ASTContext creates these. -protected: - virtual Linkage getLinkageImpl() const; - public: /// getPointeeType - Gets the type pointed to by this ObjC pointer. /// The result will always be an ObjCObjectType or sugar thereof. @@ -3152,7 +3814,7 @@ public: /// would return 'A1P<Q>' (and we'd have to make iterating over /// qualifiers more complicated). const ObjCObjectType *getObjectType() const { - return PointeeType->getAs<ObjCObjectType>(); + return PointeeType->castAs<ObjCObjectType>(); } /// getInterfaceType - If this pointer points to an Objective C @@ -3238,177 +3900,154 @@ public: /// A qualifier set is used to build a set of qualifiers. class QualifierCollector : public Qualifiers { - ASTContext *Context; - public: - QualifierCollector(Qualifiers Qs = Qualifiers()) - : Qualifiers(Qs), Context(0) {} - QualifierCollector(ASTContext &Context, Qualifiers Qs = Qualifiers()) - : Qualifiers(Qs), Context(&Context) {} - - void setContext(ASTContext &C) { Context = &C; } + QualifierCollector(Qualifiers Qs = Qualifiers()) : Qualifiers(Qs) {} /// Collect any qualifiers on the given type and return an - /// unqualified type. - const Type *strip(QualType QT) { - addFastQualifiers(QT.getLocalFastQualifiers()); - if (QT.hasLocalNonFastQualifiers()) { - const ExtQuals *EQ = QT.getExtQualsUnsafe(); - Context = &EQ->getContext(); - addQualifiers(EQ->getQualifiers()); - return EQ->getBaseType(); - } - return QT.getTypePtrUnsafe(); + /// unqualified type. The qualifiers are assumed to be consistent + /// with those already in the type. + const Type *strip(QualType type) { + addFastQualifiers(type.getLocalFastQualifiers()); + if (!type.hasLocalNonFastQualifiers()) + return type.getTypePtrUnsafe(); + + const ExtQuals *extQuals = type.getExtQualsUnsafe(); + addConsistentQualifiers(extQuals->getQualifiers()); + return extQuals->getBaseType(); } /// Apply the collected qualifiers to the given type. - QualType apply(QualType QT) const; + QualType apply(const ASTContext &Context, QualType QT) const; /// Apply the collected qualifiers to the given type. - QualType apply(const Type* T) const; - + QualType apply(const ASTContext &Context, const Type* T) const; }; // Inline function definitions. +inline const Type *QualType::getTypePtr() const { + return getCommonPtr()->BaseType; +} + +inline const Type *QualType::getTypePtrOrNull() const { + return (isNull() ? 0 : getCommonPtr()->BaseType); +} + +inline SplitQualType QualType::split() const { + if (!hasLocalNonFastQualifiers()) + return SplitQualType(getTypePtrUnsafe(), + Qualifiers::fromFastMask(getLocalFastQualifiers())); + + const ExtQuals *eq = getExtQualsUnsafe(); + Qualifiers qs = eq->getQualifiers(); + qs.addFastQualifiers(getLocalFastQualifiers()); + return SplitQualType(eq->getBaseType(), qs); +} + +inline Qualifiers QualType::getLocalQualifiers() const { + Qualifiers Quals; + if (hasLocalNonFastQualifiers()) + Quals = getExtQualsUnsafe()->getQualifiers(); + Quals.addFastQualifiers(getLocalFastQualifiers()); + return Quals; +} + +inline Qualifiers QualType::getQualifiers() const { + Qualifiers quals = getCommonPtr()->CanonicalType.getLocalQualifiers(); + quals.addFastQualifiers(getLocalFastQualifiers()); + return quals; +} + +inline unsigned QualType::getCVRQualifiers() const { + unsigned cvr = getCommonPtr()->CanonicalType.getLocalCVRQualifiers(); + cvr |= getLocalCVRQualifiers(); + return cvr; +} + +inline QualType QualType::getCanonicalType() const { + QualType canon = getCommonPtr()->CanonicalType; + return canon.withFastQualifiers(getLocalFastQualifiers()); +} + inline bool QualType::isCanonical() const { - const Type *T = getTypePtr(); - if (hasLocalQualifiers()) - return T->isCanonicalUnqualified() && !isa<ArrayType>(T); - return T->isCanonicalUnqualified(); + return getTypePtr()->isCanonicalUnqualified(); } inline bool QualType::isCanonicalAsParam() const { + if (!isCanonical()) return false; if (hasLocalQualifiers()) return false; + const Type *T = getTypePtr(); - return T->isCanonicalUnqualified() && - !isa<FunctionType>(T) && !isa<ArrayType>(T); + if (T->isVariablyModifiedType() && T->hasSizedVLAType()) + return false; + + return !isa<FunctionType>(T) && !isa<ArrayType>(T); } inline bool QualType::isConstQualified() const { return isLocalConstQualified() || - getTypePtr()->getCanonicalTypeInternal().isLocalConstQualified(); + getCommonPtr()->CanonicalType.isLocalConstQualified(); } inline bool QualType::isRestrictQualified() const { return isLocalRestrictQualified() || - getTypePtr()->getCanonicalTypeInternal().isLocalRestrictQualified(); + getCommonPtr()->CanonicalType.isLocalRestrictQualified(); } inline bool QualType::isVolatileQualified() const { return isLocalVolatileQualified() || - getTypePtr()->getCanonicalTypeInternal().isLocalVolatileQualified(); + getCommonPtr()->CanonicalType.isLocalVolatileQualified(); } inline bool QualType::hasQualifiers() const { return hasLocalQualifiers() || - getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers(); -} - -inline Qualifiers QualType::getQualifiers() const { - Qualifiers Quals = getLocalQualifiers(); - Quals.addQualifiers( - getTypePtr()->getCanonicalTypeInternal().getLocalQualifiers()); - return Quals; -} - -inline unsigned QualType::getCVRQualifiers() const { - return getLocalCVRQualifiers() | - getTypePtr()->getCanonicalTypeInternal().getLocalCVRQualifiers(); + getCommonPtr()->CanonicalType.hasLocalQualifiers(); } -/// getCVRQualifiersThroughArrayTypes - If there are CVR qualifiers for this -/// type, returns them. Otherwise, if this is an array type, recurses -/// on the element type until some qualifiers have been found or a non-array -/// type reached. -inline unsigned QualType::getCVRQualifiersThroughArrayTypes() const { - if (unsigned Quals = getCVRQualifiers()) - return Quals; - QualType CT = getTypePtr()->getCanonicalTypeInternal(); - if (const ArrayType *AT = dyn_cast<ArrayType>(CT)) - return AT->getElementType().getCVRQualifiersThroughArrayTypes(); - return 0; +inline QualType QualType::getUnqualifiedType() const { + if (!getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers()) + return QualType(getTypePtr(), 0); + + return QualType(getSplitUnqualifiedTypeImpl(*this).first, 0); } -inline void QualType::removeConst() { - removeFastQualifiers(Qualifiers::Const); +inline SplitQualType QualType::getSplitUnqualifiedType() const { + if (!getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers()) + return split(); + + return getSplitUnqualifiedTypeImpl(*this); +} + +inline void QualType::removeLocalConst() { + removeLocalFastQualifiers(Qualifiers::Const); } -inline void QualType::removeRestrict() { - removeFastQualifiers(Qualifiers::Restrict); +inline void QualType::removeLocalRestrict() { + removeLocalFastQualifiers(Qualifiers::Restrict); } -inline void QualType::removeVolatile() { - QualifierCollector Qc; - const Type *Ty = Qc.strip(*this); - if (Qc.hasVolatile()) { - Qc.removeVolatile(); - *this = Qc.apply(Ty); - } +inline void QualType::removeLocalVolatile() { + removeLocalFastQualifiers(Qualifiers::Volatile); } -inline void QualType::removeCVRQualifiers(unsigned Mask) { +inline void QualType::removeLocalCVRQualifiers(unsigned Mask) { assert(!(Mask & ~Qualifiers::CVRMask) && "mask has non-CVR bits"); + assert((int)Qualifiers::CVRMask == (int)Qualifiers::FastMask); // Fast path: we don't need to touch the slow qualifiers. - if (!(Mask & ~Qualifiers::FastMask)) { - removeFastQualifiers(Mask); - return; - } - - QualifierCollector Qc; - const Type *Ty = Qc.strip(*this); - Qc.removeCVRQualifiers(Mask); - *this = Qc.apply(Ty); + removeLocalFastQualifiers(Mask); } /// getAddressSpace - Return the address space of this type. inline unsigned QualType::getAddressSpace() const { - if (hasLocalNonFastQualifiers()) { - const ExtQuals *EQ = getExtQualsUnsafe(); - if (EQ->hasAddressSpace()) - return EQ->getAddressSpace(); - } - - QualType CT = getTypePtr()->getCanonicalTypeInternal(); - if (CT.hasLocalNonFastQualifiers()) { - const ExtQuals *EQ = CT.getExtQualsUnsafe(); - if (EQ->hasAddressSpace()) - return EQ->getAddressSpace(); - } - - if (const ArrayType *AT = dyn_cast<ArrayType>(CT)) - return AT->getElementType().getAddressSpace(); - if (const RecordType *RT = dyn_cast<RecordType>(CT)) - return RT->getAddressSpace(); - return 0; + return getQualifiers().getAddressSpace(); } /// getObjCGCAttr - Return the gc attribute of this type. inline Qualifiers::GC QualType::getObjCGCAttr() const { - if (hasLocalNonFastQualifiers()) { - const ExtQuals *EQ = getExtQualsUnsafe(); - if (EQ->hasObjCGCAttr()) - return EQ->getObjCGCAttr(); - } - - QualType CT = getTypePtr()->getCanonicalTypeInternal(); - if (CT.hasLocalNonFastQualifiers()) { - const ExtQuals *EQ = CT.getExtQualsUnsafe(); - if (EQ->hasObjCGCAttr()) - return EQ->getObjCGCAttr(); - } - - if (const ArrayType *AT = dyn_cast<ArrayType>(CT)) - return AT->getElementType().getObjCGCAttr(); - if (const ObjCObjectPointerType *PT = CT->getAs<ObjCObjectPointerType>()) - return PT->getPointeeType().getObjCGCAttr(); - // We most look at all pointer types, not just pointer to interface types. - if (const PointerType *PT = CT->getAs<PointerType>()) - return PT->getPointeeType().getObjCGCAttr(); - return Qualifiers::GCNone; + return getQualifiers().getObjCGCAttr(); } inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) { @@ -3436,26 +4075,18 @@ inline bool Qualifiers::isSupersetOf(Qualifiers Other) const { /// 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 { - // FIXME: work on arbitrary qualifiers - unsigned MyQuals = this->getCVRQualifiersThroughArrayTypes(); - unsigned OtherQuals = Other.getCVRQualifiersThroughArrayTypes(); - if (getAddressSpace() != Other.getAddressSpace()) - return false; - return MyQuals != OtherQuals && (MyQuals | OtherQuals) == MyQuals; +inline bool QualType::isMoreQualifiedThan(QualType other) const { + Qualifiers myQuals = getQualifiers(); + Qualifiers otherQuals = other.getQualifiers(); + return (myQuals != otherQuals && myQuals.compatiblyIncludes(otherQuals)); } /// 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 { - // FIXME: work on arbitrary qualifiers - unsigned MyQuals = this->getCVRQualifiersThroughArrayTypes(); - unsigned OtherQuals = Other.getCVRQualifiersThroughArrayTypes(); - if (getAddressSpace() != Other.getAddressSpace()) - return false; - return (MyQuals | OtherQuals) == MyQuals; +inline bool QualType::isAtLeastAsQualifiedAs(QualType other) const { + return getQualifiers().compatiblyIncludes(other.getQualifiers()); } /// getNonReferenceType - If Type is a reference type (e.g., const @@ -3496,7 +4127,7 @@ inline bool Type::isRValueReferenceType() const { return isa<RValueReferenceType>(CanonicalType); } inline bool Type::isFunctionPointerType() const { - if (const PointerType* T = getAs<PointerType>()) + if (const PointerType *T = getAs<PointerType>()) return T->getPointeeType()->isFunctionType(); else return false; @@ -3531,9 +4162,15 @@ inline bool Type::isVariableArrayType() const { inline bool Type::isDependentSizedArrayType() const { return isa<DependentSizedArrayType>(CanonicalType); } +inline bool Type::isBuiltinType() const { + return isa<BuiltinType>(CanonicalType); +} inline bool Type::isRecordType() const { return isa<RecordType>(CanonicalType); } +inline bool Type::isEnumeralType() const { + return isa<EnumType>(CanonicalType); +} inline bool Type::isAnyComplexType() const { return isa<ComplexType>(CanonicalType); } @@ -3586,10 +4223,6 @@ inline bool Type::isTemplateTypeParmType() const { return isa<TemplateTypeParmType>(CanonicalType); } -inline bool Type::isBuiltinType() const { - return getAs<BuiltinType>(); -} - inline bool Type::isSpecificBuiltinType(unsigned K) const { if (const BuiltinType *BT = getAs<BuiltinType>()) if (BT->getKind() == (BuiltinType::Kind) K) @@ -3597,6 +4230,12 @@ inline bool Type::isSpecificBuiltinType(unsigned K) const { return false; } +inline bool Type::isPlaceholderType() const { + if (const BuiltinType *BT = getAs<BuiltinType>()) + return BT->isPlaceholderType(); + return false; +} + /// \brief Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { @@ -3612,6 +4251,13 @@ inline bool Type::hasObjCPointerRepresentation() const { return isObjCObjectPointerType(); } +inline const Type *Type::getBaseElementTypeUnsafe() const { + const Type *type = this; + while (const ArrayType *arrayType = type->getAsArrayTypeUnsafe()) + type = arrayType->getElementType().getTypePtr(); + return type; +} + /// Insertion operator for diagnostics. This allows sending QualType's into a /// diagnostic with <<. inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, @@ -3658,6 +4304,35 @@ template <typename T> const T *Type::getAs() const { return cast<T>(getUnqualifiedDesugaredType()); } +inline const ArrayType *Type::getAsArrayTypeUnsafe() const { + // If this is directly an array type, return it. + if (const ArrayType *arr = dyn_cast<ArrayType>(this)) + return arr; + + // If the canonical form of this type isn't the right kind, reject it. + if (!isa<ArrayType>(CanonicalType)) + return 0; + + // If this is a typedef for the type, strip the typedef off without + // losing all typedef information. + return cast<ArrayType>(getUnqualifiedDesugaredType()); +} + +template <typename T> const T *Type::castAs() const { + ArrayType_cannot_be_used_with_getAs<T> at; + (void) at; + + assert(isa<T>(CanonicalType)); + if (const T *ty = dyn_cast<T>(this)) return ty; + return cast<T>(getUnqualifiedDesugaredType()); +} + +inline const ArrayType *Type::castAsArrayTypeUnsafe() const { + assert(isa<ArrayType>(CanonicalType)); + if (const ArrayType *arr = dyn_cast<ArrayType>(this)) return arr; + return cast<ArrayType>(getUnqualifiedDesugaredType()); +} + } // end namespace clang #endif diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index f1c64bd95977..c7f5ee76330c 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -20,6 +20,7 @@ #include "clang/Basic/Specifiers.h" namespace clang { + class ASTContext; class ParmVarDecl; class TypeSourceInfo; class UnqualTypeLoc; @@ -38,7 +39,7 @@ class TypeLoc { protected: // The correctness of this relies on the property that, for Type *Ty, // QualType(Ty, 0).getAsOpaquePtr() == (void*) Ty - void *Ty; + const void *Ty; void *Data; public: @@ -56,7 +57,7 @@ public: TypeLoc() : Ty(0), Data(0) { } TypeLoc(QualType ty, void *opaqueData) : Ty(ty.getAsOpaquePtr()), Data(opaqueData) { } - TypeLoc(Type *ty, void *opaqueData) + TypeLoc(const Type *ty, void *opaqueData) : Ty(ty), Data(opaqueData) { } TypeLocClass getTypeLocClass() const { @@ -76,7 +77,7 @@ public: return QualType::getFromOpaquePtr(Ty); } - Type *getTypePtr() const { + const Type *getTypePtr() const { return QualType::getFromOpaquePtr(Ty).getTypePtr(); } @@ -115,13 +116,36 @@ public: /// \brief Skips past any qualifiers, if this is qualified. UnqualTypeLoc getUnqualifiedLoc() const; // implemented in this header + TypeLoc IgnoreParens() const { + if (isa<ParenTypeLoc>(this)) + return IgnoreParensImpl(*this); + return *this; + } + /// \brief Initializes this to state that every location in this /// type is the given location. /// /// This method exists to provide a simple transition for code that /// relies on location-less types. - void initialize(SourceLocation Loc) const { - initializeImpl(*this, Loc); + void initialize(ASTContext &Context, SourceLocation Loc) const { + initializeImpl(Context, *this, Loc); + } + + /// \brief Initializes this by copying its information from another + /// TypeLoc of the same type. + void initializeFullCopy(TypeLoc Other) const { + assert(getType() == Other.getType()); + size_t Size = getFullDataSize(); + memcpy(getOpaqueData(), Other.getOpaqueData(), Size); + } + + /// \brief Initializes this by copying its information from another + /// TypeLoc of the same type. The given size must be the full data + /// size. + void initializeFullCopy(TypeLoc Other, unsigned Size) const { + assert(getType() == Other.getType()); + assert(getFullDataSize() == Size); + memcpy(getOpaqueData(), Other.getOpaqueData(), Size); } friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) { @@ -135,8 +159,9 @@ public: static bool classof(const TypeLoc *TL) { return true; } private: - static void initializeImpl(TypeLoc TL, SourceLocation Loc); + static void initializeImpl(ASTContext &Context, TypeLoc TL, SourceLocation Loc); static TypeLoc getNextTypeLocImpl(TypeLoc TL); + static TypeLoc IgnoreParensImpl(TypeLoc TL); static SourceRange getLocalSourceRangeImpl(TypeLoc TL); }; @@ -146,14 +171,14 @@ inline TypeLoc TypeSourceInfo::getTypeLoc() const { } /// \brief Wrapper of type source information for a type with -/// no direct quqlaifiers. +/// no direct qualifiers. class UnqualTypeLoc : public TypeLoc { public: UnqualTypeLoc() {} - UnqualTypeLoc(Type *Ty, void *Data) : TypeLoc(Ty, Data) {} + UnqualTypeLoc(const Type *Ty, void *Data) : TypeLoc(Ty, Data) {} - Type *getTypePtr() const { - return reinterpret_cast<Type*>(Ty); + const Type *getTypePtr() const { + return reinterpret_cast<const Type*>(Ty); } TypeLocClass getTypeLocClass() const { @@ -183,7 +208,7 @@ public: /// Initializes the local data of this type source info block to /// provide no information. - void initializeLocal(SourceLocation Loc) { + void initializeLocal(ASTContext &Context, SourceLocation Loc) { // do nothing } @@ -282,7 +307,7 @@ public: return getNextTypeLoc(asDerived()->getInnerType()); } - TypeClass *getTypePtr() const { + const TypeClass *getTypePtr() const { return cast<TypeClass>(Base::getTypePtr()); } @@ -355,7 +380,7 @@ public: return true; } - TypeClass *getTypePtr() const { + const TypeClass *getTypePtr() const { return cast<TypeClass>(Base::getTypePtr()); } }; @@ -383,7 +408,7 @@ public: SourceRange getLocalSourceRange() const { return SourceRange(getNameLoc(), getNameLoc()); } - void initializeLocal(SourceLocation Loc) { + void initializeLocal(ASTContext &Context, SourceLocation Loc) { setNameLoc(Loc); } @@ -484,7 +509,7 @@ public: getWrittenBuiltinSpecs().ModeAttr = written; } - void initializeLocal(SourceLocation Loc) { + void initializeLocal(ASTContext &Context, SourceLocation Loc) { setBuiltinLoc(Loc); if (needsExtraLocalData()) { WrittenBuiltinSpecs &wbs = getWrittenBuiltinSpecs(); @@ -568,6 +593,137 @@ class SubstTemplateTypeParmTypeLoc : SubstTemplateTypeParmType> { }; + /// \brief Wrapper for substituted template type parameters. +class SubstTemplateTypeParmPackTypeLoc : + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + SubstTemplateTypeParmPackTypeLoc, + SubstTemplateTypeParmPackType> { +}; + +struct AttributedLocInfo { + union { + Expr *ExprOperand; + + /// A raw SourceLocation. + unsigned EnumOperandLoc; + }; + + SourceRange OperandParens; + + SourceLocation AttrLoc; +}; + +/// \brief Type source information for an attributed type. +class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + AttributedTypeLoc, + AttributedType, + AttributedLocInfo> { +public: + AttributedType::Kind getAttrKind() const { + return getTypePtr()->getAttrKind(); + } + + bool hasAttrExprOperand() const { + return (getAttrKind() >= AttributedType::FirstExprOperandKind && + getAttrKind() <= AttributedType::LastExprOperandKind); + } + + bool hasAttrEnumOperand() const { + return (getAttrKind() >= AttributedType::FirstEnumOperandKind && + getAttrKind() <= AttributedType::LastEnumOperandKind); + } + + bool hasAttrOperand() const { + return hasAttrExprOperand() || hasAttrEnumOperand(); + } + + /// The modified type, which is generally canonically different from + /// the attribute type. + /// int main(int, char**) __attribute__((noreturn)) + /// ~~~ ~~~~~~~~~~~~~ + TypeLoc getModifiedLoc() const { + return getInnerTypeLoc(); + } + + /// The location of the attribute name, i.e. + /// __attribute__((regparm(1000))) + /// ^~~~~~~ + SourceLocation getAttrNameLoc() const { + return getLocalData()->AttrLoc; + } + void setAttrNameLoc(SourceLocation loc) { + getLocalData()->AttrLoc = loc; + } + + /// The attribute's expression operand, if it has one. + /// void *cur_thread __attribute__((address_space(21))) + /// ^~ + Expr *getAttrExprOperand() const { + assert(hasAttrExprOperand()); + return getLocalData()->ExprOperand; + } + void setAttrExprOperand(Expr *e) { + assert(hasAttrExprOperand()); + getLocalData()->ExprOperand = e; + } + + /// The location of the attribute's enumerated operand, if it has one. + /// void * __attribute__((objc_gc(weak))) + /// ^~~~ + SourceLocation getAttrEnumOperandLoc() const { + assert(hasAttrEnumOperand()); + return SourceLocation::getFromRawEncoding(getLocalData()->EnumOperandLoc); + } + void setAttrEnumOperandLoc(SourceLocation loc) { + assert(hasAttrEnumOperand()); + getLocalData()->EnumOperandLoc = loc.getRawEncoding(); + } + + /// The location of the parentheses around the operand, if there is + /// an operand. + /// void * __attribute__((objc_gc(weak))) + /// ^ ^ + SourceRange getAttrOperandParensRange() const { + assert(hasAttrOperand()); + return getLocalData()->OperandParens; + } + void setAttrOperandParensRange(SourceRange range) { + assert(hasAttrOperand()); + getLocalData()->OperandParens = range; + } + + SourceRange getLocalSourceRange() const { + // Note that this does *not* include the range of the attribute + // enclosure, e.g.: + // __attribute__((foo(bar))) + // ^~~~~~~~~~~~~~~ ~~ + // or + // [[foo(bar)]] + // ^~ ~~ + // That enclosure doesn't necessarily belong to a single attribute + // anyway. + SourceRange range(getAttrNameLoc()); + if (hasAttrOperand()) + range.setEnd(getAttrOperandParensRange().getEnd()); + return range; + } + + void initializeLocal(ASTContext &Context, SourceLocation loc) { + setAttrNameLoc(loc); + if (hasAttrExprOperand()) { + setAttrOperandParensRange(SourceRange(loc)); + setAttrExprOperand(0); + } else if (hasAttrEnumOperand()) { + setAttrOperandParensRange(SourceRange(loc)); + setAttrEnumOperandLoc(loc); + } + } + + QualType getInnerType() const { + return getTypePtr()->getModifiedType(); + } +}; + struct ObjCProtocolListLocInfo { SourceLocation LAngleLoc; @@ -638,7 +794,7 @@ public: return SourceRange(getLAngleLoc(), getRAngleLoc()); } - void initializeLocal(SourceLocation Loc) { + void initializeLocal(ASTContext &Context, SourceLocation Loc) { setHasBaseTypeAsWritten(true); setLAngleLoc(Loc); setRAngleLoc(Loc); @@ -682,11 +838,51 @@ public: return SourceRange(getNameLoc()); } - void initializeLocal(SourceLocation Loc) { + void initializeLocal(ASTContext &Context, SourceLocation Loc) { setNameLoc(Loc); } }; +struct ParenLocInfo { + SourceLocation LParenLoc; + SourceLocation RParenLoc; +}; + +class ParenTypeLoc + : public ConcreteTypeLoc<UnqualTypeLoc, ParenTypeLoc, ParenType, + ParenLocInfo> { +public: + SourceLocation getLParenLoc() const { + return this->getLocalData()->LParenLoc; + } + SourceLocation getRParenLoc() const { + return this->getLocalData()->RParenLoc; + } + void setLParenLoc(SourceLocation Loc) { + this->getLocalData()->LParenLoc = Loc; + } + void setRParenLoc(SourceLocation Loc) { + this->getLocalData()->RParenLoc = Loc; + } + + SourceRange getLocalSourceRange() const { + return SourceRange(getLParenLoc(), getRParenLoc()); + } + + void initializeLocal(ASTContext &Context, SourceLocation Loc) { + setLParenLoc(Loc); + setRParenLoc(Loc); + } + + TypeLoc getInnerLoc() const { + return getInnerTypeLoc(); + } + + QualType getInnerType() const { + return this->getTypePtr()->getInnerType(); + } +}; + struct PointerLikeLocInfo { SourceLocation StarLoc; @@ -712,7 +908,7 @@ public: return SourceRange(getSigilLoc(), getSigilLoc()); } - void initializeLocal(SourceLocation Loc) { + void initializeLocal(ASTContext &Context, SourceLocation Loc) { setSigilLoc(Loc); } @@ -812,6 +1008,7 @@ public: struct FunctionLocInfo { SourceLocation LParenLoc, RParenLoc; + bool TrailingReturn; }; /// \brief Wrapper for source info for functions. @@ -819,11 +1016,6 @@ class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, FunctionTypeLoc, FunctionType, FunctionLocInfo> { - // ParmVarDecls* are stored after Info, one for each argument. - ParmVarDecl **getParmArray() const { - return (ParmVarDecl**) getExtraLocalData(); - } - public: SourceLocation getLParenLoc() const { return getLocalData()->LParenLoc; @@ -839,6 +1031,18 @@ public: getLocalData()->RParenLoc = Loc; } + bool getTrailingReturn() const { + return getLocalData()->TrailingReturn; + } + void setTrailingReturn(bool Trailing) { + getLocalData()->TrailingReturn = Trailing; + } + + // ParmVarDecls* are stored after Info, one for each argument. + ParmVarDecl **getParmArray() const { + return (ParmVarDecl**) getExtraLocalData(); + } + unsigned getNumArgs() const { if (isa<FunctionNoProtoType>(getTypePtr())) return 0; @@ -855,9 +1059,10 @@ public: return SourceRange(getLParenLoc(), getRParenLoc()); } - void initializeLocal(SourceLocation Loc) { + void initializeLocal(ASTContext &Context, SourceLocation Loc) { setLParenLoc(Loc); setRParenLoc(Loc); + setTrailingReturn(false); for (unsigned i = 0, e = getNumArgs(); i != e; ++i) setArg(i, NULL); } @@ -928,7 +1133,7 @@ public: return SourceRange(getLBracketLoc(), getRBracketLoc()); } - void initializeLocal(SourceLocation Loc) { + void initializeLocal(ASTContext &Context, SourceLocation Loc) { setLBracketLoc(Loc); setRBracketLoc(Loc); setSizeExpr(NULL); @@ -997,9 +1202,6 @@ public: return getTypePtr()->getNumArgs(); } void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { -#ifndef NDEBUG - AI.validateForArgument(getTypePtr()->getArg(i)); -#endif getArgInfos()[i] = AI; } TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { @@ -1033,47 +1235,18 @@ public: return SourceRange(getTemplateNameLoc(), getRAngleLoc()); } - void initializeLocal(SourceLocation Loc) { + void initializeLocal(ASTContext &Context, SourceLocation Loc) { setLAngleLoc(Loc); setRAngleLoc(Loc); setTemplateNameLoc(Loc); - initializeArgLocs(getNumArgs(), getTypePtr()->getArgs(), + initializeArgLocs(Context, getNumArgs(), getTypePtr()->getArgs(), getArgInfos(), Loc); } - static void initializeArgLocs(unsigned NumArgs, + static void initializeArgLocs(ASTContext &Context, unsigned NumArgs, const TemplateArgument *Args, TemplateArgumentLocInfo *ArgInfos, - SourceLocation Loc) { - for (unsigned i = 0, e = NumArgs; i != e; ++i) { - TemplateArgumentLocInfo Info; -#ifndef NDEBUG - // If asserts are enabled, be sure to initialize the argument - // loc with the right kind of pointer. - switch (Args[i].getKind()) { - case TemplateArgument::Expression: - case TemplateArgument::Declaration: - Info = TemplateArgumentLocInfo((Expr*) 0); - break; - - case TemplateArgument::Type: - Info = TemplateArgumentLocInfo((TypeSourceInfo*) 0); - break; - - case TemplateArgument::Template: - Info = TemplateArgumentLocInfo(SourceRange(Loc), Loc); - break; - - case TemplateArgument::Integral: - case TemplateArgument::Pack: - case TemplateArgument::Null: - // K_None is fine. - break; - } -#endif - ArgInfos[i] = Info; - } - } + SourceLocation Loc); unsigned getExtraLocalDataSize() const { return getNumArgs() * sizeof(TemplateArgumentLocInfo); @@ -1168,7 +1341,7 @@ public: return SourceRange(getTypeofLoc(), getRParenLoc()); } - void initializeLocal(SourceLocation Loc) { + void initializeLocal(ASTContext &Context, SourceLocation Loc) { setTypeofLoc(Loc); setLParenLoc(Loc); setRParenLoc(Loc); @@ -1208,6 +1381,11 @@ class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DecltypeType> { }; +class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + AutoTypeLoc, + AutoType> { +}; + struct ElaboratedLocInfo { SourceLocation KeywordLoc; SourceRange QualifierRange; @@ -1242,7 +1420,7 @@ public: return getQualifierRange(); } - void initializeLocal(SourceLocation Loc) { + void initializeLocal(ASTContext &Context, SourceLocation Loc) { setKeywordLoc(Loc); setQualifierRange(SourceRange(Loc)); } @@ -1307,7 +1485,7 @@ public: memcpy(Data, Loc.Data, size); } - void initializeLocal(SourceLocation Loc) { + void initializeLocal(ASTContext &Context, SourceLocation Loc) { setKeywordLoc(Loc); setQualifierRange(SourceRange(Loc)); setNameLoc(Loc); @@ -1368,9 +1546,6 @@ public: } void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { -#ifndef NDEBUG - AI.validateForArgument(getTypePtr()->getArg(i)); -#endif getArgInfos()[i] = AI; } TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { @@ -1394,13 +1569,13 @@ public: memcpy(Data, Loc.Data, size); } - void initializeLocal(SourceLocation Loc) { + void initializeLocal(ASTContext &Context, SourceLocation Loc) { setKeywordLoc(Loc); setQualifierRange(SourceRange(Loc)); setNameLoc(Loc); setLAngleLoc(Loc); setRAngleLoc(Loc); - TemplateSpecializationTypeLoc::initializeArgLocs(getNumArgs(), + TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), getTypePtr()->getArgs(), getArgInfos(), Loc); } @@ -1415,6 +1590,40 @@ private: } }; + +struct PackExpansionTypeLocInfo { + SourceLocation EllipsisLoc; +}; + +class PackExpansionTypeLoc + : public ConcreteTypeLoc<UnqualTypeLoc, PackExpansionTypeLoc, + PackExpansionType, PackExpansionTypeLocInfo> { +public: + SourceLocation getEllipsisLoc() const { + return this->getLocalData()->EllipsisLoc; + } + + void setEllipsisLoc(SourceLocation Loc) { + this->getLocalData()->EllipsisLoc = Loc; + } + + SourceRange getLocalSourceRange() const { + return SourceRange(getEllipsisLoc(), getEllipsisLoc()); + } + + void initializeLocal(ASTContext &Context, SourceLocation Loc) { + setEllipsisLoc(Loc); + } + + TypeLoc getPatternLoc() const { + return getInnerTypeLoc(); + } + + QualType getInnerType() const { + return this->getTypePtr()->getPattern(); + } +}; + } #endif diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h deleted file mode 100644 index 880af267f324..000000000000 --- a/include/clang/AST/TypeLocBuilder.h +++ /dev/null @@ -1,155 +0,0 @@ -//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This files defines TypeLocBuilder, a class for building TypeLocs -// bottom-up. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_TYPELOCBUILDER_H -#define LLVM_CLANG_AST_TYPELOCBUILDER_H - -#include "clang/AST/TypeLoc.h" -#include "llvm/ADT/SmallVector.h" -#include "clang/AST/ASTContext.h" - -namespace clang { - -class TypeLocBuilder { - enum { InlineCapacity = 8 * sizeof(SourceLocation) }; - - /// The underlying location-data buffer. Data grows from the end - /// of the buffer backwards. - char *Buffer; - - /// The capacity of the current buffer. - size_t Capacity; - - /// The index of the first occupied byte in the buffer. - size_t Index; - -#ifndef NDEBUG - /// The last type pushed on this builder. - QualType LastTy; -#endif - - /// The inline buffer. - char InlineBuffer[InlineCapacity]; - - public: - TypeLocBuilder() - : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) - {} - - ~TypeLocBuilder() { - if (Buffer != InlineBuffer) - delete[] Buffer; - } - - /// Ensures that this buffer has at least as much capacity as described. - void reserve(size_t Requested) { - if (Requested > Capacity) - // For now, match the request exactly. - grow(Requested); - } - - /// Pushes a copy of the given TypeLoc onto this builder. The builder - /// must be empty for this to work. - void pushFullCopy(TypeLoc L) { -#ifndef NDEBUG - assert(LastTy.isNull() && "pushing copy on non-empty TypeLocBuilder"); - LastTy = L.getNextTypeLoc().getType(); -#endif - assert(Index == Capacity && "pushing copy on non-empty TypeLocBuilder"); - - unsigned Size = L.getFullDataSize(); - TypeLoc Copy = pushImpl(L.getType(), Size); - memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size); - } - - /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs - /// previously retrieved from this builder. - TypeSpecTypeLoc pushTypeSpec(QualType T) { - size_t LocalSize = TypeSpecTypeLoc::LocalDataSize; - return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize)); - } - - /// Resets this builder to the newly-initialized state. - void clear() { -#ifndef NDEBUG - LastTy = QualType(); -#endif - Index = Capacity; - } - - /// Pushes space for a new TypeLoc of the given type. Invalidates - /// any TypeLocs previously retrieved from this builder. - template <class TyLocType> TyLocType push(QualType T) { - size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize(); - return cast<TyLocType>(pushImpl(T, LocalSize)); - } - - /// Creates a TypeSourceInfo for the given type. - TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) { -#ifndef NDEBUG - assert(T == LastTy && "type doesn't match last type pushed!"); -#endif - - size_t FullDataSize = Capacity - Index; - TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize); - memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize); - return DI; - } - -private: - TypeLoc pushImpl(QualType T, size_t LocalSize) { -#ifndef NDEBUG - QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType(); - assert(TLast == LastTy && - "mismatch between last type and new type's inner type"); - LastTy = T; -#endif - - // If we need to grow, grow by a factor of 2. - if (LocalSize > Index) { - size_t RequiredCapacity = Capacity + (LocalSize - Index); - size_t NewCapacity = Capacity * 2; - while (RequiredCapacity > NewCapacity) - NewCapacity *= 2; - grow(NewCapacity); - } - - Index -= LocalSize; - - return TypeLoc(T, &Buffer[Index]); - } - - /// Grow to the given capacity. - void grow(size_t NewCapacity) { - assert(NewCapacity > Capacity); - - // Allocate the new buffer and copy the old data into it. - char *NewBuffer = new char[NewCapacity]; - unsigned NewIndex = Index + NewCapacity - Capacity; - memcpy(&NewBuffer[NewIndex], - &Buffer[Index], - Capacity - Index); - - if (Buffer != InlineBuffer) - delete[] Buffer; - - Buffer = NewBuffer; - Capacity = NewCapacity; - Index = NewIndex; - } -}; - -} - -#endif diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 9cb56861a9ef..b2591cc0fbac 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -79,6 +79,7 @@ ABSTRACT_TYPE(Function, Type) TYPE(FunctionProto, FunctionType) TYPE(FunctionNoProto, FunctionType) DEPENDENT_TYPE(UnresolvedUsing, Type) +NON_CANONICAL_TYPE(Paren, Type) NON_CANONICAL_TYPE(Typedef, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type) @@ -87,12 +88,16 @@ ABSTRACT_TYPE(Tag, Type) TYPE(Record, TagType) TYPE(Enum, TagType) NON_CANONICAL_TYPE(Elaborated, Type) +NON_CANONICAL_TYPE(Attributed, Type) DEPENDENT_TYPE(TemplateTypeParm, Type) NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) +DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) +NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Auto, Type) DEPENDENT_TYPE(InjectedClassName, Type) DEPENDENT_TYPE(DependentName, Type) DEPENDENT_TYPE(DependentTemplateSpecialization, Type) +DEPENDENT_TYPE(PackExpansion, Type) TYPE(ObjCObject, Type) TYPE(ObjCInterface, ObjCObjectType) TYPE(ObjCObjectPointer, Type) diff --git a/include/clang/AST/TypeVisitor.h b/include/clang/AST/TypeVisitor.h index 5c9c5285a248..c52926b1fc31 100644 --- a/include/clang/AST/TypeVisitor.h +++ b/include/clang/AST/TypeVisitor.h @@ -19,12 +19,13 @@ namespace clang { #define DISPATCH(CLASS) \ - return static_cast<ImplClass*>(this)->Visit ## CLASS(static_cast<CLASS*>(T)) + return static_cast<ImplClass*>(this)-> \ + Visit##CLASS(static_cast<const CLASS*>(T)) template<typename ImplClass, typename RetTy=void> class TypeVisitor { public: - RetTy Visit(Type *T) { + RetTy Visit(const Type *T) { // Top switch stmt: dispatch to VisitFooType for each FooType. switch (T->getTypeClass()) { default: assert(0 && "Unknown type class!"); @@ -36,13 +37,13 @@ public: // If the implementation chooses not to implement a certain visit method, fall // back on superclass. -#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(CLASS##Type *T) { \ +#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(const CLASS##Type *T) { \ DISPATCH(PARENT); \ } #include "clang/AST/TypeNodes.def" // Base case, ignore it. :) - RetTy VisitType(Type*) { return RetTy(); } + RetTy VisitType(const Type*) { return RetTy(); } }; #undef DISPATCH |