diff options
Diffstat (limited to 'include/clang/AST')
29 files changed, 2279 insertions, 549 deletions
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index 53bb785..0611395 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -16,6 +16,7 @@ namespace clang { class ASTContext; + class CXXRecordDecl; class DeclGroupRef; class TagDecl; class HandleTagDeclDefinition; @@ -68,6 +69,17 @@ public: /// modified by the introduction of an implicit zero initializer. virtual void CompleteTentativeDefinition(VarDecl *D) {} + /// \brief Callback involved at the end of a translation unit to + /// notify the consumer that a vtable for the given C++ class is + /// required. + /// + /// \param RD The class whose vtable was used. + /// + /// \param DefinitionRequired Whether a definition of this vtable is + /// required in this translation unit; otherwise, it is only needed if + /// it was actually used. + virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {} + /// PrintStats - If desired, print any statistics. virtual void PrintStats() {} diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index f8a8f17..87a12cde 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -96,11 +96,10 @@ class ASTContext { llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes; llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes; llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes; - llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes; + llvm::FoldingSet<ElaboratedType> ElaboratedTypes; llvm::FoldingSet<DependentNameType> DependentNameTypes; - llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes; + llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes; llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; - llvm::FoldingSet<ElaboratedType> ElaboratedTypes; llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; @@ -483,7 +482,7 @@ public: /// This gets the struct used to keep track of pointer to blocks, complete /// with captured variables. QualType getBlockParmType(bool BlockHasCopyDispose, - llvm::SmallVector<const Expr *, 8> &BDRDs); + llvm::SmallVectorImpl<const Expr *> &Layout); /// This builds the struct used for __block variables. QualType BuildByRefType(const char *DeclName, QualType Ty); @@ -613,8 +612,9 @@ public: const TemplateArgumentListInfo &Args, QualType Canon = QualType()); - QualType getQualifiedNameType(NestedNameSpecifier *NNS, - QualType NamedType); + QualType getElaboratedType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + QualType NamedType); QualType getDependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, @@ -623,19 +623,16 @@ public: NestedNameSpecifier *NNS, const TemplateSpecializationType *TemplateId, QualType Canon = QualType()); - QualType getElaboratedType(QualType UnderlyingType, - ElaboratedType::TagKind Tag); - QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, - ObjCProtocolDecl **Protocols = 0, - unsigned NumProtocols = 0); + QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl); + + QualType getObjCObjectType(QualType Base, + ObjCProtocolDecl * const *Protocols, + unsigned NumProtocols); - /// getObjCObjectPointerType - Return a ObjCObjectPointerType type for the - /// given interface decl and the conforming protocol list. - QualType getObjCObjectPointerType(QualType OIT, - ObjCProtocolDecl **ProtocolList = 0, - unsigned NumProtocols = 0, - unsigned Quals = 0); + /// getObjCObjectPointerType - Return a ObjCObjectPointerType type + /// for the given ObjCObjectType. + QualType getObjCObjectPointerType(QualType OIT); /// getTypeOfType - GCC extension. QualType getTypeOfExprType(Expr *e); @@ -913,6 +910,9 @@ public: CharUnits getTypeAlignInChars(QualType T); CharUnits getTypeAlignInChars(const Type *T); + std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T); + std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T); + /// 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 @@ -1184,8 +1184,8 @@ public: // Check the safety of assignment from LHS to RHS bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT); - bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS, - const ObjCInterfaceType *RHS); + bool canAssignObjCInterfaces(const ObjCObjectType *LHS, + const ObjCObjectType *RHS); bool canAssignObjCInterfacesInBlockPointer( const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT); @@ -1196,6 +1196,8 @@ public: // Functions for calculating composite types QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false); QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false); + + QualType mergeObjCGCQualifiers(QualType, QualType); /// UsualArithmeticConversionsType - handles the various conversions /// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9) @@ -1270,6 +1272,15 @@ public: TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc = SourceLocation()); + /// \brief Add a deallocation callback that will be invoked when the + /// ASTContext is destroyed. + /// + /// \brief Callback A callback function that will be invoked on destruction. + /// + /// \brief Data Pointer data that will be provided to the callback function + /// when it is called. + void AddDeallocation(void (*Callback)(void*), void *Data); + private: ASTContext(const ASTContext&); // DO NOT IMPLEMENT void operator=(const ASTContext&); // DO NOT IMPLEMENT @@ -1284,16 +1295,21 @@ private: const FieldDecl *Field, bool OutermostType = false, bool EncodingProperty = false); - + const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl); private: + /// \brief A set of deallocations that should be performed when the + /// ASTContext is destroyed. + llvm::SmallVector<std::pair<void (*)(void*), void *>, 16> Deallocations; + // FIXME: This currently contains the set of StoredDeclMaps used // by DeclContext objects. This probably should not be in ASTContext, // but we include it here so that ASTContext can quickly deallocate them. llvm::PointerIntPair<StoredDeclsMap*,1> LastSDM; friend class DeclContext; + friend class DeclarationNameTable; void ReleaseDeclContextMaps(); }; diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 1974493..3240e50 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -23,9 +23,10 @@ using llvm::dyn_cast; namespace clang { class ASTContext; + class IdentifierInfo; + class ObjCInterfaceDecl; } - // Defined in ASTContext.h void *operator new(size_t Bytes, clang::ASTContext &C, size_t Alignment = 16) throw (); @@ -44,6 +45,7 @@ public: enum Kind { Alias, Aligned, + AlignMac68k, AlwaysInline, AnalyzerNoReturn, // Clang-specific. Annotate, @@ -63,8 +65,10 @@ public: GNUInline, Hiding, IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro. + IBOutletCollectionKind, // Clang-specific. IBActionKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro. Malloc, + MaxFieldAlignment, NoDebug, NoInline, NonNull, @@ -79,13 +83,13 @@ public: NSReturnsNotRetained, // Clang/Checker-specific. Overloadable, // Clang-specific Packed, - PragmaPack, Pure, Regparm, ReqdWorkGroupSize, // OpenCL-specific Section, Sentinel, StdCall, + ThisCall, TransparentUnion, Unavailable, Unused, @@ -183,11 +187,14 @@ public: \ DEF_SIMPLE_ATTR(Packed); -class PragmaPackAttr : public Attr { +/// \brief Attribute for specifying a maximum field alignment; this is only +/// valid on record decls. +class MaxFieldAlignmentAttr : public Attr { unsigned Alignment; public: - PragmaPackAttr(unsigned alignment) : Attr(PragmaPack), Alignment(alignment) {} + MaxFieldAlignmentAttr(unsigned alignment) + : Attr(MaxFieldAlignment), Alignment(alignment) {} /// getAlignment - The specified alignment in bits. unsigned getAlignment() const { return Alignment; } @@ -196,11 +203,13 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() == PragmaPack; + return A->getKind() == MaxFieldAlignment; } - static bool classof(const PragmaPackAttr *A) { return true; } + static bool classof(const MaxFieldAlignmentAttr *A) { return true; } }; +DEF_SIMPLE_ATTR(AlignMac68k); + class AlignedAttr : public Attr { unsigned Alignment; public: @@ -317,6 +326,23 @@ public: static bool classof(const IBOutletAttr *A) { return true; } }; +class IBOutletCollectionAttr : public Attr { + const ObjCInterfaceDecl *D; +public: + IBOutletCollectionAttr(const ObjCInterfaceDecl *d = 0) + : Attr(IBOutletCollectionKind), D(d) {} + + const ObjCInterfaceDecl *getClass() const { return D; } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == IBOutletCollectionKind; + } + static bool classof(const IBOutletCollectionAttr *A) { return true; } +}; + class IBActionAttr : public Attr { public: IBActionAttr() : Attr(IBActionKind) {} @@ -457,6 +483,7 @@ public: DEF_SIMPLE_ATTR(FastCall); DEF_SIMPLE_ATTR(StdCall); +DEF_SIMPLE_ATTR(ThisCall); DEF_SIMPLE_ATTR(CDecl); DEF_SIMPLE_ATTR(TransparentUnion); DEF_SIMPLE_ATTR(ObjCNSObject); diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt new file mode 100644 index 0000000..c24ea06 --- /dev/null +++ b/include/clang/AST/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_TARGET_DEFINITIONS StmtNodes.td) +tablegen(StmtNodes.inc + -gen-clang-stmt-nodes) +add_custom_target(ClangStmtNodes + DEPENDS StmtNodes.inc) diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index edd633e..5a84e40 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -196,7 +196,7 @@ public: /// \brief Determine whether the path from the most-derived type to the /// given base type is ambiguous (i.e., it refers to multiple subobjects of /// the same base type). - bool isAmbiguous(QualType BaseType); + bool isAmbiguous(CanQualType BaseType); /// \brief Whether we are finding multiple paths to detect ambiguities. bool isFindingAmbiguities() const { return FindAmbiguities; } diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 93dcad7..4afb81d 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -643,6 +643,24 @@ struct CanProxyAdaptor<TemplateTypeParmType> }; template<> +struct CanProxyAdaptor<ObjCObjectType> + : public CanProxyBase<ObjCObjectType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceDecl *, + getInterface) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedId) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedClass) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass) + + typedef ObjCObjectPointerType::qual_iterator qual_iterator; + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) +}; + +template<> struct CanProxyAdaptor<ObjCObjectPointerType> : public CanProxyBase<ObjCObjectPointerType> { LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 834c9a0..7d5b66e 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -55,7 +55,7 @@ public: QualType getType() const { return Ty; } /// \brief Return the TypeLoc wrapper for the type source info. - TypeLoc getTypeLoc() const; + TypeLoc getTypeLoc() const; // implemented in TypeLoc.h }; /// TranslationUnitDecl - The top declaration context. @@ -138,6 +138,8 @@ public: // FIXME: Deprecated, move clients to getName(). std::string getNameAsString() const { return Name.getAsString(); } + void printName(llvm::raw_ostream &os) const { return Name.printName(os); } + /// getDeclName - Get the actual, stored name of the declaration, /// which may be a special name. DeclarationName getDeclName() const { return Name; } @@ -265,18 +267,25 @@ public: // \brief Returns true if this is an anonymous namespace declaration. // // For example: + /// \code // namespace { // ... // }; + // \endcode // q.v. C++ [namespace.unnamed] bool isAnonymousNamespace() const { return !getIdentifier(); } + /// \brief Return the next extended namespace declaration or null if this + /// is none. NamespaceDecl *getNextNamespace() { return NextNamespace; } const NamespaceDecl *getNextNamespace() const { return NextNamespace; } + + /// \brief Set the next extended namespace declaration. void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; } + /// \brief Get the original (first) namespace declaration. NamespaceDecl *getOriginalNamespace() const { if (OrigOrAnonNamespace.getInt()) return const_cast<NamespaceDecl *>(this); @@ -284,6 +293,14 @@ public: return OrigOrAnonNamespace.getPointer(); } + /// \brief Return true if this declaration is an original (first) declaration + /// of the namespace. This is false for non-original (subsequent) namespace + /// declarations and anonymous namespaces. + bool isOriginalNamespace() const { + return getOriginalNamespace() == this; + } + + /// \brief Set the original (first) namespace declaration. void setOriginalNamespace(NamespaceDecl *ND) { if (ND != this) { OrigOrAnonNamespace.setPointer(ND); @@ -502,6 +519,10 @@ private: /// or an Objective-C @catch statement. bool ExceptionVar : 1; + /// \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; + friend class StmtIteratorBase; protected: VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, @@ -509,7 +530,7 @@ protected: StorageClass SCAsWritten) : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(), ThreadSpecified(false), HasCXXDirectInit(false), - DeclaredInCondition(false), ExceptionVar(false) { + DeclaredInCondition(false), ExceptionVar(false), NRVOVariable(false) { SClass = SC; SClassAsWritten = SCAsWritten; } @@ -852,6 +873,19 @@ public: } void setExceptionVariable(bool EV) { ExceptionVar = EV; } + /// \brief Determine whether this local variable can be used with the named + /// return value optimization (NRVO). + /// + /// The named return value optimization (NRVO) works by marking certain + /// non-volatile local variables of class type as NRVO objects. These + /// locals can be allocated within the return slot of their containing + /// function, in which case there is no need to copy the object to the + /// return slot when returning from the function. Within the function body, + /// each return that returns the NRVO object will have this variable as its + /// NRVO candidate. + bool isNRVOVariable() const { return NRVOVariable; } + void setNRVOVariable(bool NRVO) { NRVOVariable = NRVO; } + /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member /// from which it was instantiated. @@ -1390,6 +1424,16 @@ public: /// returns NULL. const TemplateArgumentList *getTemplateSpecializationArgs() const; + /// \brief Retrieve the template argument list as written in the sources, + /// if any. + /// + /// If this function declaration is not a function template specialization + /// or if it had no explicit template argument list, returns NULL. + /// Note that it an explicit template argument list may be written empty, + /// e.g., template<> void foo<>(char* s); + const TemplateArgumentListInfo* + getTemplateSpecializationArgsAsWritten() const; + /// \brief Specify that this function declaration is actually a function /// template specialization. /// @@ -1409,7 +1453,8 @@ public: void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, const TemplateArgumentList *TemplateArgs, void *InsertPos, - TemplateSpecializationKind TSK = TSK_ImplicitInstantiation); + TemplateSpecializationKind TSK = TSK_ImplicitInstantiation, + const TemplateArgumentListInfo *TemplateArgsAsWritten = 0); /// \brief Specifies that this function declaration is actually a /// dependent function template specialization. @@ -1593,7 +1638,19 @@ class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> { : TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {} virtual ~TypedefDecl(); + +protected: + typedef Redeclarable<TypedefDecl> redeclarable_base; + virtual TypedefDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + public: + typedef redeclarable_base::redecl_iterator redecl_iterator; + redecl_iterator redecls_begin() const { + return redeclarable_base::redecls_begin(); + } + redecl_iterator redecls_end() const { + return redeclarable_base::redecls_end(); + } static TypedefDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, @@ -1631,11 +1688,7 @@ class TagDecl : public TypeDecl, public DeclContext, public Redeclarable<TagDecl> { public: // This is really ugly. - typedef ElaboratedType::TagKind TagKind; - static const TagKind TK_struct = ElaboratedType::TK_struct; - static const TagKind TK_union = ElaboratedType::TK_union; - static const TagKind TK_class = ElaboratedType::TK_class; - static const TagKind TK_enum = ElaboratedType::TK_enum; + typedef TagTypeKind TagKind; private: // FIXME: This can be packed into the bitfields in Decl. @@ -1651,6 +1704,12 @@ private: /// in the syntax of a declarator. bool IsEmbeddedInDeclarator : 1; +protected: + // These are used by (and only defined for) EnumDecl. + unsigned NumPositiveBits : 8; + unsigned NumNegativeBits : 8; + +private: SourceLocation TagKeywordLoc; SourceLocation RBraceLoc; @@ -1680,7 +1739,8 @@ protected: TagDecl *PrevDecl, SourceLocation TKL = SourceLocation()) : TypeDecl(DK, DC, L, Id), DeclContext(DK), TagKeywordLoc(TKL), TypedefDeclOrQualifier((TypedefDecl*) 0) { - assert((DK != Enum || TK == TK_enum) &&"EnumDecl not matched with TK_enum"); + assert((DK != Enum || TK == TTK_Enum) && + "EnumDecl not matched with TTK_Enum"); TagDeclKind = TK; IsDefinition = false; IsEmbeddedInDeclarator = false; @@ -1753,30 +1813,26 @@ public: void setDefinition(bool V) { IsDefinition = V; } const char *getKindName() const { - return ElaboratedType::getNameForTagKind(getTagKind()); + return TypeWithKeyword::getTagTypeKindName(getTagKind()); } - /// getTagKindForTypeSpec - Converts a type specifier (DeclSpec::TST) - /// into a tag kind. It is an error to provide a type specifier - /// which *isn't* a tag kind here. - static TagKind getTagKindForTypeSpec(unsigned TypeSpec); - TagKind getTagKind() const { return TagKind(TagDeclKind); } void setTagKind(TagKind TK) { TagDeclKind = TK; } - bool isStruct() const { return getTagKind() == TK_struct; } - bool isClass() const { return getTagKind() == TK_class; } - bool isUnion() const { return getTagKind() == TK_union; } - bool isEnum() const { return getTagKind() == TK_enum; } + bool isStruct() const { return getTagKind() == TTK_Struct; } + bool isClass() const { return getTagKind() == TTK_Class; } + bool isUnion() const { return getTagKind() == TTK_Union; } + bool isEnum() const { return getTagKind() == TTK_Enum; } TypedefDecl *getTypedefForAnonDecl() const { return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get<TypedefDecl*>(); } - void setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefDeclOrQualifier = TDD; } - + + void setTypedefForAnonDecl(TypedefDecl *TDD); + NestedNameSpecifier *getQualifier() const { return hasExtInfo() ? TypedefDeclOrQualifier.get<ExtInfo*>()->NNS : 0; } @@ -1820,9 +1876,16 @@ class EnumDecl : public TagDecl { /// enumeration declared within the template. EnumDecl *InstantiatedFrom; + // The number of positive and negative bits required by the + // enumerators are stored in the SubclassBits field. + enum { + NumBitsWidth = 8, + NumBitsMask = (1 << NumBitsWidth) - 1 + }; + EnumDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL) - : TagDecl(Enum, TK_enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { + : TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { IntegerType = QualType(); } public: @@ -1845,7 +1908,9 @@ public: /// added (via DeclContext::addDecl). NewType is the new underlying /// type of the enumeration type. void completeDefinition(QualType NewType, - QualType PromotionType); + QualType PromotionType, + unsigned NumPositiveBits, + unsigned NumNegativeBits); // enumerator_iterator - Iterates through the enumerators of this // enumeration. @@ -1873,6 +1938,32 @@ public: /// \brief Set the underlying integer type. void setIntegerType(QualType T) { IntegerType = T; } + /// \brief Returns the width in bits requred to store all the + /// non-negative enumerators of this enum. + unsigned getNumPositiveBits() const { + return NumPositiveBits; + } + void setNumPositiveBits(unsigned Num) { + NumPositiveBits = Num; + assert(NumPositiveBits == Num && "can't store this bitcount"); + } + + /// \brief Returns the width in bits requred to store all the + /// negative enumerators of this enum. These widths include + /// the rightmost leading 1; that is: + /// + /// MOST NEGATIVE ENUMERATOR PATTERN NUM NEGATIVE BITS + /// ------------------------ ------- ----------------- + /// -1 1111111 1 + /// -10 1110110 5 + /// -101 1001011 8 + unsigned getNumNegativeBits() const { + return NumNegativeBits; + } + void setNumNegativeBits(unsigned Num) { + NumNegativeBits = Num; + } + /// \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. @@ -1942,6 +2033,11 @@ 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; } diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index a9b948e..c15aeef 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -76,6 +76,11 @@ public: #include "clang/AST/DeclNodes.def" }; + /// \brief A placeholder type used to construct an empty shell of a + /// decl-derived type that will be filled in later (e.g., by some + /// deserialization method). + struct EmptyShell { }; + /// IdentifierNamespace - The different namespaces in which /// declarations may appear. According to C99 6.2.3, there are /// four namespaces, labels, tags, members and ordinary diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index aa649c8..c19c200 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1061,10 +1061,6 @@ class CXXBaseOrMemberInitializer { /// In above example, BaseOrMember holds the field decl. for anonymous union /// and AnonUnionMember holds field decl for au_i1. FieldDecl *AnonUnionMember; - - /// IsVirtual - If the initializer is a base initializer, this keeps track - /// of whether the base is virtual or not. - bool IsVirtual; /// LParenLoc - Location of the left paren of the ctor-initializer. SourceLocation LParenLoc; @@ -1072,6 +1068,28 @@ class CXXBaseOrMemberInitializer { /// RParenLoc - Location of the right paren of the ctor-initializer. SourceLocation RParenLoc; + /// IsVirtual - If the initializer is a base initializer, this keeps track + /// of whether the base is virtual or not. + bool IsVirtual : 1; + + /// 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, + /// it stores the number of array index variables stored after this + /// object in memory. + unsigned SourceOrderOrNumArrayIndices : 14; + + CXXBaseOrMemberInitializer(ASTContext &Context, + FieldDecl *Member, SourceLocation MemberLoc, + SourceLocation L, + Expr *Init, + SourceLocation R, + VarDecl **Indices, + unsigned NumIndices); + public: /// CXXBaseOrMemberInitializer - Creates a new base-class initializer. explicit @@ -1089,6 +1107,17 @@ public: 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); + /// \brief Destroy the base or member initializer. void Destroy(ASTContext &Context); @@ -1146,6 +1175,30 @@ public: /// \brief Determine the source range covering the entire initializer. SourceRange getSourceRange() const; + + /// isWritten - Returns true if this initializer is explicitly written + /// in the source code. + bool isWritten() const { return IsWritten; } + + /// \brief Return the source position of the initializer, counting from 0. + /// If the initializer was implicit, -1 is returned. + int getSourceOrder() const { + return IsWritten ? static_cast<int>(SourceOrderOrNumArrayIndices) : -1; + } + + /// \brief Set the source order of this initializer. This method can only + /// be called once for each initializer; it cannot be called on an + /// initializer having a positive number of (implicit) array indices. + void setSourceOrder(int pos) { + assert(!IsWritten && + "calling twice setSourceOrder() on the same initializer"); + assert(SourceOrderOrNumArrayIndices == 0 && + "setSourceOrder() used when there are implicit array indices"); + assert(pos >= 0 && + "setSourceOrder() used to make an initializer implicit"); + IsWritten = true; + SourceOrderOrNumArrayIndices = static_cast<unsigned>(pos); + } FieldDecl *getAnonUnionMember() const { return AnonUnionMember; @@ -1154,9 +1207,31 @@ public: AnonUnionMember = anonMember; } + SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } + /// \brief Determine the number of implicit array indices used while + /// described an array member initialization. + unsigned getNumArrayIndices() const { + return IsWritten ? 0 : SourceOrderOrNumArrayIndices; + } + + /// \brief Retrieve a particular array index variable used to + /// describe an array member initialization. + VarDecl *getArrayIndex(unsigned I) { + assert(I < getNumArrayIndices() && "Out of bounds member array index"); + return reinterpret_cast<VarDecl **>(this + 1)[I]; + } + const VarDecl *getArrayIndex(unsigned I) const { + assert(I < getNumArrayIndices() && "Out of bounds member array index"); + return reinterpret_cast<const VarDecl * const *>(this + 1)[I]; + } + void setArrayIndex(unsigned I, VarDecl *Index) { + assert(I < getNumArrayIndices() && "Out of bounds member array index"); + reinterpret_cast<VarDecl **>(this + 1)[I] = Index; + } + Expr *getInit() { return static_cast<Expr *>(Init); } }; @@ -1201,6 +1276,7 @@ class CXXConstructorDecl : public CXXMethodDecl { virtual void Destroy(ASTContext& C); public: + static CXXConstructorDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, @@ -1343,6 +1419,7 @@ class CXXDestructorDecl : public CXXMethodDecl { } public: + static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty); static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, bool isInline, @@ -1398,6 +1475,7 @@ class CXXConversionDecl : public CXXMethodDecl { IsExplicitSpecified(isExplicitSpecified) { } public: + static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, @@ -1438,8 +1516,10 @@ public: /// ASTs and cannot be changed without altering that abi. To help /// ensure a stable abi for this, we choose the DW_LANG_ encodings /// from the dwarf standard. - enum LanguageIDs { lang_c = /* DW_LANG_C */ 0x0002, - lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004 }; + enum LanguageIDs { + lang_c = /* DW_LANG_C */ 0x0002, + lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004 + }; private: /// Language - The language for this linkage specification. LanguageIDs Language; @@ -1457,12 +1537,20 @@ public: SourceLocation L, LanguageIDs Lang, bool Braces); + /// \brief Return the language specified by this linkage specification. LanguageIDs getLanguage() const { return Language; } - /// hasBraces - Determines whether this linkage specification had - /// braces in its syntactic form. + /// \brief Set the language specified by this linkage specification. + void setLanguage(LanguageIDs L) { Language = L; } + + /// \brief Determines whether this linkage specification had braces in + /// its syntactic form. bool hasBraces() const { return HadBraces; } + /// \brief Set whether this linkage specification has braces in its + /// syntactic form. + void setHasBraces(bool B) { HadBraces = B; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const LinkageSpecDecl *D) { return true; } static bool classofKind(Kind K) { return K == LinkageSpec; } @@ -1528,13 +1616,21 @@ class UsingDirectiveDecl : public NamedDecl { public: /// \brief Retrieve the source range of the nested-name-specifier - /// that qualifiers the namespace name. + /// that qualifies the namespace name. SourceRange getQualifierRange() const { return QualifierRange; } + /// \brief Set the source range of the nested-name-specifier that + /// qualifies the namespace name. + void setQualifierRange(SourceRange R) { QualifierRange = R; } + /// \brief Retrieve the nested-name-specifier that qualifies the /// name of the namespace. NestedNameSpecifier *getQualifier() const { return Qualifier; } + /// \brief Set the nested-name-specifier that qualifes the name of the + /// namespace. + void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } + NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; } const NamedDecl *getNominatedNamespaceAsWritten() const { return NominatedNamespace; @@ -1547,17 +1643,32 @@ public: return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace(); } - /// getCommonAncestor - returns common ancestor context of using-directive, - /// and nominated by it namespace. + /// setNominatedNamespace - Set the namespace nominataed by the + /// using-directive. + void setNominatedNamespace(NamedDecl* NS); + + /// \brief Returns the common ancestor context of this using-directive and + /// its nominated namespace. DeclContext *getCommonAncestor() { return CommonAncestor; } const DeclContext *getCommonAncestor() const { return CommonAncestor; } + /// \brief Set the common ancestor context of this using-directive and its + /// nominated namespace. + void setCommonAncestor(DeclContext* Cxt) { CommonAncestor = Cxt; } + + // FIXME: Could omit 'Key' in name. /// getNamespaceKeyLocation - Returns location of namespace keyword. SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; } + /// setNamespaceKeyLocation - Set the the location of the namespacekeyword. + void setNamespaceKeyLocation(SourceLocation L) { NamespaceLoc = L; } + /// getIdentLocation - Returns location of identifier. SourceLocation getIdentLocation() const { return IdentLoc; } + /// setIdentLocation - set the location of the identifier. + void setIdentLocation(SourceLocation L) { IdentLoc = L; } + static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, SourceLocation NamespaceLoc, @@ -1591,7 +1702,7 @@ class NamespaceAliasDecl : public NamedDecl { /// name, if any. NestedNameSpecifier *Qualifier; - /// IdentLoc - Location of namespace identifier. + /// IdentLoc - Location of namespace identifier. Accessed by TargetNameLoc. SourceLocation IdentLoc; /// Namespace - The Decl that this alias points to. Can either be a @@ -1612,10 +1723,19 @@ public: /// that qualifiers the namespace name. SourceRange getQualifierRange() const { return QualifierRange; } + /// \brief Set the source range of the nested-name-specifier that qualifies + /// the namespace name. + void setQualifierRange(SourceRange R) { QualifierRange = R; } + /// \brief Retrieve the nested-name-specifier that qualifies the /// name of the namespace. NestedNameSpecifier *getQualifier() const { return Qualifier; } + /// \brief Set the nested-name-specifier that qualifies the name of the + /// namespace. + void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } + + /// \brief Retrieve the namespace declaration aliased by this directive. NamespaceDecl *getNamespace() { if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(Namespace)) return AD->getNamespace(); @@ -1631,16 +1751,31 @@ public: /// "namespace foo = ns::bar;". SourceLocation getAliasLoc() const { return AliasLoc; } + /// Set the location o;f the alias name, e.e., 'foo' in + /// "namespace foo = ns::bar;". + void setAliasLoc(SourceLocation L) { AliasLoc = L; } + /// Returns the location of the 'namespace' keyword. SourceLocation getNamespaceLoc() const { return getLocation(); } /// Returns the location of the identifier in the named namespace. SourceLocation getTargetNameLoc() const { return IdentLoc; } + /// Set the location of the identifier in the named namespace. + void setTargetNameLoc(SourceLocation L) { IdentLoc = L; } + /// \brief Retrieve the namespace that this alias refers to, which /// may either be a NamespaceDecl or a NamespaceAliasDecl. NamedDecl *getAliasedNamespace() const { return Namespace; } + /// \brief Set the namespace or namespace alias pointed to by this + /// alias decl. + void setAliasedNamespace(NamedDecl *ND) { + assert((isa<NamespaceAliasDecl>(ND) || isa<NamespaceDecl>(ND)) && + "expecting namespace or namespace alias decl"); + Namespace = ND; + } + static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, SourceLocation AliasLoc, IdentifierInfo *Alias, @@ -1687,16 +1822,20 @@ public: return new (C) UsingShadowDecl(DC, Loc, Using, Target); } - /// Gets the underlying declaration which has been brought into the + /// \brief Gets the underlying declaration which has been brought into the /// local scope. - NamedDecl *getTargetDecl() const { - return Underlying; - } + NamedDecl *getTargetDecl() const { return Underlying; } - /// Gets the using declaration to which this declaration is tied. - UsingDecl *getUsingDecl() const { - return Using; - } + /// \brief Sets the underlying declaration which has been brought into the + /// local scope. + void setTargetDecl(NamedDecl* ND) { Underlying = ND; } + + /// \brief Gets the using declaration to which this declaration is tied. + UsingDecl *getUsingDecl() const { return Using; } + + /// \brief Sets the using declaration that introduces this target + /// declaration. + void setUsingDecl(UsingDecl* UD) { Using = UD; } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UsingShadowDecl *D) { return true; } @@ -1733,21 +1872,39 @@ class UsingDecl : public NamedDecl { } public: + // FIXME: Should be const? /// \brief Returns the source range that covers the nested-name-specifier /// preceding the namespace name. SourceRange getNestedNameRange() { return NestedNameRange; } - /// \brief Returns the source location of the "using" location itself. + /// \brief Set the source range of the nested-name-specifier. + void setNestedNameRange(SourceRange R) { NestedNameRange = R; } + + // FIXME; Should be const? + // FIXME: Naming is inconsistent with other get*Loc functions. + /// \brief Returns the source location of the "using" keyword. SourceLocation getUsingLocation() { return UsingLocation; } - /// \brief Get target nested name declaration. + /// \brief Set the source location of the 'using' keyword. + void setUsingLocation(SourceLocation L) { UsingLocation = L; } + + + /// \brief Get the target nested name declaration. NestedNameSpecifier* getTargetNestedNameDecl() { return TargetNestedName; } - /// isTypeName - Return true if using decl has 'typename'. + /// \brief Set the target nested name declaration. + void setTargetNestedNameDecl(NestedNameSpecifier *NNS) { + TargetNestedName = NNS; + } + + /// \brief Return true if the using declaration has 'typename'. bool isTypeName() const { return IsTypeName; } + /// \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(); } @@ -1765,6 +1922,12 @@ public: } } + /// \brief Return the number of shadowed declarations associated with this + /// using declaration. + unsigned getNumShadowDecls() const { + return Shadows.size(); + } + static UsingDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL, NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg); @@ -1807,14 +1970,26 @@ public: /// preceding the namespace name. SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } + /// \brief Set the source range coverting the nested-name-specifier preceding + /// the namespace name. + void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; } + /// \brief Get target nested name declaration. NestedNameSpecifier* getTargetNestedNameSpecifier() { return TargetNestedNameSpecifier; } + /// \brief Set the nested name declaration. + void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) { + TargetNestedNameSpecifier = NNS; + } + /// \brief Returns the source location of the 'using' keyword. SourceLocation getUsingLoc() const { return UsingLocation; } + /// \brief Set the source location of the 'using' keyword. + void setUsingLoc(SourceLocation L) { UsingLocation = L; } + static UnresolvedUsingValueDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, @@ -1861,17 +2036,32 @@ public: /// preceding the namespace name. SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } + /// \brief Set the source range coverting the nested-name-specifier preceding + /// the namespace name. + void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; } + /// \brief Get target nested name declaration. NestedNameSpecifier* getTargetNestedNameSpecifier() { return TargetNestedNameSpecifier; } + /// \brief Set the nested name declaration. + void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) { + TargetNestedNameSpecifier = NNS; + } + /// \brief Returns the source location of the 'using' keyword. SourceLocation getUsingLoc() const { return UsingLocation; } + /// \brief Set the source location of the 'using' keyword. + void setUsingLoc(SourceLocation L) { UsingLocation = L; } + /// \brief Returns the source location of the 'typename' keyword. SourceLocation getTypenameLoc() const { return TypenameLocation; } + /// \brief Set the source location of the 'typename' keyword. + void setTypenameLoc(SourceLocation L) { TypenameLocation = L; } + static UnresolvedUsingTypenameDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceLocation TypenameLoc, diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index 2a4b12a..9602b67 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -156,7 +156,8 @@ public: /// represents. DeclContext::lookup_result getLookupResult(ASTContext &Context) { if (isNull()) - return DeclContext::lookup_result(0, 0); + return DeclContext::lookup_result(DeclContext::lookup_iterator(0), + DeclContext::lookup_iterator(0)); if (hasDeclarationIDs()) materializeDecls(Context); diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index e34ec9f..97d1656 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -1421,13 +1421,21 @@ private: /// Null for @dynamic. Required for @synthesize. ObjCIvarDecl *PropertyIvarDecl; + + /// Null for @dynamic. Non-null if property must be copy-constructed in getter + Expr *GetterCXXConstructor; + + /// Null for @dynamic. Non-null if property has assignment operator to call + /// in Setter synthesis. + Expr *SetterCXXAssignment; ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L, ObjCPropertyDecl *property, Kind PK, ObjCIvarDecl *ivarDecl) : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc), - PropertyDecl(property), PropertyIvarDecl(ivarDecl) { + PropertyDecl(property), PropertyIvarDecl(ivarDecl), + GetterCXXConstructor(0), SetterCXXAssignment(0) { assert (PK == Dynamic || PropertyIvarDecl); } @@ -1457,7 +1465,21 @@ public: return PropertyIvarDecl; } void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { PropertyIvarDecl = Ivar; } + + Expr *getGetterCXXConstructor() const { + return GetterCXXConstructor; + } + void setGetterCXXConstructor(Expr *getterCXXConstructor) { + GetterCXXConstructor = getterCXXConstructor; + } + Expr *getSetterCXXAssignment() const { + return SetterCXXAssignment; + } + void setSetterCXXAssignment(Expr *setterCXXAssignment) { + SetterCXXAssignment = setterCXXAssignment; + } + 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; } diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 1ec38ba..b7b90b1 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -112,7 +112,7 @@ class TemplateArgumentListBuilder { unsigned MaxStructuredArgs; unsigned NumStructuredArgs; - TemplateArgument *FlatArgs; + llvm::SmallVector<TemplateArgument, 4> FlatArgs; unsigned MaxFlatArgs; unsigned NumFlatArgs; @@ -127,18 +127,12 @@ public: MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0), AddingToPack(false), PackBeginIndex(0) { } - void Append(const TemplateArgument& Arg); + void Append(const TemplateArgument &Arg); void BeginPack(); void EndPack(); - void ReleaseArgs(); - - unsigned flatSize() const { - return NumFlatArgs; - } - const TemplateArgument *getFlatArguments() const { - return FlatArgs; - } + 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. @@ -165,7 +159,7 @@ class TemplateArgumentList { /// \brief The template argument list. /// /// The integer value will be non-zero to indicate that this - /// template argument list does not own the pointer. + /// template argument list does own the pointer. llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments; /// \brief The number of template arguments in this template @@ -175,14 +169,28 @@ class TemplateArgumentList { llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments; unsigned NumStructuredArguments; + TemplateArgumentList(const TemplateArgumentList &Other); // DO NOT IMPL + void operator=(const TemplateArgumentList &Other); // DO NOT IMPL 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); - /// \brief Produces a shallow copy of the given template argument list - TemplateArgumentList(const TemplateArgumentList &Other); + /// 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); + /// Used to release the memory associated with a TemplateArgumentList + /// object. FIXME: This is currently not called anywhere, but the + /// memory will still be freed when using a BumpPtrAllocator. + void Destroy(ASTContext &C); + ~TemplateArgumentList(); /// \brief Retrieve the template argument at a given index. @@ -280,6 +288,9 @@ public: /// specialization from the function template. const TemplateArgumentList *TemplateArguments; + /// \brief The template arguments as written in the sources, if provided. + const TemplateArgumentListInfo *TemplateArgumentsAsWritten; + /// \brief The point at which this function template specialization was /// first instantiated. SourceLocation PointOfInstantiation; @@ -454,6 +465,8 @@ public: /// Declaration of a template function. class FunctionTemplateDecl : public TemplateDecl { + static void DeallocateCommon(void *Ptr); + protected: /// \brief Data that is common to all of the declarations of a given /// function template. @@ -862,7 +875,7 @@ class ClassTemplateSpecializationDecl unsigned SpecializationKind : 3; protected: - ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, + ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, @@ -870,7 +883,7 @@ protected: public: static ClassTemplateSpecializationDecl * - Create(ASTContext &Context, DeclContext *DC, SourceLocation L, + Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, ClassTemplateSpecializationDecl *PrevDecl); @@ -1024,7 +1037,7 @@ class ClassTemplatePartialSpecializationDecl llvm::PointerIntPair<ClassTemplatePartialSpecializationDecl *, 1, bool> InstantiatedFromMember; - ClassTemplatePartialSpecializationDecl(ASTContext &Context, + ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, @@ -1035,7 +1048,7 @@ class ClassTemplatePartialSpecializationDecl unsigned SequenceNumber) : ClassTemplateSpecializationDecl(Context, ClassTemplatePartialSpecialization, - DC, L, SpecializedTemplate, Builder, + TK, DC, L, SpecializedTemplate, Builder, PrevDecl), TemplateParams(Params), ArgsAsWritten(ArgInfos), NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber), @@ -1043,7 +1056,7 @@ class ClassTemplatePartialSpecializationDecl public: static ClassTemplatePartialSpecializationDecl * - Create(ASTContext &Context, DeclContext *DC, SourceLocation L, + Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, @@ -1158,6 +1171,8 @@ public: /// Declaration of a class template. class ClassTemplateDecl : public TemplateDecl { + static void DeallocateCommon(void *Ptr); + protected: /// \brief Data that is common to all of the declarations of a given /// class template. diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 9401786..8a771d5 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -314,15 +314,16 @@ inline bool operator>=(DeclarationName LHS, DeclarationName RHS) { /// retrieved using its member functions (e.g., /// getCXXConstructorName). class DeclarationNameTable { + ASTContext &Ctx; void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> * CXXOperatorIdName *CXXOperatorNames; // Operator names - void *CXXLiteralOperatorNames; // Actually a FoldingSet<...> * + void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName* DeclarationNameTable(const DeclarationNameTable&); // NONCOPYABLE DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE public: - DeclarationNameTable(); + DeclarationNameTable(ASTContext &C); ~DeclarationNameTable(); /// getIdentifier - Create a declaration name that is a simple diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 2946e46..66639e2 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -51,6 +51,7 @@ typedef UsuallyTinyPtrVector<const CXXBaseSpecifier> CXXBaseSpecifierArray; class Expr : public Stmt { QualType TR; + virtual void ANCHOR(); // key function. protected: /// TypeDependent - Whether this expression is type-dependent /// (C++ [temp.dep.expr]). @@ -247,6 +248,15 @@ public: SourceLocation DiagLoc; EvalResult() : HasSideEffects(false), Diag(0), DiagExpr(0) {} + + // isGlobalLValue - Return true if the evaluated lvalue expression + // is global. + bool isGlobalLValue() const; + // hasSideEffects - Return true if the evaluated expression has + // side effects. + bool hasSideEffects() const { + return HasSideEffects; + } }; /// Evaluate - Return true if this is a constant which we can fold using @@ -255,10 +265,6 @@ public: /// in Result. bool Evaluate(EvalResult &Result, ASTContext &Ctx) const; - /// EvaluateAsAny - The same as Evaluate, except that it also succeeds on - /// stack based objects. - bool EvaluateAsAny(EvalResult &Result, 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. @@ -282,8 +288,7 @@ public: /// with link time known address. bool EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const; - /// EvaluateAsAnyLValue - The same as EvaluateAsLValue, except that it - /// also succeeds on stack based, immutable address lvalues. + /// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue. bool EvaluateAsAnyLValue(EvalResult &Result, ASTContext &Ctx) const; /// \brief Enumeration used to describe how \c isNullPointerConstant() @@ -321,6 +326,10 @@ public: /// or CastExprs, returning their operand. Expr *IgnoreParenCasts(); + /// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off any + /// ParenExpr or ImplicitCastExprs, returning their operand. + Expr *IgnoreParenImpCasts(); + /// 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. @@ -1468,13 +1477,10 @@ public: } static bool classof(const Stmt *T) { - return T->getStmtClass() == CallExprClass || - T->getStmtClass() == CXXOperatorCallExprClass || - T->getStmtClass() == CXXMemberCallExprClass; + return T->getStmtClass() >= firstCallExprConstant && + T->getStmtClass() <= lastCallExprConstant; } static bool classof(const CallExpr *) { return true; } - static bool classof(const CXXOperatorCallExpr *) { return true; } - static bool classof(const CXXMemberCallExpr *) { return true; } // Iterators virtual child_iterator child_begin(); @@ -1933,14 +1939,8 @@ public: const CXXBaseSpecifierArray& getBasePath() const { return BasePath; } static bool classof(const Stmt *T) { - StmtClass SC = T->getStmtClass(); - if (SC >= CXXStaticCastExprClass && SC <= CXXFunctionalCastExprClass) - return true; - - if (SC >= ImplicitCastExprClass && SC <= CStyleCastExprClass) - return true; - - return false; + return T->getStmtClass() >= firstCastExprConstant && + T->getStmtClass() <= lastCastExprConstant; } static bool classof(const CastExpr *) { return true; } @@ -2037,13 +2037,8 @@ public: QualType getTypeAsWritten() const { return TInfo->getType(); } static bool classof(const Stmt *T) { - StmtClass SC = T->getStmtClass(); - if (SC >= CStyleCastExprClass && SC <= CStyleCastExprClass) - return true; - if (SC >= CXXStaticCastExprClass && SC <= CXXFunctionalCastExprClass) - return true; - - return false; + return T->getStmtClass() >= firstExplicitCastExprConstant && + T->getStmtClass() <= lastExplicitCastExprConstant; } static bool classof(const ExplicitCastExpr *) { return true; } }; @@ -2198,8 +2193,8 @@ public: bool isShiftAssignOp() const { return Opc == ShlAssign || Opc == ShrAssign; } static bool classof(const Stmt *S) { - return S->getStmtClass() == BinaryOperatorClass || - S->getStmtClass() == CompoundAssignOperatorClass; + return S->getStmtClass() >= firstBinaryOperatorConstant && + S->getStmtClass() <= lastBinaryOperatorConstant; } static bool classof(const BinaryOperator *) { return true; } diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index f9ca78a..0c493f3 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -88,10 +88,13 @@ public: /// the object argument). class CXXMemberCallExpr : public CallExpr { public: - CXXMemberCallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, + CXXMemberCallExpr(ASTContext &C, Expr *fn, Expr **args, unsigned numargs, QualType t, SourceLocation rparenloc) : CallExpr(C, CXXMemberCallExprClass, fn, args, numargs, t, rparenloc) {} + CXXMemberCallExpr(ASTContext &C, EmptyShell Empty) + : CallExpr(C, CXXMemberCallExprClass, Empty) { } + /// getImplicitObjectArgument - Retrieves the implicit object /// argument for the member call. For example, in "x.f(5)", this /// operation would return "x". @@ -318,6 +321,14 @@ public: Operand->isTypeDependent() || Operand->isValueDependent()), Operand(Operand), Range(R) { } + CXXTypeidExpr(EmptyShell Empty, bool isExpr) + : Expr(CXXTypeidExprClass, Empty) { + if (isExpr) + Operand = (Expr*)0; + else + Operand = (TypeSourceInfo*)0; + } + bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } /// \brief Retrieves the type operand of this typeid() expression after @@ -329,15 +340,25 @@ public: assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); return Operand.get<TypeSourceInfo *>(); } + + void setTypeOperandSourceInfo(TypeSourceInfo *TSI) { + assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); + Operand = TSI; + } - Expr* getExprOperand() const { + Expr *getExprOperand() const { assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); return static_cast<Expr*>(Operand.get<Stmt *>()); } - - virtual SourceRange getSourceRange() const { - return Range; + + void setExprOperand(Expr *E) { + assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); + Operand = E; } + + virtual SourceRange getSourceRange() const { return Range; } + void setSourceRange(SourceRange R) { Range = R; } + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXTypeidExprClass; } @@ -371,6 +392,11 @@ public: Type->isDependentType(), Type->isDependentType()), Loc(L), Implicit(isImplicit) { } + CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {} + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } bool isImplicit() const { return Implicit; } @@ -399,6 +425,8 @@ public: // 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) {} + CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {} + const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); } Expr *getSubExpr() { return cast_or_null<Expr>(Op); } void setSubExpr(Expr *E) { Op = E; } @@ -448,8 +476,7 @@ protected: CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param, Expr *SubExpr) - : Expr(SC, SubExpr->getType(), false, false), Param(param, true), Loc(Loc) - { + : Expr(SC, SubExpr->getType(), false, false), Param(param, true), Loc(Loc) { *reinterpret_cast<Expr **>(this + 1) = SubExpr; } @@ -457,6 +484,9 @@ protected: virtual void DoDestroy(ASTContext &C); public: + CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {} + + // Param is the parameter whose default argument is used by this // expression. static CXXDefaultArgExpr *Create(ASTContext &C, SourceLocation Loc, @@ -475,6 +505,9 @@ public: const ParmVarDecl *getParam() const { return Param.getPointer(); } ParmVarDecl *getParam() { return Param.getPointer(); } + /// isExprStored - Return true if this expression owns the expression. + bool isExprStored() const { return Param.getInt(); } + // Retrieve the actual argument to the function call. const Expr *getExpr() const { if (Param.getInt()) @@ -486,10 +519,16 @@ public: return *reinterpret_cast<Expr **> (this + 1); return getParam()->getDefaultArg(); } + + void setExpr(Expr *E) { + Param.setInt(true); + Param.setPointer((ParmVarDecl*)E); + } /// \brief Retrieve the location where this default argument was actually /// used. SourceLocation getUsedLocation() const { return Loc; } + void setUsedLocation(SourceLocation L) { Loc = L; } virtual SourceRange getSourceRange() const { // Default argument expressions have no representation in the @@ -525,8 +564,20 @@ public: const CXXDestructorDecl *getDestructor() const { return Destructor; } }; -/// CXXBindTemporaryExpr - Represents binding an expression to a temporary, -/// so its destructor can be called later. +/// \brief Represents binding an expression to a temporary. +/// +/// This ensures the destructor is called for the temporary. It should only be +/// needed for non-POD, non-trivially destructable class types. For example: +/// +/// \code +/// struct S { +/// S() { } // User defined constructor makes S non-POD. +/// ~S() { } // User defined destructor makes it non-trivial. +/// }; +/// void test() { +/// const S &s_ref = S(); // Requires a CXXBindTemporaryExpr. +/// } +/// \endcode class CXXBindTemporaryExpr : public Expr { CXXTemporary *Temp; @@ -541,11 +592,15 @@ protected: virtual void DoDestroy(ASTContext &C); public: + CXXBindTemporaryExpr(EmptyShell Empty) + : Expr(CXXBindTemporaryExprClass, Empty), Temp(0), SubExpr(0) {} + static CXXBindTemporaryExpr *Create(ASTContext &C, CXXTemporary *Temp, Expr* SubExpr); CXXTemporary *getTemporary() { return Temp; } const CXXTemporary *getTemporary() const { return Temp; } + void setTemporary(CXXTemporary *T) { Temp = T; } const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } Expr *getSubExpr() { return cast<Expr>(SubExpr); } @@ -572,8 +627,8 @@ public: /// const int &i = 10; /// /// a bind reference expression is inserted to indicate that 10 is bound to -/// a reference. (Ans also that a temporary needs to be created to hold the -/// value). +/// a reference, and that a temporary needs to be created to hold the +/// value. class CXXBindReferenceExpr : public Expr { // SubExpr - The expression being bound. Stmt *SubExpr; @@ -827,10 +882,15 @@ public: SourceLocation rParenLoc ) : Expr(CXXZeroInitValueExprClass, ty, false, false), TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} + explicit CXXZeroInitValueExpr(EmptyShell Shell) + : Expr(CXXZeroInitValueExprClass, 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 { @@ -891,6 +951,11 @@ public: Expr **constructorArgs, unsigned numConsArgs, FunctionDecl *operatorDelete, QualType ty, SourceLocation startLoc, SourceLocation endLoc); + explicit CXXNewExpr(EmptyShell Shell) + : Expr(CXXNewExprClass, Shell), SubExprs(0) { } + + void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs, + unsigned numConsArgs); virtual void DoDestroy(ASTContext &C); @@ -900,8 +965,11 @@ public: } FunctionDecl *getOperatorNew() const { return OperatorNew; } + void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } FunctionDecl *getOperatorDelete() const { return OperatorDelete; } + void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; } CXXConstructorDecl *getConstructor() const { return Constructor; } + void setConstructor(CXXConstructorDecl *D) { Constructor = D; } bool isArray() const { return Array; } Expr *getArraySize() { @@ -922,8 +990,11 @@ public: } bool isGlobalNew() const { return GlobalNew; } + void setGlobalNew(bool V) { GlobalNew = V; } bool isParenTypeId() const { return ParenTypeId; } + void setParenTypeId(bool V) { ParenTypeId = V; } bool hasInitializer() const { return Initializer; } + void setHasInitializer(bool V) { Initializer = V; } unsigned getNumConstructorArgs() const { return NumConstructorArgs; } Expr *getConstructorArg(unsigned i) { @@ -963,7 +1034,21 @@ public: const_arg_iterator constructor_arg_end() const { return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); } + + typedef Stmt **raw_arg_iterator; + raw_arg_iterator raw_arg_begin() { return SubExprs; } + raw_arg_iterator raw_arg_end() { + return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); + } + 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 { return SourceRange(StartLoc, EndLoc); } @@ -1260,7 +1345,9 @@ class OverloadExpr : public Expr { /// The results. These are undesugared, which is to say, they may /// include UsingShadowDecls. Access is relative to the naming /// class. - UnresolvedSet<4> Results; + // FIXME: Allocate this data after the OverloadExpr subclass. + DeclAccessPair *Results; + unsigned NumResults; /// The common name of these declarations. DeclarationName Name; @@ -1278,14 +1365,11 @@ class OverloadExpr : public Expr { bool HasExplicitTemplateArgs; protected: - OverloadExpr(StmtClass K, QualType T, bool Dependent, + OverloadExpr(StmtClass K, ASTContext &C, QualType T, bool Dependent, NestedNameSpecifier *Qualifier, SourceRange QRange, DeclarationName Name, SourceLocation NameLoc, - bool HasTemplateArgs) - : Expr(K, T, Dependent, Dependent), - Name(Name), Qualifier(Qualifier), QualifierRange(QRange), - NameLoc(NameLoc), HasExplicitTemplateArgs(HasTemplateArgs) - {} + bool HasTemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); public: /// Computes whether an unresolved lookup on the given declarations @@ -1309,22 +1393,17 @@ public: return llvm::PointerIntPair<OverloadExpr*,1>(cast<OverloadExpr>(E), op); } - void addDecls(UnresolvedSetIterator Begin, UnresolvedSetIterator End) { - Results.append(Begin, End); - } - /// Gets the naming class of this lookup, if any. CXXRecordDecl *getNamingClass() const; typedef UnresolvedSetImpl::iterator decls_iterator; - decls_iterator decls_begin() const { return Results.begin(); } - decls_iterator decls_end() const { return Results.end(); } - - /// Gets the decls as an unresolved set. - const UnresolvedSetImpl &getDecls() { return Results; } + decls_iterator decls_begin() const { return UnresolvedSetIterator(Results); } + decls_iterator decls_end() const { + return UnresolvedSetIterator(Results + NumResults); + } /// Gets the number of declarations in the unresolved set. - unsigned getNumDecls() const { return Results.size(); } + unsigned getNumDecls() const { return NumResults; } /// Gets the name looked up. DeclarationName getName() const { return Name; } @@ -1390,12 +1469,14 @@ class UnresolvedLookupExpr : public OverloadExpr { /// against the qualified-lookup bits. CXXRecordDecl *NamingClass; - UnresolvedLookupExpr(QualType T, bool Dependent, CXXRecordDecl *NamingClass, + UnresolvedLookupExpr(ASTContext &C, QualType T, bool Dependent, + CXXRecordDecl *NamingClass, NestedNameSpecifier *Qualifier, SourceRange QRange, DeclarationName Name, SourceLocation NameLoc, - bool RequiresADL, bool Overloaded, bool HasTemplateArgs) - : OverloadExpr(UnresolvedLookupExprClass, T, Dependent, Qualifier, QRange, - Name, NameLoc, HasTemplateArgs), + bool RequiresADL, bool Overloaded, bool HasTemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End) + : OverloadExpr(UnresolvedLookupExprClass, C, T, Dependent, Qualifier, + QRange, Name, NameLoc, HasTemplateArgs, Begin, End), RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass) {} @@ -1407,11 +1488,15 @@ public: SourceRange QualifierRange, DeclarationName Name, SourceLocation NameLoc, - bool ADL, bool Overloaded) { - return new(C) UnresolvedLookupExpr(Dependent ? C.DependentTy : C.OverloadTy, + bool ADL, bool Overloaded, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End) { + return new(C) UnresolvedLookupExpr(C, + Dependent ? C.DependentTy : C.OverloadTy, Dependent, NamingClass, Qualifier, QualifierRange, - Name, NameLoc, ADL, Overloaded, false); + Name, NameLoc, ADL, Overloaded, false, + Begin, End); } static UnresolvedLookupExpr *Create(ASTContext &C, @@ -1422,7 +1507,9 @@ public: DeclarationName Name, SourceLocation NameLoc, bool ADL, - const TemplateArgumentListInfo &Args); + const TemplateArgumentListInfo &Args, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End); /// True if this declaration should be extended by /// argument-dependent lookup. @@ -1611,7 +1698,7 @@ class CXXExprWithTemporaries : public Expr { CXXTemporary **Temps; unsigned NumTemps; - CXXExprWithTemporaries(Expr *SubExpr, CXXTemporary **Temps, + CXXExprWithTemporaries(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps, unsigned NumTemps); ~CXXExprWithTemporaries(); @@ -1619,11 +1706,17 @@ protected: virtual void DoDestroy(ASTContext &C); public: + CXXExprWithTemporaries(EmptyShell Empty) + : Expr(CXXExprWithTemporariesClass, Empty), + SubExpr(0), Temps(0), NumTemps(0) {} + static CXXExprWithTemporaries *Create(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps, unsigned NumTemps); unsigned getNumTemporaries() const { return NumTemps; } + void setNumTemporaries(ASTContext &C, unsigned N); + CXXTemporary *getTemporary(unsigned i) { assert(i < NumTemps && "Index out of range"); return Temps[i]; @@ -1631,6 +1724,10 @@ public: const CXXTemporary *getTemporary(unsigned i) const { return const_cast<CXXExprWithTemporaries*>(this)->getTemporary(i); } + void setTemporary(unsigned i, CXXTemporary *T) { + assert(i < NumTemps && "Index out of range"); + Temps[i] = T; + } Expr *getSubExpr() { return cast<Expr>(SubExpr); } const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } @@ -2020,7 +2117,7 @@ class UnresolvedMemberExpr : public OverloadExpr { /// \brief The location of the '->' or '.' operator. SourceLocation OperatorLoc; - UnresolvedMemberExpr(QualType T, bool Dependent, + UnresolvedMemberExpr(ASTContext &C, QualType T, bool Dependent, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, @@ -2028,7 +2125,8 @@ class UnresolvedMemberExpr : public OverloadExpr { SourceRange QualifierRange, DeclarationName Member, SourceLocation MemberLoc, - const TemplateArgumentListInfo *TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); public: static UnresolvedMemberExpr * @@ -2039,7 +2137,8 @@ public: SourceRange QualifierRange, DeclarationName Member, SourceLocation MemberLoc, - const TemplateArgumentListInfo *TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); /// \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 diff --git a/include/clang/AST/Makefile b/include/clang/AST/Makefile new file mode 100644 index 0000000..a25977c --- /dev/null +++ b/include/clang/AST/Makefile @@ -0,0 +1,13 @@ +LEVEL = ../../../../.. +BUILT_SOURCES = StmtNodes.inc + +TABLEGEN_INC_FILES_COMMON = 1 + +include $(LEVEL)/Makefile.common + +INPUT_TDS = $(PROJ_SRC_DIR)/StmtNodes.td + +$(ObjDir)/StmtNodes.inc.tmp : StmtNodes.td $(TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang statement node tables with tblgen" + $(Verb) $(TableGen) -gen-clang-stmt-nodes -o $(call SYSPATH, $@) $< + diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index e78476e..2b3229e 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -109,6 +109,11 @@ private: /// which is the alignment of the object without virtual bases. uint64_t 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; + /// PrimaryBase - The primary base info for this record. PrimaryBaseInfo PrimaryBase; @@ -127,7 +132,6 @@ private: CXXRecordLayoutInfo *CXXInfo; friend class ASTContext; - friend class ASTRecordLayoutBuilder; ASTRecordLayout(ASTContext &Ctx, uint64_t size, unsigned alignment, unsigned datasize, const uint64_t *fieldoffsets, @@ -139,7 +143,9 @@ private: uint64_t size, unsigned alignment, uint64_t datasize, const uint64_t *fieldoffsets, unsigned fieldcount, uint64_t nonvirtualsize, unsigned nonvirtualalign, - const PrimaryBaseInfo &PrimaryBase, + uint64_t SizeOfLargestEmptySubobject, + const CXXRecordDecl *PrimaryBase, + bool PrimaryBaseIsVirtual, const BaseOffsetsMapTy& BaseOffsets, const BaseOffsetsMapTy& VBaseOffsets); @@ -222,6 +228,11 @@ public: return CXXInfo->VBaseOffsets[VBase]; } + uint64_t getSizeOfLargestEmptySubobject() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + return CXXInfo->SizeOfLargestEmptySubobject; + } + primary_base_info_iterator primary_base_begin() const { assert(CXXInfo && "Record layout does not have C++ specific info!"); diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h new file mode 100644 index 0000000..07865e0 --- /dev/null +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -0,0 +1,768 @@ +//===--- RecursiveASTVisitor.h - Recursive AST 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 RecursiveASTVisitor interface, which recursively +// traverses the entire AST. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H +#define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/TemplateName.h" +#include "clang/AST/Type.h" + +namespace clang { + +#define DISPATCH(NAME, CLASS, Var) \ +return getDerived().Visit ## NAME(static_cast<CLASS*>(Var)) + +// We use preprocessor meta-programming to generate the Visit*() +// methods for all subclasses of Stmt, Decl, and Type. Some of the +// generated definitions, however, need to be customized. The +// meta-programming technique we use doesn't let us select which +// methods to generate. Therefore we have to generate ALL of them in +// a helper class RecursiveASTVisitorImpl, and override the ones we +// don't like in a child class RecursiveASTVisitor (C++ doesn't allow +// overriding a method in the same class). +// +// Do not use this class directly - use RecursiveASTVisitor instead. +template<typename Derived> +class RecursiveASTVisitorImpl { +public: + /// \brief Return a reference to the derived class. + Derived &getDerived() { return *static_cast<Derived*>(this); } + + /// \brief Recursively visit a statement or expression, by + /// dispatching to Visit*() based on the argument's dynamic type. + /// This is NOT meant to be overridden by a subclass. + /// + /// \returns true if the visitation was terminated early, false + /// otherwise (including when the argument is NULL). + bool Visit(Stmt *S); + + /// \brief Recursively visit a type, by dispatching to + /// Visit*Type() based on the argument's getTypeClass() property. + /// This is NOT meant to be overridden by a subclass. + /// + /// \returns true if the visitation was terminated early, false + /// otherwise (including when the argument is a Null type). + bool Visit(QualType T); + + /// \brief Recursively visit a declaration, by dispatching to + /// Visit*Decl() based on the argument's dynamic type. This is + /// NOT meant to be overridden by a subclass. + /// + /// \returns true if the visitation was terminated early, false + /// otherwise (including when the argument is NULL). + bool Visit(Decl *D); + + /// \brief Recursively visit a C++ nested-name-specifier. + /// + /// \returns true if the visitation was terminated early, false otherwise. + bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS); + + /// \brief Recursively visit a template name. + /// + /// \returns true if the visitation was terminated early, false otherwise. + bool VisitTemplateName(TemplateName Template); + + /// \brief Recursively visit a template argument. + /// + /// \returns true if the visitation was terminated early, false otherwise. + bool VisitTemplateArgument(const TemplateArgument &Arg); + + /// \brief Recursively visit a set of template arguments. + /// + /// \returns true if the visitation was terminated early, false otherwise. + bool VisitTemplateArguments(const TemplateArgument *Args, unsigned NumArgs); + + // If the implementation chooses not to implement a certain visit method, fall + // back on VisitExpr or whatever else is the superclass. +#define STMT(CLASS, PARENT) \ +bool Visit ## CLASS(CLASS *S) { DISPATCH(PARENT, PARENT, S); } +#include "clang/AST/StmtNodes.inc" + + // If the implementation doesn't implement binary operator methods, fall back + // on VisitBinaryOperator. +#define BINOP_FALLBACK(NAME) \ +bool VisitBin ## NAME(BinaryOperator *S) { \ +DISPATCH(BinaryOperator, BinaryOperator, S); \ +} + BINOP_FALLBACK(PtrMemD) BINOP_FALLBACK(PtrMemI) + BINOP_FALLBACK(Mul) BINOP_FALLBACK(Div) BINOP_FALLBACK(Rem) + BINOP_FALLBACK(Add) BINOP_FALLBACK(Sub) BINOP_FALLBACK(Shl) + BINOP_FALLBACK(Shr) + + BINOP_FALLBACK(LT) BINOP_FALLBACK(GT) BINOP_FALLBACK(LE) + BINOP_FALLBACK(GE) BINOP_FALLBACK(EQ) BINOP_FALLBACK(NE) + BINOP_FALLBACK(And) BINOP_FALLBACK(Xor) BINOP_FALLBACK(Or) + BINOP_FALLBACK(LAnd) BINOP_FALLBACK(LOr) + + BINOP_FALLBACK(Assign) + BINOP_FALLBACK(Comma) +#undef BINOP_FALLBACK + + // If the implementation doesn't implement compound assignment operator + // methods, fall back on VisitCompoundAssignOperator. +#define CAO_FALLBACK(NAME) \ +bool VisitBin ## NAME(CompoundAssignOperator *S) { \ +DISPATCH(CompoundAssignOperator, CompoundAssignOperator, S); \ +} + CAO_FALLBACK(MulAssign) CAO_FALLBACK(DivAssign) CAO_FALLBACK(RemAssign) + CAO_FALLBACK(AddAssign) CAO_FALLBACK(SubAssign) CAO_FALLBACK(ShlAssign) + CAO_FALLBACK(ShrAssign) CAO_FALLBACK(AndAssign) CAO_FALLBACK(OrAssign) + CAO_FALLBACK(XorAssign) +#undef CAO_FALLBACK + + // If the implementation doesn't implement unary operator methods, fall back + // on VisitUnaryOperator. +#define UNARYOP_FALLBACK(NAME) \ +bool VisitUnary ## NAME(UnaryOperator *S) { \ +DISPATCH(UnaryOperator, UnaryOperator, S); \ +} + UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec) + UNARYOP_FALLBACK(PreInc) UNARYOP_FALLBACK(PreDec) + UNARYOP_FALLBACK(AddrOf) UNARYOP_FALLBACK(Deref) + + UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus) + UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot) + UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag) + UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf) +#undef UNARYOP_FALLBACK + + /// \brief Basis for statement and expression visitation, which + /// visits all of the substatements and subexpressions. + /// + /// The relation between Visit(Stmt *S) and this method is that + /// the former dispatches to Visit*() based on S's dynamic type, + /// which forwards the call up the inheritance chain until + /// reaching VisitStmt(), which then calls Visit() on each + /// substatement/subexpression. + bool VisitStmt(Stmt *S); + + /// \brief Basis for type visitation, which by default does nothing. + /// + /// The relation between Visit(QualType T) and this method is + /// that the former dispatches to Visit*Type(), which forwards the + /// call up the inheritance chain until reaching VisitType(). + bool VisitType(Type *T); + +#define TYPE(Class, Base) \ + bool Visit##Class##Type(Class##Type *T); +#include "clang/AST/TypeNodes.def" + + /// \brief Basis for declaration and definition visitation, which + /// visits all of the subnodes. + /// + /// The relation between Visit(Decl *) and this method is that the + /// former dispatches to Visit*Decl(), which forwards the call up + /// the inheritance chain until reaching VisitDecl(). + bool VisitDecl(Decl *D); + +#define DECL(Class, Base) \ + bool Visit##Class##Decl(Class##Decl *D) { \ + return getDerived().Visit##Base(D); \ + } +#define ABSTRACT_DECL(Class, Base) DECL(Class, Base) +#include "clang/AST/DeclNodes.def" +}; + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::Visit(Stmt *S) { + if (!S) + return false; + + // If we have a binary expr, dispatch to the subcode of the binop. A smart + // optimizer (e.g. LLVM) will fold this comparison into the switch stmt + // below. + if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { + switch (BinOp->getOpcode()) { + case BinaryOperator::PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator, S); + case BinaryOperator::PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator, S); + case BinaryOperator::Mul: DISPATCH(BinMul, BinaryOperator, S); + case BinaryOperator::Div: DISPATCH(BinDiv, BinaryOperator, S); + case BinaryOperator::Rem: DISPATCH(BinRem, BinaryOperator, S); + case BinaryOperator::Add: DISPATCH(BinAdd, BinaryOperator, S); + case BinaryOperator::Sub: DISPATCH(BinSub, BinaryOperator, S); + case BinaryOperator::Shl: DISPATCH(BinShl, BinaryOperator, S); + case BinaryOperator::Shr: DISPATCH(BinShr, BinaryOperator, S); + + case BinaryOperator::LT: DISPATCH(BinLT, BinaryOperator, S); + case BinaryOperator::GT: DISPATCH(BinGT, BinaryOperator, S); + case BinaryOperator::LE: DISPATCH(BinLE, BinaryOperator, S); + case BinaryOperator::GE: DISPATCH(BinGE, BinaryOperator, S); + case BinaryOperator::EQ: DISPATCH(BinEQ, BinaryOperator, S); + case BinaryOperator::NE: DISPATCH(BinNE, BinaryOperator, S); + + case BinaryOperator::And: DISPATCH(BinAnd, BinaryOperator, S); + case BinaryOperator::Xor: DISPATCH(BinXor, BinaryOperator, S); + case BinaryOperator::Or : DISPATCH(BinOr, BinaryOperator, S); + case BinaryOperator::LAnd: DISPATCH(BinLAnd, BinaryOperator, S); + case BinaryOperator::LOr : DISPATCH(BinLOr, BinaryOperator, S); + case BinaryOperator::Assign: DISPATCH(BinAssign, BinaryOperator, S); + case BinaryOperator::MulAssign: + DISPATCH(BinMulAssign, CompoundAssignOperator, S); + case BinaryOperator::DivAssign: + DISPATCH(BinDivAssign, CompoundAssignOperator, S); + case BinaryOperator::RemAssign: + DISPATCH(BinRemAssign, CompoundAssignOperator, S); + case BinaryOperator::AddAssign: + DISPATCH(BinAddAssign, CompoundAssignOperator, S); + case BinaryOperator::SubAssign: + DISPATCH(BinSubAssign, CompoundAssignOperator, S); + case BinaryOperator::ShlAssign: + DISPATCH(BinShlAssign, CompoundAssignOperator, S); + case BinaryOperator::ShrAssign: + DISPATCH(BinShrAssign, CompoundAssignOperator, S); + case BinaryOperator::AndAssign: + DISPATCH(BinAndAssign, CompoundAssignOperator, S); + case BinaryOperator::OrAssign: + DISPATCH(BinOrAssign, CompoundAssignOperator, S); + case BinaryOperator::XorAssign: + DISPATCH(BinXorAssign, CompoundAssignOperator, S); + case BinaryOperator::Comma: DISPATCH(BinComma, BinaryOperator, S); + } + } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { + switch (UnOp->getOpcode()) { + case UnaryOperator::PostInc: DISPATCH(UnaryPostInc, UnaryOperator, S); + case UnaryOperator::PostDec: DISPATCH(UnaryPostDec, UnaryOperator, S); + case UnaryOperator::PreInc: DISPATCH(UnaryPreInc, UnaryOperator, S); + case UnaryOperator::PreDec: DISPATCH(UnaryPreDec, UnaryOperator, S); + case UnaryOperator::AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator, S); + case UnaryOperator::Deref: DISPATCH(UnaryDeref, UnaryOperator, S); + case UnaryOperator::Plus: DISPATCH(UnaryPlus, UnaryOperator, S); + case UnaryOperator::Minus: DISPATCH(UnaryMinus, UnaryOperator, S); + case UnaryOperator::Not: DISPATCH(UnaryNot, UnaryOperator, S); + case UnaryOperator::LNot: DISPATCH(UnaryLNot, UnaryOperator, S); + case UnaryOperator::Real: DISPATCH(UnaryReal, UnaryOperator, S); + case UnaryOperator::Imag: DISPATCH(UnaryImag, UnaryOperator, S); + case UnaryOperator::Extension: DISPATCH(UnaryExtension, UnaryOperator, S); + case UnaryOperator::OffsetOf: DISPATCH(UnaryOffsetOf, UnaryOperator, S); + } + } + + // Top switch stmt: dispatch to VisitFooStmt for each FooStmt. + switch (S->getStmtClass()) { + case Stmt::NoStmtClass: break; +#define ABSTRACT_STMT(STMT) +#define STMT(CLASS, PARENT) \ +case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS, S); +#include "clang/AST/StmtNodes.inc" + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::Visit(QualType T) { + if (T.isNull()) + return false; + + switch (T->getTypeClass()) { +#define ABSTRACT_TYPE(Class, Base) +#define TYPE(Class, Base) \ + case Type::Class: DISPATCH(Class##Type, Class##Type, T.getTypePtr()); +#include "clang/AST/TypeNodes.def" + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::Visit(Decl *D) { + if (!D) + return false; + + switch (D->getKind()) { +#define ABSTRACT_DECL(Class, Base) +#define DECL(Class, Base) \ + case Decl::Class: DISPATCH(Class##Decl, Class##Decl, D); +#include "clang/AST/DeclNodes.def" + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitNestedNameSpecifier( + NestedNameSpecifier *NNS) { + if (NNS->getPrefix() && + getDerived().VisitNestedNameSpecifier(NNS->getPrefix())) + return true; + + switch (NNS->getKind()) { + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::Global: + return false; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + return Visit(QualType(NNS->getAsType(), 0)); + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTemplateName(TemplateName Template) { + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) + return DTN->getQualifier() && + getDerived().VisitNestedNameSpecifier(DTN->getQualifier()); + + if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + return getDerived().VisitNestedNameSpecifier(QTN->getQualifier()); + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTemplateArgument( + const TemplateArgument &Arg) { + switch (Arg.getKind()) { + case TemplateArgument::Null: + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + return false; + + case TemplateArgument::Type: + return Visit(Arg.getAsType()); + + case TemplateArgument::Template: + return getDerived().VisitTemplateName(Arg.getAsTemplate()); + + case TemplateArgument::Expression: + return getDerived().Visit(Arg.getAsExpr()); + + case TemplateArgument::Pack: + return getDerived().VisitTemplateArguments(Arg.pack_begin(), + Arg.pack_size()); + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTemplateArguments( + const TemplateArgument *Args, + unsigned NumArgs) { + for (unsigned I = 0; I != NumArgs; ++I) + if (getDerived().VisitTemplateArgument(Args[I])) + return true; + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitStmt(Stmt *Node) { + for (Stmt::child_iterator C = Node->child_begin(), CEnd = Node->child_end(); + C != CEnd; ++C) { + if (Visit(*C)) + return true; + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitType(Type *T) { + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitBuiltinType(BuiltinType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitComplexType(ComplexType *T) { + if (Visit(T->getElementType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitPointerType(PointerType *T) { + if (Visit(T->getPointeeType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitBlockPointerType( + BlockPointerType *T) { + if (Visit(T->getPointeeType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitReferenceType(ReferenceType *T) { + if (Visit(T->getPointeeType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitLValueReferenceType( + LValueReferenceType *T) { + return getDerived().VisitReferenceType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitRValueReferenceType( + RValueReferenceType *T) { + return getDerived().VisitReferenceType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitMemberPointerType( + MemberPointerType *T) { + if (Visit(QualType(T->getClass(), 0)) || Visit(T->getPointeeType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitArrayType(ArrayType *T) { + if (Visit(T->getElementType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitConstantArrayType( + ConstantArrayType *T) { + return getDerived().VisitArrayType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitIncompleteArrayType( + IncompleteArrayType *T) { + return getDerived().VisitArrayType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitVariableArrayType( + VariableArrayType *T) { + if (Visit(T->getSizeExpr())) + return true; + + return getDerived().VisitArrayType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitDependentSizedArrayType( + DependentSizedArrayType *T) { + if (T->getSizeExpr() && Visit(T->getSizeExpr())) + return true; + + return getDerived().VisitArrayType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitDependentSizedExtVectorType( + DependentSizedExtVectorType *T) { + if ((T->getSizeExpr() && Visit(T->getSizeExpr())) || + Visit(T->getElementType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitVectorType(VectorType *T) { + if (Visit(T->getElementType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitExtVectorType(ExtVectorType *T) { + return getDerived().VisitVectorType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitFunctionType(FunctionType *T) { + if (Visit(T->getResultType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitFunctionNoProtoType( + FunctionNoProtoType *T) { + return getDerived().VisitFunctionType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitFunctionProtoType( + FunctionProtoType *T) { + for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(), + AEnd = T->arg_type_end(); + A != AEnd; ++A) { + if (Visit(*A)) + return true; + } + + for (FunctionProtoType::exception_iterator E = T->exception_begin(), + EEnd = T->exception_end(); + E != EEnd; ++E) { + if (Visit(*E)) + return true; + } + + return getDerived().VisitFunctionType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitUnresolvedUsingType( + UnresolvedUsingType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTypedefType(TypedefType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTypeOfExprType(TypeOfExprType *T) { + if (Visit(T->getUnderlyingExpr())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTypeOfType(TypeOfType *T) { + if (Visit(T->getUnderlyingType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitDecltypeType(DecltypeType *T) { + if (Visit(T->getUnderlyingExpr())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTagType(TagType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitRecordType(RecordType *T) { + return getDerived().VisitTagType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitEnumType(EnumType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTemplateTypeParmType( + TemplateTypeParmType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitSubstTemplateTypeParmType( + SubstTemplateTypeParmType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTemplateSpecializationType( + TemplateSpecializationType *T) { + if (getDerived().VisitTemplateName(T->getTemplateName()) || + getDerived().VisitTemplateArguments(T->getArgs(), T->getNumArgs())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitInjectedClassNameType( + InjectedClassNameType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitElaboratedType(ElaboratedType *T) { + if (T->getQualifier() && + getDerived().VisitNestedNameSpecifier(T->getQualifier())) + return true; + if (Visit(T->getNamedType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitDependentNameType( + DependentNameType *T) { + if (T->getQualifier() && + getDerived().VisitNestedNameSpecifier(T->getQualifier())) + return true; + + if (T->getTemplateId() && + getDerived().VisitTemplateSpecializationType( + const_cast<TemplateSpecializationType *>(T->getTemplateId()))) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitObjCInterfaceType( + ObjCInterfaceType *T) { + return getDerived().VisitObjCObjectType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitObjCObjectType(ObjCObjectType *T) { + // We have to watch out here because an ObjCInterfaceType's base + // type is itself. + if (T->getBaseType().getTypePtr() != T) + if (Visit(T->getBaseType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitObjCObjectPointerType( + ObjCObjectPointerType *T) { + if (Visit(T->getPointeeType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitDecl(Decl *D) { + if (DeclContext *DC = dyn_cast<DeclContext>(D)) { + for (DeclContext::decl_iterator Child = DC->decls_begin(), + ChildEnd = DC->decls_end(); + Child != ChildEnd; ++Child) + if (Visit(*Child)) + return true; + + return false; + } + + return false; +} + +/// \brief A visitor that recursively walks the entire Clang AST. +/// +/// Clients of this visitor should subclass the visitor (providing +/// themselves as the template argument, using the curiously +/// recurring template pattern) and override any of the Visit* +/// methods (except Visit()) for declaration, type, statement, +/// expression, or other AST nodes where the visitor should customize +/// behavior. Returning "true" from one of these overridden functions +/// will abort the entire traversal. An overridden Visit* method +/// will not descend further into the AST for that node unless +/// Base::Visit* is called. +template<typename Derived> +class RecursiveASTVisitor : public RecursiveASTVisitorImpl<Derived> { + typedef RecursiveASTVisitorImpl<Derived> Impl; +public: + typedef RecursiveASTVisitor<Derived> Base; + + bool VisitDeclaratorDecl(DeclaratorDecl *D); + bool VisitFunctionDecl(FunctionDecl *D); + bool VisitVarDecl(VarDecl *D); + bool VisitBlockDecl(BlockDecl *D); + bool VisitDeclStmt(DeclStmt *S); + bool VisitFunctionType(FunctionType *F); + bool VisitFunctionProtoType(FunctionProtoType *F); +}; + +#define DEFINE_VISIT(Type, Name, Statement) \ + template<typename Derived> \ + bool RecursiveASTVisitor<Derived>::Visit ## Type (Type *Name) { \ + if (Impl::Visit ## Type (Name)) return true; \ + { Statement; } \ + return false; \ + } + +DEFINE_VISIT(DeclaratorDecl, D, { + if (TypeSourceInfo *TInfo = D->getTypeSourceInfo()) + return this->Visit(TInfo->getType()); + }) + +DEFINE_VISIT(FunctionDecl, D, { + if (D->isThisDeclarationADefinition()) + return this->Visit(D->getBody()); + }) + +DEFINE_VISIT(VarDecl, D, return this->Visit(D->getInit())) + +DEFINE_VISIT(BlockDecl, D, return this->Visit(D->getBody())) + +DEFINE_VISIT(DeclStmt, S, { + for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end(); + I != E; ++I) { + if (this->Visit(*I)) + return true; + } + }) + +// FunctionType is the common base class of FunctionNoProtoType (a +// K&R-style function declaration that has no information about +// its arguments) and FunctionProtoType. +DEFINE_VISIT(FunctionType, F, return this->Visit(F->getResultType())) + +DEFINE_VISIT(FunctionProtoType, F, { + for (unsigned i = 0; i != F->getNumArgs(); ++i) { + if (this->Visit(F->getArgType(i))) + return true; + } + for (unsigned i = 0; i != F->getNumExceptions(); ++i) { + if (this->Visit(F->getExceptionType(i))) + return true; + } + }) + +#undef DEFINE_VISIT + +#undef DISPATCH + +} // end namespace clang + +#endif // LLVM_CLANG_AST_RECURSIVEASTVISITOR_H diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 0b68a40..9deae15 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -98,12 +98,14 @@ public: enum StmtClass { NoStmtClass = 0, #define STMT(CLASS, PARENT) CLASS##Class, -#define FIRST_STMT(CLASS) firstStmtConstant = CLASS##Class, -#define LAST_STMT(CLASS) lastStmtConstant = CLASS##Class, -#define FIRST_EXPR(CLASS) firstExprConstant = CLASS##Class, -#define LAST_EXPR(CLASS) lastExprConstant = CLASS##Class -#define ABSTRACT_EXPR(CLASS, PARENT) -#include "clang/AST/StmtNodes.def" +#define STMT_RANGE(BASE, FIRST, LAST) \ + first##BASE##Constant = FIRST##Class, \ + last##BASE##Constant = LAST##Class, +#define LAST_STMT_RANGE(BASE, FIRST, LAST) \ + first##BASE##Constant = FIRST##Class, \ + last##BASE##Constant = LAST##Class +#define ABSTRACT_STMT(STMT) +#include "clang/AST/StmtNodes.inc" }; private: /// \brief The statement class. @@ -1083,9 +1085,15 @@ public: class ReturnStmt : public Stmt { Stmt *RetExpr; SourceLocation RetLoc; + const VarDecl *NRVOCandidate; + public: - ReturnStmt(SourceLocation RL, Expr *E = 0) : Stmt(ReturnStmtClass), - RetExpr((Stmt*) E), RetLoc(RL) {} + ReturnStmt(SourceLocation RL) + : Stmt(ReturnStmtClass), RetExpr(0), RetLoc(RL), NRVOCandidate(0) { } + + ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate) + : Stmt(ReturnStmtClass), RetExpr((Stmt*) E), RetLoc(RL), + NRVOCandidate(NRVOCandidate) {} /// \brief Build an empty return expression. explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { } @@ -1097,6 +1105,14 @@ public: SourceLocation getReturnLoc() const { return RetLoc; } void setReturnLoc(SourceLocation L) { RetLoc = L; } + /// \brief Retrieve the variable that might be used for the named return + /// value optimization. + /// + /// The optimization itself can only be performed if the variable is + /// also marked as an NRVO object. + const VarDecl *getNRVOCandidate() const { return NRVOCandidate; } + void setNRVOCandidate(const VarDecl *Var) { NRVOCandidate = Var; } + virtual SourceRange getSourceRange() const; static bool classof(const Stmt *T) { diff --git a/include/clang/AST/StmtNodes.td b/include/clang/AST/StmtNodes.td new file mode 100644 index 0000000..60c94a6 --- /dev/null +++ b/include/clang/AST/StmtNodes.td @@ -0,0 +1,127 @@ +class Stmt<bit abstract = 0> { + bit Abstract = abstract; +} + +class DStmt<Stmt base, bit abstract = 0> : Stmt<abstract> { + Stmt Base = base; +} + +// Statements +def NullStmt : Stmt; +def CompoundStmt : Stmt; +def LabelStmt : Stmt; +def IfStmt : Stmt; +def SwitchStmt : Stmt; +def WhileStmt : Stmt; +def DoStmt : Stmt; +def ForStmt : Stmt; +def GotoStmt : Stmt; +def IndirectGotoStmt : Stmt; +def ContinueStmt : Stmt; +def BreakStmt : Stmt; +def ReturnStmt : Stmt; +def DeclStmt : Stmt; +def SwitchCase : Stmt; +def CaseStmt : DStmt<SwitchCase>; +def DefaultStmt : DStmt<SwitchCase>; + +// GNU Extensions +def AsmStmt : Stmt; + +// Obj-C statements +def ObjCAtTryStmt : Stmt; +def ObjCAtCatchStmt : Stmt; +def ObjCAtFinallyStmt : Stmt; +def ObjCAtThrowStmt : Stmt; +def ObjCAtSynchronizedStmt : Stmt; +def ObjCForCollectionStmt : Stmt; + +// C++ statments +def CXXCatchStmt : Stmt; +def CXXTryStmt : Stmt; + +// Expressions +def Expr : Stmt<1>; +def PredefinedExpr : DStmt<Expr>; +def DeclRefExpr : DStmt<Expr>; +def IntegerLiteral : DStmt<Expr>; +def FloatingLiteral : DStmt<Expr>; +def ImaginaryLiteral : DStmt<Expr>; +def StringLiteral : DStmt<Expr>; +def CharacterLiteral : DStmt<Expr>; +def ParenExpr : DStmt<Expr>; +def UnaryOperator : DStmt<Expr>; +def OffsetOfExpr : DStmt<Expr>; +def SizeOfAlignOfExpr : DStmt<Expr>; +def ArraySubscriptExpr : DStmt<Expr>; +def CallExpr : DStmt<Expr>; +def MemberExpr : DStmt<Expr>; +def CastExpr : DStmt<Expr, 1>; +def BinaryOperator : DStmt<Expr>; +def CompoundAssignOperator : DStmt<BinaryOperator>; +def ConditionalOperator : DStmt<Expr>; +def ImplicitCastExpr : DStmt<CastExpr>; +def ExplicitCastExpr : DStmt<CastExpr, 1>; +def CStyleCastExpr : DStmt<ExplicitCastExpr>; +def CompoundLiteralExpr : DStmt<Expr>; +def ExtVectorElementExpr : DStmt<Expr>; +def InitListExpr : DStmt<Expr>; +def DesignatedInitExpr : DStmt<Expr>; +def ImplicitValueInitExpr : DStmt<Expr>; +def ParenListExpr : DStmt<Expr>; +def VAArgExpr : DStmt<Expr>; + +// GNU Extensions. +def AddrLabelExpr : DStmt<Expr>; +def StmtExpr : DStmt<Expr>; +def TypesCompatibleExpr : DStmt<Expr>; +def ChooseExpr : DStmt<Expr>; +def GNUNullExpr : DStmt<Expr>; + +// C++ Expressions. +def CXXOperatorCallExpr : DStmt<CallExpr>; +def CXXMemberCallExpr : DStmt<CallExpr>; +def CXXNamedCastExpr : DStmt<ExplicitCastExpr, 1>; +def CXXStaticCastExpr : DStmt<CXXNamedCastExpr>; +def CXXDynamicCastExpr : DStmt<CXXNamedCastExpr>; +def CXXReinterpretCastExpr : DStmt<CXXNamedCastExpr>; +def CXXConstCastExpr : DStmt<CXXNamedCastExpr>; +def CXXFunctionalCastExpr : DStmt<ExplicitCastExpr>; +def CXXTypeidExpr : DStmt<Expr>; +def CXXBoolLiteralExpr : DStmt<Expr>; +def CXXNullPtrLiteralExpr : DStmt<Expr>; +def CXXThisExpr : DStmt<Expr>; +def CXXThrowExpr : DStmt<Expr>; +def CXXDefaultArgExpr : DStmt<Expr>; +def CXXZeroInitValueExpr : DStmt<Expr>; +def CXXNewExpr : DStmt<Expr>; +def CXXDeleteExpr : DStmt<Expr>; +def CXXPseudoDestructorExpr : DStmt<Expr>; +def UnresolvedLookupExpr : DStmt<Expr>; +def UnaryTypeTraitExpr : DStmt<Expr>; +def DependentScopeDeclRefExpr : DStmt<Expr>; +def CXXConstructExpr : DStmt<Expr>; +def CXXBindTemporaryExpr : DStmt<Expr>; +def CXXBindReferenceExpr : DStmt<Expr>; +def CXXExprWithTemporaries : DStmt<Expr>; +def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>; +def CXXUnresolvedConstructExpr : DStmt<Expr>; +def CXXDependentScopeMemberExpr : DStmt<Expr>; +def UnresolvedMemberExpr : DStmt<Expr>; + +// Obj-C Expressions. +def ObjCStringLiteral : DStmt<Expr>; +def ObjCEncodeExpr : DStmt<Expr>; +def ObjCMessageExpr : DStmt<Expr>; +def ObjCSelectorExpr : DStmt<Expr>; +def ObjCProtocolExpr : DStmt<Expr>; +def ObjCIvarRefExpr : DStmt<Expr>; +def ObjCPropertyRefExpr : DStmt<Expr>; +def ObjCImplicitSetterGetterRefExpr : DStmt<Expr>; +def ObjCSuperExpr : DStmt<Expr>; +def ObjCIsaExpr : DStmt<Expr>; + +// Clang Extensions. +def ShuffleVectorExpr : DStmt<Expr>; +def BlockExpr : DStmt<Expr>; +def BlockDeclRefExpr : DStmt<Expr>; diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h index 4986f08..8078451 100644 --- a/include/clang/AST/StmtVisitor.h +++ b/include/clang/AST/StmtVisitor.h @@ -105,10 +105,10 @@ public: // Top switch stmt: dispatch to VisitFooStmt for each FooStmt. switch (S->getStmtClass()) { default: assert(0 && "Unknown stmt kind!"); -#define ABSTRACT_EXPR(CLASS, PARENT) +#define ABSTRACT_STMT(STMT) #define STMT(CLASS, PARENT) \ case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS); -#include "clang/AST/StmtNodes.def" +#include "clang/AST/StmtNodes.inc" } } @@ -116,7 +116,7 @@ public: // back on VisitExpr or whatever else is the superclass. #define STMT(CLASS, PARENT) \ RetTy Visit ## CLASS(CLASS *S) { DISPATCH(PARENT, PARENT); } -#include "clang/AST/StmtNodes.def" +#include "clang/AST/StmtNodes.inc" // If the implementation doesn't implement binary operator methods, fall back // on VisitBinaryOperator. diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 50a100c..8b38001 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -28,6 +28,7 @@ namespace llvm { namespace clang { class Decl; +class DiagnosticBuilder; class Expr; class TypeSourceInfo; @@ -473,6 +474,9 @@ public: } }; -} +const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + const TemplateArgument &Arg); + +} // end namespace clang #endif diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index f3de9fa..2e3b6df 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -188,7 +188,7 @@ const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, /// declaration for "vector". The QualifiedTemplateName class is only /// used to provide "sugar" for template names that were expressed /// with a qualified name, and has no semantic meaning. In this -/// manner, it is to TemplateName what QualifiedNameType is to Type, +/// manner, it is to TemplateName what ElaboratedType is to Type, /// providing extra syntactic sugar for downstream clients. class QualifiedTemplateName : public llvm::FoldingSetNode { /// \brief The nested name specifier that qualifies the template name. diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 030c74c..c24bddb 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -92,7 +92,7 @@ namespace clang { class TemplateArgumentLoc; class TemplateArgumentListInfo; class Type; - class QualifiedNameType; + class ElaboratedType; struct PrintingPolicy; template <typename> class CanQual; @@ -396,7 +396,8 @@ enum CallingConv { CC_Default, CC_C, // __attribute__((cdecl)) CC_X86StdCall, // __attribute__((stdcall)) - CC_X86FastCall // __attribute__((fastcall)) + CC_X86FastCall, // __attribute__((fastcall)) + CC_X86ThisCall // __attribute__((thiscall)) }; @@ -755,6 +756,9 @@ public: }; private: + Type(const Type&); // DO NOT IMPLEMENT. + void operator=(const Type&); // DO NOT IMPLEMENT. + QualType CanonicalType; /// TypeClass bitfield - Enum that specifies what subclass this belongs to. @@ -764,15 +768,25 @@ private: /// 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; - - Type(const Type&); // DO NOT IMPLEMENT. - void operator=(const Type&); // DO NOT IMPLEMENT. + + /// \brief Whether the linkage of this type is already known. + mutable bool LinkageKnown : 1; + + /// \brief Linkage of this type. + mutable unsigned CachedLinkage : 2; + protected: + /// \brief Compute the linkage of this type. + virtual Linkage getLinkageImpl() const; + + enum { BitsRemainingInType = 20 }; + // 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) {} + TC(tc), Dependent(dependent), LinkageKnown(false), + CachedLinkage(NoLinkage) {} virtual ~Type() {} virtual void Destroy(ASTContext& C); friend class ASTContext; @@ -879,7 +893,7 @@ public: bool isObjCObjectPointerType() const; // Pointer to *any* ObjC object. // FIXME: change this to 'raw' interface type, so we can used 'interface' type // for the common case. - bool isObjCInterfaceType() const; // NSString or NSString<foo> + bool isObjCObjectType() const; // NSString or typeof(*(id)0) bool isObjCQualifiedInterfaceType() const; // NSString<foo> bool isObjCQualifiedIdType() const; // id<foo> bool isObjCQualifiedClassType() const; // Class<foo> @@ -920,7 +934,7 @@ public: // for object declared using an interface. const ObjCObjectPointerType *getAsObjCInterfacePointerType() const; const ObjCObjectPointerType *getAsObjCQualifiedIdType() const; - const ObjCInterfaceType *getAsObjCQualifiedInterfaceType() const; + const ObjCObjectType *getAsObjCQualifiedInterfaceType() const; const CXXRecordDecl *getCXXRecordDeclForPointerType() const; /// \brief Retrieves the CXXRecordDecl that this type refers to, either @@ -935,10 +949,6 @@ public: // immediately following this class. template <typename T> const T *getAs() const; - /// getAsPointerToObjCInterfaceType - If this is a pointer to an ObjC - /// interface, return the interface type, otherwise return null. - const ObjCInterfaceType *getAsPointerToObjCInterfaceType() const; - /// getArrayElementTypeNoTypeQual - If this is an array type, return the /// element type of the array, potentially with type qualifiers missing. /// This method should never be used when type qualifiers are meaningful. @@ -977,10 +987,13 @@ public: /// set of type specifiers. bool isSpecifierType() const; - const char *getTypeClassName() const; - /// \brief Determine the linkage of this type. - virtual Linkage getLinkage() const; + Linkage getLinkage() const; + + /// \brief Note that the linkage is no longer known. + void ClearLinkageCache(); + + const char *getTypeClassName() const; QualType getCanonicalTypeInternal() const { return CanonicalType; @@ -1040,12 +1053,25 @@ public: UndeducedAuto, // In C++0x, this represents the type of an auto variable // that has not been deduced yet. - ObjCId, // This represents the ObjC 'id' type. - ObjCClass, // This represents the ObjC 'Class' type. + + /// 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 + /// type of an ObjCObjectType. + ObjCId, + + /// The primitive Objective C 'Class' type. The type pointed to by the + /// user-visible 'Class' type. Only ever shows up in an AST as the + /// base type of an ObjCObjectType. + ObjCClass, + 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)), @@ -1073,8 +1099,6 @@ public: return TypeKind >= Float && TypeKind <= LongDouble; } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == Builtin; } static bool classof(const BuiltinType *) { return true; } }; @@ -1089,6 +1113,10 @@ class ComplexType : public Type, public llvm::FoldingSetNode { ElementType(Element) { } friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + public: QualType getElementType() const { return ElementType; } @@ -1102,8 +1130,6 @@ public: ID.AddPointer(Element.getAsOpaquePtr()); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == Complex; } static bool classof(const ComplexType *) { return true; } }; @@ -1117,6 +1143,10 @@ class PointerType : public Type, public llvm::FoldingSetNode { Type(Pointer, CanonicalPtr, Pointee->isDependentType()), PointeeType(Pointee) { } friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + public: QualType getPointeeType() const { return PointeeType; } @@ -1131,8 +1161,6 @@ public: ID.AddPointer(Pointee.getAsOpaquePtr()); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == Pointer; } static bool classof(const PointerType *) { return true; } }; @@ -1148,6 +1176,10 @@ class BlockPointerType : public Type, public llvm::FoldingSetNode { 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. @@ -1163,8 +1195,6 @@ public: ID.AddPointer(Pointee.getAsOpaquePtr()); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == BlockPointer; } @@ -1200,6 +1230,9 @@ protected: PointeeType(Referencee), SpelledAsLValue(SpelledAsLValue), InnerRef(Referencee->isReferenceType()) { } + + virtual Linkage getLinkageImpl() const; + public: bool isSpelledAsLValue() const { return SpelledAsLValue; } bool isInnerRef() const { return InnerRef; } @@ -1223,8 +1256,6 @@ public: ID.AddBoolean(SpelledAsLValue); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == LValueReference || T->getTypeClass() == RValueReference; @@ -1281,6 +1312,10 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode { PointeeType(Pointee), Class(Cls) { } friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + public: QualType getPointeeType() const { return PointeeType; } @@ -1299,8 +1334,6 @@ public: ID.AddPointer(Class); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == MemberPointer; } @@ -1342,6 +1375,9 @@ protected: ElementType(et), SizeModifier(sm), IndexTypeQuals(tq) {} friend class ASTContext; // ASTContext creates these. + + virtual Linkage getLinkageImpl() const; + public: QualType getElementType() const { return ElementType; } ArraySizeModifier getSizeModifier() const { @@ -1352,8 +1388,6 @@ public: } unsigned getIndexTypeCVRQualifiers() const { return IndexTypeQuals; } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == ConstantArray || T->getTypeClass() == VariableArray || @@ -1629,6 +1663,9 @@ protected: : Type(tc, canonType, vecType->isDependentType()), ElementType(vecType), NumElements(nElements), AltiVec(isAltiVec), Pixel(isPixel) {} friend class ASTContext; // ASTContext creates these. + + virtual Linkage getLinkageImpl() const; + public: QualType getElementType() const { return ElementType; } @@ -1655,8 +1692,6 @@ public: ID.AddBoolean(isPixel); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == Vector || T->getTypeClass() == ExtVector; } @@ -1733,6 +1768,8 @@ 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; @@ -1753,7 +1790,7 @@ class FunctionType : public Type { unsigned RegParm : 3; /// CallConv - The calling convention used by the function. - unsigned CallConv : 2; + unsigned CallConv : 3; // The type returned by the function. QualType ResultType; @@ -1821,7 +1858,7 @@ class FunctionType : public Type { // The value passed to __attribute__((regparm(x))) unsigned RegParm; // The calling convention as specified via - // __attribute__((cdecl|stdcall||fastcall)) + // __attribute__((cdecl|stdcall|fastcall|thiscall)) CallingConv CC; }; @@ -1862,6 +1899,10 @@ class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { : FunctionType(FunctionNoProto, Result, false, 0, Canonical, /*Dependent=*/false, Info) {} friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + public: // No additional state past what FunctionType provides. @@ -1879,8 +1920,6 @@ public: ID.AddPointer(ResultType.getAsOpaquePtr()); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == FunctionNoProto; } @@ -1944,6 +1983,9 @@ 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 { @@ -1984,8 +2026,6 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == FunctionProto; } @@ -2190,6 +2230,8 @@ class TagType : public Type { protected: TagType(TypeClass TC, const TagDecl *D, QualType can); + virtual Linkage getLinkageImpl() const; + public: TagDecl *getDecl() const { return decl.getPointer(); } @@ -2198,8 +2240,6 @@ public: bool isBeingDefined() const { return decl.getInt(); } void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast; } @@ -2264,68 +2304,6 @@ public: static bool classof(const EnumType *) { return true; } }; -/// ElaboratedType - A non-canonical type used to represents uses of -/// elaborated type specifiers in C++. For example: -/// -/// void foo(union MyUnion); -/// ^^^^^^^^^^^^^ -/// -/// At the moment, for efficiency we do not create elaborated types in -/// C, since outside of typedefs all references to structs would -/// necessarily be elaborated. -class ElaboratedType : public Type, public llvm::FoldingSetNode { -public: - enum TagKind { - TK_struct, - TK_union, - TK_class, - TK_enum - }; - -private: - /// The tag that was used in this elaborated type specifier. - TagKind Tag; - - /// The underlying type. - QualType UnderlyingType; - - explicit ElaboratedType(QualType Ty, TagKind Tag, QualType Canon) - : Type(Elaborated, Canon, Canon->isDependentType()), - Tag(Tag), UnderlyingType(Ty) { } - friend class ASTContext; // ASTContext creates these. - -public: - TagKind getTagKind() const { return Tag; } - QualType getUnderlyingType() const { return UnderlyingType; } - - /// \brief Remove a single level of sugar. - QualType desugar() const { return getUnderlyingType(); } - - /// \brief Returns whether this type directly provides sugar. - bool isSugared() const { return true; } - - static const char *getNameForTagKind(TagKind Kind) { - switch (Kind) { - default: assert(0 && "Unknown TagKind!"); - case TK_struct: return "struct"; - case TK_union: return "union"; - case TK_class: return "class"; - case TK_enum: return "enum"; - } - } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getUnderlyingType(), getTagKind()); - } - static void Profile(llvm::FoldingSetNodeID &ID, QualType T, TagKind Tag) { - ID.AddPointer(T.getAsOpaquePtr()); - ID.AddInteger(Tag); - } - - static bool classof(const ElaboratedType*) { return true; } - static bool classof(const Type *T) { return T->getTypeClass() == Elaborated; } -}; - class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { unsigned Depth : 15; unsigned Index : 16; @@ -2592,46 +2570,116 @@ public: static bool classof(const InjectedClassNameType *T) { return true; } }; +/// \brief The kind of a tag type. +enum TagTypeKind { + /// \brief The "struct" keyword. + TTK_Struct, + /// \brief The "union" keyword. + TTK_Union, + /// \brief The "class" keyword. + TTK_Class, + /// \brief The "enum" keyword. + TTK_Enum +}; + /// \brief The elaboration keyword that precedes a qualified type name or /// introduces an elaborated-type-specifier. enum ElaboratedTypeKeyword { - /// \brief No keyword precedes the qualified type name. - ETK_None, - /// \brief The "typename" keyword precedes the qualified type name, e.g., - /// \c typename T::type. - ETK_Typename, - /// \brief The "class" keyword introduces the elaborated-type-specifier. - ETK_Class, /// \brief The "struct" keyword introduces the elaborated-type-specifier. ETK_Struct, /// \brief The "union" keyword introduces the elaborated-type-specifier. ETK_Union, + /// \brief The "class" keyword introduces the elaborated-type-specifier. + ETK_Class, /// \brief The "enum" keyword introduces the elaborated-type-specifier. - ETK_Enum + ETK_Enum, + /// \brief The "typename" keyword precedes the qualified type name, e.g., + /// \c typename T::type. + ETK_Typename, + /// \brief No keyword precedes the qualified type name. + ETK_None }; - -/// \brief Represents a type that was referred to via a qualified -/// name, e.g., N::M::type. + +/// A helper class for Type nodes having an ElaboratedTypeKeyword. +/// The keyword in stored in the free bits of the base class. +/// 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) {} + +public: + virtual ~TypeWithKeyword(); // pin vtable to Type.cpp + + ElaboratedTypeKeyword getKeyword() const { + return static_cast<ElaboratedTypeKeyword>(Keyword); + } + + /// getKeywordForTypeSpec - Converts a type specifier (DeclSpec::TST) + /// into an elaborated type keyword. + static ElaboratedTypeKeyword getKeywordForTypeSpec(unsigned TypeSpec); + + /// getTagTypeKindForTypeSpec - Converts a type specifier (DeclSpec::TST) + /// into a tag type kind. It is an error to provide a type specifier + /// which *isn't* a tag kind here. + static TagTypeKind getTagTypeKindForTypeSpec(unsigned TypeSpec); + + /// getKeywordForTagDeclKind - Converts a TagTypeKind into an + /// elaborated type keyword. + static ElaboratedTypeKeyword getKeywordForTagTypeKind(TagTypeKind Tag); + + /// getTagTypeKindForKeyword - Converts an elaborated type keyword into + // a TagTypeKind. It is an error to provide an elaborated type keyword + /// which *isn't* a tag kind here. + static TagTypeKind getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword); + + static bool KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword); + + static const char *getKeywordName(ElaboratedTypeKeyword Keyword); + + static const char *getTagTypeKindName(TagTypeKind Kind) { + return getKeywordName(getKeywordForTagTypeKind(Kind)); + } + + class CannotCastToThisType {}; + static CannotCastToThisType classof(const Type *); +}; + +/// \brief Represents a type that was referred to using an elaborated type +/// keyword, e.g., struct S, or via a qualified name, e.g., N::M::type, +/// or both. /// /// This type is used to keep track of a type name as written in the -/// source code, including any nested-name-specifiers. The type itself -/// is always "sugar", used to express what was written in the source -/// code but containing no additional semantic information. -class QualifiedNameType : public Type, public llvm::FoldingSetNode { +/// source code, including tag keywords and any nested-name-specifiers. +/// The type itself is always "sugar", used to express what was written +/// in the source code but containing no additional semantic information. +class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { + /// \brief The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; /// \brief The type that this qualified name refers to. QualType NamedType; - QualifiedNameType(NestedNameSpecifier *NNS, QualType NamedType, - QualType CanonType) - : Type(QualifiedName, CanonType, NamedType->isDependentType()), - NNS(NNS), NamedType(NamedType) { } + ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, + QualType NamedType, QualType CanonType) + : TypeWithKeyword(Keyword, Elaborated, CanonType, + NamedType->isDependentType()), + NNS(NNS), NamedType(NamedType) { + assert(!(Keyword == ETK_None && NNS == 0) && + "ElaboratedType cannot have elaborated type keyword " + "and name qualifier both null."); + } friend class ASTContext; // ASTContext creates these public: + /// \brief Retrieve the qualification on this type. NestedNameSpecifier *getQualifier() const { return NNS; } @@ -2645,19 +2693,20 @@ public: bool isSugared() const { return true; } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, NNS, NamedType); + Profile(ID, getKeyword(), NNS, NamedType); } - static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, - QualType NamedType) { + static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, QualType NamedType) { + ID.AddInteger(Keyword); ID.AddPointer(NNS); NamedType.Profile(ID); } static bool classof(const Type *T) { - return T->getTypeClass() == QualifiedName; + return T->getTypeClass() == Elaborated; } - static bool classof(const QualifiedNameType *T) { return true; } + static bool classof(const ElaboratedType *T) { return true; } }; /// \brief Represents a qualified type name for which the type name is @@ -2669,10 +2718,8 @@ public: /// typename-specifier), "class", "struct", "union", or "enum" (for a /// dependent elaborated-type-specifier), or nothing (in contexts where we /// know that we must be referring to a type, e.g., in a base class specifier). -class DependentNameType : public Type, public llvm::FoldingSetNode { - /// \brief The keyword used to elaborate this type. - ElaboratedTypeKeyword Keyword; - +class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { + /// \brief The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; @@ -2684,16 +2731,16 @@ class DependentNameType : public Type, public llvm::FoldingSetNode { DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, QualType CanonType) - : Type(DependentName, CanonType, true), - Keyword(Keyword), NNS(NNS), Name(Name) { + : TypeWithKeyword(Keyword, DependentName, CanonType, true), + NNS(NNS), Name(Name) { assert(NNS->isDependent() && "DependentNameType requires a dependent nested-name-specifier"); } DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const TemplateSpecializationType *Ty, QualType CanonType) - : Type(DependentName, CanonType, true), - Keyword(Keyword), NNS(NNS), Name(Ty) { + : TypeWithKeyword(Keyword, DependentName, CanonType, true), + NNS(NNS), Name(Ty) { assert(NNS->isDependent() && "DependentNameType requires a dependent nested-name-specifier"); } @@ -2701,9 +2748,7 @@ class DependentNameType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these public: - /// \brief Retrieve the keyword used to elaborate this type. - ElaboratedTypeKeyword getKeyword() const { return Keyword; } - + /// \brief Retrieve the qualification on this type. NestedNameSpecifier *getQualifier() const { return NNS; } @@ -2727,7 +2772,7 @@ public: QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Keyword, NNS, Name); + Profile(ID, getKeyword(), NNS, Name); } static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, @@ -2743,153 +2788,333 @@ public: static bool classof(const DependentNameType *T) { return true; } }; -/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for -/// object oriented design. They basically correspond to C++ classes. There -/// are two kinds of interface types, normal interfaces like "NSString" and -/// qualified interfaces, which are qualified with a protocol list like -/// "NSString<NSCopyable, NSAmazing>". -class ObjCInterfaceType : public Type, public llvm::FoldingSetNode { - ObjCInterfaceDecl *Decl; +/// ObjCObjectType - Represents a class type in Objective C. +/// Every Objective C type is a combination of a base type and a +/// list of protocols. +/// +/// Given the following declarations: +/// @class C; +/// @protocol P; +/// +/// 'C' is an ObjCInterfaceType C. It is sugar for an ObjCObjectType +/// with base C and no protocols. +/// +/// 'C<P>' is an ObjCObjectType with base C and protocol list [P]. +/// +/// 'id' is a TypedefType which is sugar for an ObjCPointerType whose +/// pointee is an ObjCObjectType with base BuiltinType::ObjCIdType +/// and no protocols. +/// +/// 'id<P>' is an ObjCPointerType whose pointee is an ObjCObjecType +/// 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; - /// \brief The number of protocols stored after the ObjCInterfaceType node. - /// The list of protocols is sorted on protocol name. No protocol is enterred - /// more than once. - unsigned NumProtocols; + /// Either a BuiltinType or an InterfaceType or sugar for either. + QualType BaseType; - ObjCInterfaceType(QualType Canonical, ObjCInterfaceDecl *D, - ObjCProtocolDecl **Protos, unsigned NumP); - friend class ASTContext; // ASTContext creates these. + ObjCProtocolDecl * const *getProtocolStorage() const { + return const_cast<ObjCObjectType*>(this)->getProtocolStorage(); + } + + ObjCProtocolDecl **getProtocolStorage(); + +protected: + ObjCObjectType(QualType Canonical, QualType Base, + ObjCProtocolDecl * const *Protocols, unsigned NumProtocols); + + enum Nonce_ObjCInterface { Nonce_ObjCInterface }; + ObjCObjectType(enum Nonce_ObjCInterface) + : Type(ObjCInterface, QualType(), false), + NumProtocols(0), + BaseType(QualType(this_(), 0)) {} + +protected: + Linkage getLinkageImpl() const; // key function + public: - void Destroy(ASTContext& C); + /// getBaseType - Gets the base type of this object type. This is + /// always (possibly sugar for) one of: + /// - the 'id' builtin type (as opposed to the 'id' type visible to the + /// user, which is a typedef for an ObjCPointerType) + /// - the 'Class' builtin type (same caveat) + /// - an ObjCObjectType (currently always an ObjCInterfaceType) + QualType getBaseType() const { return BaseType; } + + bool isObjCId() const { + return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCId); + } + bool isObjCClass() const { + return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCClass); + } + bool isObjCUnqualifiedId() const { return qual_empty() && isObjCId(); } + bool isObjCUnqualifiedClass() const { return qual_empty() && isObjCClass(); } + bool isObjCUnqualifiedIdOrClass() const { + if (!qual_empty()) return false; + if (const BuiltinType *T = getBaseType()->getAs<BuiltinType>()) + return T->getKind() == BuiltinType::ObjCId || + T->getKind() == BuiltinType::ObjCClass; + return false; + } + bool isObjCQualifiedId() const { return !qual_empty() && isObjCId(); } + bool isObjCQualifiedClass() const { return !qual_empty() && isObjCClass(); } - ObjCInterfaceDecl *getDecl() const { return Decl; } + /// Gets the interface declaration for this object type, if the base type + /// really is an interface. + ObjCInterfaceDecl *getInterface() const; + + typedef ObjCProtocolDecl * const *qual_iterator; + + qual_iterator qual_begin() const { return getProtocolStorage(); } + qual_iterator qual_end() const { return qual_begin() + getNumProtocols(); } + + bool qual_empty() const { return getNumProtocols() == 0; } /// getNumProtocols - Return the number of qualifying protocols in this /// interface type, or 0 if there are none. unsigned getNumProtocols() const { return NumProtocols; } - /// \brief Retrieve the Ith protocol. + /// \brief Fetch a protocol by index. ObjCProtocolDecl *getProtocol(unsigned I) const { assert(I < getNumProtocols() && "Out-of-range protocol access"); return qual_begin()[I]; } - /// qual_iterator and friends: this provides access to the (potentially empty) - /// list of protocols qualifying this interface. - typedef ObjCProtocolDecl* const * qual_iterator; - qual_iterator qual_begin() const { - return reinterpret_cast<qual_iterator>(this + 1); - } - qual_iterator qual_end() const { - return qual_begin() + NumProtocols; - } - bool qual_empty() const { return NumProtocols == 0; } - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } + static bool classof(const Type *T) { + return T->getTypeClass() == ObjCObject || + T->getTypeClass() == ObjCInterface; + } + static bool classof(const ObjCObjectType *) { return true; } +}; + +/// ObjCObjectTypeImpl - A class providing a concrete implementation +/// of ObjCObjectType, so as to not increase the footprint of +/// ObjCInterfaceType. Code outside of ASTContext and the core type +/// system should not reference this type. +class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode { + friend class ASTContext; + + // If anyone adds fields here, ObjCObjectType::getProtocolStorage() + // will need to be modified. + + ObjCObjectTypeImpl(QualType Canonical, QualType Base, + ObjCProtocolDecl * const *Protocols, + unsigned NumProtocols) + : ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {} + +public: + void Destroy(ASTContext& C); // key function + void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, - const ObjCInterfaceDecl *Decl, - ObjCProtocolDecl * const *protocols, - unsigned NumProtocols); + QualType Base, + ObjCProtocolDecl *const *protocols, + unsigned NumProtocols); +}; - virtual Linkage getLinkage() const; +inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() { + return reinterpret_cast<ObjCProtocolDecl**>( + static_cast<ObjCObjectTypeImpl*>(this) + 1); +} + +/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for +/// object oriented design. They basically correspond to C++ classes. There +/// are two kinds of interface types, normal interfaces like "NSString" and +/// qualified interfaces, which are qualified with a protocol list like +/// "NSString<NSCopyable, NSAmazing>". +/// +/// ObjCInterfaceType guarantees the following properties when considered +/// as a subtype of its superclass, ObjCObjectType: +/// - There are no protocol qualifiers. To reinforce this, code which +/// tries to invoke the protocol methods via an ObjCInterfaceType will +/// fail to compile. +/// - It is its own base type. That is, if T is an ObjCInterfaceType*, +/// T->getBaseType() == QualType(T, 0). +class ObjCInterfaceType : public ObjCObjectType { + ObjCInterfaceDecl *Decl; + + ObjCInterfaceType(const ObjCInterfaceDecl *D) + : ObjCObjectType(Nonce_ObjCInterface), + Decl(const_cast<ObjCInterfaceDecl*>(D)) {} + friend class ASTContext; // ASTContext creates these. +public: + void Destroy(ASTContext& C); // key function + + /// getDecl - Get the declaration of this interface. + ObjCInterfaceDecl *getDecl() const { return Decl; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } static bool classof(const Type *T) { return T->getTypeClass() == ObjCInterface; } static bool classof(const ObjCInterfaceType *) { return true; } + + // Nonsense to "hide" certain members of ObjCObjectType within this + // class. People asking for protocols on an ObjCInterfaceType are + // not going to get what they want: ObjCInterfaceTypes are + // guaranteed to have no protocols. + enum { + qual_iterator, + qual_begin, + qual_end, + getNumProtocols, + getProtocol + }; }; -/// ObjCObjectPointerType - Used to represent 'id', 'Interface *', 'id <p>', -/// and 'Interface <p> *'. +inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const { + if (const ObjCInterfaceType *T = + getBaseType()->getAs<ObjCInterfaceType>()) + return T->getDecl(); + return 0; +} + +/// ObjCObjectPointerType - Used to represent a pointer to an +/// Objective C object. These are constructed from pointer +/// declarators when the pointee type is an ObjCObjectType (or sugar +/// for one). In addition, the 'id' and 'Class' types are typedefs +/// for these, and the protocol-qualified types 'id<P>' and 'Class<P>' +/// are translated into these. /// -/// Duplicate protocols are removed and protocol list is canonicalized to be in -/// alphabetical order. +/// Pointers to pointers to Objective C objects are still PointerTypes; +/// only the first level of pointer gets it own type implementation. class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { - QualType PointeeType; // A builtin or interface type. - - /// \brief The number of protocols stored after the ObjCObjectPointerType - /// node. - /// - /// The list of protocols is sorted on protocol name. No protocol is enterred - /// more than once. - unsigned NumProtocols; + QualType PointeeType; - ObjCObjectPointerType(QualType Canonical, QualType T, - ObjCProtocolDecl **Protos, unsigned NumP); + ObjCObjectPointerType(QualType Canonical, QualType Pointee) + : Type(ObjCObjectPointer, Canonical, false), + PointeeType(Pointee) {} friend class ASTContext; // ASTContext creates these. +protected: + virtual Linkage getLinkageImpl() const; + public: void Destroy(ASTContext& C); - // Get the pointee type. Pointee will either be: - // - a built-in type (for 'id' and 'Class'). - // - an interface type (for user-defined types). - // - a TypedefType whose canonical type is an interface (as in 'T' below). - // For example: typedef NSObject T; T *var; + /// getPointeeType - Gets the type pointed to by this ObjC pointer. + /// The result will always be an ObjCObjectType or sugar thereof. QualType getPointeeType() const { return PointeeType; } + /// getObjCObjectType - Gets the type pointed to by this ObjC + /// pointer. This method always returns non-null. + /// + /// This method is equivalent to getPointeeType() except that + /// it discards any typedefs (or other sugar) between this + /// type and the "outermost" object type. So for: + /// @class A; @protocol P; @protocol Q; + /// typedef A<P> AP; + /// typedef A A1; + /// typedef A1<P> A1P; + /// typedef A1P<Q> A1PQ; + /// For 'A*', getObjectType() will return 'A'. + /// For 'A<P>*', getObjectType() will return 'A<P>'. + /// For 'AP*', getObjectType() will return 'A<P>'. + /// For 'A1*', getObjectType() will return 'A'. + /// For 'A1<P>*', getObjectType() will return 'A1<P>'. + /// For 'A1P*', getObjectType() will return 'A1<P>'. + /// For 'A1PQ*', getObjectType() will return 'A1<Q>', because + /// adding protocols to a protocol-qualified base discards the + /// old qualifiers (for now). But if it didn't, getObjectType() + /// would return 'A1P<Q>' (and we'd have to make iterating over + /// qualifiers more complicated). + const ObjCObjectType *getObjectType() const { + return PointeeType->getAs<ObjCObjectType>(); + } + + /// getInterfaceType - If this pointer points to an Objective C + /// @interface type, gets the type for that interface. Any protocol + /// qualifiers on the interface are ignored. + /// + /// \return null if the base type for this pointer is 'id' or 'Class' const ObjCInterfaceType *getInterfaceType() const { - return PointeeType->getAs<ObjCInterfaceType>(); + return getObjectType()->getBaseType()->getAs<ObjCInterfaceType>(); } - /// getInterfaceDecl - returns an interface decl for user-defined types. + + /// getInterfaceDecl - If this pointer points to an Objective @interface + /// type, gets the declaration for that interface. + /// + /// \return null if the base type for this pointer is 'id' or 'Class' ObjCInterfaceDecl *getInterfaceDecl() const { - return getInterfaceType() ? getInterfaceType()->getDecl() : 0; + return getObjectType()->getInterface(); } - /// isObjCIdType - true for "id". + + /// isObjCIdType - True if this is equivalent to the 'id' type, i.e. if + /// its object type is the primitive 'id' type with no protocols. bool isObjCIdType() const { - return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) && - !NumProtocols; + return getObjectType()->isObjCUnqualifiedId(); } - /// isObjCClassType - true for "Class". + + /// isObjCClassType - True if this is equivalent to the 'Class' type, + /// i.e. if its object tive is the primitive 'Class' type with no protocols. bool isObjCClassType() const { - return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) && - !NumProtocols; + return getObjectType()->isObjCUnqualifiedClass(); } - /// isObjCQualifiedIdType - true for "id <p>". + /// isObjCQualifiedIdType - True if this is equivalent to 'id<P>' for some + /// non-empty set of protocols. bool isObjCQualifiedIdType() const { - return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) && - NumProtocols; + return getObjectType()->isObjCQualifiedId(); } - /// isObjCQualifiedClassType - true for "Class <p>". + + /// isObjCQualifiedClassType - True if this is equivalent to 'Class<P>' for + /// some non-empty set of protocols. bool isObjCQualifiedClassType() const { - return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) && - NumProtocols; + return getObjectType()->isObjCQualifiedClass(); } - /// qual_iterator and friends: this provides access to the (potentially empty) - /// list of protocols qualifying this interface. - typedef ObjCProtocolDecl* const * qual_iterator; + + /// An iterator over the qualifiers on the object type. Provided + /// for convenience. This will always iterate over the full set of + /// protocols on a type, not just those provided directly. + typedef ObjCObjectType::qual_iterator qual_iterator; qual_iterator qual_begin() const { - return reinterpret_cast<qual_iterator> (this + 1); + return getObjectType()->qual_begin(); } - qual_iterator qual_end() const { - return qual_begin() + NumProtocols; + qual_iterator qual_end() const { + return getObjectType()->qual_end(); } - bool qual_empty() const { return NumProtocols == 0; } + bool qual_empty() const { return getObjectType()->qual_empty(); } - /// getNumProtocols - Return the number of qualifying protocols in this - /// interface type, or 0 if there are none. - unsigned getNumProtocols() const { return NumProtocols; } + /// getNumProtocols - Return the number of qualifying protocols on + /// the object type. + unsigned getNumProtocols() const { + return getObjectType()->getNumProtocols(); + } - /// \brief Retrieve the Ith protocol. + /// \brief Retrieve a qualifying protocol by index on the object + /// type. ObjCProtocolDecl *getProtocol(unsigned I) const { - assert(I < getNumProtocols() && "Out-of-range protocol access"); - return qual_begin()[I]; + return getObjectType()->getProtocol(I); } bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - virtual Linkage getLinkage() const; - - void Profile(llvm::FoldingSetNodeID &ID); - static void Profile(llvm::FoldingSetNodeID &ID, QualType T, - ObjCProtocolDecl *const *protocols, - unsigned NumProtocols); + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getPointeeType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType T) { + ID.AddPointer(T.getAsOpaquePtr()); + } static bool classof(const Type *T) { return T->getTypeClass() == ObjCObjectPointer; } @@ -3128,12 +3353,6 @@ inline QualType QualType::getNonReferenceType() const { return *this; } -inline const ObjCInterfaceType *Type::getAsPointerToObjCInterfaceType() const { - if (const PointerType *PT = getAs<PointerType>()) - return PT->getPointeeType()->getAs<ObjCInterfaceType>(); - return 0; -} - inline bool Type::isFunctionType() const { return isa<FunctionType>(CanonicalType); } @@ -3200,8 +3419,8 @@ inline bool Type::isExtVectorType() const { inline bool Type::isObjCObjectPointerType() const { return isa<ObjCObjectPointerType>(CanonicalType); } -inline bool Type::isObjCInterfaceType() const { - return isa<ObjCInterfaceType>(CanonicalType); +inline bool Type::isObjCObjectType() const { + return isa<ObjCObjectType>(CanonicalType); } inline bool Type::isObjCQualifiedIdType() const { if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) @@ -3250,13 +3469,11 @@ inline bool Type::isOverloadableType() const { inline bool Type::hasPointerRepresentation() const { return (isPointerType() || isReferenceType() || isBlockPointerType() || - isObjCInterfaceType() || isObjCObjectPointerType() || - isObjCQualifiedInterfaceType() || isNullPtrType()); + isObjCObjectPointerType() || isNullPtrType()); } inline bool Type::hasObjCPointerRepresentation() const { - return (isObjCInterfaceType() || isObjCObjectPointerType() || - isObjCQualifiedInterfaceType()); + return isObjCObjectPointerType(); } /// Insertion operator for diagnostics. This allows sending QualType's into a diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index a51da74..f988f0e 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_TYPELOC_H #include "clang/AST/Type.h" +#include "clang/AST/Decl.h" #include "clang/AST/TemplateBase.h" #include "clang/Basic/Specifiers.h" @@ -84,21 +85,20 @@ public: return Data; } + /// \brief Get the begin source location. + SourceLocation getBeginLoc() const; + + /// \brief Get the end source location. + SourceLocation getEndLoc() const; + /// \brief Get the full source range. - SourceRange getFullSourceRange() const { - SourceLocation End = getSourceRange().getEnd(); - TypeLoc Cur = *this; - while (true) { - TypeLoc Next = Cur.getNextTypeLoc(); - if (Next.isNull()) break; - Cur = Next; - } - return SourceRange(Cur.getSourceRange().getBegin(), End); + SourceRange getSourceRange() const { + return SourceRange(getBeginLoc(), getEndLoc()); } /// \brief Get the local source range. - SourceRange getSourceRange() const { - return getSourceRangeImpl(*this); + SourceRange getLocalSourceRange() const { + return getLocalSourceRangeImpl(*this); } /// \brief Returns the size of the type source info data block. @@ -137,9 +137,14 @@ public: private: static void initializeImpl(TypeLoc TL, SourceLocation Loc); static TypeLoc getNextTypeLocImpl(TypeLoc TL); - static SourceRange getSourceRangeImpl(TypeLoc TL); + static SourceRange getLocalSourceRangeImpl(TypeLoc TL); }; +/// \brief Return the TypeLoc for a type source info. +inline TypeLoc TypeSourceInfo::getTypeLoc() const { + return TypeLoc(Ty, (void*)(this + 1)); +} + /// \brief Wrapper of type source information for a type with /// no direct quqlaifiers. class UnqualTypeLoc : public TypeLoc { @@ -168,7 +173,7 @@ public: /// type qualifiers. class QualifiedTypeLoc : public TypeLoc { public: - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(); } @@ -263,6 +268,16 @@ public: return TypeClass::classof(Ty); } + static bool classof(const TypeLoc *TL) { + return Derived::classofType(TL->getTypePtr()); + } + static bool classof(const UnqualTypeLoc *TL) { + return Derived::classofType(TL->getTypePtr()); + } + static bool classof(const Derived *TL) { + return true; + } + TypeLoc getNextTypeLoc() const { return getNextTypeLoc(asDerived()->getInnerType()); } @@ -361,7 +376,7 @@ public: void setNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; } - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(getNameLoc(), getNameLoc()); } void initializeLocal(SourceLocation Loc) { @@ -413,7 +428,7 @@ public: return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0; } - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(getBuiltinLoc(), getBuiltinLoc()); } @@ -553,6 +568,7 @@ class SubstTemplateTypeParmTypeLoc : struct ObjCProtocolListLocInfo { SourceLocation LAngleLoc; SourceLocation RAngleLoc; + bool HasBaseTypeAsWritten; }; // A helper class for defining ObjC TypeLocs that can qualified with @@ -560,24 +576,15 @@ struct ObjCProtocolListLocInfo { // // TypeClass basically has to be either ObjCInterfaceType or // ObjCObjectPointerType. -template <class Derived, class TypeClass, class LocalData> -class ObjCProtocolListTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, - Derived, - TypeClass, - LocalData> { +class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + ObjCObjectTypeLoc, + ObjCObjectType, + ObjCProtocolListLocInfo> { // SourceLocations are stored after Info, one for each Protocol. SourceLocation *getProtocolLocArray() const { return (SourceLocation*) this->getExtraLocalData(); } -protected: - void initializeLocalBase(SourceLocation Loc) { - setLAngleLoc(Loc); - setRAngleLoc(Loc); - for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) - setProtocolLoc(i, Loc); - } - public: SourceLocation getLAngleLoc() const { return this->getLocalData()->LAngleLoc; @@ -611,29 +618,49 @@ public: return *(this->getTypePtr()->qual_begin() + i); } - SourceRange getSourceRange() const { + bool hasBaseTypeAsWritten() const { + return getLocalData()->HasBaseTypeAsWritten; + } + + void setHasBaseTypeAsWritten(bool HasBaseType) { + getLocalData()->HasBaseTypeAsWritten = HasBaseType; + } + + TypeLoc getBaseLoc() const { + return getInnerTypeLoc(); + } + + SourceRange getLocalSourceRange() const { return SourceRange(getLAngleLoc(), getRAngleLoc()); } void initializeLocal(SourceLocation Loc) { - initializeLocalBase(Loc); + setHasBaseTypeAsWritten(true); + setLAngleLoc(Loc); + setRAngleLoc(Loc); + for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) + setProtocolLoc(i, Loc); } unsigned getExtraLocalDataSize() const { return this->getNumProtocols() * sizeof(SourceLocation); } + + QualType getInnerType() const { + return getTypePtr()->getBaseType(); + } }; -struct ObjCInterfaceLocInfo : ObjCProtocolListLocInfo { +struct ObjCInterfaceLocInfo { SourceLocation NameLoc; }; /// \brief Wrapper for source info for ObjC interfaces. -class ObjCInterfaceTypeLoc : - public ObjCProtocolListTypeLoc<ObjCInterfaceTypeLoc, - ObjCInterfaceType, - ObjCInterfaceLocInfo> { +class ObjCInterfaceTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + ObjCInterfaceTypeLoc, + ObjCInterfaceType, + ObjCInterfaceLocInfo> { public: ObjCInterfaceDecl *getIFaceDecl() const { return getTypePtr()->getDecl(); @@ -647,85 +674,16 @@ public: getLocalData()->NameLoc = Loc; } - SourceRange getSourceRange() const { - if (getNumProtocols()) - return SourceRange(getNameLoc(), getRAngleLoc()); - else - return SourceRange(getNameLoc(), getNameLoc()); + SourceRange getLocalSourceRange() const { + return SourceRange(getNameLoc()); } void initializeLocal(SourceLocation Loc) { - initializeLocalBase(Loc); setNameLoc(Loc); } }; -struct ObjCObjectPointerLocInfo : ObjCProtocolListLocInfo { - SourceLocation StarLoc; - bool HasProtocols; - bool HasBaseType; -}; - -/// Wraps an ObjCPointerType with source location information. Note -/// that not all ObjCPointerTypes actually have a star location; nor -/// are protocol locations necessarily written in the source just -/// because they're present on the type. -class ObjCObjectPointerTypeLoc : - public ObjCProtocolListTypeLoc<ObjCObjectPointerTypeLoc, - ObjCObjectPointerType, - ObjCObjectPointerLocInfo> { -public: - bool hasProtocolsAsWritten() const { - return getLocalData()->HasProtocols; - } - - void setHasProtocolsAsWritten(bool HasProtocols) { - getLocalData()->HasProtocols = HasProtocols; - } - - bool hasBaseTypeAsWritten() const { - return getLocalData()->HasBaseType; - } - - void setHasBaseTypeAsWritten(bool HasBaseType) { - getLocalData()->HasBaseType = HasBaseType; - } - - SourceLocation getStarLoc() const { - return getLocalData()->StarLoc; - } - - void setStarLoc(SourceLocation Loc) { - getLocalData()->StarLoc = Loc; - } - - SourceRange getSourceRange() const { - // Being written with protocols is incompatible with being written - // with a star. - if (hasProtocolsAsWritten()) - return SourceRange(getLAngleLoc(), getRAngleLoc()); - else - return SourceRange(getStarLoc(), getStarLoc()); - } - - void initializeLocal(SourceLocation Loc) { - initializeLocalBase(Loc); - setHasProtocolsAsWritten(false); - setHasBaseTypeAsWritten(false); - setStarLoc(Loc); - } - - TypeLoc getBaseTypeLoc() const { - return getInnerTypeLoc(); - } - - QualType getInnerType() const { - return getTypePtr()->getPointeeType(); - } -}; - - struct PointerLikeLocInfo { SourceLocation StarLoc; }; @@ -746,7 +704,7 @@ public: return this->getInnerTypeLoc(); } - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(getSigilLoc(), getSigilLoc()); } @@ -798,6 +756,20 @@ public: } }; +/// Wraps an ObjCPointerType with source location information. +class ObjCObjectPointerTypeLoc : + public PointerLikeTypeLoc<ObjCObjectPointerTypeLoc, + ObjCObjectPointerType> { +public: + SourceLocation getStarLoc() const { + return getSigilLoc(); + } + + void setStarLoc(SourceLocation Loc) { + setSigilLoc(Loc); + } +}; + class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc, ReferenceType> { @@ -871,13 +843,11 @@ public: ParmVarDecl *getArg(unsigned i) const { return getParmArray()[i]; } void setArg(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; } - TypeLoc getArgLoc(unsigned i) const; - TypeLoc getResultLoc() const { return getInnerTypeLoc(); } - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(getLParenLoc(), getRParenLoc()); } @@ -950,7 +920,7 @@ public: return getInnerTypeLoc(); } - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(getLBracketLoc(), getRBracketLoc()); } @@ -1055,7 +1025,7 @@ public: memcpy(Data, Loc.Data, size); } - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(getTemplateNameLoc(), getRAngleLoc()); } @@ -1183,7 +1153,7 @@ public: setRParenLoc(range.getEnd()); } - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(getTypeofLoc(), getRParenLoc()); } @@ -1204,7 +1174,7 @@ public: // Reimplemented to account for GNU/C++ extension // typeof unary-expression // where there are no parentheses. - SourceRange getSourceRange() const; + SourceRange getLocalSourceRange() const; }; class TypeOfTypeLoc @@ -1227,24 +1197,110 @@ class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DecltypeType> { }; -// FIXME: location of the tag keyword. -class ElaboratedTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - ElaboratedTypeLoc, - ElaboratedType> { +struct ElaboratedLocInfo { + SourceLocation KeywordLoc; + SourceRange QualifierRange; }; -// FIXME: locations for the nested name specifier; at the very least, -// a SourceRange. -class QualifiedNameTypeLoc : - public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - QualifiedNameTypeLoc, - QualifiedNameType> { +class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + ElaboratedTypeLoc, + ElaboratedType, + ElaboratedLocInfo> { +public: + SourceLocation getKeywordLoc() const { + return this->getLocalData()->KeywordLoc; + } + void setKeywordLoc(SourceLocation Loc) { + this->getLocalData()->KeywordLoc = Loc; + } + + SourceRange getQualifierRange() const { + return this->getLocalData()->QualifierRange; + } + void setQualifierRange(SourceRange Range) { + this->getLocalData()->QualifierRange = Range; + } + + SourceRange getLocalSourceRange() const { + if (getKeywordLoc().isValid()) + if (getQualifierRange().getEnd().isValid()) + return SourceRange(getKeywordLoc(), getQualifierRange().getEnd()); + else + return SourceRange(getKeywordLoc()); + else + return getQualifierRange(); + } + + void initializeLocal(SourceLocation Loc) { + setKeywordLoc(Loc); + setQualifierRange(SourceRange(Loc)); + } + + TypeLoc getNamedTypeLoc() const { + return getInnerTypeLoc(); + } + + QualType getInnerType() const { + return getTypePtr()->getNamedType(); + } + + void copy(ElaboratedTypeLoc Loc) { + unsigned size = getFullDataSize(); + assert(size == Loc.getFullDataSize()); + memcpy(Data, Loc.Data, size); + } }; -// FIXME: locations for the typename keyword and nested name specifier. -class DependentNameTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - DependentNameTypeLoc, - DependentNameType> { +struct DependentNameLocInfo { + SourceLocation KeywordLoc; + SourceRange QualifierRange; + SourceLocation NameLoc; +}; + +class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + DependentNameTypeLoc, + DependentNameType, + DependentNameLocInfo> { +public: + SourceLocation getKeywordLoc() const { + return this->getLocalData()->KeywordLoc; + } + void setKeywordLoc(SourceLocation Loc) { + this->getLocalData()->KeywordLoc = Loc; + } + + SourceRange getQualifierRange() const { + return this->getLocalData()->QualifierRange; + } + void setQualifierRange(SourceRange Range) { + this->getLocalData()->QualifierRange = Range; + } + + SourceLocation getNameLoc() const { + return this->getLocalData()->NameLoc; + } + void setNameLoc(SourceLocation Loc) { + this->getLocalData()->NameLoc = Loc; + } + + SourceRange getLocalSourceRange() const { + if (getKeywordLoc().isValid()) + return SourceRange(getKeywordLoc(), getNameLoc()); + else + return SourceRange(getQualifierRange().getBegin(), getNameLoc()); + } + + void copy(DependentNameTypeLoc Loc) { + unsigned size = getFullDataSize(); + assert(size == Loc.getFullDataSize()); + memcpy(Data, Loc.Data, size); + } + + void initializeLocal(SourceLocation Loc) { + setKeywordLoc(Loc); + setQualifierRange(SourceRange(Loc)); + setNameLoc(Loc); + } }; } diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h index c3b1c68..e729488 100644 --- a/include/clang/AST/TypeLocBuilder.h +++ b/include/clang/AST/TypeLocBuilder.h @@ -59,6 +59,20 @@ class TypeLocBuilder { 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) { diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index c665073..02508af 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -90,10 +90,10 @@ NON_CANONICAL_TYPE(Elaborated, Type) DEPENDENT_TYPE(TemplateTypeParm, Type) NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) -NON_CANONICAL_TYPE(QualifiedName, Type) DEPENDENT_TYPE(InjectedClassName, Type) DEPENDENT_TYPE(DependentName, Type) -TYPE(ObjCInterface, Type) +TYPE(ObjCObject, Type) +TYPE(ObjCInterface, ObjCObjectType) TYPE(ObjCObjectPointer, Type) #ifdef LAST_TYPE diff --git a/include/clang/AST/TypeVisitor.h b/include/clang/AST/TypeVisitor.h index 19f7f42..5c9c5285 100644 --- a/include/clang/AST/TypeVisitor.h +++ b/include/clang/AST/TypeVisitor.h @@ -1,4 +1,4 @@ -//===--- TypeVisitor.h - Visitor for Stmt subclasses ------------*- C++ -*-===// +//===--- TypeVisitor.h - Visitor for Type subclasses ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -25,7 +25,7 @@ template<typename ImplClass, typename RetTy=void> class TypeVisitor { public: RetTy Visit(Type *T) { - // Top switch stmt: dispatch to VisitFooStmt for each FooStmt. + // Top switch stmt: dispatch to VisitFooType for each FooType. switch (T->getTypeClass()) { default: assert(0 && "Unknown type class!"); #define ABSTRACT_TYPE(CLASS, PARENT) diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h index cbe0082..a548b0b 100644 --- a/include/clang/AST/UnresolvedSet.h +++ b/include/clang/AST/UnresolvedSet.h @@ -31,9 +31,13 @@ private: IteratorTy ir; friend class UnresolvedSetImpl; + friend class OverloadExpr; explicit UnresolvedSetIterator(DeclsTy::iterator ir) : ir(ir) {} explicit UnresolvedSetIterator(DeclsTy::const_iterator ir) : ir(const_cast<DeclsTy::iterator>(ir)) {} + + IteratorTy getIterator() const { return ir; } + public: UnresolvedSetIterator() {} @@ -81,9 +85,7 @@ public: bool operator>(const UnresolvedSetIterator &o) const { return ir > o.ir; } }; -/// UnresolvedSet - A set of unresolved declarations. This is needed -/// in a lot of places, but isn't really worth breaking into its own -/// header right now. +/// UnresolvedSet - A set of unresolved declarations. class UnresolvedSetImpl { typedef UnresolvedSetIterator::DeclsTy DeclsTy; |