diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-02-16 09:31:36 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-02-16 09:31:36 +0000 |
commit | fd035e6496665b1f1197868e21cb0a4594e8db6e (patch) | |
tree | 53010172e19c77ea447bcd89e117cda052ab52e0 /include/clang | |
parent | 2fce988e86bc01829142e4362d4eff1af0925147 (diff) | |
download | FreeBSD-src-fd035e6496665b1f1197868e21cb0a4594e8db6e.zip FreeBSD-src-fd035e6496665b1f1197868e21cb0a4594e8db6e.tar.gz |
Update clang to r96341.
Diffstat (limited to 'include/clang')
97 files changed, 2710 insertions, 1206 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index e5429be..2ed9fd7 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 abd36f7..2d31491 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 0000000..f5f11ca --- /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 03ab0f0..3722590 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) { - - if (size == 0) return; - assert(arg_nums); - ArgNums = new unsigned[size]; - Size = size; - memcpy(ArgNums, arg_nums, sizeof(*ArgNums)*size); - } + NonNullAttr(ASTContext &C, unsigned* arg_nums = 0, unsigned size = 0); - 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 1491b1e..79a3022 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 6d52b2b..0744289 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 775bce2..a407a16 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 73ebf52..0978c6d 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(); + + struct DefinitionData { + DefinitionData(CXXRecordDecl *D); + + /// UserDeclaredConstructor - True when this class has a + /// user-declared constructor. + bool UserDeclaredConstructor : 1; + + /// UserDeclaredCopyConstructor - True when this class has a + /// user-declared copy constructor. + bool UserDeclaredCopyConstructor : 1; + + /// UserDeclaredCopyAssignment - True when this class has a + /// user-declared copy assignment operator. + bool UserDeclaredCopyAssignment : 1; + + /// UserDeclaredDestructor - True when this class has a + /// user-declared destructor. + bool UserDeclaredDestructor : 1; + + /// Aggregate - True when this class is an aggregate. + bool Aggregate : 1; + + /// PlainOldData - True when this class is a POD-type. + bool PlainOldData : 1; + + /// Empty - true when this class is empty for traits purposes, + /// i.e. has no data members other than 0-width bit-fields, has no + /// virtual function/base, and doesn't inherit from a non-empty + /// class. Doesn't take union-ness into account. + bool Empty : 1; + + /// Polymorphic - True when this class is polymorphic, i.e. has at + /// least one virtual member or derives from a polymorphic class. + bool Polymorphic : 1; + + /// Abstract - True when this class is abstract, i.e. has at least + /// one pure virtual function, (that can come from a base class). + bool Abstract : 1; + + /// HasTrivialConstructor - True when this class has a trivial constructor. + /// + /// 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; + + /// 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; - /// UserDeclaredCopyAssignment - True when this class has a - /// user-declared copy assignment operator. - bool UserDeclaredCopyAssignment : 1; + /// NumBases - The number of base class specifiers in Bases. + unsigned NumBases; - /// UserDeclaredDestructor - True when this class has a - /// user-declared destructor. - bool UserDeclaredDestructor : 1; + /// VBases - direct and indirect virtual base classes of this class. + CXXBaseSpecifier *VBases; - /// Aggregate - True when this class is an aggregate. - bool Aggregate : 1; + /// NumVBases - The number of virtual base class specifiers in VBases. + unsigned NumVBases; - /// PlainOldData - True when this class is a POD-type. - bool PlainOldData : 1; + /// 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; - /// 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; + /// 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; - /// Polymorphic - True when this class is polymorphic, i.e. has at least one - /// virtual member or derives from a polymorphic class. - bool Polymorphic : 1; + /// Definition - The declaration which defines this record. + CXXRecordDecl *Definition; - /// 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; + } *DefinitionData; - /// 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; - - /// 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; - - /// NumBases - The number of base class specifiers in Bases. - unsigned NumBases; - - /// VBases - direct and indirect virtual base classes of this class. - CXXBaseSpecifier *VBases; - - /// NumVBases - The number of virtual base class specifiers in VBases. - unsigned NumVBases; - - /// Conversions - Overload set containing the conversion functions - /// of this C++ class (but not its inherited conversion - /// functions). Each of the entries in this overload set is a - /// CXXConversionDecl. - UnresolvedSet<4> Conversions; - - /// VisibleConversions - Overload set containing the conversion functions - /// of this C++ class and all those inherited conversion functions that - /// are visible in this class. Each of the entries in this overload set is - /// a CXXConversionDecl or a FunctionTemplateDecl. - 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 0fb0db1..e562d35 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 d8b004a..ced1747 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 59d7e43..2254724 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 2527817..114a198 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 6ce95ac..e4bc4b7 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 0b0cd64..df39b53 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 d058f83..94caa6f 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 09ea4ca..4e87c27 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 7102336..ec6149e 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 3a52550..4986f08 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 b7b60df..40e5098 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 575011a..9cf2cb7 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 055d152..9c59229 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; }; diff --git a/include/clang/Analysis/Analyses/PrintfFormatString.h b/include/clang/Analysis/Analyses/PrintfFormatString.h new file mode 100644 index 0000000..a4ad0b7 --- /dev/null +++ b/include/clang/Analysis/Analyses/PrintfFormatString.h @@ -0,0 +1,279 @@ +//==- PrintfFormatStrings.h - Analysis of printf format strings --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Handling of format string in printf and friends. The structure of format +// strings for fprintf() are described in C99 7.19.6.1. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FPRINTF_FORMAT_H +#define LLVM_CLANG_FPRINTF_FORMAT_H + +#include "clang/AST/CanonicalType.h" + +namespace clang { + +class ASTContext; + +namespace analyze_printf { + +class ArgTypeResult { +public: + enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CStrTy, + WCStrTy }; +private: + const Kind K; + QualType T; + ArgTypeResult(bool) : K(InvalidTy) {} +public: + ArgTypeResult(Kind k = UnknownTy) : K(k) {} + ArgTypeResult(QualType t) : K(SpecificTy), T(t) {} + ArgTypeResult(CanQualType t) : K(SpecificTy), T(t) {} + + static ArgTypeResult Invalid() { return ArgTypeResult(true); } + + bool isValid() const { return K != InvalidTy; } + + const QualType *getSpecificType() const { + return K == SpecificTy ? &T : 0; + } + + bool matchesType(ASTContext &C, QualType argTy) const; + + bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; } + + QualType getRepresentativeType(ASTContext &C) const; +}; + +class ConversionSpecifier { +public: + enum Kind { + InvalidSpecifier = 0, + // C99 conversion specifiers. + dArg, // 'd' + iArg, // 'i', + oArg, // 'o', + uArg, // 'u', + xArg, // 'x', + XArg, // 'X', + fArg, // 'f', + FArg, // 'F', + eArg, // 'e', + EArg, // 'E', + gArg, // 'g', + GArg, // 'G', + aArg, // 'a', + AArg, // 'A', + IntAsCharArg, // 'c' + CStrArg, // 's' + VoidPtrArg, // 'p' + OutIntPtrArg, // 'n' + PercentArg, // '%' + // Objective-C specific specifiers. + ObjCObjArg, // '@' + // GlibC specific specifiers. + PrintErrno, // 'm' + // Specifier ranges. + IntArgBeg = dArg, + IntArgEnd = iArg, + UIntArgBeg = oArg, + UIntArgEnd = XArg, + DoubleArgBeg = fArg, + DoubleArgEnd = AArg, + C99Beg = IntArgBeg, + C99End = DoubleArgEnd, + ObjCBeg = ObjCObjArg, + ObjCEnd = ObjCObjArg + }; + + ConversionSpecifier() + : Position(0), kind(InvalidSpecifier) {} + + ConversionSpecifier(const char *pos, Kind k) + : Position(pos), kind(k) {} + + const char *getStart() const { + return Position; + } + + llvm::StringRef getCharacters() const { + return llvm::StringRef(getStart(), getLength()); + } + + bool consumesDataArgument() const { + switch (kind) { + case PercentArg: + case PrintErrno: + return false; + default: + return true; + } + } + + bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; } + bool isIntArg() const { return kind >= dArg && kind <= iArg; } + bool isUIntArg() const { return kind >= oArg && kind <= XArg; } + bool isDoubleArg() const { return kind >= fArg && kind <= AArg; } + Kind getKind() const { return kind; } + unsigned getLength() const { + // Conversion specifiers currently only are represented by + // single characters, but we be flexible. + return 1; + } + +private: + const char *Position; + Kind kind; +}; + +enum LengthModifier { + None, + AsChar, // 'hh' + AsShort, // 'h' + AsLong, // 'l' + AsLongLong, // 'll', 'q' (BSD, deprecated) + AsIntMax, // 'j' + AsSizeT, // 'z' + AsPtrDiff, // 't' + AsLongDouble, // 'L' + AsWideChar = AsLong // for '%ls' +}; + +class OptionalAmount { +public: + enum HowSpecified { NotSpecified, Constant, Arg }; + + OptionalAmount(HowSpecified h, const char *st) + : start(st), hs(h), amt(0) {} + + OptionalAmount() + : start(0), hs(NotSpecified), amt(0) {} + + OptionalAmount(unsigned i, const char *st) + : start(st), hs(Constant), amt(i) {} + + HowSpecified getHowSpecified() const { return hs; } + bool hasDataArgument() const { return hs == Arg; } + + unsigned getConstantAmount() const { + assert(hs == Constant); + return amt; + } + + const char *getStart() const { + return start; + } + + ArgTypeResult getArgType(ASTContext &Ctx) const; + +private: + const char *start; + HowSpecified hs; + unsigned amt; +}; + +class FormatSpecifier { + LengthModifier LM; + unsigned IsLeftJustified : 1; + unsigned HasPlusPrefix : 1; + unsigned HasSpacePrefix : 1; + unsigned HasAlternativeForm : 1; + unsigned HasLeadingZeroes : 1; + unsigned flags : 5; + ConversionSpecifier CS; + OptionalAmount FieldWidth; + OptionalAmount Precision; +public: + FormatSpecifier() : LM(None), + IsLeftJustified(0), HasPlusPrefix(0), HasSpacePrefix(0), + HasAlternativeForm(0), HasLeadingZeroes(0) {} + + static FormatSpecifier Parse(const char *beg, const char *end); + + // Methods for incrementally constructing the FormatSpecifier. + void setConversionSpecifier(const ConversionSpecifier &cs) { + CS = cs; + } + void setLengthModifier(LengthModifier lm) { + LM = lm; + } + void setIsLeftJustified() { IsLeftJustified = 1; } + void setHasPlusPrefix() { HasPlusPrefix = 1; } + void setHasSpacePrefix() { HasSpacePrefix = 1; } + void setHasAlternativeForm() { HasAlternativeForm = 1; } + void setHasLeadingZeros() { HasLeadingZeroes = 1; } + + // Methods for querying the format specifier. + + const ConversionSpecifier &getConversionSpecifier() const { + return CS; + } + + LengthModifier getLengthModifier() const { + return LM; + } + + const OptionalAmount &getFieldWidth() const { + return FieldWidth; + } + + void setFieldWidth(const OptionalAmount &Amt) { + FieldWidth = Amt; + } + + void setPrecision(const OptionalAmount &Amt) { + Precision = Amt; + } + + const OptionalAmount &getPrecision() const { + return Precision; + } + + /// \brief Returns the builtin type that a data argument + /// paired with this format specifier should have. This method + /// will return null if the format specifier does not have + /// a matching data argument or the matching argument matches + /// more than one type. + ArgTypeResult getArgType(ASTContext &Ctx) const; + + bool isLeftJustified() const { return (bool) IsLeftJustified; } + bool hasPlusPrefix() const { return (bool) HasPlusPrefix; } + bool hasAlternativeForm() const { return (bool) HasAlternativeForm; } + bool hasLeadingZeros() const { return (bool) HasLeadingZeroes; } + bool hasSpacePrefix() const { return (bool) HasSpacePrefix; } +}; + +class FormatStringHandler { +public: + FormatStringHandler() {} + virtual ~FormatStringHandler(); + + virtual void HandleIncompleteFormatSpecifier(const char *startSpecifier, + unsigned specifierLen) {} + + virtual void HandleNullChar(const char *nullCharacter) {} + + virtual void + HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen) {} + + virtual bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen) { + return true; + } +}; + +bool ParseFormatString(FormatStringHandler &H, + const char *beg, const char *end); + +} // end printf namespace +} // end clang namespace +#endif diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h index 2b367b7..cd771ac 100644 --- a/include/clang/Analysis/Analyses/UninitializedValues.h +++ b/include/clang/Analysis/Analyses/UninitializedValues.h @@ -70,5 +70,8 @@ public: void InitializeValues(const CFG& cfg); }; + +void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags, + bool FullUninitTaint=false); } // end namespace clang #endif diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index c82bb96..ea4f5b2 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -32,7 +32,6 @@ class LiveVariables; class ParentMap; class ImplicitParamDecl; class LocationContextManager; -class BlockDataRegion; class StackFrameContext; /// AnalysisContext contains the context data for the function or method under @@ -207,35 +206,23 @@ public: }; class BlockInvocationContext : public LocationContext { - llvm::PointerUnion<const BlockDataRegion *, const BlockDecl *> Data; + // FIXME: Add back context-sensivity (we don't want libAnalysis to know + // about MemRegion). + const BlockDecl *BD; friend class LocationContextManager; BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent, - const BlockDataRegion *br) - : LocationContext(Block, ctx, parent), Data(br) {} - - BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent, const BlockDecl *bd) - : LocationContext(Block, ctx, parent), Data(bd) {} + : LocationContext(Block, ctx, parent), BD(bd) {} public: ~BlockInvocationContext() {} - - const BlockDataRegion *getBlockRegion() const { - return Data.is<const BlockDataRegion*>() ? - Data.get<const BlockDataRegion*>() : 0; - } - - const BlockDecl *getBlockDecl() const; - + + const BlockDecl *getBlockDecl() const { return BD; } + void Profile(llvm::FoldingSetNodeID &ID); - - static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, - const LocationContext *parent, const BlockDataRegion *br){ - ProfileCommon(ID, Block, ctx, parent, br); - } - + static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, const LocationContext *parent, const BlockDecl *bd) { ProfileCommon(ID, Block, ctx, parent, bd); @@ -260,10 +247,6 @@ public: const LocationContext *parent, const Stmt *s); - const BlockInvocationContext * - getBlockInvocation(AnalysisContext *ctx, const LocationContext *parent, - const BlockDataRegion *BR); - /// Discard all previously created LocationContext objects. void clear(); private: diff --git a/include/clang/Analysis/Support/Optional.h b/include/clang/Analysis/Support/Optional.h index 40f38be..a4e6d51 100644 --- a/include/clang/Analysis/Support/Optional.h +++ b/include/clang/Analysis/Support/Optional.h @@ -20,19 +20,27 @@ namespace clang { template<typename T> class Optional { - const T x; + T x; unsigned hasVal : 1; public: - explicit Optional() : hasVal(false) {} + explicit Optional() : x(), hasVal(false) {} Optional(const T &y) : x(y), hasVal(true) {} static inline Optional create(const T* y) { return y ? Optional(*y) : Optional(); } + Optional &operator=(const T &y) { + x = y; + hasVal = true; + return *this; + } + const T* getPointer() const { assert(hasVal); return &x; } + const T& getValue() const { assert(hasVal); return x; } operator bool() const { return hasVal; } + bool hasValue() const { return hasVal; } const T* operator->() const { return getPointer(); } const T& operator*() const { assert(hasVal); return x; } }; diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 0894563..3251ec4 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -12,9 +12,6 @@ // //===----------------------------------------------------------------------===// -// FIXME: this needs to be the full list supported by GCC. Right now, I'm just -// adding stuff on demand. -// // FIXME: This should really be a .td file, but that requires modifying tblgen. // Perhaps tblgen should have plugins. @@ -52,6 +49,7 @@ // * -> pointer // & -> reference // C -> const +// D -> volatile // The third value provided to the macro specifies information about attributes // of the function. These must be kept in sync with the predicates in the @@ -235,7 +233,7 @@ BUILTIN(__builtin_islessgreater , "i.", "nc") BUILTIN(__builtin_isunordered , "i.", "nc") // Unary FP classification -// BUILTIN(__builtin_fpclassify, "iiiii.", "nc") +BUILTIN(__builtin_fpclassify, "iiiii.", "nc") BUILTIN(__builtin_isfinite, "i.", "nc") BUILTIN(__builtin_isinf, "i.", "nc") BUILTIN(__builtin_isinf_sign, "i.", "nc") @@ -277,7 +275,7 @@ BUILTIN(__builtin_va_copy, "vAA", "n") BUILTIN(__builtin_stdarg_start, "vA.", "n") BUILTIN(__builtin_bcmp, "iv*v*z", "n") BUILTIN(__builtin_bcopy, "vv*v*z", "n") -BUILTIN(__builtin_bzero, "vv*z", "n") +BUILTIN(__builtin_bzero, "vv*z", "nF") BUILTIN(__builtin_memchr, "v*vC*iz", "nF") BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF") BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF") @@ -308,11 +306,19 @@ BUILTIN(__builtin_extract_return_addr, "v*v*", "n") BUILTIN(__builtin_frame_address, "v*Ui", "n") BUILTIN(__builtin_flt_rounds, "i", "nc") BUILTIN(__builtin_setjmp, "iv**", "") -BUILTIN(__builtin_longjmp, "vv**i", "") +BUILTIN(__builtin_longjmp, "vv**i", "r") BUILTIN(__builtin_unwind_init, "v", "") BUILTIN(__builtin_eh_return_data_regno, "ii", "nc") BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:") +// GCC exception builtins +BUILTIN(__builtin_eh_return, "vzv*", "") // FIXME: Takes intptr_t, not size_t! +BUILTIN(__builtin_frob_return_addr, "v*v*", "n") +BUILTIN(__builtin_dwarf_cfa, "v*", "n") +BUILTIN(__builtin_init_dwarf_reg_size_table, "vv*", "n") +BUILTIN(__builtin_dwarf_sp_column, "Ui", "n") +BUILTIN(__builtin_extend_pointer, "iv*", "n") + // GCC Object size checking builtins BUILTIN(__builtin_object_size, "zv*i", "n") BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "nF") @@ -438,18 +444,18 @@ BUILTIN(__sync_nand_and_fetch_16, "LLLiLLLi*LLLi.", "n") BUILTIN(__sync_bool_compare_and_swap, "v.", "") -BUILTIN(__sync_bool_compare_and_swap_1, "bc*cc.", "n") -BUILTIN(__sync_bool_compare_and_swap_2, "bs*ss.", "n") -BUILTIN(__sync_bool_compare_and_swap_4, "bi*ii.", "n") -BUILTIN(__sync_bool_compare_and_swap_8, "bLLi*LLi.", "n") -BUILTIN(__sync_bool_compare_and_swap_16, "bLLLi*LLLiLLLi.", "n") +BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "n") +BUILTIN(__sync_bool_compare_and_swap_2, "bsD*ss.", "n") +BUILTIN(__sync_bool_compare_and_swap_4, "biD*ii.", "n") +BUILTIN(__sync_bool_compare_and_swap_8, "bLLiD*LLiLLi.", "n") +BUILTIN(__sync_bool_compare_and_swap_16, "bLLLiD*LLLiLLLi.", "n") BUILTIN(__sync_val_compare_and_swap, "v.", "") -BUILTIN(__sync_val_compare_and_swap_1, "cc*cc.", "n") -BUILTIN(__sync_val_compare_and_swap_2, "ss*ss.", "n") -BUILTIN(__sync_val_compare_and_swap_4, "ii*ii.", "n") -BUILTIN(__sync_val_compare_and_swap_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_val_compare_and_swap_16, "LLLiLLLi*LLLiLLLi.", "n") +BUILTIN(__sync_val_compare_and_swap_1, "ccD*cc.", "n") +BUILTIN(__sync_val_compare_and_swap_2, "ssD*ss.", "n") +BUILTIN(__sync_val_compare_and_swap_4, "iiD*ii.", "n") +BUILTIN(__sync_val_compare_and_swap_8, "LLiLLiD*LLiLLi.", "n") +BUILTIN(__sync_val_compare_and_swap_16, "LLLiLLLiD*LLLiLLLi.", "n") BUILTIN(__sync_lock_test_and_set, "v.", "") BUILTIN(__sync_lock_test_and_set_1, "cc*c.", "n") @@ -527,6 +533,7 @@ LIBBUILTIN(strndup, "c*cC*z", "f", "string.h") // POSIX strings.h LIBBUILTIN(index, "c*cC*i", "f", "strings.h") LIBBUILTIN(rindex, "c*cC*i", "f", "strings.h") +LIBBUILTIN(bzero, "vv*z", "f", "strings.h") // POSIX unistd.h LIBBUILTIN(_exit, "vi", "fr", "unistd.h") // POSIX setjmp.h diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index c5d6d7c..d2516f8 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -23,16 +23,19 @@ namespace llvm { template <typename T> class SmallVectorImpl; + class raw_ostream; } namespace clang { class DeclContext; class DiagnosticBuilder; class DiagnosticClient; + class FileManager; class IdentifierInfo; class LangOptions; class PartialDiagnostic; class Preprocessor; + class SourceManager; class SourceRange; // Import the diagnostic enums themselves. @@ -400,6 +403,13 @@ public: /// \brief Clear out the current diagnostic. void Clear() { CurDiagID = ~0U; } + /// Deserialize - Deserialize the first diagnostic within the memory + /// [Memory, MemoryEnd), producing a new diagnostic builder describing the + /// deserialized diagnostic. If the memory does not contain a + /// diagnostic, returns a diagnostic builder with no diagnostic ID. + DiagnosticBuilder Deserialize(FileManager &FM, SourceManager &SM, + const char *&Memory, const char *MemoryEnd); + private: /// getDiagnosticMappingInfo - Return the mapping info currently set for the /// specified builtin diagnostic. This returns the high bit encoding, or zero @@ -472,7 +482,7 @@ private: /// DiagRanges - The list of ranges added to this diagnostic. It currently /// only support 10 ranges, could easily be extended if needed. - const SourceRange *DiagRanges[10]; + SourceRange DiagRanges[10]; enum { MaxCodeModificationHints = 3 }; @@ -568,6 +578,9 @@ public: /// been emitted. ~DiagnosticBuilder() { Emit(); } + /// isActive - Determine whether this diagnostic is still active. + bool isActive() const { return DiagObj != 0; } + /// Operator bool: conversion of DiagnosticBuilder to bool always returns /// true. This allows is to be used in boolean error contexts like: /// return Diag(...); @@ -596,7 +609,7 @@ public: sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) && "Too many arguments to diagnostic!"); if (DiagObj) - DiagObj->DiagRanges[NumRanges++] = &R; + DiagObj->DiagRanges[NumRanges++] = R; } void AddCodeModificationHint(const CodeModificationHint &Hint) const { @@ -759,9 +772,9 @@ public: return DiagObj->NumDiagRanges; } - const SourceRange &getRange(unsigned Idx) const { + SourceRange getRange(unsigned Idx) const { assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!"); - return *DiagObj->DiagRanges[Idx]; + return DiagObj->DiagRanges[Idx]; } unsigned getNumCodeModificationHints() const { @@ -786,6 +799,12 @@ public: /// output buffer using the arguments stored in this diagnostic. void FormatDiagnostic(const char *DiagStr, const char *DiagEnd, llvm::SmallVectorImpl<char> &OutStr) const; + + /// Serialize - Serialize the given diagnostic (with its diagnostic + /// level) to the given stream. Serialization is a lossy operation, + /// since the specific diagnostic ID and any macro-instantiation + /// information is lost. + void Serialize(Diagnostic::Level DiagLevel, llvm::raw_ostream &OS) const; }; /// DiagnosticClient - This is an abstract interface implemented by clients of diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td index f075aaa..b6c2b13 100644 --- a/include/clang/Basic/DiagnosticASTKinds.td +++ b/include/clang/Basic/DiagnosticASTKinds.td @@ -26,4 +26,33 @@ def err_asm_empty_symbolic_operand_name : Error< def err_asm_invalid_operand_number : Error< "invalid operand number in inline asm string">; +// Importing ASTs +def err_odr_variable_type_inconsistent : Error< + "external variable %0 declared with incompatible types in different " + "translation units (%1 vs. %2)">; +def err_odr_variable_multiple_def : Error< + "external variable %0 defined in multiple translation units">; +def note_odr_value_here : Note<"declared here with type %0">; +def note_odr_defined_here : Note<"also defined here">; +def err_odr_function_type_inconsistent : Error< + "external function %0 declared with incompatible types in different " + "translation units (%1 vs. %2)">; +def warn_odr_tag_type_inconsistent : Warning< + "type %0 has incompatible definitions in different translation units">; +def note_odr_tag_kind_here: Note< + "%0 is a %select{struct|union|class|enum}1 here">; +def note_odr_field : Note<"field %0 has type %1 here">; +def note_odr_missing_field : Note<"no corresponding field here">; +def note_odr_bit_field : Note<"bit-field %0 with type %1 and length %2 here">; +def note_odr_not_bit_field : Note<"field %0 is not a bit-field">; +def note_odr_base : Note<"class has base type %0">; +def note_odr_virtual_base : Note< + "%select{non-virtual|virtual}0 derivation here">; +def note_odr_missing_base : Note<"no corresponding base class here">; +def note_odr_number_of_bases : Note< + "class has %0 base %plural{1:class|:classes}0">; +def note_odr_enumerator : Note<"enumerator %0 with value %1 here">; +def note_odr_missing_enumerator : Note<"no corresponding enumerator here">; + +def err_unsupported_ast_node: Error<"cannot import unsupported AST node %0">; } diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 7e14a32..66f84db 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -31,6 +31,9 @@ def note_also_found : Note<"also found">; // Parse && Lex def err_expected_colon : Error<"expected ':'">; +def err_expected_colon_after_setter_name : Error< + "method name referenced in property setter attribute " + "must end with ':'">; // Parse && Sema def err_no_declarators : Error<"declaration does not declare anything">; diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 8cdf850..dc5ccfd 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -62,6 +62,8 @@ def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">; def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">; def err_drv_invalid_remap_file : Error< "invalid option '%0' not of the form <from-file>;<to-file>">; +def err_drv_invalid_gcc_output_type : Error< + "invalid output type '%0' for use with gcc tool">; def warn_drv_input_file_unused : Warning< "%0: '%1' input unused when '%2' is present">; @@ -85,5 +87,7 @@ def warn_ignoring_ftabstop_value : Warning< "ignoring invalid -ftabstop value '%0', using default value %1">; def warn_drv_missing_resource_library : Warning< "missing resource library '%0', link may fail">; +def warn_drv_conflicting_deployment_targets : Warning< + "conflicting deployment targets, both MACOSX_DEPLOYMENT_TARGET '%0' and IPHONEOS_DEPLOYMENT_TARGET '%1' are present in environment">; } diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 66a841a..79147ea 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -19,6 +19,8 @@ def err_fe_invalid_code_complete_file : Error< "cannot locate code-completion file %0">, DefaultFatal; def err_fe_stdout_binary : Error<"unable to change standard output to binary">, DefaultFatal; +def err_fe_stderr_binary : Error<"unable to change standard error to binary">, + DefaultFatal; def err_fe_dependency_file_requires_MT : Error< "-dependency-file requires at least one -MT option">; def err_fe_incompatible_options : Error< @@ -80,6 +82,8 @@ def note_fixit_main_file_unchanged : Note< def warn_fixit_no_changes : Note< "FIX-IT detected errors it could not fix; no output will be generated">; +def err_fe_clang : Error<"error invoking%s: %s">, DefaultFatal; + // PCH reader def err_relocatable_without_without_isysroot : Error< "must specify system root with -isysroot when building a relocatable " @@ -105,6 +109,10 @@ def warn_pch_objective_c2 : Error< def warn_pch_nonfragile_abi : Error< "PCH file was compiled with the %select{32-bit|non-fragile}0 Objective-C " "ABI but the %select{32-bit|non-fragile}1 Objective-C ABI is selected">; +def warn_pch_nonfragile_abi2 : Error< + "PCH file was compiled with the %select{32-bit|enhanced non-fragile}0 " + "Objective-C ABI but the %select{32-bit|enhanced non-fragile}1 " + "Objective-C ABI is selected">; def warn_pch_extensions : Error< "extensions were %select{enabled|disabled}0 in PCH file but are " "currently %select{enabled|disabled}1">; @@ -132,6 +140,9 @@ def warn_pch_elide_constructors : Error< def warn_pch_exceptions : Error< "exceptions were %select{disabled|enabled}0 in PCH file but " "are currently %select{disabled|enabled}1">; +def warn_pch_sjlj_exceptions : Error< + "sjlj-exceptions were %select{disabled|enabled}0 in PCH file but " + "are currently %select{disabled|enabled}1">; def warn_pch_objc_runtime : Error< "PCH file was compiled with the %select{NeXT|GNU}0 runtime but the " "%select{NeXT|GNU}1 runtime is selected">; diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 03aad86..82f9eca 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -96,7 +96,8 @@ def : DiagGroup<"strict-overflow">; def InvalidOffsetof : DiagGroup<"invalid-offsetof">; def : DiagGroup<"strict-prototypes">; def : DiagGroup<"strict-selector-match">; -def Switch : DiagGroup<"switch">; +def SwitchEnum : DiagGroup<"switch-enum">; +def Switch : DiagGroup<"switch", [SwitchEnum]>; def Trigraphs : DiagGroup<"trigraphs">; def : DiagGroup<"type-limits">; @@ -118,6 +119,7 @@ def VectorConversions : DiagGroup<"vector-conversions">; // clang specific def VolatileRegisterVar : DiagGroup<"volatile-register-var">; def : DiagGroup<"write-strings">; def CharSubscript : DiagGroup<"char-subscripts">; +def ForceAlignArgPointer : DiagGroup<"force-align-arg-pointer">; // Aggregation warning settings. @@ -178,4 +180,4 @@ def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment // A warning group for warnings that we want to have on by default in clang, // but which aren't on by default in GCC. def NonGCC : DiagGroup<"non-gcc", - [SignCompare, Conversion]>; + [SignCompare, Conversion, ForceAlignArgPointer]>; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index c6d0605..bc26c3b 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -14,6 +14,8 @@ let Component = "Parse" in { def w_asm_qualifier_ignored : Warning<"ignored %0 qualifier on asm">; +def warn_file_asm_volatile : Warning< + "meaningless 'volatile' on asm outside function">; def ext_empty_source_file : Extension<"ISO C forbids an empty source file">; def ext_top_level_semi : Extension< @@ -158,12 +160,20 @@ def err_typename_invalid_functionspec : Error< "type name does not allow function specifier to be specified">; def err_invalid_decl_spec_combination : Error< "cannot combine with previous '%0' declaration specifier">; +def err_invalid_vector_decl_spec_combination : Error< + "cannot combine with previous '%0' declaration specifier. \"__vector\" must be first">; +def err_invalid_pixel_decl_spec_combination : Error< + "\"__pixel\" must be preceded by \"__vector\". '%0' declaration specifier not allowed here">; +def err_invalid_vector_double_decl_spec_combination : Error< + "cannot use \"double\" with \"__vector\"">; +def warn_vector_long_decl_spec_combination : Warning< + "Use of \"long\" with \"__vector\" is deprecated">; def err_friend_invalid_in_context : Error< "'friend' used outside of class">; def err_unknown_typename : Error< "unknown type name %0">; def err_use_of_tag_name_without_tag : Error< - "use of tagged type %0 without '%1' tag">; + "must use '%1' tag to refer to type %0%select{| in this scope}2">; def err_expected_ident_in_using : Error< "expected an identifier in using directive">; def err_unexected_colon_in_nested_name_spec : Error< @@ -303,6 +313,9 @@ def err_out_of_line_type_names_constructor : Error< def err_expected_qualified_after_typename : Error< "expected a qualified name after 'typename'">; +def err_expected_semi_after_tagdecl : Error< + "expected ';' after %0">; + def err_typename_refers_to_non_type_template : Error< "typename specifier refers to a non-template">; def err_expected_type_name_after_typename : Error< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 8d75d2e..19b242e 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -85,7 +85,11 @@ def warn_unused_variable : Warning<"unused variable %0">, InGroup<UnusedVariable>, DefaultIgnore; def warn_decl_in_param_list : Warning< "declaration of %0 will not be visible outside of this function">; - +def err_array_star_in_function_definition : Error< + "variable length array must be bound in function definition">; +def warn_unused_function : Warning<"unused function %0">, + InGroup<UnusedFunction>, DefaultIgnore; + def warn_implicit_function_decl : Warning< "implicit declaration of function %0">, InGroup<ImplicitFunctionDeclare>, DefaultIgnore; @@ -388,6 +392,11 @@ def err_deleted_non_function : Error< def err_deleted_decl_not_first : Error< "deleted definition must be first declaration">; +def warn_weak_vtable : Warning< + "%0 has no out-of-line virtual method definitions; its vtable will be " + "emitted in every translation unit">, + InGroup<DiagGroup<"weak-vtables">>, DefaultIgnore; + // C++ exception specifications def err_exception_spec_in_typedef : Error< "exception specifications are not allowed in typedefs">; @@ -410,17 +419,20 @@ def err_deep_exception_specs_differ : Error< // C++ access checking def err_class_redeclared_with_different_access : Error< "%0 redeclared with '%1' access">; +def err_access_private : Error<"%0 is a private member of %1">; +def err_access_ctor_private : Error<"calling a private constructor of %0">; +// Say something about the context for these? +def err_access_protected : Error<"%0 is a protected member of %1">; +def err_access_ctor_protected : Error<"calling a protected constructor of %0">; def note_previous_access_declaration : Note< "previously declared '%1' here">; def err_access_outside_class : Error< "access to %select{private|protected}0 member outside any class context">; -def note_access_natural : Note<"declared %select{private|protected}0 here">; +def note_access_natural : Note< + "%select{|implicitly }1declared %select{private|protected}0 here">; def note_access_constrained_by_path : Note< - "access to decl constrained by %select{private|protected}0 inheritance">; -def err_access_protected : Error< - "access to protected member of %0 from %1, which is not a subclass">; -def err_access_private : Error< - "access to private member of %0 from %1">; + "constrained by %select{|implicitly }1%select{private|protected}0" + " inheritance here">; // C++ name lookup def err_incomplete_nested_name_spec : Error< @@ -446,10 +458,14 @@ def err_mutable_nonmember : Error< "'mutable' can only be applied to member variables">; def err_virtual_non_function : Error< "'virtual' can only appear on non-static member functions">; -def err_explicit_non_function : Error< - "'explicit' can only appear on non-static member functions">; def err_virtual_out_of_class : Error< "'virtual' can only be specified inside the class definition">; +def err_explicit_non_function : Error< + "'explicit' can only appear on non-static member functions">; +def err_explicit_out_of_class : Error< + "'explicit' can only be specified inside the class definition">; +def err_explicit_non_ctor_or_conv_function : Error< + "'explicit' can only be applied to a constructor or conversion function">; def err_static_not_bitfield : Error<"static member %0 cannot be a bit-field">; def err_static_out_of_line : Error< "'static' can only be specified inside the class definition">; @@ -498,9 +514,8 @@ def note_overridden_virtual_function : Note< "overridden virtual function is here">; def err_covariant_return_inaccessible_base : Error< - "return type of virtual function %2 is not covariant with the return type " - "of the function it overrides " - "(conversion from %0 to inaccessible base class %1)">, NoSFINAE; + "invalid covariant return for virtual function: %1 is a " + "%select{private|protected}2 base class of %0">, NoSFINAE; def err_covariant_return_ambiguous_derived_to_base_conv : Error< "return type of virtual function %3 is not covariant with the return type of " "the function it overrides (ambiguous conversion from derived class " @@ -547,7 +562,7 @@ def err_destructor_name : Error< def err_init_conversion_failed : Error< "cannot initialize %select{a variable|a parameter|return object|an " "exception object|a member subobject|an array element|a new value|a value|a " - "base class|an array element}0 of type %1 with an %select{rvalue|lvalue}2 of " + "base class|a vector element}0 of type %1 with an %select{rvalue|lvalue}2 of " "type %3">; def err_lvalue_to_rvalue_ref : Error<"rvalue reference cannot bind to lvalue">; @@ -556,14 +571,14 @@ def err_invalid_initialization : Error< def err_lvalue_to_rvalue_ambig_ref : Error<"rvalue reference cannot bind to lvalue " "due to multiple conversion functions">; def err_not_reference_to_const_init : Error< - "non-const lvalue reference to type %0 cannot be initialized " - "with a %select{value|temporary}1 of type %2">; + "%select{non-const|volatile}0 lvalue reference to type %1 cannot be " + "initialized with a %select{value|temporary}2 of type %3">; def err_lvalue_reference_bind_to_temporary : Error< - "non-const lvalue reference to type %0 cannot bind to a temporary of type " - "%1">; + "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a " + "temporary of type %2">; def err_lvalue_reference_bind_to_unrelated : Error< - "non-const lvalue reference to type %0 cannot bind to a value of unrelated " - "type %1">; + "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a " + "value of unrelated type %2">; def err_reference_bind_drops_quals : Error< "binding of reference to type %0 to a value of type %1 drops qualifiers">; def err_reference_bind_failed : Error< @@ -580,10 +595,14 @@ def err_reference_init_drops_quals : Error< "qualifiers">; def err_reference_bind_to_bitfield : Error< "%select{non-const|volatile}0 reference cannot bind to bit-field %1">; +def err_reference_bind_to_vector_element : Error< + "%select{non-const|volatile}0 reference cannot bind to vector element">; def err_reference_var_requires_init : Error< "declaration of reference variable %0 requires an initializer">; def err_const_var_requires_init : Error< "declaration of const variable '%0' requires an initializer">; +def err_reference_without_init : Error< + "reference to type %0 requires an initializer">; def err_reference_has_multiple_inits : Error< "reference cannot be initialized with multiple values">; def err_init_non_aggr_init_list : Error< @@ -597,13 +616,16 @@ def warn_field_is_uninit : Warning<"field is uninitialized when used here">, def err_temp_copy_no_viable : Error< "no viable copy constructor %select{copying variable|copying parameter|" - "returning object|throwing object}0 of type %1">; + "returning object|throwing object|copying member subobject|copying array " + "element}0 of type %1">; def err_temp_copy_ambiguous : Error< "ambiguous copy constructor call when %select{copying variable|copying " - "parameter|returning object|throwing object}0 of type %1">; + "parameter|returning object|throwing object|copying member subobject|copying " + "array element}0 of type %1">; def err_temp_copy_deleted : Error< "%select{copying variable|copying parameter|returning object|throwing " - "object}0 of type %1 invokes deleted copy constructor">; + "object|copying member subobject|copying array element}0 of type %1 invokes " + "deleted copy constructor">; // C++0x decltype def err_cannot_determine_declared_type_of_overloaded_function : Error< @@ -702,6 +724,9 @@ def err_attribute_aligned_not_power_of_two : Error< def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< "'%0' redeclared without %1 attribute: previous %1 ignored">; def warn_attribute_ignored : Warning<"%0 attribute ignored">; +def warn_faap_attribute_ignored : Warning< + "force_align_arg_pointer used on function pointer; attribute ignored">, + InGroup<ForceAlignArgPointer>; def warn_attribute_precede_definition : Warning< "attribute declaration must precede definition">; def warn_attribute_void_function : Warning< @@ -728,13 +753,18 @@ def err_attribute_wrong_decl_type : Error< "parameter or Objective-C method |function, method or block|" "virtual method or class|function, method, or parameter|class|virtual method" "|member}1 types">; +def warn_function_attribute_wrong_type : Warning< + "%0 only applies to function types; type here is %1">; def warn_gnu_inline_attribute_requires_inline : Warning< "'gnu_inline' attribute requires function to be marked 'inline'," " attribute ignored">; +def err_cconv_change : Error< + "function declared '%0' here was previously declared " + "%select{'%2'|without calling convention}1">; def err_cconv_knr : Error< - "function with no prototype cannot use '%0' calling convention">; + "function with no prototype cannot use %0 calling convention">; def err_cconv_varargs : Error< - "variadic function cannot use '%0' calling convention">; + "variadic function cannot use %0 calling convention">; def warn_impcast_vector_scalar : Warning< "implicit cast turns vector to scalar: %0 to %1">, @@ -873,10 +903,7 @@ def err_uninitialized_member_for_assign : Error< "assignment operator">; def note_first_required_here : Note< "synthesized method is first required here">; -def err_null_intialized_reference_member : Error< - "cannot initialize the member to null in default constructor because " - "reference member %0 cannot be null-initialized">; -def err_unintialized_member_in_ctor : Error< +def err_uninitialized_member_in_ctor : Error< "%select{|implicit default }0constructor for %1 must explicitly initialize " "the %select{reference|const}2 member %3">; @@ -915,6 +942,12 @@ def note_ovl_candidate : Note<"candidate " "is the implicit default constructor|" "is the implicit copy constructor|" "is the implicit copy assignment operator}0%1">; + +def note_ovl_candidate_bad_deduction : Note< + "candidate template ignored: failed template argument deduction">; +def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: " + "couldn't infer template argument %0">; + // Note that we don't treat templates differently for this diagnostic. def note_ovl_candidate_arity : Note<"candidate " "%select{function|function|constructor|function|function|constructor|" @@ -941,6 +974,13 @@ def note_ovl_candidate_bad_conv_incomplete : Note<"candidate " "constructor (the implicit copy constructor)|" "function (the implicit copy assignment operator)}0%1 " "not viable: cannot convert argument of incomplete type %2 to %3">; +def note_ovl_candidate_bad_overload : Note<"candidate " + "%select{function|function|constructor|" + "function |function |constructor |" + "constructor (the implicit default constructor)|" + "constructor (the implicit copy constructor)|" + "function (the implicit copy assignment operator)}0%1" + " not viable: no overload of %3 matching %2 for %ordinal4 argument">; def note_ovl_candidate_bad_conv : Note<"candidate " "%select{function|function|constructor|" "function |function |constructor |" @@ -1068,9 +1108,6 @@ def err_template_tag_noparams : Error< def err_template_decl_ref : Error< "cannot refer to class template %0 without a template argument list">; -def err_typedef_in_def_scope : Error< - "cannot use typedef %0 in scope specifier for out-of-line declaration">; - // C++ Template Argument Lists def err_template_arg_list_different_arity : Error< "%select{too few|too many}0 template arguments for " @@ -1122,6 +1159,8 @@ def err_template_arg_no_ref_bind : Error< def err_template_arg_ref_bind_ignores_quals : Error< "reference binding of non-type template parameter of type %0 to template " "argument of type %1 ignores qualifiers">; +def err_template_arg_not_decl_ref : Error< + "non-type template argument does not refer to any declaration">; def err_template_arg_not_object_or_func_form : Error< "non-type template argument does not directly refer to an object or " "function">; @@ -1236,6 +1275,8 @@ def err_partial_spec_redeclared : Error< "class template partial specialization %0 cannot be redeclared">; def note_prev_partial_spec_here : Note< "previous declaration of class template partial specialization %0 is here">; +def err_partial_spec_fully_specialized : Error< + "partial specialization of %0 does not use any of its template parameters">; // C++ Function template specializations def err_function_template_spec_no_match : Error< @@ -1442,9 +1483,13 @@ def err_forward_ref_enum : Error< def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">; def err_duplicate_member : Error<"duplicate member %0">; def ext_enum_value_not_int : Extension< - "ISO C restricts enumerator values to range of 'int' (%0 is too large)">; + "ISO C restricts enumerator values to range of 'int' (%0 is too " + "%select{small|large}1)">; def warn_enum_too_large : Warning< "enumeration values exceed range of largest integer">; +def warn_enumerator_too_large : Warning< + "enumerator value %0 is not representable in the largest integer type">; + def warn_illegal_constant_array_size : Extension< "size of static array must be an integer constant expression">; def err_vla_decl_in_file_scope : Error< @@ -1677,6 +1722,8 @@ def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">; def err_no_member : Error<"no member named %0 in %1">; def err_member_redeclared : Error<"class member cannot be redeclared">; +def err_member_def_undefined_record : Error< + "out-of-line definition of %0 from class %1 without definition">; def err_member_def_does_not_match : Error< "out-of-line definition of %0 does not match any declaration in %1">; def err_nonstatic_member_out_of_line : Error< @@ -1824,7 +1871,11 @@ def ext_integer_complement_complex : Extension< def error_nosetter_property_assignment : Error< "setter method is needed to assign to object using property" " assignment syntax">; def error_no_subobject_property_setting : Error< - "cannot assign to a sub-structure of an ivar using property" " assignment syntax">; + "cannot assign to a sub-structure of an ivar using property" + " assignment syntax">; +def error_no_subobject_property_getter_setting : Error< + "cannot assign to a sub-structure returned via a getter using property" + " assignment syntax">; def ext_freestanding_complex : Extension< "complex numbers are an extension in a freestanding C99 implementation">; @@ -1915,7 +1966,9 @@ def err_ambiguous_base_to_derived_cast : Error< def err_static_downcast_via_virtual : Error< "cannot cast %0 to %1 via virtual base %2">; def err_downcast_from_inaccessible_base : Error< - "cannot cast %1 to %0 due to inaccessible conversion path">; + "cannot cast %select{private|protected}2 base class %1 to %0">; +def err_upcast_to_inaccessible_base : Error< + "cannot cast %0 to its %select{private|protected}2 base class %1">; def err_bad_dynamic_cast_not_ref_or_ptr : Error< "%0 is not a reference or pointer">; def err_bad_dynamic_cast_not_class : Error<"%0 is not a class">; @@ -1942,7 +1995,8 @@ def err_new_paren_array_nonconst : Error< def err_array_size_not_integral : Error< "array size expression must have integral or enumerated type, not %0">; def err_default_init_const : Error< - "default initialization of an object of const type %0">; + "default initialization of an object of const type %0" + "%select{| requires a user-provided default constructor}1">; def err_delete_operand : Error<"cannot delete expression of type %0">; def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete " "expression of type %0 to a pointer">; @@ -2245,8 +2299,6 @@ def error_multiple_base_initialization : Error < def err_mem_init_not_member_or_class : Error< "member initializer %0 does not name a non-static data member or base " "class">; -def err_mem_initializer_mismatch : Error< - "Too many arguments for member initializer %0">; def warn_field_initialized : Warning< "member '%0' will be initialized after">, @@ -2435,11 +2487,16 @@ def warn_printf_write_back : Warning< def warn_printf_insufficient_data_args : Warning< "more '%%' conversions than data arguments">, InGroup<Format>; def warn_printf_too_many_data_args : Warning< - "more data arguments than '%%' conversions">, InGroup<FormatExtraArgs>; + "more data arguments than format specifiers">, InGroup<FormatExtraArgs>; def warn_printf_invalid_conversion : Warning< - "invalid conversion '%0'">, InGroup<Format>; + "invalid conversion specifier '%0'">, InGroup<Format>; +def warn_printf_incomplete_specifier : Warning< + "incomplete format specifier">, InGroup<Format>; def warn_printf_missing_format_string : Warning< "format string missing">, InGroup<Format>; +def warn_printf_conversion_argument_type_mismatch : Warning< + "conversion specifies type %0 but the argument has type %1">, + InGroup<Format>; def warn_null_arg : Warning< "null passed to a callee which requires a non-null argument">, InGroup<NonNull>; @@ -2454,12 +2511,18 @@ def warn_printf_asterisk_width_missing_arg : Warning< def warn_printf_asterisk_precision_missing_arg : Warning< "'.*' specified field precision is missing a matching 'int' argument">; def warn_printf_asterisk_width_wrong_type : Warning< - "field width should have type 'int', but argument has type %0">, + "field width should have type %0, but argument has type %1">, InGroup<Format>; def warn_printf_asterisk_precision_wrong_type : Warning< - "field precision should have type 'int', but argument has type %0">, + "field precision should have type %0, but argument has type %1">, InGroup<Format>; - +def warn_printf_nonsensical_precision: Warning< + "precision used in '%0' conversion specifier (where it has no meaning)">, + InGroup<Format>; +def warn_printf_nonsensical_flag: Warning< + "flag '%0' results in undefined behavior in '%1' conversion specifier">, + InGroup<Format>; + // CHECK: returning address/reference of stack memory def warn_ret_stack_addr : Warning< "address of stack memory associated with local variable %0 returned">; @@ -2511,6 +2574,10 @@ def warn_case_value_overflow : Warning< "overflow converting case value to switch condition type (%0 to %1)">; def err_duplicate_case : Error<"duplicate case value '%0'">; def warn_case_empty_range : Warning<"empty case range specified">; +def warn_missing_cases : Warning<"enumeration value %0 not handled in switch">, + InGroup<DiagGroup<"switch-enum"> >; +def not_in_enum : Warning<"case value not in enumerated type %0">, + InGroup<DiagGroup<"switch-enum"> >; def err_typecheck_statement_requires_scalar : Error< "statement requires expression of scalar type (%0 invalid)">; def err_typecheck_statement_requires_integer : Error< @@ -2679,6 +2746,7 @@ def err_undeclared_protocol_suggest : Error< "cannot find protocol declaration for %0; did you mean %1?">; def note_base_class_specified_here : Note< "base class %0 specified here">; + } diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 2b6092d..d909f83 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -40,12 +40,14 @@ public: unsigned ObjC1 : 1; // Objective-C 1 support enabled. unsigned ObjC2 : 1; // Objective-C 2 support enabled. unsigned ObjCNonFragileABI : 1; // Objective-C modern abi enabled + unsigned ObjCNonFragileABI2 : 1; // Objective-C enhanced modern abi enabled unsigned PascalStrings : 1; // Allow Pascal strings unsigned WritableStrings : 1; // Allow writable strings unsigned LaxVectorConversions : 1; unsigned AltiVec : 1; // Support AltiVec-style vector initializers. unsigned Exceptions : 1; // Support exception handling. + unsigned SjLjExceptions : 1; // Use setjmp-longjump exception handling. unsigned RTTI : 1; // Support RTTI information. unsigned NeXTRuntime : 1; // Use NeXT runtime. @@ -95,7 +97,9 @@ public: // operators unsigned ElideConstructors : 1; // Whether C++ copy constructors should be // elided if possible. - unsigned CatchUndefined :1; // Generate code to check for undefined ops. + unsigned CatchUndefined : 1; // Generate code to check for undefined ops. + unsigned DumpVtableLayouts : 1; // Dump the layouts of all the emitted + // vtables. private: unsigned GC : 2; // Objective-C Garbage Collection modes. We // declare this enum as unsigned because MSVC @@ -124,10 +128,10 @@ public: Trigraphs = BCPLComment = Bool = DollarIdents = AsmPreprocessor = 0; GNUMode = ImplicitInt = Digraphs = 0; HexFloats = 0; - GC = ObjC1 = ObjC2 = ObjCNonFragileABI = 0; + GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0; C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0; CXXOperatorNames = PascalStrings = WritableStrings = 0; - Exceptions = Freestanding = NoBuiltin = 0; + Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0; NeXTRuntime = 1; RTTI = 1; LaxVectorConversions = 1; @@ -136,8 +140,7 @@ public: SymbolVisibility = (unsigned) Default; - // FIXME: The default should be 1. - ThreadsafeStatics = 0; + ThreadsafeStatics = 1; POSIXThreads = 0; Blocks = 0; BlockIntrospection = 0; @@ -167,6 +170,7 @@ public: CharIsSigned = 1; ShortWChar = 0; CatchUndefined = 0; + DumpVtableLayouts = 0; } GCMode getGCMode() const { return (GCMode) GC; } diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h new file mode 100644 index 0000000..de0de34 --- /dev/null +++ b/include/clang/Basic/Linkage.h @@ -0,0 +1,57 @@ +//===--- Linkage.h - Linkage enumeration and utilities ----------*- 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 Linkage enumeration and various utility +// functions. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_BASIC_LINKAGE_H +#define LLVM_CLANG_BASIC_LINKAGE_H + +namespace clang { + +/// \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 within a unique namespace. From the + /// langauge perspective, these entities have external + /// linkage. However, since they reside in an anonymous namespace, + /// their names are unique to this translation unit, which is + /// equivalent to having internal linkage from the code-generation + /// point of view. + UniqueExternalLinkage, + + /// \brief External linkage, which indicates that the entity can + /// be referred to from other translation units. + ExternalLinkage +}; + +/// \brief Determine whether the given linkage is semantically +/// external. +inline bool isExternalLinkage(Linkage L) { + return L == UniqueExternalLinkage || L == ExternalLinkage; +} + +/// \brief Compute the minimum linkage given two linages. +static inline Linkage minLinkage(Linkage L1, Linkage L2) { + return L1 < L2? L1 : L2; +} + +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_LINKAGE_H diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h index 0d97012..873aaee 100644 --- a/include/clang/Basic/PartialDiagnostic.h +++ b/include/clang/Basic/PartialDiagnostic.h @@ -1,4 +1,4 @@ -//===--- PartialDiagnostic.h - Diagnostic "closures" ----------------------===// +//===--- PartialDiagnostic.h - Diagnostic "closures" ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index b4cf959..15ece68 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -669,12 +669,20 @@ public: ::const_iterator fileinfo_iterator; fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); } fileinfo_iterator fileinfo_end() const { return FileInfos.end(); } + bool hasFileInfo(const FileEntry *File) const { + return FileInfos.find(File) != FileInfos.end(); + } /// PrintStats - Print statistics to stderr. /// void PrintStats() const; unsigned sloc_entry_size() const { return SLocEntryTable.size(); } + + // FIXME: Exposing this is a little gross; what we want is a good way + // to iterate the entries that were not defined in a PCH file (or + // any other external source). + unsigned sloc_loaded_entry_size() const { return SLocEntryLoaded.size(); } const SrcMgr::SLocEntry &getSLocEntry(unsigned ID) const { assert(ID < SLocEntryTable.size() && "Invalid id"); diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index 4cace86..9e54762a 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -77,6 +77,7 @@ namespace clang { AS_private, AS_none }; -} + +} // end namespace clang #endif // LLVM_CLANG_BASIC_SPECIFIERS_H diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 97e0495..bc2cf19 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -226,11 +226,11 @@ public: /// isValidGCCRegisterName - Returns whether the passed in string /// is a valid register name according to GCC. This is used by Sema for /// inline asm statements. - bool isValidGCCRegisterName(const char *Name) const; + bool isValidGCCRegisterName(llvm::StringRef Name) const; // getNormalizedGCCRegisterName - Returns the "normalized" GCC register name. // For example, on x86 it will return "ax" when "eax" is passed in. - const char *getNormalizedGCCRegisterName(const char *Name) const; + llvm::StringRef getNormalizedGCCRegisterName(llvm::StringRef Name) const; struct ConstraintInfo { enum { @@ -246,10 +246,9 @@ public: std::string ConstraintStr; // constraint: "=rm" std::string Name; // Operand name: [foo] with no []'s. public: - ConstraintInfo(const char *str, unsigned strlen, const std::string &name) - : Flags(0), TiedOperand(-1), ConstraintStr(str, str+strlen), Name(name) {} - explicit ConstraintInfo(const std::string &Str, const std::string &name) - : Flags(0), TiedOperand(-1), ConstraintStr(Str), Name(name) {} + ConstraintInfo(llvm::StringRef ConstraintStr, llvm::StringRef Name) + : Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()), + Name(Name.str()) {} const std::string &getConstraintStr() const { return ConstraintStr; } const std::string &getName() const { return Name; } @@ -321,12 +320,6 @@ public: virtual bool useGlobalsForAutomaticVariables() const { return false; } - /// getUnicodeStringSection - Return the section to use for unicode - /// string literals, or 0 if no special section is used. - virtual const char *getUnicodeStringSection() const { - return 0; - } - /// getCFStringSection - Return the section to use for CFString /// literals, or 0 if no special section is used. virtual const char *getCFStringSection() const { @@ -343,7 +336,7 @@ public: /// and give good diagnostics in cases when the assembler or code generator /// would otherwise reject the section specifier. /// - virtual std::string isValidSectionSpecifier(const llvm::StringRef &SR) const { + virtual std::string isValidSectionSpecifier(llvm::StringRef SR) const { return ""; } diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index bb022f1..522ac13 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -227,7 +227,7 @@ KEYWORD(__func__ , KEYALL) // C++ 2.11p1: Keywords. KEYWORD(asm , KEYCXX|KEYGNU) -KEYWORD(bool , BOOLSUPPORT) +KEYWORD(bool , BOOLSUPPORT|KEYALTIVEC) KEYWORD(catch , KEYCXX) KEYWORD(class , KEYCXX) KEYWORD(const_cast , KEYCXX) @@ -235,7 +235,7 @@ KEYWORD(delete , KEYCXX) KEYWORD(dynamic_cast , KEYCXX) KEYWORD(explicit , KEYCXX) KEYWORD(export , KEYCXX) -KEYWORD(false , BOOLSUPPORT) +KEYWORD(false , BOOLSUPPORT|KEYALTIVEC) KEYWORD(friend , KEYCXX) KEYWORD(mutable , KEYCXX) KEYWORD(namespace , KEYCXX) @@ -249,7 +249,7 @@ KEYWORD(static_cast , KEYCXX) KEYWORD(template , KEYCXX) KEYWORD(this , KEYCXX) KEYWORD(throw , KEYCXX) -KEYWORD(true , BOOLSUPPORT) +KEYWORD(true , BOOLSUPPORT|KEYALTIVEC) KEYWORD(try , KEYCXX) KEYWORD(typename , KEYCXX) KEYWORD(typeid , KEYCXX) @@ -340,6 +340,10 @@ KEYWORD(__ptr64 , KEYALL) KEYWORD(__w64 , KEYALL) KEYWORD(__forceinline , KEYALL) +// Altivec Extension. +KEYWORD(__vector , KEYALTIVEC) +KEYWORD(__pixel , KEYALTIVEC) + // Alternate spelling for various tokens. There are GCC extensions in all // languages, but should not be disabled in strict conformance mode. ALIAS("__attribute__", __attribute, KEYALL) diff --git a/include/clang/Basic/Version.h b/include/clang/Basic/Version.h index 4710b6b..2728637 100644 --- a/include/clang/Basic/Version.h +++ b/include/clang/Basic/Version.h @@ -56,16 +56,16 @@ namespace clang { /// \brief Retrieves the repository revision number (or identifer) from which /// this Clang was built. - llvm::StringRef getClangRevision(); + std::string getClangRevision(); /// \brief Retrieves the full repository version that is an amalgamation of /// the information in getClangRepositoryPath() and getClangRevision(). - llvm::StringRef getClangFullRepositoryVersion(); + std::string getClangFullRepositoryVersion(); /// \brief Retrieves a string representing the complete clang version, /// which includes the clang version number, the repository version, /// and the vendor tag. - const char *getClangFullVersion(); + std::string getClangFullVersion(); } #endif // LLVM_CLANG_BASIC_VERSION_H diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Checker/BugReporter/BugReporter.h index 6f6681a..6c41668 100644 --- a/include/clang/Analysis/PathSensitive/BugReporter.h +++ b/include/clang/Checker/BugReporter/BugReporter.h @@ -17,9 +17,9 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Analysis/PathSensitive/GRState.h" -#include "clang/Analysis/PathSensitive/ExplodedGraph.h" -#include "clang/Analysis/PathSensitive/BugType.h" +#include "clang/Checker/PathSensitive/GRState.h" +#include "clang/Checker/PathSensitive/ExplodedGraph.h" +#include "clang/Checker/BugReporter/BugType.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" @@ -202,7 +202,7 @@ public: ~RangedBugReport(); // FIXME: Move this out of line. - void addRange(SourceRange R) { + void addRange(SourceRange R) { assert(R.isValid()); Ranges.push_back(R); } @@ -464,6 +464,10 @@ const Stmt *GetRetValExpr(const ExplodedNode *N); void registerTrackNullOrUndefValue(BugReporterContext& BRC, const void *stmt, const ExplodedNode* N); +void registerFindLastStore(BugReporterContext& BRC, const void *memregion, + const ExplodedNode *N); + + } // end namespace clang::bugreporter //===----------------------------------------------------------------------===// diff --git a/include/clang/Analysis/PathSensitive/BugType.h b/include/clang/Checker/BugReporter/BugType.h index b75a818..4f1523a 100644 --- a/include/clang/Analysis/PathSensitive/BugType.h +++ b/include/clang/Checker/BugReporter/BugType.h @@ -14,7 +14,6 @@ #ifndef LLVM_CLANG_ANALYSIS_BUGTYPE #define LLVM_CLANG_ANALYSIS_BUGTYPE -#include "clang/Analysis/PathSensitive/BugReporter.h" #include <llvm/ADT/FoldingSet.h> #include <string> diff --git a/include/clang/Analysis/PathDiagnostic.h b/include/clang/Checker/BugReporter/PathDiagnostic.h index d380c45..d380c45 100644 --- a/include/clang/Analysis/PathDiagnostic.h +++ b/include/clang/Checker/BugReporter/PathDiagnostic.h diff --git a/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h b/include/clang/Checker/Checkers/DereferenceChecker.h index a84183e..a84183e 100644 --- a/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h +++ b/include/clang/Checker/Checkers/DereferenceChecker.h diff --git a/include/clang/Analysis/LocalCheckers.h b/include/clang/Checker/Checkers/LocalCheckers.h index 9c343e0..4a9e381 100644 --- a/include/clang/Analysis/LocalCheckers.h +++ b/include/clang/Checker/Checkers/LocalCheckers.h @@ -31,13 +31,11 @@ class BugReporter; class ObjCImplementationDecl; class LangOptions; class GRExprEngine; +class TranslationUnitDecl; void CheckDeadStores(CFG &cfg, LiveVariables &L, ParentMap &map, BugReporter& BR); -void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags, - bool FullUninitTaint=false); - GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled, const LangOptions& lopts); @@ -53,8 +51,8 @@ void RegisterAppleChecks(GRExprEngine& Eng, const Decl &D); void RegisterExperimentalChecks(GRExprEngine &Eng); void RegisterExperimentalInternalChecks(GRExprEngine &Eng); +void CheckLLVMConventions(TranslationUnitDecl &TU, BugReporter &BR); void CheckSecuritySyntaxOnly(const Decl *D, BugReporter &BR); - void CheckSizeofPointer(const Decl *D, BugReporter &BR); void RegisterCallInliner(GRExprEngine &Eng); diff --git a/include/clang/Checker/DomainSpecific/CocoaConventions.h b/include/clang/Checker/DomainSpecific/CocoaConventions.h new file mode 100644 index 0000000..ee3d648 --- /dev/null +++ b/include/clang/Checker/DomainSpecific/CocoaConventions.h @@ -0,0 +1,40 @@ +//===- CocoaConventions.h - Special handling of Cocoa conventions -*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CHECKER_DS_COCOA +#define LLVM_CLANG_CHECKER_DS_COCOA + +#include "clang/Basic/IdentifierTable.h" +#include "clang/AST/Type.h" + +namespace clang { +namespace cocoa { + + enum NamingConvention { NoConvention, CreateRule, InitRule }; + + NamingConvention deriveNamingConvention(Selector S); + + static inline bool followsFundamentalRule(Selector S) { + return deriveNamingConvention(S) == CreateRule; + } + + bool isRefType(QualType RetTy, llvm::StringRef Prefix, + llvm::StringRef Name = llvm::StringRef()); + + bool isCFObjectRef(QualType T); + + bool isCocoaObjectRef(QualType T); + +}} + +#endif diff --git a/include/clang/Analysis/ManagerRegistry.h b/include/clang/Checker/ManagerRegistry.h index 9729938..ebfd28e 100644 --- a/include/clang/Analysis/ManagerRegistry.h +++ b/include/clang/Checker/ManagerRegistry.h @@ -14,7 +14,7 @@ #ifndef LLVM_CLANG_ANALYSIS_MANAGER_REGISTRY_H #define LLVM_CLANG_ANALYSIS_MANAGER_REGISTRY_H -#include "clang/Analysis/PathSensitive/GRState.h" +#include "clang/Checker/PathSensitive/GRState.h" namespace clang { diff --git a/include/clang/Analysis/PathSensitive/AnalysisManager.h b/include/clang/Checker/PathSensitive/AnalysisManager.h index 8288864..fdf52a7 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisManager.h +++ b/include/clang/Checker/PathSensitive/AnalysisManager.h @@ -15,9 +15,9 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSISMANAGER_H #define LLVM_CLANG_ANALYSIS_ANALYSISMANAGER_H -#include "clang/Analysis/PathSensitive/BugReporter.h" -#include "clang/Analysis/PathSensitive/AnalysisContext.h" -#include "clang/Analysis/PathDiagnostic.h" +#include "clang/Analysis/AnalysisContext.h" +#include "clang/Checker/BugReporter/BugReporter.h" +#include "clang/Checker/BugReporter/PathDiagnostic.h" namespace clang { diff --git a/include/clang/Analysis/PathSensitive/BasicValueFactory.h b/include/clang/Checker/PathSensitive/BasicValueFactory.h index 12f0ce2..2f0b6c2 100644 --- a/include/clang/Analysis/PathSensitive/BasicValueFactory.h +++ b/include/clang/Checker/PathSensitive/BasicValueFactory.h @@ -16,8 +16,8 @@ #ifndef LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H #define LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H -#include "clang/Analysis/PathSensitive/SymbolManager.h" -#include "clang/Analysis/PathSensitive/SVals.h" +#include "clang/Checker/PathSensitive/SymbolManager.h" +#include "clang/Checker/PathSensitive/SVals.h" #include "clang/AST/ASTContext.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/APSInt.h" @@ -46,19 +46,19 @@ public: }; class LazyCompoundValData : public llvm::FoldingSetNode { - const GRState *state; + const void *store; const TypedRegion *region; public: - LazyCompoundValData(const GRState *st, const TypedRegion *r) - : state(st), region(r) {} + LazyCompoundValData(const void *st, const TypedRegion *r) + : store(st), region(r) {} - const GRState *getState() const { return state; } + const void *getStore() const { return store; } const TypedRegion *getRegion() const { return region; } - static void Profile(llvm::FoldingSetNodeID& ID, const GRState *state, + static void Profile(llvm::FoldingSetNodeID& ID, const void *store, const TypedRegion *region); - void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, state, region); } + void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); } }; class BasicValueFactory { @@ -169,7 +169,7 @@ public: const CompoundValData *getCompoundValData(QualType T, llvm::ImmutableList<SVal> Vals); - const LazyCompoundValData *getLazyCompoundValData(const GRState *state, + const LazyCompoundValData *getLazyCompoundValData(const void *store, const TypedRegion *region); llvm::ImmutableList<SVal> getEmptySValList() { diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Checker/PathSensitive/Checker.h index 924a8b1..d498044 100644 --- a/include/clang/Analysis/PathSensitive/Checker.h +++ b/include/clang/Checker/PathSensitive/Checker.h @@ -15,9 +15,9 @@ #ifndef LLVM_CLANG_ANALYSIS_CHECKER #define LLVM_CLANG_ANALYSIS_CHECKER #include "clang/Analysis/Support/SaveAndRestore.h" -#include "clang/Analysis/PathSensitive/GRCoreEngine.h" -#include "clang/Analysis/PathSensitive/GRState.h" -#include "clang/Analysis/PathSensitive/GRExprEngine.h" +#include "clang/Checker/PathSensitive/GRCoreEngine.h" +#include "clang/Checker/PathSensitive/GRState.h" +#include "clang/Checker/PathSensitive/GRExprEngine.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/StmtCXX.h" diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.def b/include/clang/Checker/PathSensitive/CheckerVisitor.def index 7ec27ef..2edc4a3 100644 --- a/include/clang/Analysis/PathSensitive/CheckerVisitor.def +++ b/include/clang/Checker/PathSensitive/CheckerVisitor.def @@ -22,7 +22,6 @@ PREVISIT(ArraySubscriptExpr, Stmt) PREVISIT(BinaryOperator, Stmt) PREVISIT(CallExpr, Stmt) -PREVISIT(CastExpr, Stmt) PREVISIT(CXXOperatorCallExpr, CallExpr) PREVISIT(DeclStmt, Stmt) PREVISIT(ObjCMessageExpr, Stmt) diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.h b/include/clang/Checker/PathSensitive/CheckerVisitor.h index 37ec8de..72f0ae1 100644 --- a/include/clang/Analysis/PathSensitive/CheckerVisitor.h +++ b/include/clang/Checker/PathSensitive/CheckerVisitor.h @@ -13,7 +13,7 @@ #ifndef LLVM_CLANG_ANALYSIS_CHECKERVISITOR #define LLVM_CLANG_ANALYSIS_CHECKERVISITOR -#include "clang/Analysis/PathSensitive/Checker.h" +#include "clang/Checker/PathSensitive/Checker.h" namespace clang { @@ -42,7 +42,6 @@ public: return; case Stmt::ImplicitCastExprClass: - case Stmt::ExplicitCastExprClass: case Stmt::CStyleCastExprClass: static_cast<ImplClass*>(this)->PreVisitCastExpr(C, static_cast<const CastExpr*>(S)); @@ -57,7 +56,7 @@ public: case Stmt::NAME ## Class:\ static_cast<ImplClass*>(this)->PreVisit ## NAME(C,static_cast<const NAME*>(S));\ break; -#include "clang/Analysis/PathSensitive/CheckerVisitor.def" +#include "clang/Checker/PathSensitive/CheckerVisitor.def" } } @@ -76,24 +75,26 @@ case Stmt::NAME ## Class:\ static_cast<ImplClass*>(this)->\ PostVisit ## NAME(C,static_cast<const NAME*>(S));\ break; -#include "clang/Analysis/PathSensitive/CheckerVisitor.def" +#include "clang/Checker/PathSensitive/CheckerVisitor.def" } } void PreVisitStmt(CheckerContext &C, const Stmt *S) {} void PostVisitStmt(CheckerContext &C, const Stmt *S) {} + + void PreVisitCastExpr(CheckerContext &C, const CastExpr *E) { + static_cast<ImplClass*>(this)->PreVisitStmt(C, E); + } #define PREVISIT(NAME, FALLBACK) \ void PreVisit ## NAME(CheckerContext &C, const NAME* S) {\ - PreVisit ## FALLBACK(C, S);\ + static_cast<ImplClass*>(this)->PreVisit ## FALLBACK(C, S);\ } -#include "clang/Analysis/PathSensitive/CheckerVisitor.def" - #define POSTVISIT(NAME, FALLBACK) \ void PostVisit ## NAME(CheckerContext &C, const NAME* S) {\ - PostVisit ## FALLBACK(C, S);\ + static_cast<ImplClass*>(this)->PostVisit ## FALLBACK(C, S);\ } -#include "clang/Analysis/PathSensitive/CheckerVisitor.def" +#include "clang/Checker/PathSensitive/CheckerVisitor.def" }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/ConstraintManager.h b/include/clang/Checker/PathSensitive/ConstraintManager.h index c829280..ce7d1b3 100644 --- a/include/clang/Analysis/PathSensitive/ConstraintManager.h +++ b/include/clang/Checker/PathSensitive/ConstraintManager.h @@ -15,7 +15,7 @@ #define LLVM_CLANG_ANALYSIS_CONSTRAINT_MANAGER_H // FIXME: Typedef LiveSymbolsTy/DeadSymbolsTy at a more appropriate place. -#include "clang/Analysis/PathSensitive/Store.h" +#include "clang/Checker/PathSensitive/Store.h" namespace llvm { class APSInt; diff --git a/include/clang/Analysis/PathSensitive/Environment.h b/include/clang/Checker/PathSensitive/Environment.h index 6d5c567..0852c31 100644 --- a/include/clang/Analysis/PathSensitive/Environment.h +++ b/include/clang/Checker/PathSensitive/Environment.h @@ -16,11 +16,11 @@ // For using typedefs in StoreManager. Should find a better place for these // typedefs. -#include "clang/Analysis/PathSensitive/Store.h" +#include "clang/Checker/PathSensitive/Store.h" #include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/SmallVector.h" -#include "clang/Analysis/PathSensitive/SVals.h" +#include "clang/Checker/PathSensitive/SVals.h" #include "llvm/Support/Allocator.h" #include "llvm/ADT/FoldingSet.h" diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Checker/PathSensitive/ExplodedGraph.h index fb5e1b8..d6c4436 100644 --- a/include/clang/Analysis/PathSensitive/ExplodedGraph.h +++ b/include/clang/Checker/PathSensitive/ExplodedGraph.h @@ -16,7 +16,7 @@ #define LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH #include "clang/Analysis/ProgramPoint.h" -#include "clang/Analysis/PathSensitive/AnalysisContext.h" +#include "clang/Analysis/AnalysisContext.h" #include "clang/AST/Decl.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/FoldingSet.h" diff --git a/include/clang/Analysis/PathSensitive/GRAuditor.h b/include/clang/Checker/PathSensitive/GRAuditor.h index 015c82e..015c82e 100644 --- a/include/clang/Analysis/PathSensitive/GRAuditor.h +++ b/include/clang/Checker/PathSensitive/GRAuditor.h diff --git a/include/clang/Analysis/PathSensitive/GRBlockCounter.h b/include/clang/Checker/PathSensitive/GRBlockCounter.h index 67ed953..67ed953 100644 --- a/include/clang/Analysis/PathSensitive/GRBlockCounter.h +++ b/include/clang/Checker/PathSensitive/GRBlockCounter.h diff --git a/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h index 74f7a14..6da4581 100644 --- a/include/clang/Analysis/PathSensitive/GRCoreEngine.h +++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h @@ -16,11 +16,11 @@ #define LLVM_CLANG_ANALYSIS_GRENGINE #include "clang/AST/Expr.h" -#include "clang/Analysis/PathSensitive/ExplodedGraph.h" -#include "clang/Analysis/PathSensitive/GRWorkList.h" -#include "clang/Analysis/PathSensitive/GRBlockCounter.h" -#include "clang/Analysis/PathSensitive/GRAuditor.h" -#include "clang/Analysis/PathSensitive/GRSubEngine.h" +#include "clang/Checker/PathSensitive/ExplodedGraph.h" +#include "clang/Checker/PathSensitive/GRWorkList.h" +#include "clang/Checker/PathSensitive/GRBlockCounter.h" +#include "clang/Checker/PathSensitive/GRAuditor.h" +#include "clang/Checker/PathSensitive/GRSubEngine.h" #include "llvm/ADT/OwningPtr.h" namespace clang { diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index df90ad9..90a2cd5 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -16,13 +16,13 @@ #ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE #define LLVM_CLANG_ANALYSIS_GREXPRENGINE -#include "clang/Analysis/PathSensitive/AnalysisManager.h" -#include "clang/Analysis/PathSensitive/GRSubEngine.h" -#include "clang/Analysis/PathSensitive/GRCoreEngine.h" -#include "clang/Analysis/PathSensitive/GRState.h" -#include "clang/Analysis/PathSensitive/GRSimpleAPICheck.h" -#include "clang/Analysis/PathSensitive/GRTransferFuncs.h" -#include "clang/Analysis/PathSensitive/BugReporter.h" +#include "clang/Checker/PathSensitive/AnalysisManager.h" +#include "clang/Checker/PathSensitive/GRSubEngine.h" +#include "clang/Checker/PathSensitive/GRCoreEngine.h" +#include "clang/Checker/PathSensitive/GRState.h" +#include "clang/Checker/PathSensitive/GRSimpleAPICheck.h" +#include "clang/Checker/PathSensitive/GRTransferFuncs.h" +#include "clang/Checker/BugReporter/BugReporter.h" #include "clang/AST/Type.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprCXX.h" @@ -328,17 +328,6 @@ protected: void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred, ExplodedNodeSet& Dst, bool asLValue); - void VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME, - ObjCMessageExpr::arg_iterator I, - ObjCMessageExpr::arg_iterator E, - ExplodedNode* Pred, ExplodedNodeSet& Dst, - bool asLValue); - - void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, - ExplodedNode* Pred, - ExplodedNodeSet& Dst, - bool asLValue); - /// VisitReturnStmt - Transfer function logic for return statements. void VisitReturnStmt(ReturnStmt* R, ExplodedNode* Pred, ExplodedNodeSet& Dst); diff --git a/include/clang/Analysis/PathSensitive/GRExprEngineBuilders.h b/include/clang/Checker/PathSensitive/GRExprEngineBuilders.h index 60db406..5503412 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngineBuilders.h +++ b/include/clang/Checker/PathSensitive/GRExprEngineBuilders.h @@ -14,7 +14,7 @@ #ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE_BUILDERS #define LLVM_CLANG_ANALYSIS_GREXPRENGINE_BUILDERS -#include "clang/Analysis/PathSensitive/GRExprEngine.h" +#include "clang/Checker/PathSensitive/GRExprEngine.h" #include "clang/Analysis/Support/SaveAndRestore.h" namespace clang { diff --git a/include/clang/Analysis/PathSensitive/GRSimpleAPICheck.h b/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h index 978ff08..383463b 100644 --- a/include/clang/Analysis/PathSensitive/GRSimpleAPICheck.h +++ b/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h @@ -16,8 +16,8 @@ #ifndef LLVM_CLANG_ANALYSIS_GRAPICHECKS #define LLVM_CLANG_ANALYSIS_GRAPICHECKS -#include "clang/Analysis/PathSensitive/GRAuditor.h" -#include "clang/Analysis/PathSensitive/GRState.h" +#include "clang/Checker/PathSensitive/GRAuditor.h" +#include "clang/Checker/PathSensitive/GRState.h" namespace clang { diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Checker/PathSensitive/GRState.h index 11cdac0..4e44697 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Checker/PathSensitive/GRState.h @@ -16,11 +16,11 @@ // FIXME: Reduce the number of includes. -#include "clang/Analysis/PathSensitive/Environment.h" -#include "clang/Analysis/PathSensitive/Store.h" -#include "clang/Analysis/PathSensitive/ConstraintManager.h" -#include "clang/Analysis/PathSensitive/ValueManager.h" -#include "clang/Analysis/PathSensitive/GRCoreEngine.h" +#include "clang/Checker/PathSensitive/Environment.h" +#include "clang/Checker/PathSensitive/Store.h" +#include "clang/Checker/PathSensitive/ConstraintManager.h" +#include "clang/Checker/PathSensitive/ValueManager.h" +#include "clang/Checker/PathSensitive/GRCoreEngine.h" #include "clang/AST/Expr.h" #include "clang/AST/Decl.h" #include "clang/AST/ASTContext.h" @@ -216,7 +216,7 @@ public: /// in 'state' plus the bindings for the CompoundLiteral. 'R' is the region /// for the compound literal and 'BegInit' and 'EndInit' represent an /// array of initializer values. - const GRState* bindCompoundLiteral(const CompoundLiteralExpr* CL, + const GRState *bindCompoundLiteral(const CompoundLiteralExpr* CL, const LocationContext *LC, SVal V) const; @@ -607,19 +607,24 @@ inline const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx, inline const GRState * GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL, const LocationContext *LC, SVal V) const { - return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, LC, V); + Store new_store = + getStateManager().StoreMgr->BindCompoundLiteral(St, CL, LC, V); + return makeWithStore(new_store); } inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const { - return getStateManager().StoreMgr->BindDecl(this, VR, IVal); + Store new_store = getStateManager().StoreMgr->BindDecl(St, VR, IVal); + return makeWithStore(new_store); } inline const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const { - return getStateManager().StoreMgr->BindDeclWithNoInit(this, VR); + Store new_store = getStateManager().StoreMgr->BindDeclWithNoInit(St, VR); + return makeWithStore(new_store); } inline const GRState *GRState::bindLoc(Loc LV, SVal V) const { - return getStateManager().StoreMgr->Bind(this, LV, V); + Store new_store = getStateManager().StoreMgr->Bind(St, LV, V); + return makeWithStore(new_store); } inline const GRState *GRState::bindLoc(SVal LV, SVal V) const { @@ -671,11 +676,11 @@ inline SVal GRState::getSValAsScalarOrLoc(const Stmt *S) const { } inline SVal GRState::getSVal(Loc LV, QualType T) const { - return getStateManager().StoreMgr->Retrieve(this, LV, T).getSVal(); + return getStateManager().StoreMgr->Retrieve(St, LV, T); } inline SVal GRState::getSVal(const MemRegion* R) const { - return getStateManager().StoreMgr->Retrieve(this, loc::MemRegionVal(R)).getSVal(); + return getStateManager().StoreMgr->Retrieve(St, loc::MemRegionVal(R)); } inline BasicValueFactory &GRState::getBasicVals() const { diff --git a/include/clang/Analysis/PathSensitive/GRStateTrait.h b/include/clang/Checker/PathSensitive/GRStateTrait.h index 5189a1f..5189a1f 100644 --- a/include/clang/Analysis/PathSensitive/GRStateTrait.h +++ b/include/clang/Checker/PathSensitive/GRStateTrait.h diff --git a/include/clang/Analysis/PathSensitive/GRSubEngine.h b/include/clang/Checker/PathSensitive/GRSubEngine.h index 5b383fa..ce57c2c 100644 --- a/include/clang/Analysis/PathSensitive/GRSubEngine.h +++ b/include/clang/Checker/PathSensitive/GRSubEngine.h @@ -13,7 +13,7 @@ #ifndef LLVM_CLANG_ANALYSIS_GRSUBENGINE_H #define LLVM_CLANG_ANALYSIS_GRSUBENGINE_H -#include "clang/Analysis/PathSensitive/SVals.h" +#include "clang/Checker/PathSensitive/SVals.h" namespace clang { diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Checker/PathSensitive/GRTransferFuncs.h index b058460..04634ef 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Checker/PathSensitive/GRTransferFuncs.h @@ -15,9 +15,9 @@ #ifndef LLVM_CLANG_ANALYSIS_GRTF #define LLVM_CLANG_ANALYSIS_GRTF -#include "clang/Analysis/PathSensitive/SVals.h" -#include "clang/Analysis/PathSensitive/GRCoreEngine.h" -#include "clang/Analysis/PathSensitive/GRState.h" +#include "clang/Checker/PathSensitive/SVals.h" +#include "clang/Checker/PathSensitive/GRCoreEngine.h" +#include "clang/Checker/PathSensitive/GRState.h" #include <vector> namespace clang { diff --git a/include/clang/Analysis/PathSensitive/GRWorkList.h b/include/clang/Checker/PathSensitive/GRWorkList.h index 857fa31..b8f90fa 100644 --- a/include/clang/Analysis/PathSensitive/GRWorkList.h +++ b/include/clang/Checker/PathSensitive/GRWorkList.h @@ -15,7 +15,7 @@ #ifndef LLVM_CLANG_ANALYSIS_GRWORKLIST #define LLVM_CLANG_ANALYSIS_GRWORKLIST -#include "clang/Analysis/PathSensitive/GRBlockCounter.h" +#include "clang/Checker/PathSensitive/GRBlockCounter.h" #include <cstddef> namespace clang { diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Checker/PathSensitive/MemRegion.h index 3bcedbe..12bc0b7 100644 --- a/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/include/clang/Checker/PathSensitive/MemRegion.h @@ -18,8 +18,8 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" -#include "clang/Analysis/PathSensitive/SymbolManager.h" -#include "clang/Analysis/PathSensitive/SVals.h" +#include "clang/Checker/PathSensitive/SymbolManager.h" +#include "clang/Checker/PathSensitive/SVals.h" #include "clang/AST/ASTContext.h" #include "llvm/Support/Casting.h" #include "llvm/ADT/FoldingSet.h" @@ -249,17 +249,20 @@ public: class ElementRegion; -class RegionRawOffset : public std::pair<const MemRegion*, int64_t> { +class RegionRawOffset { private: friend class ElementRegion; + const MemRegion *Region; + int64_t Offset; + RegionRawOffset(const MemRegion* reg, int64_t offset = 0) - : std::pair<const MemRegion*, int64_t>(reg, offset) {} + : Region(reg), Offset(offset) {} public: // FIXME: Eventually support symbolic offsets. - int64_t getByteOffset() const { return second; } - const MemRegion *getRegion() const { return first; } + int64_t getByteOffset() const { return Offset; } + const MemRegion *getRegion() const { return Region; } void dumpToStream(llvm::raw_ostream& os) const; void dump() const; diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Checker/PathSensitive/SVals.h index 9206817..65a8a2c 100644 --- a/include/clang/Analysis/PathSensitive/SVals.h +++ b/include/clang/Checker/PathSensitive/SVals.h @@ -15,7 +15,7 @@ #ifndef LLVM_CLANG_ANALYSIS_RVALUE_H #define LLVM_CLANG_ANALYSIS_RVALUE_H -#include "clang/Analysis/PathSensitive/SymbolManager.h" +#include "clang/Checker/PathSensitive/SymbolManager.h" #include "llvm/Support/Casting.h" #include "llvm/ADT/ImmutableList.h" @@ -388,7 +388,7 @@ public: const LazyCompoundValData *getCVData() const { return static_cast<const LazyCompoundValData*>(Data); } - const GRState *getState() const; + const void *getStore() const; const TypedRegion *getRegion() const; static bool classof(const SVal *V) { diff --git a/include/clang/Analysis/PathSensitive/SValuator.h b/include/clang/Checker/PathSensitive/SValuator.h index 4a4b502..9beb8cb 100644 --- a/include/clang/Analysis/PathSensitive/SValuator.h +++ b/include/clang/Checker/PathSensitive/SValuator.h @@ -16,7 +16,7 @@ #define LLVM_CLANG_ANALYSIS_SVALUATOR #include "clang/AST/Expr.h" -#include "clang/Analysis/PathSensitive/SVals.h" +#include "clang/Checker/PathSensitive/SVals.h" namespace clang { @@ -38,33 +38,8 @@ public: SValuator(ValueManager &valMgr) : ValMgr(valMgr) {} virtual ~SValuator() {} - template <typename T> - class GenericCastResult : public std::pair<const GRState *, T> { - public: - const GRState *getState() const { return this->first; } - T getSVal() const { return this->second; } - GenericCastResult(const GRState *s, T v) - : std::pair<const GRState*,T>(s, v) {} - }; + SVal EvalCast(SVal V, QualType castTy, QualType originalType); - class CastResult : public GenericCastResult<SVal> { - public: - CastResult(const GRState *s, SVal v) : GenericCastResult<SVal>(s, v) {} - }; - - class DefinedOrUnknownCastResult : - public GenericCastResult<DefinedOrUnknownSVal> { - public: - DefinedOrUnknownCastResult(const GRState *s, DefinedOrUnknownSVal v) - : GenericCastResult<DefinedOrUnknownSVal>(s, v) {} - }; - - CastResult EvalCast(SVal V, const GRState *ST, - QualType castTy, QualType originalType); - - DefinedOrUnknownCastResult EvalCast(DefinedOrUnknownSVal V, const GRState *ST, - QualType castTy, QualType originalType); - virtual SVal EvalMinus(NonLoc val) = 0; virtual SVal EvalComplement(NonLoc val) = 0; diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Checker/PathSensitive/Store.h index 5606df0..c660e7b 100644 --- a/include/clang/Analysis/PathSensitive/Store.h +++ b/include/clang/Checker/PathSensitive/Store.h @@ -14,9 +14,9 @@ #ifndef LLVM_CLANG_ANALYSIS_STORE_H #define LLVM_CLANG_ANALYSIS_STORE_H -#include "clang/Analysis/PathSensitive/MemRegion.h" -#include "clang/Analysis/PathSensitive/SVals.h" -#include "clang/Analysis/PathSensitive/ValueManager.h" +#include "clang/Checker/PathSensitive/MemRegion.h" +#include "clang/Checker/PathSensitive/SVals.h" +#include "clang/Checker/PathSensitive/ValueManager.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" @@ -41,6 +41,7 @@ protected: /// MRMgr - Manages region objects associated with this StoreManager. MemRegionManager &MRMgr; + ASTContext &Ctx; StoreManager(GRStateManager &stateMgr); @@ -54,8 +55,7 @@ public: /// expected type of the returned value. This is used if the value is /// lazily computed. /// \return The value bound to the location \c loc. - virtual SValuator::CastResult Retrieve(const GRState *state, Loc loc, - QualType T = QualType()) = 0; + virtual SVal Retrieve(Store store, Loc loc, QualType T = QualType()) = 0; /// Return a state with the specified value bound to the given location. /// \param[in] state The analysis state. @@ -64,7 +64,7 @@ public: /// \return A pointer to a GRState object that contains the same bindings as /// \c state with the addition of having the value specified by \c val bound /// to the location given for \c loc. - virtual const GRState *Bind(const GRState *state, Loc loc, SVal val) = 0; + virtual Store Bind(Store store, Loc loc, SVal val) = 0; virtual Store Remove(Store St, Loc L) = 0; @@ -72,10 +72,9 @@ public: /// in 'store' plus the bindings for the CompoundLiteral. 'R' is the region /// for the compound literal and 'BegInit' and 'EndInit' represent an /// array of initializer values. - virtual const GRState *BindCompoundLiteral(const GRState *state, - const CompoundLiteralExpr* cl, - const LocationContext *LC, - SVal v) = 0; + virtual Store BindCompoundLiteral(Store store, + const CompoundLiteralExpr* cl, + const LocationContext *LC, SVal v) = 0; /// getInitialStore - Returns the initial "empty" store representing the /// value bindings upon entry to an analyzed function. @@ -88,20 +87,30 @@ public: /// getSubRegionMap - Returns an opaque map object that clients can query /// to get the subregions of a given MemRegion object. It is the // caller's responsibility to 'delete' the returned map. - virtual SubRegionMap *getSubRegionMap(const GRState *state) = 0; + virtual SubRegionMap *getSubRegionMap(Store store) = 0; - virtual SVal getLValueVar(const VarDecl *VD, const LocationContext *LC) = 0; + virtual SVal getLValueVar(const VarDecl *VD, const LocationContext *LC) { + return ValMgr.makeLoc(MRMgr.getVarRegion(VD, LC)); + } - virtual SVal getLValueString(const StringLiteral* sl) = 0; + virtual SVal getLValueString(const StringLiteral* S) { + return ValMgr.makeLoc(MRMgr.getStringRegion(S)); + } - SVal getLValueCompoundLiteral(const CompoundLiteralExpr* cl, - const LocationContext *LC); + SVal getLValueCompoundLiteral(const CompoundLiteralExpr* CL, + const LocationContext *LC) { + return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC)); + } - virtual SVal getLValueIvar(const ObjCIvarDecl* decl, SVal base) = 0; + virtual SVal getLValueIvar(const ObjCIvarDecl* decl, SVal base) { + return getLValueFieldOrIvar(decl, base); + } - virtual SVal getLValueField(const FieldDecl* D, SVal Base) = 0; + virtual SVal getLValueField(const FieldDecl* D, SVal Base) { + return getLValueFieldOrIvar(D, Base); + } - virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base)=0; + virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base); // FIXME: Make out-of-line. virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state, @@ -129,33 +138,31 @@ public: const MemRegion *CastRegion(const MemRegion *region, QualType CastToTy); /// EvalBinOp - Perform pointer arithmetic. - virtual SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode Op, + virtual SVal EvalBinOp(BinaryOperator::Opcode Op, Loc lhs, NonLoc rhs, QualType resultTy) { return UnknownVal(); } - virtual void RemoveDeadBindings(GRState &state, Stmt* Loc, - SymbolReaper& SymReaper, + virtual Store RemoveDeadBindings(Store store, Stmt* Loc, + SymbolReaper& SymReaper, llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0; - virtual const GRState *BindDecl(const GRState *ST, const VarRegion *VR, - SVal initVal) = 0; + virtual Store BindDecl(Store store, const VarRegion *VR, SVal initVal) = 0; - virtual const GRState *BindDeclWithNoInit(const GRState *ST, - const VarRegion *VR) = 0; + virtual Store BindDeclWithNoInit(Store store, const VarRegion *VR) = 0; typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols; - virtual const GRState *InvalidateRegion(const GRState *state, - const MemRegion *R, - const Expr *E, unsigned Count, - InvalidatedSymbols *IS) = 0; + virtual Store InvalidateRegion(Store store, + const MemRegion *R, + const Expr *E, unsigned Count, + InvalidatedSymbols *IS) = 0; - virtual const GRState *InvalidateRegions(const GRState *state, - const MemRegion * const *Begin, - const MemRegion * const *End, - const Expr *E, unsigned Count, - InvalidatedSymbols *IS); + virtual Store InvalidateRegions(Store store, + const MemRegion * const *Begin, + const MemRegion * const *End, + const Expr *E, unsigned Count, + InvalidatedSymbols *IS); // FIXME: Make out-of-line. virtual const GRState *setExtent(const GRState *state, @@ -192,6 +199,9 @@ protected: /// as another region. SVal CastRetrievedVal(SVal val, const TypedRegion *R, QualType castTy, bool performTestOnly = true); + +private: + SVal getLValueFieldOrIvar(const Decl* D, SVal Base); }; // FIXME: Do we still need this? @@ -214,7 +224,7 @@ public: StoreManager *CreateBasicStoreManager(GRStateManager& StMgr); StoreManager *CreateRegionStoreManager(GRStateManager& StMgr); StoreManager *CreateFieldsOnlyRegionStoreManager(GRStateManager& StMgr); - +StoreManager *CreateFlatStoreManager(GRStateManager &StMgr); } // end clang namespace #endif diff --git a/include/clang/Checker/PathSensitive/SummaryManager.h b/include/clang/Checker/PathSensitive/SummaryManager.h new file mode 100644 index 0000000..fd23189 --- /dev/null +++ b/include/clang/Checker/PathSensitive/SummaryManager.h @@ -0,0 +1,57 @@ +//== SummaryManager.h - Generic handling of function summaries --*- 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 SummaryManager and related classes, which provides +// a generic mechanism for managing function summaries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CHECKER_SUMMARY +#define LLVM_CLANG_CHECKER_SUMMARY + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Allocator.h" + +namespace clang { + +namespace summMgr { + + +/* Key kinds: + + - C functions + - C++ functions (name + parameter types) + - ObjC methods: + - Class, selector (class method) + - Class, selector (instance method) + - Category, selector (instance method) + - Protocol, selector (instance method) + - C++ methods + - Class, function name + parameter types + const + */ + +class SummaryKey { + +}; + +} // end namespace clang::summMgr + +class SummaryManagerImpl { + +}; + + +template <typename T> +class SummaryManager : SummaryManagerImpl { + +}; + +} // end clang namespace + +#endif diff --git a/include/clang/Analysis/PathSensitive/SymbolManager.h b/include/clang/Checker/PathSensitive/SymbolManager.h index 8eb3196..8eb3196 100644 --- a/include/clang/Analysis/PathSensitive/SymbolManager.h +++ b/include/clang/Checker/PathSensitive/SymbolManager.h diff --git a/include/clang/Analysis/PathSensitive/ValueManager.h b/include/clang/Checker/PathSensitive/ValueManager.h index 9cec3c4..ea3af57 100644 --- a/include/clang/Analysis/PathSensitive/ValueManager.h +++ b/include/clang/Checker/PathSensitive/ValueManager.h @@ -17,11 +17,11 @@ #define LLVM_CLANG_ANALYSIS_AGGREGATE_VALUE_MANAGER_H #include "llvm/ADT/OwningPtr.h" -#include "clang/Analysis/PathSensitive/MemRegion.h" -#include "clang/Analysis/PathSensitive/SVals.h" -#include "clang/Analysis/PathSensitive/BasicValueFactory.h" -#include "clang/Analysis/PathSensitive/SymbolManager.h" -#include "clang/Analysis/PathSensitive/SValuator.h" +#include "clang/Checker/PathSensitive/MemRegion.h" +#include "clang/Checker/PathSensitive/SVals.h" +#include "clang/Checker/PathSensitive/BasicValueFactory.h" +#include "clang/Checker/PathSensitive/SymbolManager.h" +#include "clang/Checker/PathSensitive/SValuator.h" namespace llvm { class BumpPtrAllocator; } @@ -115,8 +115,8 @@ public: return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals)); } - NonLoc makeLazyCompoundVal(const GRState *state, const TypedRegion *R) { - return nonloc::LazyCompoundVal(BasicVals.getLazyCompoundValData(state, R)); + NonLoc makeLazyCompoundVal(const void *store, const TypedRegion *R) { + return nonloc::LazyCompoundVal(BasicVals.getLazyCompoundValData(store, R)); } NonLoc makeZeroArrayIndex() { diff --git a/include/clang/CodeGen/CodeGenOptions.h b/include/clang/CodeGen/CodeGenOptions.h index 8682715..e1d4ad1 100644 --- a/include/clang/CodeGen/CodeGenOptions.h +++ b/include/clang/CodeGen/CodeGenOptions.h @@ -41,6 +41,8 @@ public: unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled. unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled. unsigned NoZeroInitializedInBSS : 1; /// -fno-zero-initialized-in-bss + unsigned ObjCLegacyDispatch: 1; /// Use legacy Objective-C dispatch, even with + /// 2.0 runtime. unsigned OptimizationLevel : 3; /// The -O[0-4] option specified. unsigned OptimizeSize : 1; /// If -Os is specified. unsigned SoftFloat : 1; /// -soft-float. @@ -90,12 +92,13 @@ public: NoCommon = 0; NoImplicitFloat = 0; NoZeroInitializedInBSS = 0; + ObjCLegacyDispatch = 0; OptimizationLevel = 0; OptimizeSize = 0; - UnrollLoops = 0; SoftFloat = 0; TimePasses = 0; UnitAtATime = 1; + UnrollLoops = 0; UnwindTables = 0; VerifyModule = 1; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 2511dfb..047363e 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -38,19 +38,21 @@ def analysis_CFGView : Flag<"-cfg-view">, HelpText<"View Control-Flow Graphs using GraphViz">; def analysis_DisplayLiveVariables : Flag<"-dump-live-variables">, HelpText<"Print results of live variable analysis">; -def analysis_SecuritySyntacticChecks : Flag<"-warn-security-syntactic">, +def analysis_LLVMConventionChecker : Flag<"-analyzer-check-llvm-conventions">, + HelpText<"Check code for LLVM codebase conventions (domain-specific)">; +def analysis_SecuritySyntacticChecks : Flag<"-analyzer-check-security-syntactic">, HelpText<"Perform quick security checks that require no data flow">; -def analysis_WarnDeadStores : Flag<"-warn-dead-stores">, +def analysis_WarnDeadStores : Flag<"-analyzer-check-dead-stores">, HelpText<"Warn about stores to dead variables">; def analysis_WarnUninitVals : Flag<"-warn-uninit-values">, HelpText<"Warn about uses of uninitialized variables">; -def analysis_WarnObjCMethSigs : Flag<"-warn-objc-methodsigs">, +def analysis_WarnObjCMethSigs : Flag<"-analyzer-check-objc-methodsigs">, HelpText<"Warn about Objective-C method signatures with type incompatibilities">; -def analysis_WarnObjCDealloc : Flag<"-warn-objc-missing-dealloc">, +def analysis_WarnObjCDealloc : Flag<"-analyzer-check-objc-missing-dealloc">, HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">; -def analysis_WarnObjCUnusedIvars : Flag<"-warn-objc-unused-ivars">, +def analysis_WarnObjCUnusedIvars : Flag<"-analyzer-check-objc-unused-ivars">, HelpText<"Warn about private ivars that are never used">; -def analysis_CheckerCFRef : Flag<"-checker-cfref">, +def analysis_ObjCMemChecker : Flag<"-analyzer-check-objc-mem">, HelpText<"Run the [Core] Foundation reference count checker">; def analysis_WarnSizeofPointer : Flag<"-warn-sizeof-pointer">, HelpText<"Warn about unintended use of sizeof() on pointer expressions">; @@ -102,6 +104,8 @@ def analyzer_viz_egraph_ubigraph : Flag<"-analyzer-viz-egraph-ubigraph">, def disable_llvm_optzns : Flag<"-disable-llvm-optzns">, HelpText<"Don't run LLVM optimization passes">; +def disable_llvm_verifier : Flag<"-disable-llvm-verifier">, + HelpText<"Don't run the LLVM IR verifier pass">; def disable_red_zone : Flag<"-disable-red-zone">, HelpText<"Do not emit code that uses the red zone.">; def dwarf_debug_flags : Separate<"-dwarf-debug-flags">, @@ -115,6 +119,10 @@ def no_implicit_float : Flag<"-no-implicit-float">, HelpText<"Don't generate implicit floating point instructions (x86-only)">; def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, HelpText<"Disallow merging of constants.">; +def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, + HelpText<"Do not emit code to make initialization of local statics thread safe">; +def fdump_vtable_layouts : Flag<"-fdump-vtable-layouts">, + HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">; def masm_verbose : Flag<"-masm-verbose">, HelpText<"Generate verbose assembly output">; def mcode_model : Separate<"-mcode-model">, @@ -165,6 +173,7 @@ def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, HelpText<"Do not include source line and caret with diagnostics">; def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, HelpText<"Do not include fixit information in diagnostics">; +def fdiagnostics_binary : Flag<"-fdiagnostics-binary">; def w : Flag<"-w">, HelpText<"Suppress all warnings">; def pedantic : Flag<"-pedantic">; def pedantic_errors : Flag<"-pedantic-errors">; @@ -197,6 +206,9 @@ def verify : Flag<"-verify">, // CompilerInvocation out of a driver-derived argument vector. def cc1 : Flag<"-cc1">; +def ast_merge : Separate<"-ast-merge">, + MetaVarName<"<ast file>">, + HelpText<"Merge the given AST file into the translation unit being compiled.">; def code_completion_at : Separate<"-code-completion-at">, MetaVarName<"<file>:<line>:<column>">, HelpText<"Dump code-completion information at a location">; @@ -280,6 +292,8 @@ def emit_llvm_bc : Flag<"-emit-llvm-bc">, HelpText<"Build ASTs then convert to LLVM, emit .bc file">; def emit_llvm_only : Flag<"-emit-llvm-only">, HelpText<"Build ASTs and convert to LLVM, discarding output">; +def emit_obj : Flag<"-emit-obj">, + HelpText<"Emit native object files">; def rewrite_test : Flag<"-rewrite-test">, HelpText<"Rewriter playground">; def rewrite_objc : Flag<"-rewrite-objc">, @@ -319,6 +333,8 @@ def fblocks : Flag<"-fblocks">, def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">; def fexceptions : Flag<"-fexceptions">, HelpText<"Enable support for exception handling">; +def fsjlj_exceptions : Flag<"-fsjlj-exceptions">, + HelpText<"Use SjLj style exceptions">; def ffreestanding : Flag<"-ffreestanding">, HelpText<"Assert that the compilation takes place in a freestanding environment">; def fgnu_runtime : Flag<"-fgnu-runtime">, @@ -346,10 +362,14 @@ def fobjc_gc : Flag<"-fobjc-gc">, HelpText<"Enable Objective-C garbage collection">; def fobjc_gc_only : Flag<"-fobjc-gc-only">, HelpText<"Use GC exclusively for Objective-C related memory management">; +def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">, + HelpText<"Use legacy dispatch with the Objective-C non-fragile ABI">; def print_ivar_layout : Flag<"-print-ivar-layout">, HelpText<"Enable Objective-C Ivar layout bitmap print trace">; def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, HelpText<"enable objective-c's nonfragile abi">; +def fobjc_nonfragile_abi2 : Flag<"-fobjc-nonfragile-abi2">, + HelpText<"enable objective-c's enhanced nonfragile abi">; def ftrapv : Flag<"-ftrapv">, HelpText<"Trap on integer overflow">; def pic_level : Separate<"-pic-level">, diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index 3186471..64f88ed 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -77,32 +77,36 @@ public: /// Information about the host which can be overriden by the user. std::string HostBits, HostMachine, HostSystem, HostRelease; + /// Name to use when calling the generic gcc. + std::string CCCGenericGCCName; + /// Whether the driver should follow g++ like behavior. - bool CCCIsCXX : 1; + unsigned CCCIsCXX : 1; /// Echo commands while executing (in -v style). - bool CCCEcho : 1; + unsigned CCCEcho : 1; /// Only print tool bindings, don't build any jobs. - bool CCCPrintBindings : 1; - - /// Name to use when calling the generic gcc. - std::string CCCGenericGCCName; + unsigned CCCPrintBindings : 1; private: + /// Whether to check that input files exist when constructing compilation + /// jobs. + unsigned CheckInputsExist : 1; + /// Use the clang compiler where possible. - bool CCCUseClang : 1; + unsigned CCCUseClang : 1; /// Use clang for handling C++ and Objective-C++ inputs. - bool CCCUseClangCXX : 1; + unsigned CCCUseClangCXX : 1; /// Use clang as a preprocessor (clang's preprocessor will still be /// used where an integrated CPP would). - bool CCCUseClangCPP : 1; + unsigned CCCUseClangCPP : 1; public: /// Use lazy precompiled headers for PCH support. - bool CCCUsePCH; + unsigned CCCUsePCH : 1; private: /// Only use clang for the given architectures (only used when @@ -129,6 +133,10 @@ public: const Diagnostic &getDiags() const { return Diags; } + bool getCheckInputsExist() const { return CheckInputsExist; } + + void setCheckInputsExist(bool Value) { CheckInputsExist = Value; } + /// @} /// @name Primary Functionality /// @{ diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 955d98e..4693e5c 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -252,6 +252,7 @@ def fconstant_string_class_EQ : Joined<"-fconstant-string-class=">, Group<f_Grou def fcreate_profile : Flag<"-fcreate-profile">, Group<f_Group>; def fdebug_pass_arguments : Flag<"-fdebug-pass-arguments">, Group<f_Group>; def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group<f_Group>; +def fdiagnostics_binary : Flag<"-fdiagnostics-binary">, Group<f_Group>, Flags<[HelpHidden]>; def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_Group>; def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_Group>; def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>; @@ -302,6 +303,7 @@ def fno_keep_inline_functions : Flag<"-fno-keep-inline-functions">, Group<clang_ def fno_math_errno : Flag<"-fno-math-errno">, Group<f_Group>; def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, Group<f_Group>; def fno_ms_extensions : Flag<"-fno-ms-extensions">, Group<f_Group>; +def fno_objc_legacy_dispatch : Flag<"-fno-objc-legacy-dispatch">, Group<f_Group>; def fno_omit_frame_pointer : Flag<"-fno-omit-frame-pointer">, Group<f_Group>; def fno_pascal_strings : Flag<"-fno-pascal-strings">, Group<f_Group>; def fno_rtti : Flag<"-fno-rtti">, Group<f_Group>; @@ -309,6 +311,7 @@ def fno_show_column : Flag<"-fno-show-column">, Group<f_Group>; def fno_show_source_location : Flag<"-fno-show-source-location">, Group<f_Group>; def fno_stack_protector : Flag<"-fno-stack-protector">, Group<f_Group>; def fno_strict_aliasing : Flag<"-fno-strict-aliasing">, Group<clang_ignored_f_Group>; +def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group<f_Group>; def fno_unit_at_a_time : Flag<"-fno-unit-at-a-time">, Group<f_Group>; def fno_unwind_tables : Flag<"-fno-unwind-tables">, Group<f_Group>; def fno_working_directory : Flag<"-fno-working-directory">, Group<f_Group>; @@ -317,8 +320,10 @@ def fobjc_atdefs : Flag<"-fobjc-atdefs">, Group<clang_ignored_f_Group>; def fobjc_call_cxx_cdtors : Flag<"-fobjc-call-cxx-cdtors">, Group<clang_ignored_f_Group>; def fobjc_gc_only : Flag<"-fobjc-gc-only">, Group<f_Group>; def fobjc_gc : Flag<"-fobjc-gc">, Group<f_Group>; +def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">, Group<f_Group>; def fobjc_new_property : Flag<"-fobjc-new-property">, Group<clang_ignored_f_Group>; def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, Group<f_Group>; +def fobjc_nonfragile_abi2 : Flag<"-fobjc-nonfragile-abi2">, Group<f_Group>; def fobjc_sender_dependent_dispatch : Flag<"-fobjc-sender-dependent-dispatch">, Group<f_Group>; def fobjc : Flag<"-fobjc">, Group<f_Group>; def fomit_frame_pointer : Flag<"-fomit-frame-pointer">, Group<f_Group>; @@ -348,6 +353,7 @@ def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption]>; def ftabstop_EQ : Joined<"-ftabstop=">, Group<f_Group>; def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group<f_Group>; def fterminated_vtables : Flag<"-fterminated-vtables">, Group<f_Group>; +def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>; def ftime_report : Flag<"-ftime-report">, Group<f_Group>; def ftrapv : Flag<"-ftrapv">, Group<f_Group>; def funit_at_a_time : Flag<"-funit-at-a-time">, Group<f_Group>; @@ -374,6 +380,7 @@ def image__base : Separate<"-image_base">; def include_ : JoinedOrSeparate<"-include">, Group<clang_i_Group>, EnumName<"include">; def init : Separate<"-init">; def install__name : Separate<"-install_name">; +def integrated_as : Flag<"-integrated-as">, Flags<[DriverOption]>; def iprefix : JoinedOrSeparate<"-iprefix">, Group<clang_i_Group>; def iquote : JoinedOrSeparate<"-iquote">, Group<clang_i_Group>; def isysroot : JoinedOrSeparate<"-isysroot">, Group<clang_i_Group>; @@ -398,10 +405,10 @@ def mfix_and_continue : Flag<"-mfix-and-continue">, Group<clang_ignored_m_Group> def mfloat_abi_EQ : Joined<"-mfloat-abi=">, Group<m_Group>; def mfpu_EQ : Joined<"-mfpu=">, Group<m_Group>; def mhard_float : Flag<"-mhard-float">, Group<m_Group>; -def miphoneos_version_min_EQ : Joined<"-miphoneos-version-min=">, Group<m_Group>; +def miphoneos_version_min_EQ : Joined<"-miphoneos-version-min=">, Group<m_Group>, Flags<[DriverOption]>; def mkernel : Flag<"-mkernel">, Group<m_Group>; def mllvm : Separate<"-mllvm">; -def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group<m_Group>; +def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group<m_Group>, Flags<[DriverOption]>; def mmmx : Flag<"-mmmx">, Group<m_x86_Features_Group>; def mno_3dnowa : Flag<"-mno-3dnowa">, Group<m_x86_Features_Group>; def mno_3dnow : Flag<"-mno-3dnow">, Group<m_x86_Features_Group>; @@ -416,7 +423,10 @@ def mno_sse4a : Flag<"-mno-sse4a">, Group<m_x86_Features_Group>; def mno_sse4 : Flag<"-mno-sse4">, Group<m_x86_Features_Group>; def mno_sse : Flag<"-mno-sse">, Group<m_x86_Features_Group>; def mno_ssse3 : Flag<"-mno-ssse3">, Group<m_x86_Features_Group>; + def mno_thumb : Flag<"-mno-thumb">, Group<m_Group>; +def marm : Flag<"-marm">, Alias<mno_thumb>; + def mno_warn_nonportable_cfstrings : Flag<"-mno-warn-nonportable-cfstrings">, Group<m_Group>; def mpascal_strings : Flag<"-mpascal-strings">, Group<m_Group>; def mred_zone : Flag<"-mred-zone">, Group<m_Group>; @@ -438,6 +448,7 @@ def m_Joined : Joined<"-m">, Group<m_Group>; def no_canonical_prefixes : Flag<"-no-canonical-prefixes">, Flags<[DriverOption, HelpHidden]>, HelpText<"Use relative instead of canonical paths">; def no_cpp_precomp : Flag<"-no-cpp-precomp">; +def no_integrated_as : Flag<"-no-integrated-as">, Flags<[DriverOption]>; def no_integrated_cpp : Flag<"-no-integrated-cpp">, Flags<[DriverOption]>; def no__dead__strip__inits__and__terms : Flag<"-no_dead_strip_inits_and_terms">; def nobuiltininc : Flag<"-nobuiltininc">; @@ -481,6 +492,8 @@ def pthread : Flag<"-pthread">; def p : Flag<"-p">; def read__only__relocs : Separate<"-read_only_relocs">; def remap : Flag<"-remap">; +def rewrite_objc : Flag<"-rewrite-objc">, Flags<[DriverOption]>, + HelpText<"Rewrite Objective-C source to C++">; def rpath : Separate<"-rpath">, Flags<[LinkerInput]>; def r : Flag<"-r">; def save_temps : Flag<"-save-temps">, Flags<[DriverOption]>, diff --git a/include/clang/Driver/Tool.h b/include/clang/Driver/Tool.h index 8a89f01..851e423 100644 --- a/include/clang/Driver/Tool.h +++ b/include/clang/Driver/Tool.h @@ -45,6 +45,7 @@ public: virtual bool acceptsPipedInput() const = 0; virtual bool canPipeOutput() const = 0; + virtual bool hasIntegratedAssembler() const { return false; } virtual bool hasIntegratedCPP() const = 0; /// ConstructJob - Construct jobs to perform the action \arg JA, diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index cc8d438..9a82973 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -53,9 +53,9 @@ public: const Driver &getDriver() const; const llvm::Triple &getTriple() const { return Triple; } - std::string getArchName() const { return Triple.getArchName(); } - std::string getPlatform() const { return Triple.getVendorName(); } - std::string getOS() const { return Triple.getOSName(); } + llvm::StringRef getArchName() const { return Triple.getArchName(); } + llvm::StringRef getPlatform() const { return Triple.getVendorName(); } + llvm::StringRef getOS() const { return Triple.getOSName(); } std::string getTripleString() const { return Triple.getTriple(); @@ -90,10 +90,19 @@ public: /// IsBlocksDefault - Does this tool chain enable -fblocks by default. virtual bool IsBlocksDefault() const { return false; } + /// IsIntegratedAssemblerDefault - Does this tool chain enable -integrated-as + /// by default. + virtual bool IsIntegratedAssemblerDefault() const { return false; } + /// IsObjCNonFragileABIDefault - Does this tool chain set /// -fobjc-nonfragile-abi by default. virtual bool IsObjCNonFragileABIDefault() const { return false; } + /// IsObjCLegacyDispatchDefault - Does this tool chain set + /// -fobjc-legacy-dispatch by default (this is only used with the non-fragile + /// ABI). + virtual bool IsObjCLegacyDispatchDefault() const { return false; } + /// GetDefaultStackProtectorLevel - Get the default stack protector level for /// this tool chain (0=off, 1=on, 2=all). virtual unsigned GetDefaultStackProtectorLevel() const { return 0; } @@ -114,6 +123,9 @@ public: /// UseDwarfDebugFlags - Embed the compile options to clang into the Dwarf /// compile unit information. virtual bool UseDwarfDebugFlags() const { return false; } + + /// UseSjLjExceptions - Does this tool chain use SjLj exceptions. + virtual bool UseSjLjExceptions() const { return false; } }; } // end namespace driver diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def index d66fe92..61a5043 100644 --- a/include/clang/Driver/Types.def +++ b/include/clang/Driver/Types.def @@ -72,6 +72,7 @@ TYPE("ast", AST, INVALID, "ast", "u") TYPE("llvm-asm", LLVMAsm, INVALID, "s", "") TYPE("llvm-bc", LLVMBC, INVALID, "o", "") TYPE("plist", Plist, INVALID, "plist", "") +TYPE("rewritten-objc", RewrittenObjC,INVALID, "cpp", "") TYPE("precompiled-header", PCH, INVALID, "gch", "A") TYPE("object", Object, INVALID, "o", "") TYPE("treelang", Treelang, INVALID, 0, "u") diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index 978b0d2..7ec5063 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -73,10 +73,11 @@ ASTConsumer *CreateObjCRewriter(const std::string &InFile, // assembly. This runs optimizations depending on the CodeGenOptions // parameter. The output depends on the Action parameter. enum BackendAction { - Backend_EmitAssembly, // Emit native assembly - Backend_EmitBC, // Emit LLVM bitcode file + Backend_EmitAssembly, // Emit native assembly files + Backend_EmitBC, // Emit LLVM bitcode files Backend_EmitLL, // Emit human-readable LLVM assembly - Backend_EmitNothing // Don't emit anything (benchmarking mode) + Backend_EmitNothing, // Don't emit anything (benchmarking mode) + Backend_EmitObj // Emit native object files }; ASTConsumer *CreateBackendConsumer(BackendAction Action, Diagnostic &Diags, diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 2659dbb..f122dd9 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -53,6 +53,10 @@ class ASTUnit { llvm::OwningPtr<ASTContext> Ctx; bool tempFile; + /// Optional owned invocation, just used to make the invocation used in + /// LoadFromCommandLine available. + llvm::OwningPtr<CompilerInvocation> Invocation; + // OnlyLocalDecls - when true, walking this AST should only visit declarations // that come from the AST itself, not from included precompiled headers. // FIXME: This is temporary; eventually, CIndex will always do this. @@ -131,7 +135,6 @@ public: static ASTUnit *LoadFromPCHFile(const std::string &Filename, Diagnostic &Diags, bool OnlyLocalDecls = false, - bool UseBumpAllocator = false, RemappedFile *RemappedFiles = 0, unsigned NumRemappedFiles = 0); @@ -139,14 +142,14 @@ public: /// CompilerInvocation object. /// /// \param CI - The compiler invocation to use; it must have exactly one input - /// source file. + /// source file. The ASTUnit takes ownership of the CompilerInvocation object. /// /// \param Diags - The diagnostics engine to use for reporting errors; its /// lifetime is expected to extend past that of the returned ASTUnit. // // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we // shouldn't need to specify them at construction time. - static ASTUnit *LoadFromCompilerInvocation(const CompilerInvocation &CI, + static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI, Diagnostic &Diags, bool OnlyLocalDecls = false); @@ -169,7 +172,6 @@ public: Diagnostic &Diags, llvm::StringRef ResourceFilesPath, bool OnlyLocalDecls = false, - bool UseBumpAllocator = false, RemappedFile *RemappedFiles = 0, unsigned NumRemappedFiles = 0); }; diff --git a/include/clang/Frontend/Analyses.def b/include/clang/Frontend/Analyses.def index 7d55673..287c67e 100644 --- a/include/clang/Frontend/Analyses.def +++ b/include/clang/Frontend/Analyses.def @@ -24,28 +24,32 @@ ANALYSIS(CFGView, "cfg-view", ANALYSIS(DisplayLiveVariables, "dump-live-variables", "Print results of live variable analysis", Code) -ANALYSIS(SecuritySyntacticChecks, "warn-security-syntactic", +ANALYSIS(SecuritySyntacticChecks, "analyzer-check-security-syntactic", "Perform quick security checks that require no data flow", Code) -ANALYSIS(WarnDeadStores, "warn-dead-stores", +ANALYSIS(LLVMConventionChecker, "analyzer-check-llvm-conventions", + "Check code for LLVM codebase conventions (domain-specific)", + TranslationUnit) + +ANALYSIS(WarnDeadStores, "analyzer-check-dead-stores", "Warn about stores to dead variables", Code) ANALYSIS(WarnUninitVals, "warn-uninit-values", "Warn about uses of uninitialized variables", Code) -ANALYSIS(WarnObjCMethSigs, "warn-objc-methodsigs", +ANALYSIS(WarnObjCMethSigs, "analyzer-check-objc-methodsigs", "Warn about Objective-C method signatures with type incompatibilities", ObjCImplementation) -ANALYSIS(WarnObjCDealloc, "warn-objc-missing-dealloc", +ANALYSIS(WarnObjCDealloc, "analyzer-check-objc-missing-dealloc", "Warn about Objective-C classes that lack a correct implementation of -dealloc", ObjCImplementation) -ANALYSIS(WarnObjCUnusedIvars, "warn-objc-unused-ivars", +ANALYSIS(WarnObjCUnusedIvars, "analyzer-check-objc-unused-ivars", "Warn about private ivars that are never used", ObjCImplementation) -ANALYSIS(CheckerCFRef, "checker-cfref", +ANALYSIS(ObjCMemChecker, "analyzer-check-objc-mem", "Run the [Core] Foundation reference count checker", Code) ANALYSIS(WarnSizeofPointer, "warn-sizeof-pointer", @@ -61,6 +65,7 @@ ANALYSIS(InlineCall, "inline-call", ANALYSIS_STORE(BasicStore, "basic", "Use basic analyzer store", CreateBasicStoreManager) ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store", CreateRegionStoreManager) +ANALYSIS_STORE(FlatStore, "flat", "Use flat analyzer store", CreateFlatStoreManager) #ifndef ANALYSIS_CONSTRAINTS #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index edafe62..1be4118 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -58,11 +58,10 @@ class TargetInfo; /// and a long form that takes explicit instances of any required objects. class CompilerInstance { /// The LLVM context used for this instance. - llvm::LLVMContext *LLVMContext; - bool OwnsLLVMContext; + llvm::OwningPtr<llvm::LLVMContext> LLVMContext; /// The options used in this compiler instance. - CompilerInvocation Invocation; + llvm::OwningPtr<CompilerInvocation> Invocation; /// The diagnostics engine instance. llvm::OwningPtr<Diagnostic> Diagnostics; @@ -97,11 +96,10 @@ class CompilerInstance { /// The list of active output files. std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles; + void operator=(const CompilerInstance &); // DO NOT IMPLEMENT + CompilerInstance(const CompilerInstance&); // DO NOT IMPLEMENT public: - /// Create a new compiler instance with the given LLVM context, optionally - /// taking ownership of it. - CompilerInstance(llvm::LLVMContext *_LLVMContext = 0, - bool _OwnsLLVMContext = true); + CompilerInstance(); ~CompilerInstance(); /// @name High-Level Operations @@ -150,93 +148,101 @@ public: return *LLVMContext; } + llvm::LLVMContext *takeLLVMContext() { return LLVMContext.take(); } + /// setLLVMContext - Replace the current LLVM context and take ownership of /// \arg Value. - void setLLVMContext(llvm::LLVMContext *Value, bool TakeOwnership = true) { - LLVMContext = Value; - OwnsLLVMContext = TakeOwnership; - } + void setLLVMContext(llvm::LLVMContext *Value); /// } /// @name Compiler Invocation and Options /// { - CompilerInvocation &getInvocation() { return Invocation; } - const CompilerInvocation &getInvocation() const { return Invocation; } - void setInvocation(const CompilerInvocation &Value) { Invocation = Value; } + bool hasInvocation() const { return Invocation != 0; } + + CompilerInvocation &getInvocation() { + assert(Invocation && "Compiler instance has no invocation!"); + return *Invocation; + } + + CompilerInvocation *takeInvocation() { return Invocation.take(); } + + /// setInvocation - Replace the current invocation; the compiler instance + /// takes ownership of \arg Value. + void setInvocation(CompilerInvocation *Value); /// } /// @name Forwarding Methods /// { AnalyzerOptions &getAnalyzerOpts() { - return Invocation.getAnalyzerOpts(); + return Invocation->getAnalyzerOpts(); } const AnalyzerOptions &getAnalyzerOpts() const { - return Invocation.getAnalyzerOpts(); + return Invocation->getAnalyzerOpts(); } CodeGenOptions &getCodeGenOpts() { - return Invocation.getCodeGenOpts(); + return Invocation->getCodeGenOpts(); } const CodeGenOptions &getCodeGenOpts() const { - return Invocation.getCodeGenOpts(); + return Invocation->getCodeGenOpts(); } DependencyOutputOptions &getDependencyOutputOpts() { - return Invocation.getDependencyOutputOpts(); + return Invocation->getDependencyOutputOpts(); } const DependencyOutputOptions &getDependencyOutputOpts() const { - return Invocation.getDependencyOutputOpts(); + return Invocation->getDependencyOutputOpts(); } DiagnosticOptions &getDiagnosticOpts() { - return Invocation.getDiagnosticOpts(); + return Invocation->getDiagnosticOpts(); } const DiagnosticOptions &getDiagnosticOpts() const { - return Invocation.getDiagnosticOpts(); + return Invocation->getDiagnosticOpts(); } FrontendOptions &getFrontendOpts() { - return Invocation.getFrontendOpts(); + return Invocation->getFrontendOpts(); } const FrontendOptions &getFrontendOpts() const { - return Invocation.getFrontendOpts(); + return Invocation->getFrontendOpts(); } HeaderSearchOptions &getHeaderSearchOpts() { - return Invocation.getHeaderSearchOpts(); + return Invocation->getHeaderSearchOpts(); } const HeaderSearchOptions &getHeaderSearchOpts() const { - return Invocation.getHeaderSearchOpts(); + return Invocation->getHeaderSearchOpts(); } LangOptions &getLangOpts() { - return Invocation.getLangOpts(); + return Invocation->getLangOpts(); } const LangOptions &getLangOpts() const { - return Invocation.getLangOpts(); + return Invocation->getLangOpts(); } PreprocessorOptions &getPreprocessorOpts() { - return Invocation.getPreprocessorOpts(); + return Invocation->getPreprocessorOpts(); } const PreprocessorOptions &getPreprocessorOpts() const { - return Invocation.getPreprocessorOpts(); + return Invocation->getPreprocessorOpts(); } PreprocessorOutputOptions &getPreprocessorOutputOpts() { - return Invocation.getPreprocessorOutputOpts(); + return Invocation->getPreprocessorOutputOpts(); } const PreprocessorOutputOptions &getPreprocessorOutputOpts() const { - return Invocation.getPreprocessorOutputOpts(); + return Invocation->getPreprocessorOutputOpts(); } TargetOptions &getTargetOpts() { - return Invocation.getTargetOpts(); + return Invocation->getTargetOpts(); } const TargetOptions &getTargetOpts() const { - return Invocation.getTargetOpts(); + return Invocation->getTargetOpts(); } /// } diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h index 13039bb..b37c180 100644 --- a/include/clang/Frontend/DiagnosticOptions.h +++ b/include/clang/Frontend/DiagnosticOptions.h @@ -31,9 +31,12 @@ public: unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable /// diagnostics. unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences. - unsigned VerifyDiagnostics; /// Check that diagnostics match the expected + unsigned VerifyDiagnostics: 1; /// Check that diagnostics match the expected /// diagnostics, indicated by markers in the /// input source file. + unsigned BinaryOutput : 1; /// Emit diagnostics via the diagnostic + /// binary serialization mechanism, to be + /// deserialized by, e.g., the CIndex library. /// The distance between tab stops. unsigned TabStop; @@ -66,6 +69,7 @@ public: ShowOptionNames = 0; ShowSourceRanges = 0; VerifyDiagnostics = 0; + BinaryOutput = 0; } }; diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h index 3042767..7b7db37 100644 --- a/include/clang/Frontend/FrontendAction.h +++ b/include/clang/Frontend/FrontendAction.h @@ -18,6 +18,7 @@ namespace clang { class ASTUnit; class ASTConsumer; class CompilerInstance; +class ASTMergeAction; /// FrontendAction - Abstract base class for actions which can be performed by /// the frontend. @@ -25,6 +26,7 @@ class FrontendAction { std::string CurrentFile; llvm::OwningPtr<ASTUnit> CurrentASTUnit; CompilerInstance *Instance; + friend class ASTMergeAction; protected: /// @name Implementation Action Interface @@ -104,6 +106,10 @@ public: return *CurrentASTUnit; } + ASTUnit *takeCurrentASTUnit() { + return CurrentASTUnit.take(); + } + void setCurrentFile(llvm::StringRef Value, ASTUnit *AST = 0); /// @} @@ -167,7 +173,7 @@ public: }; /// ASTFrontendAction - Abstract base class to use for AST consumer based -/// frontend actios. +/// frontend actions. class ASTFrontendAction : public FrontendAction { /// ExecuteAction - Implement the ExecuteAction interface by running Sema on /// the already initialized AST consumer. diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index 33bb8aa..cbb3508 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -11,6 +11,8 @@ #define LLVM_CLANG_FRONTEND_FRONTENDACTIONS_H #include "clang/Frontend/FrontendAction.h" +#include <string> +#include <vector> namespace clang { class FixItRewriter; @@ -119,6 +121,43 @@ public: virtual bool hasCodeCompletionSupport() const { return true; } }; +/** + * \brief Frontend action adaptor that merges ASTs together. + * + * This action takes an existing AST file and "merges" it into the AST + * context, producing a merged context. This action is an action + * adaptor, which forwards most of its calls to another action that + * will consume the merged context. + */ +class ASTMergeAction : public FrontendAction { + /// \brief The action that the merge action adapts. + FrontendAction *AdaptedAction; + + /// \brief The set of AST files to merge. + std::vector<std::string> ASTFiles; + +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); + + virtual bool BeginSourceFileAction(CompilerInstance &CI, + llvm::StringRef Filename); + + virtual void ExecuteAction(); + virtual void EndSourceFileAction(); + +public: + ASTMergeAction(FrontendAction *AdaptedAction, + std::string *ASTFiles, unsigned NumASTFiles); + virtual ~ASTMergeAction(); + + virtual bool usesPreprocessorOnly() const; + virtual bool usesCompleteTranslationUnit(); + virtual bool hasPCHSupport() const; + virtual bool hasASTSupport() const; + virtual bool hasCodeCompletionSupport() const; +}; + //===----------------------------------------------------------------------===// // Code Gen AST Actions //===----------------------------------------------------------------------===// @@ -154,6 +193,11 @@ public: EmitLLVMOnlyAction(); }; +class EmitObjAction : public CodeGenAction { +public: + EmitObjAction(); +}; + //===----------------------------------------------------------------------===// // Preprocessor Actions //===----------------------------------------------------------------------===// diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index 735a86a..80ba778 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -31,6 +31,7 @@ namespace frontend { EmitHTML, ///< Translate input source into HTML. EmitLLVM, ///< Emit a .ll file. EmitLLVMOnly, ///< Generate LLVM IR, but do not + EmitObj, ///< Emit a .o file. FixIt, ///< Parse and apply any fixits to the source. GeneratePCH, ///< Generate pre-compiled header. GeneratePTH, ///< Generate pre-tokenized header. @@ -109,6 +110,9 @@ public: /// The list of plugins to load. std::vector<std::string> Plugins; + /// \brief The list of AST files to merge. + std::vector<std::string> ASTMergeFiles; + public: FrontendOptions() { DebugCodeCompletionPrinter = 1; diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 1a9f4ce..e22d37b 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -221,7 +221,11 @@ namespace clang { /// \brief Record code for the version control branch and revision /// information of the compiler used to build this PCH file. - VERSION_CONTROL_BRANCH_REVISION = 21 + VERSION_CONTROL_BRANCH_REVISION = 21, + + /// \brief Record code for the array of unused static functions. + UNUSED_STATIC_FUNCS = 22 + }; /// \brief Record types used within a source manager block. @@ -686,7 +690,11 @@ namespace clang { // \brief A CXXConstCastExpr record. EXPR_CXX_CONST_CAST, // \brief A CXXFunctionalCastExpr record. - EXPR_CXX_FUNCTIONAL_CAST + EXPR_CXX_FUNCTIONAL_CAST, + // \brief A CXXBoolLiteralExpr record. + EXPR_CXX_BOOL_LITERAL, + // \brief A CXXNullPtrLiteralExpr record. + EXPR_CXX_NULL_PTR_LITERAL }; /// \brief The kinds of designators that can occur in a diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 9665ce1..065006f 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -306,6 +306,10 @@ private: /// \brief The set of tentative definitions stored in the the PCH /// file. llvm::SmallVector<uint64_t, 16> TentativeDefinitions; + + /// \brief The set of tentative definitions stored in the the PCH + /// file. + llvm::SmallVector<uint64_t, 16> UnusedStaticFuncs; /// \brief The set of locally-scoped external declarations stored in /// the the PCH file. diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index 0f36df4..6a6e319 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -199,6 +199,9 @@ public: /// the current file. SourceLocation getSourceLocation() { return getSourceLocation(BufferPtr); } + /// \brief Return the current location in the buffer. + const char *getBufferLocation() const { return BufferPtr; } + /// Stringify - Convert the specified string into a C string by escaping '\' /// and " characters. This does not add surrounding ""'s to the string. /// If Charify is true, this escapes the ' character instead of ". diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index 604eae1..b5dde9a 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -124,6 +124,10 @@ public: UintData = L.getRawEncoding(); } + SourceLocation getLastLoc() const { + return isAnnotation() ? getAnnotationEndLoc() : getLocation(); + } + /// getAnnotationRange - SourceRange of the group of tokens that this /// annotation token represents. SourceRange getAnnotationRange() const { diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index ff33f50..ec542f0 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -459,6 +459,8 @@ public: virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D) { return DeclPtrTy(); } + virtual void ActOnObjCCatchParam(DeclPtrTy D) { + } /// AddInitializerToDecl - This action is called immediately after /// ActOnDeclarator (when an initializer is present). The code is factored @@ -808,6 +810,11 @@ public: return StmtEmpty(); } + /// ActOnSwitchBodyError - This is called if there is an error parsing the + /// body of the switch stmt instead of ActOnFinishSwitchStmt. + virtual void ActOnSwitchBodyError(SourceLocation SwitchLoc, StmtArg Switch, + StmtArg Body) {} + virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, StmtArg Body) { return StmtEmpty(); @@ -897,7 +904,7 @@ public: bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, - std::string *Names, + IdentifierInfo **Names, MultiExprArg Constraints, MultiExprArg Exprs, ExprArg AsmString, @@ -1270,7 +1277,8 @@ public: /// definition. virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc, IdentifierInfo *Ident, - SourceLocation LBrace) { + SourceLocation LBrace, + AttributeList *AttrList) { return DeclPtrTy(); } @@ -1649,9 +1657,12 @@ public: /// a well-formed program), ColonLoc is the location of the ':' that /// starts the constructor initializer, and MemInit/NumMemInits /// contains the individual member (and base) initializers. + /// AnyErrors will be true if there were any invalid member initializers + /// that are not represented in the list. virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl, SourceLocation ColonLoc, - MemInitTy **MemInits, unsigned NumMemInits){ + MemInitTy **MemInits, unsigned NumMemInits, + bool AnyErrors){ } virtual void ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {} diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index f923b5e..4fe81a7 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -153,6 +153,8 @@ private: /*TSC*/unsigned TypeSpecComplex : 2; /*TSS*/unsigned TypeSpecSign : 2; /*TST*/unsigned TypeSpecType : 5; + bool TypeAltiVecVector : 1; + bool TypeAltiVecPixel : 1; bool TypeSpecOwned : 1; // type-qualifiers @@ -193,7 +195,7 @@ private: SourceRange Range; SourceLocation StorageClassSpecLoc, SCS_threadLoc; - SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc; + SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc, AltiVecLoc; SourceRange TypeofParensRange; SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc; SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc; @@ -213,6 +215,8 @@ public: TypeSpecComplex(TSC_unspecified), TypeSpecSign(TSS_unspecified), TypeSpecType(TST_unspecified), + TypeAltiVecVector(false), + TypeAltiVecPixel(false), TypeSpecOwned(false), TypeQualifiers(TSS_unspecified), FS_inline_specified(false), @@ -250,6 +254,8 @@ public: TSC getTypeSpecComplex() const { return (TSC)TypeSpecComplex; } TSS getTypeSpecSign() const { return (TSS)TypeSpecSign; } TST getTypeSpecType() const { return (TST)TypeSpecType; } + bool isTypeAltiVecVector() const { return TypeAltiVecVector; } + bool isTypeAltiVecPixel() const { return TypeAltiVecPixel; } bool isTypeSpecOwned() const { return TypeSpecOwned; } void *getTypeRep() const { return TypeRep; } CXXScopeSpec &getTypeSpecScope() { return TypeScope; } @@ -260,6 +266,7 @@ public: SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; } SourceLocation getTypeSpecSignLoc() const { return TSSLoc; } SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; } + SourceLocation getAltiVecLoc() const { return AltiVecLoc; } SourceRange getTypeofParensRange() const { return TypeofParensRange; } void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; } @@ -344,6 +351,10 @@ public: unsigned &DiagID); bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, void *Rep = 0, bool Owned = false); + bool SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID); + bool SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID); bool SetTypeSpecError(); void UpdateTypeRep(void *Rep) { TypeRep = Rep; } diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index e7cb0a2..f4d3d3e 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -81,6 +81,11 @@ class Parser { /// Ident_super - IdentifierInfo for "super", to support fast /// comparison. IdentifierInfo *Ident_super; + /// Ident_vector and Ident_pixel - cached IdentifierInfo's for + /// "vector" and "pixel" fast comparison. Only present if + /// AltiVec enabled. + IdentifierInfo *Ident_vector; + IdentifierInfo *Ident_pixel; llvm::OwningPtr<PragmaHandler> PackHandler; llvm::OwningPtr<PragmaHandler> UnusedHandler; @@ -320,6 +325,81 @@ private: /// annotated. bool TryAnnotateCXXScopeToken(bool EnteringContext = false); + /// TryAltiVecToken - Check for context-sensitive AltiVec identifier tokens, + /// replacing them with the non-context-sensitive keywords. This returns + /// true if the token was replaced. + bool TryAltiVecToken(DeclSpec &DS, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID, bool &isInvalid) { + if (getLang().AltiVec) { + if (Tok.getIdentifierInfo() == Ident_vector) { + const Token nextToken = NextToken(); + switch (nextToken.getKind()) { + case tok::kw_short: + case tok::kw_long: + case tok::kw_signed: + case tok::kw_unsigned: + case tok::kw_void: + case tok::kw_char: + case tok::kw_int: + case tok::kw_float: + case tok::kw_double: + case tok::kw_bool: + case tok::kw___pixel: + isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID); + return true; + case tok::identifier: + if (nextToken.getIdentifierInfo() == Ident_pixel) { + isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID); + return true; + } + break; + default: + break; + } + } else if ((Tok.getIdentifierInfo() == Ident_pixel) && + DS.isTypeAltiVecVector()) { + isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID); + return true; + } + } + return false; + } + + /// TryAltiVecVectorToken - Check for context-sensitive AltiVec vector + /// identifier token, replacing it with the non-context-sensitive __vector. + /// This returns true if the token was replaced. + bool TryAltiVecVectorToken() { + if (getLang().AltiVec) { + if (Tok.getIdentifierInfo() == Ident_vector) { + const Token nextToken = NextToken(); + switch (nextToken.getKind()) { + case tok::kw_short: + case tok::kw_long: + case tok::kw_signed: + case tok::kw_unsigned: + case tok::kw_void: + case tok::kw_char: + case tok::kw_int: + case tok::kw_float: + case tok::kw_double: + case tok::kw_bool: + case tok::kw___pixel: + Tok.setKind(tok::kw___vector); + return true; + case tok::identifier: + if (nextToken.getIdentifierInfo() == Ident_pixel) { + Tok.setKind(tok::kw___vector); + return true; + } + break; + default: + break; + } + } + } + return false; + } + /// TentativeParsingAction - An object that is used as a kind of "tentative /// parsing transaction". It gets instantiated to mark the token position and /// after the token consumption is done, Commit() or Revert() is called to @@ -1009,9 +1089,9 @@ private: OwningStmtResult ParseReturnStatement(AttributeList *Attr); OwningStmtResult ParseAsmStatement(bool &msAsm); OwningStmtResult FuzzyParseMicrosoftAsmStatement(); - bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names, - llvm::SmallVectorImpl<ExprTy*> &Constraints, - llvm::SmallVectorImpl<ExprTy*> &Exprs); + bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, + llvm::SmallVectorImpl<ExprTy *> &Constraints, + llvm::SmallVectorImpl<ExprTy *> &Exprs); //===--------------------------------------------------------------------===// // C++ 6: Statements and Blocks @@ -1065,7 +1145,8 @@ private: bool ParseOptionalTypeSpecifier(DeclSpec &DS, bool &isInvalid, const char *&PrevSpec, unsigned &DiagID, - const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), + bool SuppressDeclarations = false); void ParseSpecifierQualifierList(DeclSpec &DS); @@ -1311,7 +1392,8 @@ private: void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc, DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), - AccessSpecifier AS = AS_none); + AccessSpecifier AS = AS_none, + bool SuppressDeclarations = false); void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType, DeclPtrTy TagDecl); void ParseCXXClassMemberDeclaration(AccessSpecifier AS, |