diff options
Diffstat (limited to 'include/clang/AST')
| -rw-r--r-- | include/clang/AST/ASTContext.h | 46 | ||||
| -rw-r--r-- | include/clang/AST/ASTDiagnostic.h | 22 | ||||
| -rw-r--r-- | include/clang/AST/ASTImporter.h | 234 | ||||
| -rw-r--r-- | include/clang/AST/Attr.h | 78 | ||||
| -rw-r--r-- | include/clang/AST/CXXInheritance.h | 11 | ||||
| -rw-r--r-- | include/clang/AST/Decl.h | 377 | ||||
| -rw-r--r-- | include/clang/AST/DeclBase.h | 86 | ||||
| -rw-r--r-- | include/clang/AST/DeclCXX.h | 492 | ||||
| -rw-r--r-- | include/clang/AST/DeclObjC.h | 70 | ||||
| -rw-r--r-- | include/clang/AST/DeclTemplate.h | 53 | ||||
| -rw-r--r-- | include/clang/AST/DeclarationName.h | 12 | ||||
| -rw-r--r-- | include/clang/AST/Expr.h | 19 | ||||
| -rw-r--r-- | include/clang/AST/ExprCXX.h | 418 | ||||
| -rw-r--r-- | include/clang/AST/ExprObjC.h | 10 | ||||
| -rw-r--r-- | include/clang/AST/Stmt.h | 93 | ||||
| -rw-r--r-- | include/clang/AST/StmtCXX.h | 27 | ||||
| -rw-r--r-- | include/clang/AST/StmtNodes.def | 9 | ||||
| -rw-r--r-- | include/clang/AST/StmtVisitor.h | 1 | ||||
| -rw-r--r-- | include/clang/AST/Type.h | 170 | ||||
| -rw-r--r-- | include/clang/AST/TypeNodes.def | 5 | ||||
| -rw-r--r-- | include/clang/AST/UnresolvedSet.h | 116 |
21 files changed, 1512 insertions, 837 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index e5429bec143c..2ed9fd708018 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -27,6 +27,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Allocator.h" #include <vector> @@ -46,6 +47,7 @@ namespace clang { class SourceManager; class TargetInfo; // Decls + class DeclContext; class CXXMethodDecl; class CXXRecordDecl; class Decl; @@ -502,7 +504,8 @@ public: /// getVectorType - Return the unique reference to a vector type of /// the specified element type and size. VectorType must be a built-in type. - QualType getVectorType(QualType VectorType, unsigned NumElts); + QualType getVectorType(QualType VectorType, unsigned NumElts, + bool AltiVec, bool IsPixel); /// getExtVectorType - Return the unique reference to an extended vector type /// of the specified element type and size. VectorType must be a built-in @@ -534,11 +537,11 @@ public: /// getTypeDeclType - Return the unique reference to the type for /// the specified type declaration. - QualType getTypeDeclType(TypeDecl *Decl, TypeDecl* PrevDecl=0); + QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl* PrevDecl=0); /// getTypedefType - Return the unique reference to the type for the /// specified typename decl. - QualType getTypedefType(TypedefDecl *Decl); + QualType getTypedefType(const TypedefDecl *Decl); QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced, QualType Replacement); @@ -835,13 +838,23 @@ public: return getTypeInfo(T).second; } + /// getTypeAlignInChars - Return the ABI-specified alignment of a type, in + /// characters. This method does not work on incomplete types. + CharUnits getTypeAlignInChars(QualType T); + CharUnits getTypeAlignInChars(const Type *T); + /// getPreferredTypeAlign - Return the "preferred" alignment of the specified /// type for the current target in bits. This can be different than the ABI /// alignment in cases where it is beneficial for performance to overalign /// a data type. unsigned getPreferredTypeAlign(const Type *T); - unsigned getDeclAlignInBytes(const Decl *D, bool RefAsPointee = false); + /// getDeclAlign - Return a conservative estimate of the alignment of + /// the specified decl. Note that bitfields do not have a valid alignment, so + /// this method will assert on them. + /// If @p RefAsPointee, references are treated like their underlying type + /// (for alignof), else they're treated like pointers (for CodeGen). + CharUnits getDeclAlign(const Decl *D, bool RefAsPointee = false); /// getASTRecordLayout - Get or compute information about the layout of the /// specified record (struct/union/class), which indicates its size and field @@ -878,7 +891,7 @@ public: unsigned CountSynthesizedIvars(const ObjCInterfaceDecl *OI); unsigned CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD); void CollectInheritedProtocols(const Decl *CDecl, - llvm::SmallVectorImpl<ObjCProtocolDecl*> &Protocols); + llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols); //===--------------------------------------------------------------------===// // Type Operators @@ -960,6 +973,20 @@ public: NestedNameSpecifier * getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS); + /// \brief Retrieves the canonical representation of the given + /// calling convention. + CallingConv getCanonicalCallConv(CallingConv CC) { + if (CC == CC_C) + return CC_Default; + return CC; + } + + /// \brief Determines whether two calling conventions name the same + /// calling convention. + bool isSameCallConv(CallingConv lcc, CallingConv rcc) { + return (getCanonicalCallConv(lcc) == getCanonicalCallConv(rcc)); + } + /// \brief Retrieves the "canonical" template name that refers to a /// given template. /// @@ -1187,6 +1214,15 @@ private: const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl); + +private: + // 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. + std::vector<void*> SDMs; + friend class DeclContext; + void *CreateStoredDeclsMap(); + void ReleaseDeclContextMaps(); }; /// @brief Utility function for constructing a nullary selector. diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h index abd36f7e5f0f..2d314913469e 100644 --- a/include/clang/AST/ASTDiagnostic.h +++ b/include/clang/AST/ASTDiagnostic.h @@ -1,4 +1,4 @@ -//===--- DiagnosticAST.h - Diagnostics for the AST library ------*- C++ -*-===// +//===--- ASTDiagnostic.h - Diagnostics for the AST library ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -22,6 +22,26 @@ namespace clang { NUM_BUILTIN_AST_DIAGNOSTICS }; } // end namespace diag + + /// \brief Diagnostic argument formatting function for diagnostics that + /// involve AST nodes. + /// + /// This function formats diagnostic arguments for various AST nodes, + /// including types, declaration names, nested name specifiers, and + /// declaration contexts, into strings that can be printed as part of + /// diagnostics. It is meant to be used as the argument to + /// \c Diagnostic::SetArgToStringFn(), where the cookie is an \c ASTContext + /// pointer. + void FormatASTNodeDiagnosticArgument(Diagnostic::ArgumentKind Kind, + intptr_t Val, + const char *Modifier, + unsigned ModLen, + const char *Argument, + unsigned ArgLen, + const Diagnostic::ArgumentValue *PrevArgs, + unsigned NumPrevArgs, + llvm::SmallVectorImpl<char> &Output, + void *Cookie); } // end namespace clang #endif diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h new file mode 100644 index 000000000000..f5f11ca83662 --- /dev/null +++ b/include/clang/AST/ASTImporter.h @@ -0,0 +1,234 @@ +//===--- ASTImporter.h - Importing ASTs from other Contexts -----*- 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 ASTImporter class which imports AST nodes from one +// context into another context. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_ASTIMPORTER_H +#define LLVM_CLANG_AST_ASTIMPORTER_H + +#include "clang/AST/Type.h" +#include "clang/AST/DeclarationName.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + class ASTContext; + class Decl; + class DeclContext; + class Diagnostic; + class Expr; + class FileManager; + class IdentifierInfo; + class NestedNameSpecifier; + class Stmt; + class TypeSourceInfo; + + /// \brief Imports selected nodes from one AST context into another context, + /// merging AST nodes where appropriate. + class ASTImporter { + public: + typedef llvm::DenseSet<std::pair<Decl *, Decl *> > NonEquivalentDeclSet; + + private: + /// \brief The contexts we're importing to and from. + ASTContext &ToContext, &FromContext; + + /// \brief The file managers we're importing to and from. + FileManager &ToFileManager, &FromFileManager; + + /// \brief The diagnostics object that we should use to emit diagnostics. + Diagnostic &Diags; + + /// \brief Mapping from the already-imported types in the "from" context + /// to the corresponding types in the "to" context. + llvm::DenseMap<Type *, Type *> ImportedTypes; + + /// \brief Mapping from the already-imported declarations in the "from" + /// context to the corresponding declarations in the "to" context. + llvm::DenseMap<Decl *, Decl *> ImportedDecls; + + /// \brief Mapping from the already-imported statements in the "from" + /// context to the corresponding statements in the "to" context. + llvm::DenseMap<Stmt *, Stmt *> ImportedStmts; + + /// \brief Mapping from the already-imported FileIDs in the "from" source + /// manager to the corresponding FileIDs in the "to" source manager. + llvm::DenseMap<unsigned, FileID> ImportedFileIDs; + + /// \brief Imported, anonymous tag declarations that are missing their + /// corresponding typedefs. + llvm::SmallVector<TagDecl *, 4> AnonTagsWithPendingTypedefs; + + /// \brief Declaration (from, to) pairs that are known not to be equivalent + /// (which we have already complained about). + NonEquivalentDeclSet NonEquivalentDecls; + + public: + ASTImporter(Diagnostic &Diags, + ASTContext &ToContext, FileManager &ToFileManager, + ASTContext &FromContext, FileManager &FromFileManager); + + virtual ~ASTImporter(); + + /// \brief Import the given type from the "from" context into the "to" + /// context. + /// + /// \returns the equivalent type in the "to" context, or a NULL type if + /// an error occurred. + QualType Import(QualType FromT); + + /// \brief Import the given type source information from the + /// "from" context into the "to" context. + /// + /// \returns the equivalent type source information in the "to" + /// context, or NULL if an error occurred. + TypeSourceInfo *Import(TypeSourceInfo *FromTSI); + + /// \brief Import the given declaration from the "from" context into the + /// "to" context. + /// + /// \returns the equivalent declaration in the "to" context, or a NULL type + /// if an error occurred. + Decl *Import(Decl *FromD); + + /// \brief Import the given declaration context from the "from" + /// AST context into the "to" AST context. + /// + /// \returns the equivalent declaration context in the "to" + /// context, or a NULL type if an error occurred. + DeclContext *ImportContext(DeclContext *FromDC); + + /// \brief Import the given expression from the "from" context into the + /// "to" context. + /// + /// \returns the equivalent expression in the "to" context, or NULL if + /// an error occurred. + Expr *Import(Expr *FromE); + + /// \brief Import the given statement from the "from" context into the + /// "to" context. + /// + /// \returns the equivalent statement in the "to" context, or NULL if + /// an error occurred. + Stmt *Import(Stmt *FromS); + + /// \brief Import the given nested-name-specifier from the "from" + /// context into the "to" context. + /// + /// \returns the equivalent nested-name-specifier in the "to" + /// context, or NULL if an error occurred. + NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS); + + /// \brief Import the given source location from the "from" context into + /// the "to" context. + /// + /// \returns the equivalent source location in the "to" context, or an + /// invalid source location if an error occurred. + SourceLocation Import(SourceLocation FromLoc); + + /// \brief Import the given source range from the "from" context into + /// the "to" context. + /// + /// \returns the equivalent source range in the "to" context, or an + /// invalid source location if an error occurred. + SourceRange Import(SourceRange FromRange); + + /// \brief Import the given declaration name from the "from" + /// context into the "to" context. + /// + /// \returns the equivalent declaration name in the "to" context, + /// or an empty declaration name if an error occurred. + DeclarationName Import(DeclarationName FromName); + + /// \brief Import the given identifier from the "from" context + /// into the "to" context. + /// + /// \returns the equivalent identifier in the "to" context. + IdentifierInfo *Import(IdentifierInfo *FromId); + + /// \brief Import the given file ID from the "from" context into the + /// "to" context. + /// + /// \returns the equivalent file ID in the source manager of the "to" + /// context. + FileID Import(FileID); + + /// \brief Cope with a name conflict when importing a declaration into the + /// given context. + /// + /// This routine is invoked whenever there is a name conflict while + /// importing a declaration. The returned name will become the name of the + /// imported declaration. By default, the returned name is the same as the + /// original name, leaving the conflict unresolve such that name lookup + /// for this name is likely to find an ambiguity later. + /// + /// Subclasses may override this routine to resolve the conflict, e.g., by + /// renaming the declaration being imported. + /// + /// \param Name the name of the declaration being imported, which conflicts + /// with other declarations. + /// + /// \param DC the declaration context (in the "to" AST context) in which + /// the name is being imported. + /// + /// \param IDNS the identifier namespace in which the name will be found. + /// + /// \param Decls the set of declarations with the same name as the + /// declaration being imported. + /// + /// \param NumDecls the number of conflicting declarations in \p Decls. + /// + /// \returns the name that the newly-imported declaration should have. + virtual DeclarationName HandleNameConflict(DeclarationName Name, + DeclContext *DC, + unsigned IDNS, + NamedDecl **Decls, + unsigned NumDecls); + + /// \brief Retrieve the context that AST nodes are being imported into. + ASTContext &getToContext() const { return ToContext; } + + /// \brief Retrieve the context that AST nodes are being imported from. + ASTContext &getFromContext() const { return FromContext; } + + /// \brief Retrieve the file manager that AST nodes are being imported into. + FileManager &getToFileManager() const { return ToFileManager; } + + /// \brief Retrieve the file manager that AST nodes are being imported from. + FileManager &getFromFileManager() const { return FromFileManager; } + + /// \brief Retrieve the diagnostic formatter. + Diagnostic &getDiags() const { return Diags; } + + /// \brief Report a diagnostic in the "to" context. + DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID); + + /// \brief Report a diagnostic in the "from" context. + DiagnosticBuilder FromDiag(SourceLocation Loc, unsigned DiagID); + + /// \brief Return the set of declarations that we know are not equivalent. + NonEquivalentDeclSet &getNonEquivalentDecls() { return NonEquivalentDecls; } + + /// \brief Note that we have imported the "from" declaration by mapping it + /// to the (potentially-newly-created) "to" declaration. + /// + /// \returns \p To + Decl *Imported(Decl *From, Decl *To); + + /// \brief Determine whether the given types are structurally + /// equivalent. + bool IsStructurallyEquivalent(QualType From, QualType To); + }; +} + +#endif // LLVM_CLANG_AST_ASTIMPORTER_H diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 03ab0f07020b..37225907c6de 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -18,7 +18,6 @@ #include "llvm/ADT/StringRef.h" #include <cassert> #include <cstring> -#include <string> #include <algorithm> using llvm::dyn_cast; @@ -96,7 +95,8 @@ public: FIRST_TARGET_ATTRIBUTE, DLLExport, DLLImport, - MSP430Interrupt + MSP430Interrupt, + X86ForceAlignArgPointer }; private: @@ -119,8 +119,7 @@ protected: assert(Next == 0 && "Destroy didn't work"); } public: - - void Destroy(ASTContext &C); + virtual void Destroy(ASTContext &C); /// \brief Whether this attribute should be merged to new /// declarations. @@ -156,6 +155,18 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Attr *) { return true; } }; + +class AttrWithString : public Attr { +private: + const char *Str; + unsigned StrLen; +protected: + AttrWithString(Attr::Kind AK, ASTContext &C, llvm::StringRef s); + llvm::StringRef getString() const { return llvm::StringRef(Str, StrLen); } + void ReplaceString(ASTContext &C, llvm::StringRef newS); +public: + virtual void Destroy(ASTContext &C); +}; #define DEF_SIMPLE_ATTR(ATTR) \ class ATTR##Attr : public Attr { \ @@ -213,12 +224,12 @@ public: static bool classof(const AlignedAttr *A) { return true; } }; -class AnnotateAttr : public Attr { - std::string Annotation; +class AnnotateAttr : public AttrWithString { public: - AnnotateAttr(llvm::StringRef ann) : Attr(Annotate), Annotation(ann) {} + AnnotateAttr(ASTContext &C, llvm::StringRef ann) + : AttrWithString(Annotate, C, ann) {} - const std::string& getAnnotation() const { return Annotation; } + llvm::StringRef getAnnotation() const { return getString(); } virtual Attr* clone(ASTContext &C) const; @@ -229,12 +240,12 @@ public: static bool classof(const AnnotateAttr *A) { return true; } }; -class AsmLabelAttr : public Attr { - std::string Label; +class AsmLabelAttr : public AttrWithString { public: - AsmLabelAttr(llvm::StringRef L) : Attr(AsmLabel), Label(L) {} + AsmLabelAttr(ASTContext &C, llvm::StringRef L) + : AttrWithString(AsmLabel, C, L) {} - const std::string& getLabel() const { return Label; } + llvm::StringRef getLabel() const { return getString(); } virtual Attr* clone(ASTContext &C) const; @@ -247,12 +258,12 @@ public: DEF_SIMPLE_ATTR(AlwaysInline); -class AliasAttr : public Attr { - std::string Aliasee; +class AliasAttr : public AttrWithString { public: - AliasAttr(llvm::StringRef aliasee) : Attr(Alias), Aliasee(aliasee) {} + AliasAttr(ASTContext &C, llvm::StringRef aliasee) + : AttrWithString(Alias, C, aliasee) {} - const std::string& getAliasee() const { return Aliasee; } + llvm::StringRef getAliasee() const { return getString(); } virtual Attr *clone(ASTContext &C) const; @@ -321,12 +332,12 @@ DEF_SIMPLE_ATTR(AnalyzerNoReturn); DEF_SIMPLE_ATTR(Deprecated); DEF_SIMPLE_ATTR(Final); -class SectionAttr : public Attr { - std::string Name; +class SectionAttr : public AttrWithString { public: - SectionAttr(llvm::StringRef N) : Attr(Section), Name(N) {} + SectionAttr(ASTContext &C, llvm::StringRef N) + : AttrWithString(Section, C, N) {} - const std::string& getName() const { return Name; } + llvm::StringRef getName() const { return getString(); } virtual Attr *clone(ASTContext &C) const; @@ -350,19 +361,9 @@ class NonNullAttr : public Attr { unsigned* ArgNums; unsigned Size; public: - NonNullAttr(unsigned* arg_nums = 0, unsigned size = 0) : Attr(NonNull), - ArgNums(0), Size(0) { + NonNullAttr(ASTContext &C, unsigned* arg_nums = 0, unsigned size = 0); - if (size == 0) return; - assert(arg_nums); - ArgNums = new unsigned[size]; - Size = size; - memcpy(ArgNums, arg_nums, sizeof(*ArgNums)*size); - } - - virtual ~NonNullAttr() { - delete [] ArgNums; - } + virtual void Destroy(ASTContext &C); typedef const unsigned *iterator; iterator begin() const { return ArgNums; } @@ -379,15 +380,14 @@ public: static bool classof(const NonNullAttr *A) { return true; } }; -class FormatAttr : public Attr { - std::string Type; +class FormatAttr : public AttrWithString { int formatIdx, firstArg; public: - FormatAttr(llvm::StringRef type, int idx, int first) : Attr(Format), - Type(type), formatIdx(idx), firstArg(first) {} + FormatAttr(ASTContext &C, llvm::StringRef type, int idx, int first) + : AttrWithString(Format, C, type), formatIdx(idx), firstArg(first) {} - const std::string& getType() const { return Type; } - void setType(llvm::StringRef type) { Type = type; } + llvm::StringRef getType() const { return getString(); } + void setType(ASTContext &C, llvm::StringRef type); int getFormatIdx() const { return formatIdx; } int getFirstArg() const { return firstArg; } @@ -570,6 +570,8 @@ public: static bool classof(const MSP430InterruptAttr *A) { return true; } }; +DEF_SIMPLE_ATTR(X86ForceAlignArgPointer); + #undef DEF_SIMPLE_ATTR } // end namespace clang diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index 1491b1edbbac..79a3022ee014 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -161,7 +161,8 @@ class CXXBasePaths { void ComputeDeclsFound(); public: - typedef std::list<CXXBasePath>::const_iterator paths_iterator; + typedef std::list<CXXBasePath>::iterator paths_iterator; + typedef std::list<CXXBasePath>::const_iterator const_paths_iterator; typedef NamedDecl **decl_iterator; /// BasePaths - Construct a new BasePaths structure to record the @@ -175,8 +176,10 @@ public: ~CXXBasePaths() { delete [] DeclsFound; } - paths_iterator begin() const { return Paths.begin(); } - paths_iterator end() const { return Paths.end(); } + paths_iterator begin() { return Paths.begin(); } + paths_iterator end() { return Paths.end(); } + const_paths_iterator begin() const { return Paths.begin(); } + const_paths_iterator end() const { return Paths.end(); } CXXBasePath& front() { return Paths.front(); } const CXXBasePath& front() const { return Paths.front(); } @@ -206,7 +209,7 @@ public: const RecordType* getDetectedVirtual() const { return DetectedVirtual; } - + /// \brief Retrieve the type from which this base-paths search /// began CXXRecordDecl *getOrigin() const { return Origin; } diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 6d52b2b2bc91..07442896dc4b 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -19,6 +19,7 @@ #include "clang/AST/Redeclarable.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" +#include "clang/Basic/Linkage.h" namespace clang { class CXXTemporary; @@ -75,8 +76,9 @@ public: static TranslationUnitDecl *Create(ASTContext &C); // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return D->getKind() == TranslationUnit; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TranslationUnitDecl *D) { return true; } + static bool classofKind(Kind K) { return K == TranslationUnit; } static DeclContext *castToDeclContext(const TranslationUnitDecl *D) { return static_cast<DeclContext *>(const_cast<TranslationUnitDecl*>(D)); } @@ -194,23 +196,6 @@ public: return DC->isRecord(); } - /// \brief Describes the different kinds of linkage - /// (C++ [basic.link], C99 6.2.2) that an entity may have. - enum Linkage { - /// \brief No linkage, which means that the entity is unique and - /// can only be referred to from within its scope. - NoLinkage = 0, - - /// \brief Internal linkage, which indicates that the entity can - /// be referred to from within the translation unit (but not other - /// translation units). - InternalLinkage, - - /// \brief External linkage, which indicates that the entity can - /// be referred to from other translation units. - ExternalLinkage - }; - /// \brief Determine what kind of linkage this entity has. Linkage getLinkage() const; @@ -221,10 +206,9 @@ public: return const_cast<NamedDecl*>(this)->getUnderlyingDecl(); } - static bool classof(const Decl *D) { - return D->getKind() >= NamedFirst && D->getKind() <= NamedLast; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const NamedDecl *D) { return true; } + static bool classofKind(Kind K) { return K >= NamedFirst && K <= NamedLast; } }; /// NamespaceDecl - Represent a C++ namespace. @@ -301,8 +285,9 @@ public: void setRBracLoc(SourceLocation RBrace) { RBracLoc = RBrace; } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return D->getKind() == Namespace; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const NamespaceDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Namespace; } static DeclContext *castToDeclContext(const NamespaceDecl *D) { return static_cast<DeclContext *>(const_cast<NamespaceDecl*>(D)); } @@ -326,10 +311,9 @@ public: void setType(QualType newType) { DeclType = newType; } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() >= ValueFirst && D->getKind() <= ValueLast; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ValueDecl *D) { return true; } + static bool classofKind(Kind K) { return K >= ValueFirst && K <= ValueLast; } }; /// \brief Represents a ValueDecl that came out of a declarator. @@ -349,10 +333,11 @@ public: SourceLocation getTypeSpecStartLoc() const; // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() >= DeclaratorFirst && D->getKind() <= DeclaratorLast; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const DeclaratorDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= DeclaratorFirst && K <= DeclaratorLast; + } }; /// \brief Structure used to store a statement, the constant value to @@ -474,14 +459,142 @@ public: SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S); - virtual ~VarDecl(); virtual void Destroy(ASTContext& C); + virtual ~VarDecl(); + + virtual SourceRange getSourceRange() const; StorageClass getStorageClass() const { return (StorageClass)SClass; } void setStorageClass(StorageClass SC) { SClass = SC; } - virtual SourceRange getSourceRange() const; + void setThreadSpecified(bool T) { ThreadSpecified = T; } + bool isThreadSpecified() const { + return ThreadSpecified; + } + + /// hasLocalStorage - Returns true if a variable with function scope + /// is a non-static local variable. + bool hasLocalStorage() const { + if (getStorageClass() == None) + return !isFileVarDecl(); + + // Return true for: Auto, Register. + // Return false for: Extern, Static, PrivateExtern. + + return getStorageClass() <= Register; + } + + /// hasExternStorage - Returns true if a variable has extern or + /// __private_extern__ storage. + bool hasExternalStorage() const { + return getStorageClass() == Extern || getStorageClass() == PrivateExtern; + } + + /// hasGlobalStorage - Returns true for all variables that do not + /// have local storage. This includs all global variables as well + /// as static variables declared within a function. + bool hasGlobalStorage() const { return !hasLocalStorage(); } + + /// \brief Determines whether this variable is a variable with + /// external, C linkage. + bool isExternC() const; + + /// isBlockVarDecl - Returns true for local variable declarations. Note that + /// this includes static variables inside of functions. + /// + /// void foo() { int x; static int y; extern int z; } + /// + bool isBlockVarDecl() const { + if (getKind() != Decl::Var) + return false; + if (const DeclContext *DC = getDeclContext()) + return DC->getLookupContext()->isFunctionOrMethod(); + return false; + } + + /// \brief Determines whether this is a static data member. + /// + /// This will only be true in C++, and applies to, e.g., the + /// variable 'x' in: + /// \code + /// struct S { + /// static int x; + /// }; + /// \endcode + bool isStaticDataMember() const { + // If it wasn't static, it would be a FieldDecl. + return getDeclContext()->isRecord(); + } + + virtual VarDecl *getCanonicalDecl(); + const VarDecl *getCanonicalDecl() const { + return const_cast<VarDecl*>(this)->getCanonicalDecl(); + } + + enum DefinitionKind { + DeclarationOnly, ///< This declaration is only a declaration. + TentativeDefinition, ///< This declaration is a tentative definition. + Definition ///< This declaration is definitely a definition. + }; + + /// \brief Check whether this declaration is a definition. If this could be + /// a tentative definition (in C), don't check whether there's an overriding + /// definition. + DefinitionKind isThisDeclarationADefinition() const; + + /// \brief Get the tentative definition that acts as the real definition in + /// a TU. Returns null if there is a proper definition available. + VarDecl *getActingDefinition(); + const VarDecl *getActingDefinition() const { + return const_cast<VarDecl*>(this)->getActingDefinition(); + } + + /// \brief Determine whether this is a tentative definition of a + /// variable in C. + bool isTentativeDefinitionNow() const; + + /// \brief Get the real (not just tentative) definition for this declaration. + VarDecl *getDefinition(); + const VarDecl *getDefinition() const { + return const_cast<VarDecl*>(this)->getDefinition(); + } + + /// \brief Determine whether this is or was instantiated from an out-of-line + /// definition of a static data member. + bool isOutOfLine() const; + + /// \brief If this is a static data member, find its out-of-line definition. + VarDecl *getOutOfLineDefinition(); + + /// isFileVarDecl - Returns true for file scoped variable declaration. + bool isFileVarDecl() const { + if (getKind() != Decl::Var) + return false; + if (const DeclContext *Ctx = getDeclContext()) { + Ctx = Ctx->getLookupContext(); + if (isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx) ) + return true; + } + if (isStaticDataMember()) + return true; + + return false; + } + + /// getAnyInitializer - Get the initializer for this variable, no matter which + /// declaration it is attached to. + const Expr *getAnyInitializer() const { + const VarDecl *D; + return getAnyInitializer(D); + } + /// getAnyInitializer - Get the initializer for this variable, no matter which + /// declaration it is attached to. Also get that declaration. + const Expr *getAnyInitializer(const VarDecl *&D) const; + + bool hasInit() const { + return !Init.isNull(); + } const Expr *getInit() const { if (Init.isNull()) return 0; @@ -521,7 +634,7 @@ public: return StmtPtr; } - void setInit(ASTContext &C, Expr *I); + void setInit(Expr *I); EvaluatedStmt *EnsureEvaluatedStmt() const { EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>(); @@ -614,17 +727,6 @@ public: Eval->IsICE = IsICE; } - /// \brief Retrieve the definition of this variable, which may come - /// from a previous declaration. Def will be set to the VarDecl that - /// contains the initializer, and the result will be that - /// initializer. - const Expr *getDefinition(const VarDecl *&Def) const; - - void setThreadSpecified(bool T) { ThreadSpecified = T; } - bool isThreadSpecified() const { - return ThreadSpecified; - } - void setCXXDirectInitializer(bool T) { HasCXXDirectInit = T; } /// hasCXXDirectInitializer - If true, the initializer was a direct @@ -648,67 +750,6 @@ public: void setDeclaredInCondition(bool InCondition) { DeclaredInCondition = InCondition; } - - virtual VarDecl *getCanonicalDecl(); - const VarDecl *getCanonicalDecl() const { - return const_cast<VarDecl*>(this)->getCanonicalDecl(); - } - - /// hasLocalStorage - Returns true if a variable with function scope - /// is a non-static local variable. - bool hasLocalStorage() const { - if (getStorageClass() == None) - return !isFileVarDecl(); - - // Return true for: Auto, Register. - // Return false for: Extern, Static, PrivateExtern. - - return getStorageClass() <= Register; - } - - /// hasExternStorage - Returns true if a variable has extern or - /// __private_extern__ storage. - bool hasExternalStorage() const { - return getStorageClass() == Extern || getStorageClass() == PrivateExtern; - } - - /// hasGlobalStorage - Returns true for all variables that do not - /// have local storage. This includs all global variables as well - /// as static variables declared within a function. - bool hasGlobalStorage() const { return !hasLocalStorage(); } - - /// isBlockVarDecl - Returns true for local variable declarations. Note that - /// this includes static variables inside of functions. - /// - /// void foo() { int x; static int y; extern int z; } - /// - bool isBlockVarDecl() const { - if (getKind() != Decl::Var) - return false; - if (const DeclContext *DC = getDeclContext()) - return DC->getLookupContext()->isFunctionOrMethod(); - return false; - } - - /// \brief Determines whether this is a static data member. - /// - /// This will only be true in C++, and applies to, e.g., the - /// variable 'x' in: - /// \code - /// struct S { - /// static int x; - /// }; - /// \endcode - bool isStaticDataMember() const { - return getDeclContext()->isRecord(); - } - - /// \brief Determine whether this is or was instantiated from an out-of-line - /// definition of a static data member. - bool isOutOfLine() const; - - /// \brief If this is a static data member, find its out-of-line definition. - VarDecl *getOutOfLineDefinition(); /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member @@ -728,35 +769,11 @@ public: /// data member of a class template, set the template specialiation kind. void setTemplateSpecializationKind(TemplateSpecializationKind TSK, SourceLocation PointOfInstantiation = SourceLocation()); - - /// isFileVarDecl - Returns true for file scoped variable declaration. - bool isFileVarDecl() const { - if (getKind() != Decl::Var) - return false; - if (const DeclContext *Ctx = getDeclContext()) { - Ctx = Ctx->getLookupContext(); - if (isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx) ) - return true; - } - if (isStaticDataMember()) - return true; - - return false; - } - - /// \brief Determine whether this is a tentative definition of a - /// variable in C. - bool isTentativeDefinition(ASTContext &Context) const; - - /// \brief Determines whether this variable is a variable with - /// external, C linkage. - bool isExternC() const; // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() >= VarFirst && D->getKind() <= VarLast; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const VarDecl *D) { return true; } + static bool classofKind(Kind K) { return K >= VarFirst && K <= VarLast; } }; class ImplicitParamDecl : public VarDecl { @@ -770,7 +787,8 @@ public: QualType T); // Implement isa/cast/dyncast/etc. static bool classof(const ImplicitParamDecl *D) { return true; } - static bool classof(const Decl *D) { return D->getKind() == ImplicitParam; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == ImplicitParam; } }; /// ParmVarDecl - Represent a parameter to a function. @@ -876,10 +894,9 @@ public: void setOwningFunction(DeclContext *FD) { setDeclContext(FD); } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return (D->getKind() == ParmVar); - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ParmVarDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ParmVar; } }; /// FunctionDecl - An instance of this class is created to represent a @@ -1096,8 +1113,6 @@ public: unsigned getBuiltinID() const; - unsigned getNumParmVarDeclsFromType() const; - // Iterator access to formal parameters. unsigned param_size() const { return getNumParams(); } typedef ParmVarDecl **param_iterator; @@ -1110,7 +1125,7 @@ public: param_const_iterator param_end() const { return ParamInfo+param_size(); } /// getNumParams - Return the number of parameters this function must have - /// based on its functiontype. This is the length of the PararmInfo array + /// based on its FunctionType. This is the length of the ParamInfo array /// after it has been created. unsigned getNumParams() const; @@ -1122,7 +1137,7 @@ public: assert(i < getNumParams() && "Illegal param #"); return ParamInfo[i]; } - void setParams(ASTContext& C, ParmVarDecl **NewParamInfo, unsigned NumParams); + void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams); /// getMinRequiredArguments - Returns the minimum number of arguments /// needed to call this function. This may be fewer than the number of @@ -1267,8 +1282,7 @@ public: /// be inserted. /// /// \param TSK the kind of template specialization this is. - void setFunctionTemplateSpecialization(ASTContext &Context, - FunctionTemplateDecl *Template, + void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, const TemplateArgumentList *TemplateArgs, void *InsertPos, TemplateSpecializationKind TSK = TSK_ImplicitInstantiation); @@ -1295,10 +1309,11 @@ public: bool isOutOfLine() const; // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FunctionDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= FunctionFirst && K <= FunctionLast; + } static DeclContext *castToDeclContext(const FunctionDecl *D) { return static_cast<DeclContext *>(const_cast<FunctionDecl*>(D)); } @@ -1347,11 +1362,20 @@ public: Expr *getBitWidth() const { return BitWidth; } void setBitWidth(Expr *BW) { BitWidth = BW; } - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() >= FieldFirst && D->getKind() <= FieldLast; + /// getParent - Returns the parent of this field declaration, which + /// is the struct in which this method is defined. + const RecordDecl *getParent() const { + return cast<RecordDecl>(getDeclContext()); } + + RecordDecl *getParent() { + return cast<RecordDecl>(getDeclContext()); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FieldDecl *D) { return true; } + static bool classofKind(Kind K) { return K >= FieldFirst && K <= FieldLast; } }; /// EnumConstantDecl - An instance of this object exists for each enum constant @@ -1385,8 +1409,9 @@ public: void setInitVal(const llvm::APSInt &V) { Val = V; } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return D->getKind() == EnumConstant; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const EnumConstantDecl *D) { return true; } + static bool classofKind(Kind K) { return K == EnumConstant; } friend class StmtIteratorBase; }; @@ -1418,10 +1443,9 @@ public: void setTypeForDecl(Type *TD) { TypeForDecl = TD; } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() >= TypeFirst && D->getKind() <= TypeLast; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TypeDecl *D) { return true; } + static bool classofKind(Kind K) { return K >= TypeFirst && K <= TypeLast; } }; @@ -1460,8 +1484,9 @@ public: } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return D->getKind() == Typedef; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TypedefDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Typedef; } }; class TypedefDecl; @@ -1486,6 +1511,11 @@ private: /// it is a declaration ("struct foo;"). bool IsDefinition : 1; + /// IsEmbeddedInDeclarator - True if this tag declaration is + /// "embedded" (i.e., defined or declared for the very first time) + /// in the syntax of a declarator, + bool IsEmbeddedInDeclarator : 1; + /// TypedefForAnonDecl - If a TagDecl is anonymous and part of a typedef, /// this points to the TypedefDecl. Used for mangling. TypedefDecl *TypedefForAnonDecl; @@ -1502,6 +1532,7 @@ protected: assert((DK != Enum || TK == TK_enum) &&"EnumDecl not matched with TK_enum"); TagDeclKind = TK; IsDefinition = false; + IsEmbeddedInDeclarator = false; setPreviousDeclaration(PrevDecl); } @@ -1535,6 +1566,13 @@ public: return IsDefinition; } + bool isEmbeddedInDeclarator() const { + return IsEmbeddedInDeclarator; + } + void setEmbeddedInDeclarator(bool isInDeclarator) { + IsEmbeddedInDeclarator = isInDeclarator; + } + /// \brief Whether this declaration declares a type that is /// dependent, i.e., a type that somehow depends on template /// parameters. @@ -1557,7 +1595,9 @@ public: /// specific TagDecl is defining declaration, not whether or not the /// struct/union/class/enum type is defined. This method returns NULL if /// there is no TagDecl that defines the struct/union/class/enum. - TagDecl* getDefinition(ASTContext& C) const; + TagDecl* getDefinition() const; + + void setDefinition(bool V) { IsDefinition = V; } const char *getKindName() const { return ElaboratedType::getNameForTagKind(getTagKind()); @@ -1583,10 +1623,9 @@ public: void setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefForAnonDecl = TDD; } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() >= TagFirst && D->getKind() <= TagLast; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TagDecl *D) { return true; } + static bool classofKind(Kind K) { return K >= TagFirst && K <= TagLast; } static DeclContext *castToDeclContext(const TagDecl *D) { return static_cast<DeclContext *>(const_cast<TagDecl*>(D)); @@ -1594,8 +1633,6 @@ public: static TagDecl *castFromDeclContext(const DeclContext *DC) { return static_cast<TagDecl *>(const_cast<DeclContext*>(DC)); } - - void setDefinition(bool V) { IsDefinition = V; } }; /// EnumDecl - Represents an enum. As an extension, we allow forward-declared @@ -1641,7 +1678,7 @@ public: /// declaration as being defined; it's enumerators have already been /// added (via DeclContext::addDecl). NewType is the new underlying /// type of the enumeration type. - void completeDefinition(ASTContext &C, QualType NewType, + void completeDefinition(QualType NewType, QualType PromotionType); // enumerator_iterator - Iterates through the enumerators of this @@ -1679,8 +1716,9 @@ public: void setInstantiationOfMemberEnum(EnumDecl *IF) { InstantiatedFrom = IF; } - static bool classof(const Decl *D) { return D->getKind() == Enum; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const EnumDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Enum; } }; @@ -1763,8 +1801,8 @@ public: /// RecordDecl is defining declaration, not whether or not the record /// type is defined. This method returns NULL if there is no RecordDecl /// that defines the struct/union/tag. - RecordDecl* getDefinition(ASTContext& C) const { - return cast_or_null<RecordDecl>(TagDecl::getDefinition(C)); + RecordDecl* getDefinition() const { + return cast_or_null<RecordDecl>(TagDecl::getDefinition()); } // Iterator access to field members. The field iterator only visits @@ -1787,12 +1825,13 @@ public: /// completeDefinition - Notes that the definition of this type is /// now complete. - void completeDefinition(ASTContext& C); + void completeDefinition(); - static bool classof(const Decl *D) { - return D->getKind() >= RecordFirst && D->getKind() <= RecordLast; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const RecordDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= RecordFirst && K <= RecordLast; + } }; class FileScopeAsmDecl : public Decl { @@ -1807,10 +1846,9 @@ public: StringLiteral *getAsmString() { return AsmString; } void setAsmString(StringLiteral *Asm) { AsmString = Asm; } - static bool classof(const Decl *D) { - return D->getKind() == FileScopeAsm; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FileScopeAsmDecl *D) { return true; } + static bool classofKind(Kind K) { return K == FileScopeAsm; } }; /// BlockDecl - This represents a block literal declaration, which is like an @@ -1869,11 +1907,12 @@ public: assert(i < getNumParams() && "Illegal param #"); return ParamInfo[i]; } - void setParams(ASTContext& C, ParmVarDecl **NewParamInfo, unsigned NumParams); + void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams); // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return D->getKind() == Block; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const BlockDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Block; } static DeclContext *castToDeclContext(const BlockDecl *D) { return static_cast<DeclContext *>(const_cast<BlockDecl*>(D)); } diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 775bce2a15fc..a407a1627747 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -480,6 +480,7 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *) { return true; } + static bool classofKind(Kind K) { return true; } static DeclContext *castToDeclContext(const Decl *); static Decl *castFromDeclContext(const DeclContext *); @@ -1020,17 +1021,43 @@ inline bool Decl::isTemplateParameter() const { getKind() == TemplateTemplateParm; } + +// Specialization selected when ToTy is not a known subclass of DeclContext. +template <class ToTy, + bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value> +struct cast_convert_decl_context { + static const ToTy *doit(const DeclContext *Val) { + return static_cast<const ToTy*>(Decl::castFromDeclContext(Val)); + } + + static ToTy *doit(DeclContext *Val) { + return static_cast<ToTy*>(Decl::castFromDeclContext(Val)); + } +}; + +// Specialization selected when ToTy is a known subclass of DeclContext. +template <class ToTy> +struct cast_convert_decl_context<ToTy, true> { + static const ToTy *doit(const DeclContext *Val) { + return static_cast<const ToTy*>(Val); + } + + static ToTy *doit(DeclContext *Val) { + return static_cast<ToTy*>(Val); + } +}; + + } // end clang. namespace llvm { -/// Implement a isa_impl_wrap specialization to check whether a DeclContext is -/// a specific Decl. +/// isa<T>(DeclContext*) template<class ToTy> struct isa_impl_wrap<ToTy, const ::clang::DeclContext,const ::clang::DeclContext> { static bool doit(const ::clang::DeclContext &Val) { - return ToTy::classof(::clang::Decl::castFromDeclContext(&Val)); + return ToTy::classofKind(Val.getDeclKind()); } }; template<class ToTy> @@ -1038,6 +1065,34 @@ struct isa_impl_wrap<ToTy, ::clang::DeclContext, ::clang::DeclContext> : public isa_impl_wrap<ToTy, const ::clang::DeclContext,const ::clang::DeclContext> {}; +/// cast<T>(DeclContext*) +template<class ToTy> +struct cast_convert_val<ToTy, + const ::clang::DeclContext,const ::clang::DeclContext> { + static const ToTy &doit(const ::clang::DeclContext &Val) { + return *::clang::cast_convert_decl_context<ToTy>::doit(&Val); + } +}; +template<class ToTy> +struct cast_convert_val<ToTy, ::clang::DeclContext, ::clang::DeclContext> { + static ToTy &doit(::clang::DeclContext &Val) { + return *::clang::cast_convert_decl_context<ToTy>::doit(&Val); + } +}; +template<class ToTy> +struct cast_convert_val<ToTy, + const ::clang::DeclContext*, const ::clang::DeclContext*> { + static const ToTy *doit(const ::clang::DeclContext *Val) { + return ::clang::cast_convert_decl_context<ToTy>::doit(Val); + } +}; +template<class ToTy> +struct cast_convert_val<ToTy, ::clang::DeclContext*, ::clang::DeclContext*> { + static ToTy *doit(::clang::DeclContext *Val) { + return ::clang::cast_convert_decl_context<ToTy>::doit(Val); + } +}; + /// Implement cast_convert_val for Decl -> DeclContext conversions. template<class FromTy> struct cast_convert_val< ::clang::DeclContext, FromTy, FromTy> { @@ -1067,31 +1122,6 @@ struct cast_convert_val< const ::clang::DeclContext, FromTy*, FromTy*> { } }; -/// Implement cast_convert_val for DeclContext -> Decl conversions. -template<class ToTy> -struct cast_convert_val<ToTy, - const ::clang::DeclContext,const ::clang::DeclContext> { - static ToTy &doit(const ::clang::DeclContext &Val) { - return *reinterpret_cast<ToTy*>(ToTy::castFromDeclContext(&Val)); - } -}; -template<class ToTy> -struct cast_convert_val<ToTy, ::clang::DeclContext, ::clang::DeclContext> - : public cast_convert_val<ToTy, - const ::clang::DeclContext,const ::clang::DeclContext> {}; - -template<class ToTy> -struct cast_convert_val<ToTy, - const ::clang::DeclContext*, const ::clang::DeclContext*> { - static ToTy *doit(const ::clang::DeclContext *Val) { - return reinterpret_cast<ToTy*>(ToTy::castFromDeclContext(Val)); - } -}; -template<class ToTy> -struct cast_convert_val<ToTy, ::clang::DeclContext*, ::clang::DeclContext*> - : public cast_convert_val<ToTy, - const ::clang::DeclContext*,const ::clang::DeclContext*> {}; - } // end namespace llvm #endif diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 73ebf52d383b..0978c6da9d66 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -145,6 +145,10 @@ public: /// class (or not). bool isVirtual() const { return Virtual; } + /// \brief Determine whether this base class if a base of a class declared + /// with the 'class' keyword (vs. one declared with the 'struct' keyword). + bool isBaseOfClass() const { return BaseOfClass; } + /// getAccessSpecifier - Returns the access specifier for this base /// specifier. This is the actual base specifier as used for /// semantic analysis, so the result can never be AS_none. To @@ -174,115 +178,137 @@ public: /// FIXME: This class will disappear once we've properly taught RecordDecl /// to deal with C++-specific things. class CXXRecordDecl : public RecordDecl { - /// UserDeclaredConstructor - True when this class has a - /// user-declared constructor. - bool UserDeclaredConstructor : 1; - /// UserDeclaredCopyConstructor - True when this class has a - /// user-declared copy constructor. - bool UserDeclaredCopyConstructor : 1; + friend void TagDecl::startDefinition(); - /// UserDeclaredCopyAssignment - True when this class has a - /// user-declared copy assignment operator. - bool UserDeclaredCopyAssignment : 1; + struct DefinitionData { + DefinitionData(CXXRecordDecl *D); - /// UserDeclaredDestructor - True when this class has a - /// user-declared destructor. - bool UserDeclaredDestructor : 1; + /// UserDeclaredConstructor - True when this class has a + /// user-declared constructor. + bool UserDeclaredConstructor : 1; - /// Aggregate - True when this class is an aggregate. - bool Aggregate : 1; + /// UserDeclaredCopyConstructor - True when this class has a + /// user-declared copy constructor. + bool UserDeclaredCopyConstructor : 1; - /// PlainOldData - True when this class is a POD-type. - bool PlainOldData : 1; + /// UserDeclaredCopyAssignment - True when this class has a + /// user-declared copy assignment operator. + bool UserDeclaredCopyAssignment : 1; - /// Empty - true when this class is empty for traits purposes, i.e. has no - /// data members other than 0-width bit-fields, has no virtual function/base, - /// and doesn't inherit from a non-empty class. Doesn't take union-ness into - /// account. - bool Empty : 1; + /// UserDeclaredDestructor - True when this class has a + /// user-declared destructor. + bool UserDeclaredDestructor : 1; - /// Polymorphic - True when this class is polymorphic, i.e. has at least one - /// virtual member or derives from a polymorphic class. - bool Polymorphic : 1; + /// Aggregate - True when this class is an aggregate. + bool Aggregate : 1; - /// Abstract - True when this class is abstract, i.e. has at least one - /// pure virtual function, (that can come from a base class). - bool Abstract : 1; + /// PlainOldData - True when this class is a POD-type. + bool PlainOldData : 1; - /// HasTrivialConstructor - True when this class has a trivial constructor. - /// - /// C++ [class.ctor]p5. A constructor is trivial if it is an - /// implicitly-declared default constructor and if: - /// * its class has no virtual functions and no virtual base classes, and - /// * all the direct base classes of its class have trivial constructors, and - /// * for all the nonstatic data members of its class that are of class type - /// (or array thereof), each such class has a trivial constructor. - bool HasTrivialConstructor : 1; + /// Empty - true when this class is empty for traits purposes, + /// i.e. has no data members other than 0-width bit-fields, has no + /// virtual function/base, and doesn't inherit from a non-empty + /// class. Doesn't take union-ness into account. + bool Empty : 1; - /// HasTrivialCopyConstructor - True when this class has a trivial copy - /// constructor. - /// - /// C++ [class.copy]p6. A copy constructor for class X is trivial - /// if it is implicitly declared and if - /// * class X has no virtual functions and no virtual base classes, and - /// * each direct base class of X has a trivial copy constructor, and - /// * for all the nonstatic data members of X that are of class type (or - /// array thereof), each such class type has a trivial copy constructor; - /// otherwise the copy constructor is non-trivial. - bool HasTrivialCopyConstructor : 1; + /// Polymorphic - True when this class is polymorphic, i.e. has at + /// least one virtual member or derives from a polymorphic class. + bool Polymorphic : 1; - /// HasTrivialCopyAssignment - True when this class has a trivial copy - /// assignment operator. - /// - /// C++ [class.copy]p11. A copy assignment operator for class X is - /// trivial if it is implicitly declared and if - /// * class X has no virtual functions and no virtual base classes, and - /// * each direct base class of X has a trivial copy assignment operator, and - /// * for all the nonstatic data members of X that are of class type (or - /// array thereof), each such class type has a trivial copy assignment - /// operator; - /// otherwise the copy assignment operator is non-trivial. - bool HasTrivialCopyAssignment : 1; + /// Abstract - True when this class is abstract, i.e. has at least + /// one pure virtual function, (that can come from a base class). + bool Abstract : 1; - /// HasTrivialDestructor - True when this class has a trivial destructor. - /// - /// C++ [class.dtor]p3. A destructor is trivial if it is an - /// implicitly-declared destructor and if: - /// * all of the direct base classes of its class have trivial destructors - /// and - /// * for all of the non-static data members of its class that are of class - /// type (or array thereof), each such class has a trivial destructor. - bool HasTrivialDestructor : 1; + /// HasTrivialConstructor - True when this class has a trivial constructor. + /// + /// C++ [class.ctor]p5. A constructor is trivial if it is an + /// implicitly-declared default constructor and if: + /// * its class has no virtual functions and no virtual base classes, and + /// * all the direct base classes of its class have trivial constructors, and + /// * for all the nonstatic data members of its class that are of class type + /// (or array thereof), each such class has a trivial constructor. + bool HasTrivialConstructor : 1; + + /// HasTrivialCopyConstructor - True when this class has a trivial copy + /// constructor. + /// + /// C++ [class.copy]p6. A copy constructor for class X is trivial + /// if it is implicitly declared and if + /// * class X has no virtual functions and no virtual base classes, and + /// * each direct base class of X has a trivial copy constructor, and + /// * for all the nonstatic data members of X that are of class type (or + /// array thereof), each such class type has a trivial copy constructor; + /// otherwise the copy constructor is non-trivial. + bool HasTrivialCopyConstructor : 1; + + /// HasTrivialCopyAssignment - True when this class has a trivial copy + /// assignment operator. + /// + /// C++ [class.copy]p11. A copy assignment operator for class X is + /// trivial if it is implicitly declared and if + /// * class X has no virtual functions and no virtual base classes, and + /// * each direct base class of X has a trivial copy assignment operator, and + /// * for all the nonstatic data members of X that are of class type (or + /// array thereof), each such class type has a trivial copy assignment + /// operator; + /// otherwise the copy assignment operator is non-trivial. + bool HasTrivialCopyAssignment : 1; - /// ComputedVisibleConversions - True when visible conversion functions are - /// already computed and are available. - bool ComputedVisibleConversions : 1; + /// HasTrivialDestructor - True when this class has a trivial destructor. + /// + /// C++ [class.dtor]p3. A destructor is trivial if it is an + /// implicitly-declared destructor and if: + /// * all of the direct base classes of its class have trivial destructors + /// and + /// * for all of the non-static data members of its class that are of class + /// type (or array thereof), each such class has a trivial destructor. + bool HasTrivialDestructor : 1; + + /// ComputedVisibleConversions - True when visible conversion functions are + /// already computed and are available. + bool ComputedVisibleConversions : 1; - /// Bases - Base classes of this class. - /// FIXME: This is wasted space for a union. - CXXBaseSpecifier *Bases; + /// Bases - Base classes of this class. + /// FIXME: This is wasted space for a union. + CXXBaseSpecifier *Bases; + + /// NumBases - The number of base class specifiers in Bases. + unsigned NumBases; + + /// VBases - direct and indirect virtual base classes of this class. + CXXBaseSpecifier *VBases; + + /// NumVBases - The number of virtual base class specifiers in VBases. + unsigned NumVBases; - /// NumBases - The number of base class specifiers in Bases. - unsigned NumBases; + /// Conversions - Overload set containing the conversion functions + /// of this C++ class (but not its inherited conversion + /// functions). Each of the entries in this overload set is a + /// CXXConversionDecl. + UnresolvedSet<4> Conversions; - /// VBases - direct and indirect virtual base classes of this class. - CXXBaseSpecifier *VBases; + /// VisibleConversions - Overload set containing the conversion + /// functions of this C++ class and all those inherited conversion + /// functions that are visible in this class. Each of the entries + /// in this overload set is a CXXConversionDecl or a + /// FunctionTemplateDecl. + UnresolvedSet<4> VisibleConversions; - /// NumVBases - The number of virtual base class specifiers in VBases. - unsigned NumVBases; + /// Definition - The declaration which defines this record. + CXXRecordDecl *Definition; - /// Conversions - Overload set containing the conversion functions - /// of this C++ class (but not its inherited conversion - /// functions). Each of the entries in this overload set is a - /// CXXConversionDecl. - UnresolvedSet<4> Conversions; + } *DefinitionData; - /// VisibleConversions - Overload set containing the conversion functions - /// of this C++ class and all those inherited conversion functions that - /// are visible in this class. Each of the entries in this overload set is - /// a CXXConversionDecl or a FunctionTemplateDecl. - UnresolvedSet<4> VisibleConversions; + struct DefinitionData &data() { + assert(DefinitionData && "queried property of class with no definition"); + return *DefinitionData; + } + + const struct DefinitionData &data() const { + assert(DefinitionData && "queried property of class with no definition"); + return *DefinitionData; + } /// \brief The template or declaration that this declaration /// describes or was instantiated from, respectively. @@ -336,6 +362,13 @@ public: return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl()); } + CXXRecordDecl *getDefinition() const { + if (!DefinitionData) return 0; + return data().Definition; + } + + bool hasDefinition() const { return DefinitionData != 0; } + static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation TKL = SourceLocation(), @@ -345,21 +378,22 @@ public: virtual void Destroy(ASTContext& C); bool isDynamicClass() const { - return Polymorphic || NumVBases != 0; + return data().Polymorphic || data().NumVBases != 0; } /// setBases - Sets the base classes of this struct or class. - void setBases(ASTContext &C, - CXXBaseSpecifier const * const *Bases, unsigned NumBases); + void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases); /// getNumBases - Retrieves the number of base classes of this /// class. - unsigned getNumBases() const { return NumBases; } + unsigned getNumBases() const { return data().NumBases; } - base_class_iterator bases_begin() { return Bases; } - base_class_const_iterator bases_begin() const { return Bases; } - base_class_iterator bases_end() { return Bases + NumBases; } - base_class_const_iterator bases_end() const { return Bases + NumBases; } + base_class_iterator bases_begin() { return data().Bases; } + base_class_const_iterator bases_begin() const { return data().Bases; } + base_class_iterator bases_end() { return bases_begin() + data().NumBases; } + base_class_const_iterator bases_end() const { + return bases_begin() + data().NumBases; + } reverse_base_class_iterator bases_rbegin() { return reverse_base_class_iterator(bases_end()); } @@ -375,12 +409,14 @@ public: /// getNumVBases - Retrieves the number of virtual base classes of this /// class. - unsigned getNumVBases() const { return NumVBases; } + unsigned getNumVBases() const { return data().NumVBases; } - base_class_iterator vbases_begin() { return VBases; } - base_class_const_iterator vbases_begin() const { return VBases; } - base_class_iterator vbases_end() { return VBases + NumVBases; } - base_class_const_iterator vbases_end() const { return VBases + NumVBases; } + base_class_iterator vbases_begin() { return data().VBases; } + base_class_const_iterator vbases_begin() const { return data().VBases; } + base_class_iterator vbases_end() { return vbases_begin() + data().NumVBases; } + base_class_const_iterator vbases_end() const { + return vbases_begin() + data().NumVBases; + } reverse_base_class_iterator vbases_rbegin() { return reverse_base_class_iterator(vbases_end()); } @@ -445,17 +481,14 @@ public: /// user-declared constructors. When true, a default constructor /// will not be implicitly declared. bool hasUserDeclaredConstructor() const { - assert((isDefinition() || - cast<RecordType>(getTypeForDecl())->isBeingDefined()) && - "Incomplete record decl!"); - return UserDeclaredConstructor; + return data().UserDeclaredConstructor; } /// hasUserDeclaredCopyConstructor - Whether this class has a /// user-declared copy constructor. When false, a copy constructor /// will be implicitly declared. bool hasUserDeclaredCopyConstructor() const { - return UserDeclaredCopyConstructor; + return data().UserDeclaredCopyConstructor; } /// addedAssignmentOperator - Notify the class that another assignment @@ -467,45 +500,45 @@ public: /// user-declared copy assignment operator. When false, a copy /// assigment operator will be implicitly declared. bool hasUserDeclaredCopyAssignment() const { - return UserDeclaredCopyAssignment; + return data().UserDeclaredCopyAssignment; } /// hasUserDeclaredDestructor - Whether this class has a /// user-declared destructor. When false, a destructor will be /// implicitly declared. - bool hasUserDeclaredDestructor() const { return UserDeclaredDestructor; } + bool hasUserDeclaredDestructor() const { + return data().UserDeclaredDestructor; + } /// setUserDeclaredDestructor - Set whether this class has a /// user-declared destructor. If not set by the time the class is /// fully defined, a destructor will be implicitly declared. void setUserDeclaredDestructor(bool UCD) { - UserDeclaredDestructor = UCD; + data().UserDeclaredDestructor = UCD; } /// getConversions - Retrieve the overload set containing all of the /// conversion functions in this class. UnresolvedSetImpl *getConversionFunctions() { - assert((this->isDefinition() || - cast<RecordType>(getTypeForDecl())->isBeingDefined()) && - "getConversionFunctions() called on incomplete type"); - return &Conversions; + return &data().Conversions; } const UnresolvedSetImpl *getConversionFunctions() const { - assert((this->isDefinition() || - cast<RecordType>(getTypeForDecl())->isBeingDefined()) && - "getConversionFunctions() called on incomplete type"); - return &Conversions; + return &data().Conversions; } typedef UnresolvedSetImpl::iterator conversion_iterator; - conversion_iterator conversion_begin() const { return Conversions.begin(); } - conversion_iterator conversion_end() const { return Conversions.end(); } + conversion_iterator conversion_begin() const { + return getConversionFunctions()->begin(); + } + conversion_iterator conversion_end() const { + return getConversionFunctions()->end(); + } /// Replaces a conversion function with a new declaration. /// /// Returns true if the old conversion was found. bool replaceConversion(const NamedDecl* Old, NamedDecl *New) { - return Conversions.replace(Old, New); + return getConversionFunctions()->replace(Old, New); } /// getVisibleConversionFunctions - get all conversion functions visible @@ -532,11 +565,11 @@ public: /// [dcl.init.aggr]), which is a class with no user-declared /// constructors, no private or protected non-static data members, /// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1). - bool isAggregate() const { return Aggregate; } + bool isAggregate() const { return data().Aggregate; } /// setAggregate - Set whether this class is an aggregate (C++ /// [dcl.init.aggr]). - void setAggregate(bool Agg) { Aggregate = Agg; } + void setAggregate(bool Agg) { data().Aggregate = Agg; } /// setMethodAsVirtual - Make input method virtual and set the necesssary /// special function bits and other bits accordingly. @@ -546,66 +579,74 @@ public: /// that is an aggregate that has no non-static non-POD data members, no /// reference data members, no user-defined copy assignment operator and no /// user-defined destructor. - bool isPOD() const { return PlainOldData; } + bool isPOD() const { return data().PlainOldData; } /// setPOD - Set whether this class is a POD-type (C++ [class]p4). - void setPOD(bool POD) { PlainOldData = POD; } + void setPOD(bool POD) { data().PlainOldData = POD; } /// isEmpty - Whether this class is empty (C++0x [meta.unary.prop]), which /// means it has a virtual function, virtual base, data member (other than /// 0-width bit-field) or inherits from a non-empty class. Does NOT include /// a check for union-ness. - bool isEmpty() const { return Empty; } + bool isEmpty() const { return data().Empty; } /// Set whether this class is empty (C++0x [meta.unary.prop]) - void setEmpty(bool Emp) { Empty = Emp; } + void setEmpty(bool Emp) { data().Empty = Emp; } /// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]), /// which means that the class contains or inherits a virtual function. - bool isPolymorphic() const { return Polymorphic; } + bool isPolymorphic() const { return data().Polymorphic; } /// setPolymorphic - Set whether this class is polymorphic (C++ /// [class.virtual]). - void setPolymorphic(bool Poly) { Polymorphic = Poly; } + void setPolymorphic(bool Poly) { data().Polymorphic = Poly; } /// isAbstract - Whether this class is abstract (C++ [class.abstract]), /// which means that the class contains or inherits a pure virtual function. - bool isAbstract() const { return Abstract; } + bool isAbstract() const { return data().Abstract; } /// setAbstract - Set whether this class is abstract (C++ [class.abstract]) - void setAbstract(bool Abs) { Abstract = Abs; } + void setAbstract(bool Abs) { data().Abstract = Abs; } // hasTrivialConstructor - Whether this class has a trivial constructor // (C++ [class.ctor]p5) - bool hasTrivialConstructor() const { return HasTrivialConstructor; } + bool hasTrivialConstructor() const { return data().HasTrivialConstructor; } // setHasTrivialConstructor - Set whether this class has a trivial constructor // (C++ [class.ctor]p5) - void setHasTrivialConstructor(bool TC) { HasTrivialConstructor = TC; } + void setHasTrivialConstructor(bool TC) { data().HasTrivialConstructor = TC; } // hasTrivialCopyConstructor - Whether this class has a trivial copy // constructor (C++ [class.copy]p6) - bool hasTrivialCopyConstructor() const { return HasTrivialCopyConstructor; } + bool hasTrivialCopyConstructor() const { + return data().HasTrivialCopyConstructor; + } // setHasTrivialCopyConstructor - Set whether this class has a trivial // copy constructor (C++ [class.copy]p6) - void setHasTrivialCopyConstructor(bool TC) { HasTrivialCopyConstructor = TC; } + void setHasTrivialCopyConstructor(bool TC) { + data().HasTrivialCopyConstructor = TC; + } // hasTrivialCopyAssignment - Whether this class has a trivial copy // assignment operator (C++ [class.copy]p11) - bool hasTrivialCopyAssignment() const { return HasTrivialCopyAssignment; } + bool hasTrivialCopyAssignment() const { + return data().HasTrivialCopyAssignment; + } // setHasTrivialCopyAssignment - Set whether this class has a // trivial copy assignment operator (C++ [class.copy]p11) - void setHasTrivialCopyAssignment(bool TC) { HasTrivialCopyAssignment = TC; } + void setHasTrivialCopyAssignment(bool TC) { + data().HasTrivialCopyAssignment = TC; + } // hasTrivialDestructor - Whether this class has a trivial destructor // (C++ [class.dtor]p3) - bool hasTrivialDestructor() const { return HasTrivialDestructor; } + bool hasTrivialDestructor() const { return data().HasTrivialDestructor; } // setHasTrivialDestructor - Set whether this class has a trivial destructor // (C++ [class.dtor]p3) - void setHasTrivialDestructor(bool TC) { HasTrivialDestructor = TC; } + void setHasTrivialDestructor(bool TC) { data().HasTrivialDestructor = TC; } /// \brief If this record is an instantiation of a member class, /// retrieves the member class from which it was instantiated. @@ -826,10 +867,11 @@ public: return (PathAccess > DeclAccess ? PathAccess : DeclAccess); } - static bool classof(const Decl *D) { - return D->getKind() == CXXRecord || - D->getKind() == ClassTemplateSpecialization || - D->getKind() == ClassTemplatePartialSpecialization; + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { + return K == CXXRecord || + K == ClassTemplateSpecialization || + K == ClassTemplatePartialSpecialization; } static bool classof(const CXXRecordDecl *D) { return true; } static bool classof(const ClassTemplateSpecializationDecl *D) { @@ -911,10 +953,11 @@ public: bool hasInlineBody() const; // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() >= CXXMethod && D->getKind() <= CXXConversion; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXMethodDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= CXXMethod && K <= CXXConversion; + } }; /// CXXBaseOrMemberInitializer - Represents a C++ base or member @@ -939,9 +982,9 @@ class CXXBaseOrMemberInitializer { /// \brief The source location for the field name. SourceLocation MemberLocation; - /// Args - The arguments used to initialize the base or member. - Stmt **Args; - unsigned NumArgs; + /// \brief The argument used to initialize the base or member, which may + /// end up constructing an object (when multiple arguments are involved). + Stmt *Init; /// \brief Stores either the constructor to call to initialize this base or /// member (a CXXConstructorDecl pointer), or stores the anonymous union of @@ -961,7 +1004,7 @@ class CXXBaseOrMemberInitializer { /// @endcode /// In above example, BaseOrMember holds the field decl. for anonymous union /// and AnonUnionMember holds field decl for au_i1. - llvm::PointerUnion<CXXConstructorDecl *, FieldDecl *> CtorOrAnonUnion; + FieldDecl *AnonUnionMember; /// LParenLoc - Location of the left paren of the ctor-initializer. SourceLocation LParenLoc; @@ -973,30 +1016,22 @@ public: /// CXXBaseOrMemberInitializer - Creates a new base-class initializer. explicit CXXBaseOrMemberInitializer(ASTContext &Context, - TypeSourceInfo *TInfo, CXXConstructorDecl *C, + TypeSourceInfo *TInfo, SourceLocation L, - Expr **Args, unsigned NumArgs, + Expr *Init, SourceLocation R); /// CXXBaseOrMemberInitializer - Creates a new member initializer. explicit CXXBaseOrMemberInitializer(ASTContext &Context, FieldDecl *Member, SourceLocation MemberLoc, - CXXConstructorDecl *C, SourceLocation L, - Expr **Args, unsigned NumArgs, + SourceLocation L, + Expr *Init, SourceLocation R); /// \brief Destroy the base or member initializer. void Destroy(ASTContext &Context); - /// arg_iterator - Iterates through the member initialization - /// arguments. - typedef ExprIterator arg_iterator; - - /// arg_const_iterator - Iterates through the member initialization - /// arguments. - typedef ConstExprIterator const_arg_iterator; - /// isBaseInitializer - Returns true when this initializer is /// initializing a base class. bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); } @@ -1046,32 +1081,16 @@ public: SourceRange getSourceRange() const; FieldDecl *getAnonUnionMember() const { - return CtorOrAnonUnion.dyn_cast<FieldDecl *>(); + return AnonUnionMember; } void setAnonUnionMember(FieldDecl *anonMember) { - CtorOrAnonUnion = anonMember; - } - - const CXXConstructorDecl *getConstructor() const { - return CtorOrAnonUnion.dyn_cast<CXXConstructorDecl *>(); + AnonUnionMember = anonMember; } SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } - /// arg_begin() - Retrieve an iterator to the first initializer argument. - arg_iterator arg_begin() { return Args; } - /// arg_begin() - Retrieve an iterator to the first initializer argument. - const_arg_iterator const_arg_begin() const { return Args; } - - /// arg_end() - Retrieve an iterator past the last initializer argument. - arg_iterator arg_end() { return Args + NumArgs; } - /// arg_end() - Retrieve an iterator past the last initializer argument. - const_arg_iterator const_arg_end() const { return Args + NumArgs; } - - /// getNumArgs - Determine the number of arguments used to - /// initialize the member or base. - unsigned getNumArgs() const { return NumArgs; } + Expr *getInit() { return static_cast<Expr *>(Init); } }; /// CXXConstructorDecl - Represents a C++ constructor within a @@ -1084,8 +1103,9 @@ public: /// }; /// @endcode class CXXConstructorDecl : public CXXMethodDecl { - /// Explicit - Whether this constructor is explicit. - bool Explicit : 1; + /// IsExplicitSpecified - Whether this constructor declaration has the + /// 'explicit' keyword specified. + bool IsExplicitSpecified : 1; /// ImplicitlyDefined - Whether this constructor was implicitly /// defined by the compiler. When false, the constructor was defined @@ -1103,9 +1123,10 @@ class CXXConstructorDecl : public CXXMethodDecl { CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - bool isExplicit, bool isInline, bool isImplicitlyDeclared) + bool isExplicitSpecified, bool isInline, + bool isImplicitlyDeclared) : CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false, isInline), - Explicit(isExplicit), ImplicitlyDefined(false), + IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false), BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) { setImplicit(isImplicitlyDeclared); } @@ -1118,8 +1139,15 @@ public: bool isExplicit, bool isInline, bool isImplicitlyDeclared); + /// isExplicitSpecified - Whether this constructor declaration has the + /// 'explicit' keyword specified. + bool isExplicitSpecified() const { return IsExplicitSpecified; } + /// isExplicit - Whether this constructor was marked "explicit" or not. - bool isExplicit() const { return Explicit; } + bool isExplicit() const { + return cast<CXXConstructorDecl>(getFirstDeclaration()) + ->isExplicitSpecified(); + } /// isImplicitlyDefined - Whether this constructor was implicitly /// defined. If false, then this constructor was defined by the @@ -1212,10 +1240,9 @@ public: bool isCopyConstructorLikeSpecialization() const; // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() == CXXConstructor; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXConstructorDecl *D) { return true; } + static bool classofKind(Kind K) { return K == CXXConstructor; } }; /// CXXDestructorDecl - Represents a C++ destructor within a @@ -1274,10 +1301,9 @@ public: const FunctionDecl *getOperatorDelete() const { return OperatorDelete; } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() == CXXDestructor; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXDestructorDecl *D) { return true; } + static bool classofKind(Kind K) { return K == CXXDestructor; } }; /// CXXConversionDecl - Represents a C++ conversion function within a @@ -1290,16 +1316,16 @@ public: /// }; /// @endcode class CXXConversionDecl : public CXXMethodDecl { - /// Explicit - Whether this conversion function is marked - /// "explicit", meaning that it can only be applied when the user + /// IsExplicitSpecified - Whether this conversion function declaration is + /// marked "explicit", meaning that it can only be applied when the user /// explicitly wrote a cast. This is a C++0x feature. - bool Explicit : 1; + bool IsExplicitSpecified : 1; CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isExplicit) + bool isInline, bool isExplicitSpecified) : CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false, isInline), - Explicit(isExplicit) { } + IsExplicitSpecified(isExplicitSpecified) { } public: static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, @@ -1307,10 +1333,18 @@ public: QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicit); + /// IsExplicitSpecified - Whether this conversion function declaration is + /// marked "explicit", meaning that it can only be applied when the user + /// explicitly wrote a cast. This is a C++0x feature. + bool isExplicitSpecified() const { return IsExplicitSpecified; } + /// isExplicit - Whether this is an explicit conversion operator /// (C++0x only). Explicit conversion operators are only considered /// when the user has explicitly written a cast. - bool isExplicit() const { return Explicit; } + bool isExplicit() const { + return cast<CXXConversionDecl>(getFirstDeclaration()) + ->isExplicitSpecified(); + } /// getConversionType - Returns the type that this conversion /// function is converting to. @@ -1319,10 +1353,9 @@ public: } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() == CXXConversion; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXConversionDecl *D) { return true; } + static bool classofKind(Kind K) { return K == CXXConversion; } }; /// FriendDecl - Represents the declaration of a friend entity, @@ -1391,10 +1424,9 @@ public: void setSpecialization(bool WS) { WasSpecialization = WS; } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() == Decl::Friend; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FriendDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Decl::Friend; } }; /// LinkageSpecDecl - This represents a linkage specification. For example: @@ -1432,10 +1464,9 @@ public: /// braces in its syntactic form. bool hasBraces() const { return HadBraces; } - static bool classof(const Decl *D) { - return D->getKind() == LinkageSpec; - } + 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; } static DeclContext *castToDeclContext(const LinkageSpecDecl *D) { return static_cast<DeclContext *>(const_cast<LinkageSpecDecl*>(D)); } @@ -1537,10 +1568,9 @@ public: NamedDecl *Nominated, DeclContext *CommonAncestor); - static bool classof(const Decl *D) { - return D->getKind() == Decl::UsingDirective; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UsingDirectiveDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Decl::UsingDirective; } // Friend for getUsingDirectiveName. friend class DeclContext; @@ -1598,6 +1628,16 @@ public: return const_cast<NamespaceAliasDecl*>(this)->getNamespace(); } + /// Returns the location of the alias name, i.e. 'foo' in + /// "namespace foo = ns::bar;". + SourceLocation getAliasLoc() const { return AliasLoc; } + + /// 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; } + /// \brief Retrieve the namespace that this alias refers to, which /// may either be a NamespaceDecl or a NamespaceAliasDecl. NamedDecl *getAliasedNamespace() const { return Namespace; } @@ -1610,10 +1650,9 @@ public: SourceLocation IdentLoc, NamedDecl *Namespace); - static bool classof(const Decl *D) { - return D->getKind() == Decl::NamespaceAlias; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const NamespaceAliasDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Decl::NamespaceAlias; } }; /// UsingShadowDecl - Represents a shadow declaration introduced into @@ -1660,10 +1699,9 @@ public: return Using; } - static bool classof(const Decl *D) { - return D->getKind() == Decl::UsingShadow; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UsingShadowDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Decl::UsingShadow; } }; /// UsingDecl - Represents a C++ using-declaration. For example: @@ -1732,10 +1770,9 @@ public: SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL, NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg); - static bool classof(const Decl *D) { - return D->getKind() == Decl::Using; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UsingDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Decl::Using; } }; /// UnresolvedUsingValueDecl - Represents a dependent using @@ -1784,10 +1821,9 @@ public: SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, SourceLocation TargetNameLoc, DeclarationName TargetName); - static bool classof(const Decl *D) { - return D->getKind() == Decl::UnresolvedUsingValue; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UnresolvedUsingValueDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Decl::UnresolvedUsingValue; } }; /// UnresolvedUsingTypenameDecl - Represents a dependent using @@ -1843,10 +1879,9 @@ public: SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, SourceLocation TargetNameLoc, DeclarationName TargetName); - static bool classof(const Decl *D) { - return D->getKind() == Decl::UnresolvedUsingTypename; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Decl::UnresolvedUsingTypename; } }; /// StaticAssertDecl - Represents a C++0x static_assert declaration. @@ -1872,10 +1907,9 @@ public: virtual ~StaticAssertDecl(); virtual void Destroy(ASTContext& C); - static bool classof(const Decl *D) { - return D->getKind() == Decl::StaticAssert; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(StaticAssertDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Decl::StaticAssert; } }; /// Insertion operator for diagnostics. This allows sending AccessSpecifier's diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 0fb0db13bb57..e562d352e070 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -193,6 +193,9 @@ public: ImplementationControl impControl = None); virtual ObjCMethodDecl *getCanonicalDecl(); + const ObjCMethodDecl *getCanonicalDecl() const { + return const_cast<ObjCMethodDecl*>(this)->getCanonicalDecl(); + } ObjCDeclQualifier getObjCDeclQualifier() const { return ObjCDeclQualifier(objcDeclQualifier); @@ -277,8 +280,9 @@ public: bool isThisDeclarationADefinition() const { return Body; } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return D->getKind() == ObjCMethod; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCMethodDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCMethod; } static DeclContext *castToDeclContext(const ObjCMethodDecl *D) { return static_cast<DeclContext *>(const_cast<ObjCMethodDecl*>(D)); } @@ -383,11 +387,12 @@ public: } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() >= ObjCContainerFirst && - D->getKind() <= ObjCContainerLast; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCContainerDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= ObjCContainerFirst && + K <= ObjCContainerLast; + } static DeclContext *castToDeclContext(const ObjCContainerDecl *D) { return static_cast<DeclContext *>(const_cast<ObjCContainerDecl*>(D)); @@ -584,8 +589,9 @@ public: Type *getTypeForDecl() const { return TypeForDecl; } void setTypeForDecl(Type *TD) const { TypeForDecl = TD; } - static bool classof(const Decl *D) { return D->getKind() == ObjCInterface; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCInterfaceDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCInterface; } }; /// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC @@ -630,8 +636,9 @@ public: } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return D->getKind() == ObjCIvar; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCIvarDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCIvar; } private: // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum unsigned DeclAccess : 3; @@ -657,8 +664,9 @@ public: virtual void Destroy(ASTContext& C); // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return D->getKind() == ObjCAtDefsField; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCAtDefsFieldDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCAtDefsField; } }; /// ObjCProtocolDecl - Represents a protocol declaration. ObjC protocols @@ -749,8 +757,9 @@ public: SourceLocation getLocEnd() const { return EndLoc; } void setLocEnd(SourceLocation LE) { EndLoc = LE; } - static bool classof(const Decl *D) { return D->getKind() == ObjCProtocol; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCProtocolDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCProtocol; } }; /// ObjCClassDecl - Specifies a list of forward class declarations. For example: @@ -796,8 +805,9 @@ public: void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, const SourceLocation *Locs, unsigned Num); - static bool classof(const Decl *D) { return D->getKind() == ObjCClass; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCClassDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCClass; } }; /// ObjCForwardProtocolDecl - Specifies a list of forward protocol declarations. @@ -846,10 +856,9 @@ public: const SourceLocation *Locs, ASTContext &C) { ReferencedProtocols.set(List, Num, Locs, C); } - static bool classof(const Decl *D) { - return D->getKind() == ObjCForwardProtocol; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCForwardProtocolDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCForwardProtocol; } }; /// ObjCCategoryDecl - Represents a category declaration. A category allows @@ -940,6 +949,8 @@ public: ClassInterface->setCategoryList(this); } + bool IsClassExtension() const { return getIdentifier() == 0; } + SourceLocation getAtLoc() const { return AtLoc; } void setAtLoc(SourceLocation At) { AtLoc = At; } @@ -950,8 +961,9 @@ public: return SourceRange(AtLoc, getAtEndRange().getEnd()); } - static bool classof(const Decl *D) { return D->getKind() == ObjCCategory; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCCategoryDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCCategory; } }; class ObjCImplDecl : public ObjCContainerDecl { @@ -997,10 +1009,11 @@ public: return propimpl_iterator(decls_end()); } - static bool classof(const Decl *D) { - return D->getKind() >= ObjCImplFirst && D->getKind() <= ObjCImplLast; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCImplDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= ObjCImplFirst && K <= ObjCImplLast; + } }; /// ObjCCategoryImplDecl - An object of this class encapsulates a category @@ -1068,8 +1081,9 @@ public: return getName(); } - static bool classof(const Decl *D) { return D->getKind() == ObjCCategoryImpl;} + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCCategoryImplDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCCategoryImpl;} }; /// ObjCImplementationDecl - Represents a class definition - this is where @@ -1152,10 +1166,9 @@ public: return ivar_begin() == ivar_end(); } - static bool classof(const Decl *D) { - return D->getKind() == ObjCImplementation; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCImplementationDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCImplementation; } }; /// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is @@ -1176,10 +1189,9 @@ public: ObjCInterfaceDecl *getClassInterface() { return AliasedClass; } void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; } - static bool classof(const Decl *D) { - return D->getKind() == ObjCCompatibleAlias; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCCompatibleAliasDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCCompatibleAlias; } }; @@ -1294,10 +1306,9 @@ public: return PropertyIvarDecl; } - static bool classof(const Decl *D) { - return D->getKind() == ObjCProperty; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCPropertyDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCProperty; } }; /// ObjCPropertyImplDecl - Represents implementation declaration of a property @@ -1354,10 +1365,9 @@ public: } void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { PropertyIvarDecl = Ivar; } - static bool classof(const Decl *D) { - return D->getKind() == ObjCPropertyImpl; - } + 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; } }; } // end namespace clang diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index d8b004a049ce..ced174716c7a 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -247,13 +247,14 @@ public: NamedDecl *getTemplatedDecl() const { return TemplatedDecl; } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() >= TemplateFirst && D->getKind() <= TemplateLast; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TemplateDecl *D) { return true; } static bool classof(const FunctionTemplateDecl *D) { return true; } static bool classof(const ClassTemplateDecl *D) { return true; } static bool classof(const TemplateTemplateParmDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= TemplateFirst && K <= TemplateLast; + } protected: NamedDecl *TemplatedDecl; @@ -510,10 +511,9 @@ public: NamedDecl *Decl); // Implement isa/cast/dyncast support - static bool classof(const Decl *D) - { return D->getKind() == FunctionTemplate; } - static bool classof(const FunctionTemplateDecl *D) - { return true; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const FunctionTemplateDecl *D) { return true; } + static bool classofKind(Kind K) { return K == FunctionTemplate; } }; //===----------------------------------------------------------------------===// @@ -634,10 +634,9 @@ public: bool isParameterPack() const { return ParameterPack; } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() == TemplateTypeParm; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TemplateTypeParmDecl *D) { return true; } + static bool classofKind(Kind K) { return K == TemplateTypeParm; } }; /// NonTypeTemplateParmDecl - Declares a non-type template parameter, @@ -682,10 +681,9 @@ public: } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() == NonTypeTemplateParm; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const NonTypeTemplateParmDecl *D) { return true; } + static bool classofKind(Kind K) { return K == NonTypeTemplateParm; } }; /// TemplateTemplateParmDecl - Declares a template template parameter, @@ -735,10 +733,9 @@ public: } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() == TemplateTemplateParm; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TemplateTemplateParmDecl *D) { return true; } + static bool classofKind(Kind K) { return K == TemplateTemplateParm; } }; /// \brief Represents a class template specialization, which refers to @@ -903,9 +900,10 @@ public: TemplateArgs[Arg].Profile(ID, Context); } - static bool classof(const Decl *D) { - return D->getKind() == ClassTemplateSpecialization || - D->getKind() == ClassTemplatePartialSpecialization; + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { + return K == ClassTemplateSpecialization || + K == ClassTemplatePartialSpecialization; } static bool classof(const ClassTemplateSpecializationDecl *) { @@ -1039,8 +1037,9 @@ public: // FIXME: Add Profile support! - static bool classof(const Decl *D) { - return D->getKind() == ClassTemplatePartialSpecialization; + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { + return K == ClassTemplatePartialSpecialization; } static bool classof(const ClassTemplatePartialSpecializationDecl *) { @@ -1212,10 +1211,9 @@ public: } // Implement isa/cast/dyncast support - static bool classof(const Decl *D) - { return D->getKind() == ClassTemplate; } - static bool classof(const ClassTemplateDecl *D) - { return true; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const ClassTemplateDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ClassTemplate; } virtual void Destroy(ASTContext& C); }; @@ -1293,9 +1291,8 @@ public: } // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() == Decl::FriendTemplate; - } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == Decl::FriendTemplate; } static bool classof(const FriendTemplateDecl *D) { return true; } }; diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 59d7e439e570..2254724410d0 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -274,30 +274,34 @@ public: static DeclarationName getTombstoneMarker() { return DeclarationName(uintptr_t(-2)); } + + static int compare(DeclarationName LHS, DeclarationName RHS); void dump() const; }; /// Ordering on two declaration names. If both names are identifiers, /// this provides a lexicographical ordering. -bool operator<(DeclarationName LHS, DeclarationName RHS); +inline bool operator<(DeclarationName LHS, DeclarationName RHS) { + return DeclarationName::compare(LHS, RHS) < 0; +} /// Ordering on two declaration names. If both names are identifiers, /// this provides a lexicographical ordering. inline bool operator>(DeclarationName LHS, DeclarationName RHS) { - return RHS < LHS; + return DeclarationName::compare(LHS, RHS) > 0; } /// Ordering on two declaration names. If both names are identifiers, /// this provides a lexicographical ordering. inline bool operator<=(DeclarationName LHS, DeclarationName RHS) { - return !(RHS < LHS); + return DeclarationName::compare(LHS, RHS) <= 0; } /// Ordering on two declaration names. If both names are identifiers, /// this provides a lexicographical ordering. inline bool operator>=(DeclarationName LHS, DeclarationName RHS) { - return !(LHS < RHS); + return DeclarationName::compare(LHS, RHS) >= 0; } /// DeclarationNameTable - Used to store and retrieve DeclarationName diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 252781767169..114a19800f50 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -149,7 +149,8 @@ public: LV_DuplicateVectorComponents, LV_InvalidExpression, LV_MemberFunction, - LV_SubObjCPropertySetting + LV_SubObjCPropertySetting, + LV_SubObjCPropertyGetterSetting }; isLvalueResult isLvalue(ASTContext &Ctx) const; @@ -179,7 +180,8 @@ public: MLV_ReadonlyProperty, MLV_NoSetterProperty, MLV_MemberFunction, - MLV_SubObjCPropertySetting + MLV_SubObjCPropertySetting, + MLV_SubObjCPropertyGetterSetting }; isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = 0) const; @@ -192,6 +194,9 @@ public: return const_cast<Expr*>(this)->getBitField(); } + /// \brief Returns whether this expression refers to a vector element. + bool refersToVectorElement() const; + /// isIntegerConstantExpr - Return true if this expression is a valid integer /// constant expression, and, if so, return its value in Result. If not a /// valid i-c-e, return false and fill in Loc (if specified) with the location @@ -563,7 +568,10 @@ public: enum IdentType { Func, Function, - PrettyFunction + PrettyFunction, + /// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the + /// 'virtual' keyword is omitted for virtual member functions. + PrettyFunctionNoVirtual }; private: @@ -584,8 +592,7 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - static std::string ComputeName(ASTContext &Context, IdentType IT, - const Decl *CurrentDecl); + static std::string ComputeName(IdentType IT, const Decl *CurrentDecl); virtual SourceRange getSourceRange() const { return SourceRange(Loc); } @@ -1745,7 +1752,7 @@ public: static bool classof(const Stmt *T) { StmtClass SC = T->getStmtClass(); - if (SC >= ExplicitCastExprClass && SC <= CStyleCastExprClass) + if (SC >= CStyleCastExprClass && SC <= CStyleCastExprClass) return true; if (SC >= CXXNamedCastExprClass && SC <= CXXFunctionalCastExprClass) return true; diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 6ce95ac5227f..e4bc4b746439 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -241,10 +241,17 @@ public: CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) : Expr(CXXBoolLiteralExprClass, Ty, false, false), Value(val), Loc(l) {} + explicit CXXBoolLiteralExpr(EmptyShell Empty) + : Expr(CXXBoolLiteralExprClass, Empty) { } + bool getValue() const { return Value; } + void setValue(bool V) { Value = V; } virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXBoolLiteralExprClass; } @@ -262,8 +269,14 @@ public: CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) : Expr(CXXNullPtrLiteralExprClass, Ty, false, false), Loc(l) {} + explicit CXXNullPtrLiteralExpr(EmptyShell Empty) + : Expr(CXXNullPtrLiteralExprClass, Empty) { } + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXNullPtrLiteralExprClass; } @@ -544,6 +557,68 @@ public: virtual child_iterator child_end(); }; +/// CXXBindReferenceExpr - Represents binding an expression to a reference. +/// In the example: +/// +/// 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). +class CXXBindReferenceExpr : public Expr { + // SubExpr - The expression being bound. + Stmt *SubExpr; + + // ExtendsLifetime - Whether binding this reference extends the lifetime of + // the expression being bound. FIXME: Add C++ reference. + bool ExtendsLifetime; + + /// RequiresTemporaryCopy - Whether binding the subexpression requires a + /// temporary copy. + bool RequiresTemporaryCopy; + + CXXBindReferenceExpr(Expr *subexpr, bool ExtendsLifetime, + bool RequiresTemporaryCopy) + : Expr(CXXBindReferenceExprClass, subexpr->getType(), false, false), + SubExpr(subexpr), ExtendsLifetime(ExtendsLifetime), + RequiresTemporaryCopy(RequiresTemporaryCopy) { } + ~CXXBindReferenceExpr() { } + +protected: + virtual void DoDestroy(ASTContext &C); + +public: + static CXXBindReferenceExpr *Create(ASTContext &C, Expr *SubExpr, + bool ExtendsLifetime, + bool RequiresTemporaryCopy); + + const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } + Expr *getSubExpr() { return cast<Expr>(SubExpr); } + void setSubExpr(Expr *E) { SubExpr = E; } + + virtual SourceRange getSourceRange() const { + return SubExpr->getSourceRange(); + } + + /// requiresTemporaryCopy - Whether binding the subexpression requires a + /// temporary copy. + bool requiresTemporaryCopy() const { return RequiresTemporaryCopy; } + + // extendsLifetime - Whether binding this reference extends the lifetime of + // the expression being bound. FIXME: Add C++ reference. + bool extendsLifetime() { return ExtendsLifetime; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXBindReferenceExprClass; + } + static bool classof(const CXXBindReferenceExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + /// CXXConstructExpr - Represents a call to a C++ constructor. class CXXConstructExpr : public Expr { CXXConstructorDecl *Constructor; @@ -551,6 +626,7 @@ class CXXConstructExpr : public Expr { SourceLocation Loc; bool Elidable : 1; bool ZeroInitialization : 1; + bool BaseInitialization : 1; Stmt **Args; unsigned NumArgs; @@ -559,7 +635,8 @@ protected: SourceLocation Loc, CXXConstructorDecl *d, bool elidable, Expr **args, unsigned numargs, - bool ZeroInitialization = false); + bool ZeroInitialization = false, + bool BaseInitialization = false); ~CXXConstructExpr() { } virtual void DoDestroy(ASTContext &C); @@ -573,7 +650,8 @@ public: SourceLocation Loc, CXXConstructorDecl *D, bool Elidable, Expr **Args, unsigned NumArgs, - bool ZeroInitialization = false); + bool ZeroInitialization = false, + bool BaseInitialization = false); CXXConstructorDecl* getConstructor() const { return Constructor; } @@ -593,6 +671,11 @@ public: ZeroInitialization = ZeroInit; } + /// \brief Determines whether this constructor is actually constructing + /// a base class (rather than a complete object). + bool isBaseInitialization() const { return BaseInitialization; } + void setBaseInitialization(bool BI) { BaseInitialization = BI; } + typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; @@ -779,15 +862,14 @@ class CXXNewExpr : public Expr { SourceLocation EndLoc; public: - CXXNewExpr(bool globalNew, FunctionDecl *operatorNew, Expr **placementArgs, - unsigned numPlaceArgs, bool ParenTypeId, Expr *arraySize, - CXXConstructorDecl *constructor, bool initializer, + CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, + Expr **placementArgs, unsigned numPlaceArgs, bool ParenTypeId, + Expr *arraySize, CXXConstructorDecl *constructor, bool initializer, Expr **constructorArgs, unsigned numConsArgs, FunctionDecl *operatorDelete, QualType ty, SourceLocation startLoc, SourceLocation endLoc); - ~CXXNewExpr() { - delete[] SubExprs; - } + + virtual void DoDestroy(ASTContext &C); QualType getAllocatedType() const { assert(getType()->isPointerType()); @@ -1059,33 +1141,123 @@ public: virtual child_iterator child_end(); }; -/// \brief A reference to a name which we were able to look up during -/// parsing but could not resolve to a specific declaration. This -/// arises in several ways: -/// * we might be waiting for argument-dependent lookup -/// * the name might resolve to an overloaded function -/// and eventually: -/// * the lookup might have included a function template -/// These never include UnresolvedUsingValueDecls, which are always -/// class members and therefore appear only in -/// UnresolvedMemberLookupExprs. -class UnresolvedLookupExpr : public Expr { +/// \brief A reference to an overloaded function set, either an +/// \t UnresolvedLookupExpr or an \t UnresolvedMemberExpr. +class OverloadExpr : public Expr { /// The results. These are undesugared, which is to say, they may - /// include UsingShadowDecls. + /// include UsingShadowDecls. Access is relative to the naming + /// class. UnresolvedSet<4> Results; - /// The name declared. + /// The common name of these declarations. DeclarationName Name; - /// The qualifier given, if any. + /// The scope specifier, if any. NestedNameSpecifier *Qualifier; - - /// The source range of the nested name specifier. + + /// The source range of the scope specifier. SourceRange QualifierRange; /// The location of the name. SourceLocation NameLoc; + /// True if the name was a template-id. + bool HasExplicitTemplateArgs; + +protected: + OverloadExpr(StmtClass K, 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) + {} + +public: + /// Computes whether an unresolved lookup on the given declarations + /// and optional template arguments is type- and value-dependent. + static bool ComputeDependence(UnresolvedSetIterator Begin, + UnresolvedSetIterator End, + const TemplateArgumentListInfo *Args); + + /// Finds the overloaded expression in the given expression of + /// OverloadTy. + /// + /// \return the expression (which must be there) and true if it is + /// within an address-of operator. + static llvm::PointerIntPair<OverloadExpr*,1> find(Expr *E) { + assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload)); + + bool op = false; + E = E->IgnoreParens(); + if (isa<UnaryOperator>(E)) + op = true, E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens(); + return llvm::PointerIntPair<OverloadExpr*,1>(cast<OverloadExpr>(E), op); + } + + void addDecls(UnresolvedSetIterator Begin, UnresolvedSetIterator End) { + Results.append(Begin, End); + } + + 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; } + + /// Gets the number of declarations in the unresolved set. + unsigned getNumDecls() const { return Results.size(); } + + /// Gets the name looked up. + DeclarationName getName() const { return Name; } + void setName(DeclarationName N) { Name = N; } + + /// Gets the location of the name. + SourceLocation getNameLoc() const { return NameLoc; } + void setNameLoc(SourceLocation Loc) { NameLoc = Loc; } + + /// Fetches the nested-name qualifier, if one was given. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + /// Fetches the range of the nested-name qualifier. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// \brief Determines whether this expression had an explicit + /// template argument list, e.g. f<int>. + bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } + + ExplicitTemplateArgumentList &getExplicitTemplateArgs(); // defined far below + + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { + return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs(); + } + + ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() { + if (hasExplicitTemplateArgs()) + return &getExplicitTemplateArgs(); + return 0; + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnresolvedLookupExprClass || + T->getStmtClass() == UnresolvedMemberExprClass; + } + static bool classof(const OverloadExpr *) { return true; } +}; + +/// \brief A reference to a name which we were able to look up during +/// parsing but could not resolve to a specific declaration. This +/// arises in several ways: +/// * we might be waiting for argument-dependent lookup +/// * the name might resolve to an overloaded function +/// and eventually: +/// * the lookup might have included a function template +/// These never include UnresolvedUsingValueDecls, which are always +/// class members and therefore appear only in +/// UnresolvedMemberLookupExprs. +class UnresolvedLookupExpr : public OverloadExpr { /// True if these lookup results should be extended by /// argument-dependent lookup if this is the operand of a function /// call. @@ -1095,35 +1267,40 @@ class UnresolvedLookupExpr : public Expr { /// trivially rederivable if we urgently need to kill this field. bool Overloaded; - /// True if the name looked up had explicit template arguments. - /// This requires all the results to be function templates. - bool HasExplicitTemplateArgs; + /// The naming class (C++ [class.access.base]p5) of the lookup, if + /// any. This can generally be recalculated from the context chain, + /// but that can be fairly expensive for unqualified lookups. If we + /// want to improve memory use here, this could go in a union + /// against the qualified-lookup bits. + CXXRecordDecl *NamingClass; - UnresolvedLookupExpr(QualType T, bool Dependent, + UnresolvedLookupExpr(QualType T, bool Dependent, CXXRecordDecl *NamingClass, NestedNameSpecifier *Qualifier, SourceRange QRange, DeclarationName Name, SourceLocation NameLoc, bool RequiresADL, bool Overloaded, bool HasTemplateArgs) - : Expr(UnresolvedLookupExprClass, T, Dependent, Dependent), - Name(Name), Qualifier(Qualifier), QualifierRange(QRange), - NameLoc(NameLoc), RequiresADL(RequiresADL), Overloaded(Overloaded), - HasExplicitTemplateArgs(HasTemplateArgs) + : OverloadExpr(UnresolvedLookupExprClass, T, Dependent, Qualifier, QRange, + Name, NameLoc, HasTemplateArgs), + RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass) {} public: static UnresolvedLookupExpr *Create(ASTContext &C, bool Dependent, + CXXRecordDecl *NamingClass, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, DeclarationName Name, SourceLocation NameLoc, bool ADL, bool Overloaded) { return new(C) UnresolvedLookupExpr(Dependent ? C.DependentTy : C.OverloadTy, - Dependent, Qualifier, QualifierRange, + Dependent, NamingClass, + Qualifier, QualifierRange, Name, NameLoc, ADL, Overloaded, false); } static UnresolvedLookupExpr *Create(ASTContext &C, bool Dependent, + CXXRecordDecl *NamingClass, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, DeclarationName Name, @@ -1131,20 +1308,6 @@ public: bool ADL, const TemplateArgumentListInfo &Args); - /// Computes whether an unresolved lookup on the given declarations - /// and optional template arguments is type- and value-dependent. - static bool ComputeDependence(UnresolvedSetImpl::const_iterator Begin, - UnresolvedSetImpl::const_iterator End, - const TemplateArgumentListInfo *Args); - - void addDecl(NamedDecl *Decl) { - Results.addDecl(Decl); - } - - typedef UnresolvedSetImpl::iterator decls_iterator; - decls_iterator decls_begin() const { return Results.begin(); } - decls_iterator decls_end() const { return Results.end(); } - /// True if this declaration should be extended by /// argument-dependent lookup. bool requiresADL() const { return RequiresADL; } @@ -1152,25 +1315,20 @@ public: /// True if this lookup is overloaded. bool isOverloaded() const { return Overloaded; } - /// Fetches the name looked up. - DeclarationName getName() const { return Name; } - - /// Gets the location of the name. - SourceLocation getNameLoc() const { return NameLoc; } - - /// Fetches the nested-name qualifier, if one was given. - NestedNameSpecifier *getQualifier() const { return Qualifier; } - - /// Fetches the range of the nested-name qualifier. - SourceRange getQualifierRange() const { return QualifierRange; } - - /// Determines whether this lookup had explicit template arguments. - bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } + /// Gets the 'naming class' (in the sense of C++0x + /// [class.access.base]p5) of the lookup. This is the scope + /// that was looked in to find these results. + CXXRecordDecl *getNamingClass() const { return NamingClass; } // Note that, inconsistently with the explicit-template-argument AST // nodes, users are *forbidden* from calling these methods on objects // without explicit template arguments. + ExplicitTemplateArgumentList &getExplicitTemplateArgs() { + assert(hasExplicitTemplateArgs()); + return *reinterpret_cast<ExplicitTemplateArgumentList*>(this + 1); + } + /// Gets a reference to the explicit template argument list. const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { assert(hasExplicitTemplateArgs()); @@ -1200,8 +1358,8 @@ public: } virtual SourceRange getSourceRange() const { - SourceRange Range(NameLoc); - if (Qualifier) Range.setBegin(QualifierRange.getBegin()); + SourceRange Range(getNameLoc()); + if (getQualifier()) Range.setBegin(getQualifierRange().getBegin()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); return Range; } @@ -1456,11 +1614,24 @@ public: arg_iterator arg_begin() { return reinterpret_cast<Expr**>(this + 1); } arg_iterator arg_end() { return arg_begin() + NumArgs; } + typedef const Expr* const * const_arg_iterator; + const_arg_iterator arg_begin() const { + return reinterpret_cast<const Expr* const *>(this + 1); + } + const_arg_iterator arg_end() const { + return arg_begin() + NumArgs; + } + Expr *getArg(unsigned I) { assert(I < NumArgs && "Argument index out-of-range"); return *(arg_begin() + I); } + const Expr *getArg(unsigned I) const { + assert(I < NumArgs && "Argument index out-of-range"); + return *(arg_begin() + I); + } + virtual SourceRange getSourceRange() const { return SourceRange(TyBeginLoc, RParenLoc); } @@ -1713,19 +1884,7 @@ public: /// In the final AST, an explicit access always becomes a MemberExpr. /// An implicit access may become either a MemberExpr or a /// DeclRefExpr, depending on whether the member is static. -class UnresolvedMemberExpr : public Expr { - /// The results. These are undesugared, which is to say, they may - /// include UsingShadowDecls. - UnresolvedSet<4> Results; - - /// \brief The expression for the base pointer or class reference, - /// e.g., the \c x in x.f. This can be null if this is an 'unbased' - /// member expression - Stmt *Base; - - /// \brief The type of the base expression; never null. - QualType BaseType; - +class UnresolvedMemberExpr : public OverloadExpr { /// \brief Whether this member expression used the '->' operator or /// the '.' operator. bool IsArrow : 1; @@ -1734,39 +1893,17 @@ class UnresolvedMemberExpr : public Expr { /// declaration. bool HasUnresolvedUsing : 1; - /// \brief Whether this member expression has explicitly-specified template - /// arguments. - bool HasExplicitTemplateArgs : 1; + /// \brief The expression for the base pointer or class reference, + /// e.g., the \c x in x.f. This can be null if this is an 'unbased' + /// member expression + Stmt *Base; + + /// \brief The type of the base expression; never null. + QualType BaseType; /// \brief The location of the '->' or '.' operator. SourceLocation OperatorLoc; - /// \brief The nested-name-specifier that precedes the member name, if any. - NestedNameSpecifier *Qualifier; - - /// \brief The source range covering the nested name specifier. - SourceRange QualifierRange; - - /// \brief The member to which this member expression refers, which - /// can be a name or an overloaded operator. - DeclarationName MemberName; - - /// \brief The location of the member name. - SourceLocation MemberLoc; - - /// \brief Retrieve the explicit template argument list that followed the - /// member template name. - ExplicitTemplateArgumentList *getExplicitTemplateArgs() { - assert(HasExplicitTemplateArgs); - return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); - } - - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - const ExplicitTemplateArgumentList *getExplicitTemplateArgs() const { - return const_cast<UnresolvedMemberExpr*>(this)->getExplicitTemplateArgs(); - } - UnresolvedMemberExpr(QualType T, bool Dependent, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, @@ -1788,19 +1925,6 @@ public: SourceLocation MemberLoc, const TemplateArgumentListInfo *TemplateArgs); - /// Adds a declaration to the unresolved set. By assumption, all of - /// these happen at initialization time and properties like - /// 'Dependent' and 'HasUnresolvedUsing' take them into account. - void addDecl(NamedDecl *Decl) { - Results.addDecl(Decl); - } - - typedef UnresolvedSetImpl::iterator decls_iterator; - decls_iterator decls_begin() const { return Results.begin(); } - decls_iterator decls_end() const { return Results.end(); } - - unsigned getNumDecls() const { return Results.size(); } - /// \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 /// location of the operator is invalid in this case. @@ -1812,6 +1936,10 @@ public: assert(!isImplicitAccess()); return cast<Expr>(Base); } + const Expr *getBase() const { + assert(!isImplicitAccess()); + return cast<Expr>(Base); + } void setBase(Expr *E) { Base = E; } QualType getBaseType() const { return BaseType; } @@ -1825,57 +1953,60 @@ public: SourceLocation getOperatorLoc() const { return OperatorLoc; } void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } - /// \brief Retrieve the nested-name-specifier that qualifies the member - /// name. - NestedNameSpecifier *getQualifier() const { return Qualifier; } - - /// \brief Retrieve the source range covering the nested-name-specifier - /// that qualifies the member name. - SourceRange getQualifierRange() const { return QualifierRange; } + /// \brief Retrieves the naming class of this lookup. + CXXRecordDecl *getNamingClass() const; /// \brief Retrieve the name of the member that this expression /// refers to. - DeclarationName getMemberName() const { return MemberName; } - void setMemberName(DeclarationName N) { MemberName = N; } + DeclarationName getMemberName() const { return getName(); } + void setMemberName(DeclarationName N) { setName(N); } // \brief Retrieve the location of the name of the member that this // expression refers to. - SourceLocation getMemberLoc() const { return MemberLoc; } - void setMemberLoc(SourceLocation L) { MemberLoc = L; } + SourceLocation getMemberLoc() const { return getNameLoc(); } + void setMemberLoc(SourceLocation L) { setNameLoc(L); } - /// \brief Determines whether this member expression actually had a C++ - /// template argument list explicitly specified, e.g., x.f<int>. - bool hasExplicitTemplateArgs() const { - return HasExplicitTemplateArgs; + /// \brief Retrieve the explicit template argument list that followed the + /// member template name. + ExplicitTemplateArgumentList &getExplicitTemplateArgs() { + assert(hasExplicitTemplateArgs()); + return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { + assert(hasExplicitTemplateArgs()); + return *reinterpret_cast<const ExplicitTemplateArgumentList *>(this + 1); } /// \brief Copies the template arguments into the given structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - getExplicitTemplateArgs()->copyInto(List); + getExplicitTemplateArgs().copyInto(List); } /// \brief Retrieve the location of the left angle bracket following /// the member name ('<'). SourceLocation getLAngleLoc() const { - return getExplicitTemplateArgs()->LAngleLoc; + return getExplicitTemplateArgs().LAngleLoc; } /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { - return getExplicitTemplateArgs()->getTemplateArgs(); + return getExplicitTemplateArgs().getTemplateArgs(); } /// \brief Retrieve the number of template arguments provided as /// part of this template-id. unsigned getNumTemplateArgs() const { - return getExplicitTemplateArgs()->NumTemplateArgs; + return getExplicitTemplateArgs().NumTemplateArgs; } /// \brief Retrieve the location of the right angle bracket /// following the template arguments ('>'). SourceLocation getRAngleLoc() const { - return getExplicitTemplateArgs()->RAngleLoc; + return getExplicitTemplateArgs().RAngleLoc; } virtual SourceRange getSourceRange() const { @@ -1885,12 +2016,12 @@ public: else if (getQualifier()) Range.setBegin(getQualifierRange().getBegin()); else - Range.setBegin(MemberLoc); + Range.setBegin(getMemberLoc()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); else - Range.setEnd(MemberLoc); + Range.setEnd(getMemberLoc()); return Range; } @@ -1904,6 +2035,13 @@ public: virtual child_iterator child_end(); }; +inline ExplicitTemplateArgumentList &OverloadExpr::getExplicitTemplateArgs() { + if (isa<UnresolvedLookupExpr>(this)) + return cast<UnresolvedLookupExpr>(this)->getExplicitTemplateArgs(); + else + return cast<UnresolvedMemberExpr>(this)->getExplicitTemplateArgs(); +} + } // end namespace clang #endif diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 0b0cd64ad721..df39b535eb3e 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -367,7 +367,7 @@ class ObjCMessageExpr : public Expr { public: /// This constructor is used to represent class messages where the /// ObjCInterfaceDecl* of the receiver is not known. - ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo, + ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName, Selector selInfo, QualType retType, ObjCMethodDecl *methDecl, SourceLocation LBrac, SourceLocation RBrac, Expr **ArgExprs, unsigned NumArgs); @@ -375,13 +375,13 @@ public: /// This constructor is used to represent class messages where the /// ObjCInterfaceDecl* of the receiver is known. // FIXME: clsName should be typed to ObjCInterfaceType - ObjCMessageExpr(ObjCInterfaceDecl *cls, Selector selInfo, + ObjCMessageExpr(ASTContext &C, ObjCInterfaceDecl *cls, Selector selInfo, QualType retType, ObjCMethodDecl *methDecl, SourceLocation LBrac, SourceLocation RBrac, Expr **ArgExprs, unsigned NumArgs); // constructor for instance messages. - ObjCMessageExpr(Expr *receiver, Selector selInfo, + ObjCMessageExpr(ASTContext &C, Expr *receiver, Selector selInfo, QualType retType, ObjCMethodDecl *methDecl, SourceLocation LBrac, SourceLocation RBrac, Expr **ArgExprs, unsigned NumArgs); @@ -389,9 +389,7 @@ public: explicit ObjCMessageExpr(EmptyShell Empty) : Expr(ObjCMessageExprClass, Empty), SubExprs(0), NumArgs(0) {} - ~ObjCMessageExpr() { - delete [] SubExprs; - } + virtual void DoDestroy(ASTContext &C); /// getReceiver - Returns the receiver of the message expression. /// This can be NULL if the message is for class methods. For diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index d058f838a008..94caa6faad66 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -102,6 +102,7 @@ public: #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" }; private: @@ -1120,21 +1121,27 @@ class AsmStmt : public Stmt { unsigned NumOutputs; unsigned NumInputs; + unsigned NumClobbers; - llvm::SmallVector<std::string, 4> Names; - llvm::SmallVector<StringLiteral*, 4> Constraints; - llvm::SmallVector<Stmt*, 4> Exprs; + // FIXME: If we wanted to, we could allocate all of these in one big array. + IdentifierInfo **Names; + StringLiteral **Constraints; + Stmt **Exprs; + StringLiteral **Clobbers; - llvm::SmallVector<StringLiteral*, 4> Clobbers; +protected: + virtual void DoDestroy(ASTContext &Ctx); + public: - AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile, bool msasm, - unsigned numoutputs, unsigned numinputs, - std::string *names, StringLiteral **constraints, + AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile, + bool msasm, unsigned numoutputs, unsigned numinputs, + IdentifierInfo **names, StringLiteral **constraints, Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, StringLiteral **clobbers, SourceLocation rparenloc); /// \brief Build an empty inline-assembly statement. - explicit AsmStmt(EmptyShell Empty) : Stmt(AsmStmtClass, Empty) { } + explicit AsmStmt(EmptyShell Empty) : Stmt(AsmStmtClass, Empty), + Names(0), Constraints(0), Exprs(0), Clobbers(0) { } SourceLocation getAsmLoc() const { return AsmLoc; } void setAsmLoc(SourceLocation L) { AsmLoc = L; } @@ -1208,14 +1215,21 @@ public: unsigned getNumOutputs() const { return NumOutputs; } - const std::string &getOutputName(unsigned i) const { + IdentifierInfo *getOutputIdentifier(unsigned i) const { return Names[i]; } + llvm::StringRef getOutputName(unsigned i) const { + if (IdentifierInfo *II = getOutputIdentifier(i)) + return II->getName(); + + return llvm::StringRef(); + } + /// getOutputConstraint - Return the constraint string for the specified /// output operand. All output constraints are known to be non-empty (either /// '=' or '+'). - std::string getOutputConstraint(unsigned i) const; + llvm::StringRef getOutputConstraint(unsigned i) const; const StringLiteral *getOutputConstraintLiteral(unsigned i) const { return Constraints[i]; @@ -1224,7 +1238,6 @@ public: return Constraints[i]; } - Expr *getOutputExpr(unsigned i); const Expr *getOutputExpr(unsigned i) const { @@ -1246,13 +1259,20 @@ public: unsigned getNumInputs() const { return NumInputs; } - const std::string &getInputName(unsigned i) const { + IdentifierInfo *getInputIdentifier(unsigned i) const { return Names[i + NumOutputs]; } + llvm::StringRef getInputName(unsigned i) const { + if (IdentifierInfo *II = getInputIdentifier(i)) + return II->getName(); + + return llvm::StringRef(); + } + /// getInputConstraint - Return the specified input constraint. Unlike output /// constraints, these can be empty. - std::string getInputConstraint(unsigned i) const; + llvm::StringRef getInputConstraint(unsigned i) const; const StringLiteral *getInputConstraintLiteral(unsigned i) const { return Constraints[i + NumOutputs]; @@ -1261,32 +1281,31 @@ public: return Constraints[i + NumOutputs]; } - Expr *getInputExpr(unsigned i); const Expr *getInputExpr(unsigned i) const { return const_cast<AsmStmt*>(this)->getInputExpr(i); } - void setOutputsAndInputs(unsigned NumOutputs, - unsigned NumInputs, - const std::string *Names, - StringLiteral **Constraints, - Stmt **Exprs); + void setOutputsAndInputsAndClobbers(ASTContext &C, + IdentifierInfo **Names, + StringLiteral **Constraints, + Stmt **Exprs, + unsigned NumOutputs, + unsigned NumInputs, + StringLiteral **Clobbers, + unsigned NumClobbers); //===--- Other ---===// /// getNamedOperand - Given a symbolic operand reference like %[foo], /// translate this into a numeric value needed to reference the same operand. /// This returns -1 if the operand name is invalid. - int getNamedOperand(const std::string &SymbolicName) const; - + int getNamedOperand(llvm::StringRef SymbolicName) const; - - unsigned getNumClobbers() const { return Clobbers.size(); } + unsigned getNumClobbers() const { return NumClobbers; } StringLiteral *getClobber(unsigned i) { return Clobbers[i]; } const StringLiteral *getClobber(unsigned i) const { return Clobbers[i]; } - void setClobbers(StringLiteral **Clobbers, unsigned NumClobbers); virtual SourceRange getSourceRange() const { return SourceRange(AsmLoc, RParenLoc); @@ -1301,19 +1320,19 @@ public: typedef ConstExprIterator const_inputs_iterator; inputs_iterator begin_inputs() { - return Exprs.data() + NumOutputs; + return &Exprs[0] + NumOutputs; } inputs_iterator end_inputs() { - return Exprs.data() + NumOutputs + NumInputs; + return &Exprs[0] + NumOutputs + NumInputs; } const_inputs_iterator begin_inputs() const { - return Exprs.data() + NumOutputs; + return &Exprs[0] + NumOutputs; } const_inputs_iterator end_inputs() const { - return Exprs.data() + NumOutputs + NumInputs; + return &Exprs[0] + NumOutputs + NumInputs; } // Output expr iterators. @@ -1322,27 +1341,17 @@ public: typedef ConstExprIterator const_outputs_iterator; outputs_iterator begin_outputs() { - return Exprs.data(); + return &Exprs[0]; } outputs_iterator end_outputs() { - return Exprs.data() + NumOutputs; + return &Exprs[0] + NumOutputs; } const_outputs_iterator begin_outputs() const { - return Exprs.data(); + return &Exprs[0]; } const_outputs_iterator end_outputs() const { - return Exprs.data() + NumOutputs; - } - - // Input name iterator. - - const std::string *begin_output_names() const { - return &Names[0]; - } - - const std::string *end_output_names() const { - return &Names[0] + NumOutputs; + return &Exprs[0] + NumOutputs; } // Child iterators diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index 09ea4ca2101b..4e87c2701c26 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -59,31 +59,42 @@ public: /// class CXXTryStmt : public Stmt { SourceLocation TryLoc; - // First place is the guarded CompoundStatement. Subsequent are the handlers. - // More than three handlers should be rare. - llvm::SmallVector<Stmt*, 4> Stmts; + unsigned NumHandlers; + + CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers, + unsigned numHandlers); public: - CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, - Stmt **handlers, unsigned numHandlers); + static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc, + Stmt *tryBlock, Stmt **handlers, + unsigned numHandlers); virtual SourceRange getSourceRange() const { return SourceRange(getTryLoc(), getEndLoc()); } SourceLocation getTryLoc() const { return TryLoc; } - SourceLocation getEndLoc() const { return Stmts.back()->getLocEnd(); } + SourceLocation getEndLoc() const { + Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1); + return Stmts[NumHandlers]->getLocEnd(); + } - CompoundStmt *getTryBlock() { return llvm::cast<CompoundStmt>(Stmts[0]); } + CompoundStmt *getTryBlock() { + Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1); + return llvm::cast<CompoundStmt>(Stmts[0]); + } const CompoundStmt *getTryBlock() const { + Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1); return llvm::cast<CompoundStmt>(Stmts[0]); } - unsigned getNumHandlers() const { return Stmts.size() - 1; } + unsigned getNumHandlers() const { return NumHandlers; } CXXCatchStmt *getHandler(unsigned i) { + Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1); return llvm::cast<CXXCatchStmt>(Stmts[i + 1]); } const CXXCatchStmt *getHandler(unsigned i) const { + Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1); return llvm::cast<CXXCatchStmt>(Stmts[i + 1]); } diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index 7102336180cf..ec6149e55f11 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -68,8 +68,7 @@ STMT(CXXTryStmt , Stmt) LAST_STMT(CXXTryStmt) // Expressions. -ABSTRACT_EXPR(Expr , Stmt) -FIRST_EXPR(Expr) +ABSTRACT_EXPR(Expr , Stmt) EXPR(PredefinedExpr , Expr) EXPR(DeclRefExpr , Expr) EXPR(IntegerLiteral , Expr) @@ -83,12 +82,12 @@ EXPR(SizeOfAlignOfExpr , Expr) EXPR(ArraySubscriptExpr , Expr) EXPR(CallExpr , Expr) EXPR(MemberExpr , Expr) -EXPR(CastExpr , Expr) +ABSTRACT_EXPR(CastExpr , Expr) EXPR(BinaryOperator , Expr) EXPR(CompoundAssignOperator, BinaryOperator) EXPR(ConditionalOperator , Expr) EXPR(ImplicitCastExpr , CastExpr) -EXPR(ExplicitCastExpr , CastExpr) +ABSTRACT_EXPR(ExplicitCastExpr, CastExpr) EXPR(CStyleCastExpr , ExplicitCastExpr) EXPR(CompoundLiteralExpr , Expr) EXPR(ExtVectorElementExpr , Expr) @@ -129,6 +128,7 @@ EXPR(UnaryTypeTraitExpr , Expr) EXPR(DependentScopeDeclRefExpr , Expr) EXPR(CXXConstructExpr , Expr) EXPR(CXXBindTemporaryExpr , Expr) +EXPR(CXXBindReferenceExpr , Expr) EXPR(CXXExprWithTemporaries , Expr) EXPR(CXXTemporaryObjectExpr , CXXConstructExpr) EXPR(CXXUnresolvedConstructExpr, Expr) @@ -152,6 +152,7 @@ EXPR(ShuffleVectorExpr , Expr) EXPR(BlockExpr , Expr) EXPR(BlockDeclRefExpr , Expr) +FIRST_EXPR(PredefinedExpr) LAST_EXPR(BlockDeclRefExpr) #undef ABSTRACT_EXPR diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h index 3a525507dad3..4986f08ac124 100644 --- a/include/clang/AST/StmtVisitor.h +++ b/include/clang/AST/StmtVisitor.h @@ -105,6 +105,7 @@ 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 STMT(CLASS, PARENT) \ case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS); #include "clang/AST/StmtNodes.def" diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index b7b60df5acb4..40e50988e6d2 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -16,6 +16,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/Linkage.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateName.h" #include "llvm/Support/Casting.h" @@ -750,24 +751,22 @@ class Type { public: enum TypeClass { #define TYPE(Class, Base) Class, +#define LAST_TYPE(Class) TypeLast = Class, #define ABSTRACT_TYPE(Class, Base) #include "clang/AST/TypeNodes.def" TagFirst = Record, TagLast = Enum }; -protected: - enum { TypeClassBitSize = 6 }; - private: QualType CanonicalType; - /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]). - bool Dependent : 1; - /// TypeClass bitfield - Enum that specifies what subclass this belongs to. + unsigned TC : 8; + + /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]). /// Note that this should stay at the end of the ivars for Type so that /// subclasses can pack their bitfields into the same word. - unsigned TC : TypeClassBitSize; + bool Dependent : 1; Type(const Type&); // DO NOT IMPLEMENT. void operator=(const Type&); // DO NOT IMPLEMENT. @@ -776,7 +775,7 @@ protected: Type *this_() { return this; } Type(TypeClass tc, QualType Canonical, bool dependent) : CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical), - Dependent(dependent), TC(tc) {} + TC(tc), Dependent(dependent) {} virtual ~Type() {} virtual void Destroy(ASTContext& C); friend class ASTContext; @@ -974,6 +973,9 @@ public: const char *getTypeClassName() const; + /// \brief Determine the linkage of this type. + virtual Linkage getLinkage() const; + QualType getCanonicalTypeInternal() const { return CanonicalType; } void dump() const; static bool classof(const Type *) { return true; } @@ -1062,6 +1064,8 @@ 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 +1093,8 @@ 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; } }; @@ -1116,6 +1122,8 @@ 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; } }; @@ -1146,6 +1154,8 @@ public: ID.AddPointer(Pointee.getAsOpaquePtr()); } + virtual Linkage getLinkage() const; + static bool classof(const Type *T) { return T->getTypeClass() == BlockPointer; } @@ -1183,7 +1193,8 @@ protected: } public: bool isSpelledAsLValue() const { return SpelledAsLValue; } - + bool isInnerRef() const { return InnerRef; } + QualType getPointeeTypeAsWritten() const { return PointeeType; } QualType getPointeeType() const { // FIXME: this might strip inner qualifiers; okay? @@ -1203,6 +1214,8 @@ public: ID.AddBoolean(SpelledAsLValue); } + virtual Linkage getLinkage() const; + static bool classof(const Type *T) { return T->getTypeClass() == LValueReference || T->getTypeClass() == RValueReference; @@ -1277,6 +1290,8 @@ public: ID.AddPointer(Class); } + virtual Linkage getLinkage() const; + static bool classof(const Type *T) { return T->getTypeClass() == MemberPointer; } @@ -1328,6 +1343,8 @@ public: } unsigned getIndexTypeCVRQualifiers() const { return IndexTypeQuals; } + virtual Linkage getLinkage() const; + static bool classof(const Type *T) { return T->getTypeClass() == ConstantArray || T->getTypeClass() == VariableArray || @@ -1576,7 +1593,8 @@ public: /// VectorType - GCC generic vector type. This type is created using /// __attribute__((vector_size(n)), where "n" specifies the vector size in -/// bytes. Since the constructor takes the number of vector elements, the +/// bytes; or from an Altivec __vector or vector declaration. +/// Since the constructor takes the number of vector elements, the /// client is responsible for converting the size into the number of elements. class VectorType : public Type, public llvm::FoldingSetNode { protected: @@ -1586,13 +1604,21 @@ protected: /// NumElements - The number of elements in the vector. unsigned NumElements; - VectorType(QualType vecType, unsigned nElements, QualType canonType) : + /// AltiVec - True if this is for an Altivec vector. + bool AltiVec; + + /// Pixel - True if this is for an Altivec vector pixel. + bool Pixel; + + VectorType(QualType vecType, unsigned nElements, QualType canonType, + bool isAltiVec, bool isPixel) : Type(Vector, canonType, vecType->isDependentType()), - ElementType(vecType), NumElements(nElements) {} + ElementType(vecType), NumElements(nElements), + AltiVec(isAltiVec), Pixel(isPixel) {} VectorType(TypeClass tc, QualType vecType, unsigned nElements, - QualType canonType) + QualType canonType, bool isAltiVec, bool isPixel) : Type(tc, canonType, vecType->isDependentType()), ElementType(vecType), - NumElements(nElements) {} + NumElements(nElements), AltiVec(isAltiVec), Pixel(isPixel) {} friend class ASTContext; // ASTContext creates these. public: @@ -1602,15 +1628,26 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } + bool isAltiVec() const { return AltiVec; } + + bool isPixel() const { return Pixel; } + void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getElementType(), getNumElements(), getTypeClass()); + Profile(ID, getElementType(), getNumElements(), getTypeClass(), + AltiVec, Pixel); } static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType, - unsigned NumElements, TypeClass TypeClass) { + unsigned NumElements, TypeClass TypeClass, + bool isAltiVec, bool isPixel) { ID.AddPointer(ElementType.getAsOpaquePtr()); ID.AddInteger(NumElements); ID.AddInteger(TypeClass); + ID.AddBoolean(isAltiVec); + ID.AddBoolean(isPixel); } + + virtual Linkage getLinkage() const; + static bool classof(const Type *T) { return T->getTypeClass() == Vector || T->getTypeClass() == ExtVector; } @@ -1624,7 +1661,7 @@ public: /// points, colors, and textures (modeled after OpenGL Shading Language). class ExtVectorType : public VectorType { ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) : - VectorType(ExtVector, vecType, nElements, canonType) {} + VectorType(ExtVector, vecType, nElements, canonType, false, false) {} friend class ASTContext; // ASTContext creates these. public: static int getPointAccessorIdx(char c) { @@ -1723,6 +1760,8 @@ public: bool getNoReturnAttr() const { return NoReturn; } CallingConv getCallConv() const { return (CallingConv)CallConv; } + static llvm::StringRef getNameForCallConv(CallingConv CC); + static bool classof(const Type *T) { return T->getTypeClass() == FunctionNoProto || T->getTypeClass() == FunctionProto; @@ -1745,14 +1784,17 @@ public: QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getResultType(), getNoReturnAttr()); + Profile(ID, getResultType(), getNoReturnAttr(), getCallConv()); } static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType, - bool NoReturn) { + bool NoReturn, CallingConv CallConv) { + ID.AddInteger(CallConv); ID.AddInteger(NoReturn); ID.AddPointer(ResultType.getAsOpaquePtr()); } + virtual Linkage getLinkage() const; + static bool classof(const Type *T) { return T->getTypeClass() == FunctionNoProto; } @@ -1856,6 +1898,8 @@ 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; } @@ -1867,7 +1911,7 @@ public: bool isVariadic, unsigned TypeQuals, bool hasExceptionSpec, bool anyExceptionSpec, unsigned NumExceptions, exception_iterator Exs, - bool NoReturn); + bool NoReturn, CallingConv CallConv); }; @@ -1878,8 +1922,9 @@ public: class UnresolvedUsingType : public Type { UnresolvedUsingTypenameDecl *Decl; - UnresolvedUsingType(UnresolvedUsingTypenameDecl *D) - : Type(UnresolvedUsing, QualType(), true), Decl(D) {} + UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D) + : Type(UnresolvedUsing, QualType(), true), + Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {} friend class ASTContext; // ASTContext creates these. public: @@ -1906,8 +1951,9 @@ public: class TypedefType : public Type { TypedefDecl *Decl; protected: - TypedefType(TypeClass tc, TypedefDecl *D, QualType can) - : Type(tc, can, can->isDependentType()), Decl(D) { + TypedefType(TypeClass tc, const TypedefDecl *D, QualType can) + : Type(tc, can, can->isDependentType()), + Decl(const_cast<TypedefDecl*>(D)) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); } friend class ASTContext; // ASTContext creates these. @@ -1950,8 +1996,12 @@ public: static bool classof(const TypeOfExprType *) { return true; } }; -/// Subclass of TypeOfExprType that is used for canonical, dependent +/// \brief Internal representation of canonical, dependent /// typeof(expr) types. +/// +/// This class is used internally by the ASTContext to manage +/// canonical, dependent types, only. Clients will only see instances +/// of this class via TypeOfExprType nodes. class DependentTypeOfExprType : public TypeOfExprType, public llvm::FoldingSetNode { ASTContext &Context; @@ -2018,8 +2068,12 @@ public: static bool classof(const DecltypeType *) { return true; } }; -/// Subclass of DecltypeType that is used for canonical, dependent -/// C++0x decltype types. +/// \brief Internal representation of canonical, dependent +/// decltype(expr) types. +/// +/// This class is used internally by the ASTContext to manage +/// canonical, dependent types, only. Clients will only see instances +/// of this class via DecltypeType nodes. class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode { ASTContext &Context; @@ -2048,7 +2102,7 @@ class TagType : public Type { friend class TagDecl; protected: - TagType(TypeClass TC, TagDecl *D, QualType can); + TagType(TypeClass TC, const TagDecl *D, QualType can); public: TagDecl *getDecl() const { return decl.getPointer(); } @@ -2058,6 +2112,8 @@ 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; } @@ -2070,10 +2126,10 @@ public: /// to detect TagType objects of structs/unions/classes. class RecordType : public TagType { protected: - explicit RecordType(RecordDecl *D) - : TagType(Record, reinterpret_cast<TagDecl*>(D), QualType()) { } + explicit RecordType(const RecordDecl *D) + : TagType(Record, reinterpret_cast<const TagDecl*>(D), QualType()) { } explicit RecordType(TypeClass TC, RecordDecl *D) - : TagType(TC, reinterpret_cast<TagDecl*>(D), QualType()) { } + : TagType(TC, reinterpret_cast<const TagDecl*>(D), QualType()) { } friend class ASTContext; // ASTContext creates these. public: @@ -2103,8 +2159,8 @@ public: /// EnumType - This is a helper class that allows the use of isa/cast/dyncast /// to detect TagType objects of enums. class EnumType : public TagType { - explicit EnumType(EnumDecl *D) - : TagType(Enum, reinterpret_cast<TagDecl*>(D), QualType()) { } + explicit EnumType(const EnumDecl *D) + : TagType(Enum, reinterpret_cast<const TagDecl*>(D), QualType()) { } friend class ASTContext; // ASTContext creates these. public: @@ -2512,12 +2568,12 @@ public: class ObjCInterfaceType : public Type, public llvm::FoldingSetNode { ObjCInterfaceDecl *Decl; - // List of protocols for this protocol conforming object type - // List is sorted on protocol name. No protocol is enterred more than once. - ObjCProtocolDecl **Protocols; + /// \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; - ObjCInterfaceType(ASTContext &Ctx, QualType Canonical, ObjCInterfaceDecl *D, + ObjCInterfaceType(QualType Canonical, ObjCInterfaceDecl *D, ObjCProtocolDecl **Protos, unsigned NumP); friend class ASTContext; // ASTContext creates these. public: @@ -2529,14 +2585,20 @@ public: /// interface type, or 0 if there are none. unsigned getNumProtocols() const { return NumProtocols; } + /// \brief Retrieve the Ith protocol. + 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 Protocols; + return reinterpret_cast<qual_iterator>(this + 1); } qual_iterator qual_end() const { - return Protocols ? Protocols + NumProtocols : 0; + return qual_begin() + NumProtocols; } bool qual_empty() const { return NumProtocols == 0; } @@ -2546,7 +2608,10 @@ public: void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, const ObjCInterfaceDecl *Decl, - ObjCProtocolDecl **protocols, unsigned NumProtocols); + ObjCProtocolDecl * const *protocols, + unsigned NumProtocols); + + virtual Linkage getLinkage() const; static bool classof(const Type *T) { return T->getTypeClass() == ObjCInterface; @@ -2562,12 +2627,14 @@ public: class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { QualType PointeeType; // A builtin or interface type. - // List of protocols for this protocol conforming object type - // List is sorted on protocol name. No protocol is entered more than once. - ObjCProtocolDecl **Protocols; + /// \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; - ObjCObjectPointerType(ASTContext &Ctx, QualType Canonical, QualType T, + ObjCObjectPointerType(QualType Canonical, QualType T, ObjCProtocolDecl **Protos, unsigned NumP); friend class ASTContext; // ASTContext creates these. @@ -2614,10 +2681,10 @@ public: typedef ObjCProtocolDecl* const * qual_iterator; qual_iterator qual_begin() const { - return Protocols; + return reinterpret_cast<qual_iterator> (this + 1); } qual_iterator qual_end() const { - return Protocols ? Protocols + NumProtocols : NULL; + return qual_begin() + NumProtocols; } bool qual_empty() const { return NumProtocols == 0; } @@ -2625,12 +2692,21 @@ public: /// interface type, or 0 if there are none. unsigned getNumProtocols() const { return NumProtocols; } + /// \brief Retrieve the Ith protocol. + ObjCProtocolDecl *getProtocol(unsigned I) const { + assert(I < getNumProtocols() && "Out-of-range protocol access"); + return qual_begin()[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 **protocols, unsigned NumProtocols); + ObjCProtocolDecl *const *protocols, + unsigned NumProtocols); static bool classof(const Type *T) { return T->getTypeClass() == ObjCObjectPointer; } diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 575011a8724c..9cf2cb7bd773 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -87,6 +87,11 @@ DEPENDENT_TYPE(Typename, Type) TYPE(ObjCInterface, Type) TYPE(ObjCObjectPointer, Type) +#ifdef LAST_TYPE +LAST_TYPE(ObjCObjectPointer) +#undef LAST_TYPE +#endif + // These types are always leaves in the type hierarchy. #ifdef LEAF_TYPE LEAF_TYPE(Enum) diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h index 055d15264674..9c59229e3134 100644 --- a/include/clang/AST/UnresolvedSet.h +++ b/include/clang/AST/UnresolvedSet.h @@ -16,7 +16,6 @@ #define LLVM_CLANG_AST_UNRESOLVEDSET_H #include <iterator> -#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" #include "clang/Basic/Specifiers.h" @@ -24,12 +23,58 @@ namespace clang { class NamedDecl; +/// A POD class for pairing a NamedDecl* with an access specifier. +/// Can be put into unions. +class DeclAccessPair { + NamedDecl *Ptr; // we'd use llvm::PointerUnion, but it isn't trivial + + enum { Mask = 0x3 }; + +public: + static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS) { + DeclAccessPair p; + p.set(D, AS); + return p; + } + + NamedDecl *getDecl() const { + return (NamedDecl*) (~Mask & (uintptr_t) Ptr); + } + AccessSpecifier getAccess() const { + return AccessSpecifier(Mask & (uintptr_t) Ptr); + } + + void setDecl(NamedDecl *D) { + set(D, getAccess()); + } + void setAccess(AccessSpecifier AS) { + set(getDecl(), AS); + } + void set(NamedDecl *D, AccessSpecifier AS) { + Ptr = reinterpret_cast<NamedDecl*>(uintptr_t(AS) | + reinterpret_cast<uintptr_t>(D)); + } + + operator NamedDecl*() const { return getDecl(); } + NamedDecl *operator->() const { return getDecl(); } +}; +} + +// Take a moment to tell SmallVector that this is POD. +namespace llvm { +template<typename> struct isPodLike; +template<> struct isPodLike<clang::DeclAccessPair> { + static const bool value = true; +}; +} + +namespace clang { + /// The iterator over UnresolvedSets. Serves as both the const and /// non-const iterator. class UnresolvedSetIterator { - - typedef llvm::PointerIntPair<NamedDecl*, 2> DeclEntry; - typedef llvm::SmallVectorImpl<DeclEntry> DeclsTy; +private: + typedef llvm::SmallVectorImpl<DeclAccessPair> DeclsTy; typedef DeclsTy::iterator IteratorTy; IteratorTy ir; @@ -47,8 +92,8 @@ public: typedef NamedDecl *reference; typedef std::iterator_traits<IteratorTy>::iterator_category iterator_category; - NamedDecl *getDecl() const { return ir->getPointer(); } - AccessSpecifier getAccess() const { return AccessSpecifier(ir->getInt()); } + NamedDecl *getDecl() const { return ir->getDecl(); } + AccessSpecifier getAccess() const { return ir->getAccess(); } NamedDecl *operator*() const { return getDecl(); } @@ -87,7 +132,6 @@ public: /// in a lot of places, but isn't really worth breaking into its own /// header right now. class UnresolvedSetImpl { - typedef UnresolvedSetIterator::DeclEntry DeclEntry; typedef UnresolvedSetIterator::DeclsTy DeclsTy; // Don't allow direct construction, and only permit subclassing by @@ -114,7 +158,7 @@ public: } void addDecl(NamedDecl *D, AccessSpecifier AS) { - decls().push_back(DeclEntry(D, AS)); + decls().push_back(DeclAccessPair::make(D, AS)); } /// Replaces the given declaration with the new one, once. @@ -122,19 +166,24 @@ public: /// \return true if the set changed bool replace(const NamedDecl* Old, NamedDecl *New) { for (DeclsTy::iterator I = decls().begin(), E = decls().end(); I != E; ++I) - if (I->getPointer() == Old) - return (I->setPointer(New), true); + if (I->getDecl() == Old) + return (I->setDecl(New), true); return false; } /// Replaces the declaration at the given iterator with the new one, /// preserving the original access bits. void replace(iterator I, NamedDecl *New) { - I.ir->setPointer(New); + I.ir->setDecl(New); } void replace(iterator I, NamedDecl *New, AccessSpecifier AS) { - *I.ir = DeclEntry(New, AS); + I.ir->set(New, AS); + } + + void erase(unsigned I) { + decls()[I] = decls().back(); + decls().pop_back(); } void erase(iterator I) { @@ -142,6 +191,10 @@ public: decls().pop_back(); } + void setAccess(iterator I, AccessSpecifier AS) { + I.ir->setAccess(AS); + } + void clear() { decls().clear(); } void set_size(unsigned N) { decls().set_size(N); } @@ -152,41 +205,8 @@ public: decls().append(I.ir, E.ir); } - /// A proxy reference for implementing operator[]. - class Proxy { - DeclEntry &Ref; - - friend class UnresolvedSetImpl; - Proxy(DeclEntry &Ref) : Ref(Ref) {} - - public: - NamedDecl *getDecl() const { return Ref.getPointer(); } - void setDecl(NamedDecl *D) { Ref.setPointer(D); } - - AccessSpecifier getAccess() const { return AccessSpecifier(Ref.getInt()); } - void setAccess(AccessSpecifier AS) const { Ref.setInt(AS); } - - NamedDecl* operator->() const { return getDecl(); } - operator NamedDecl*() const { return getDecl(); } - Proxy &operator=(const Proxy &D) { Ref = D.Ref; return *this; } - }; - Proxy operator[](unsigned I) { return Proxy(decls()[I]); } - - /// A proxy reference for implementing operator[] const. - class ConstProxy { - const DeclEntry &Ref; - - friend class UnresolvedSetImpl; - ConstProxy(const DeclEntry &Ref) : Ref(Ref) {} - - public: - NamedDecl *getDecl() const { return Ref.getPointer(); } - AccessSpecifier getAccess() const { return AccessSpecifier(Ref.getInt()); } - - NamedDecl *operator->() const { return getDecl(); } - operator NamedDecl*() const { return getDecl(); } - }; - ConstProxy operator[](unsigned I) const { return ConstProxy(decls()[I]); } + DeclAccessPair &operator[](unsigned I) { return decls()[I]; } + const DeclAccessPair &operator[](unsigned I) const { return decls()[I]; } private: // These work because the only permitted subclass is UnresolvedSetImpl @@ -202,7 +222,7 @@ private: /// A set of unresolved declarations template <unsigned InlineCapacity> class UnresolvedSet : public UnresolvedSetImpl { - llvm::SmallVector<UnresolvedSetImpl::DeclEntry, InlineCapacity> Decls; + llvm::SmallVector<DeclAccessPair, InlineCapacity> Decls; }; |
