From c72c57c9e9b69944e3e009cd5e209634839581d3 Mon Sep 17 00:00:00 2001 From: dim Date: Mon, 8 Apr 2013 18:45:10 +0000 Subject: Vendor import of clang trunk r178860: http://llvm.org/svn/llvm-project/cfe/trunk@178860 --- include/clang/AST/APValue.h | 2 +- include/clang/AST/AST.h | 2 +- include/clang/AST/ASTConsumer.h | 15 +- include/clang/AST/ASTContext.h | 253 +++++++-- include/clang/AST/ASTImporter.h | 3 + include/clang/AST/ASTMutationListener.h | 9 +- include/clang/AST/ASTTypeTraits.h | 211 ++++++++ include/clang/AST/ASTUnresolvedSet.h | 86 +++ include/clang/AST/ASTVector.h | 12 +- include/clang/AST/Attr.h | 171 ++---- include/clang/AST/AttrIterator.h | 142 +++++ include/clang/AST/BuiltinTypes.def | 14 + include/clang/AST/CMakeLists.txt | 13 + include/clang/AST/CXXInheritance.h | 4 +- include/clang/AST/CanonicalType.h | 69 +-- include/clang/AST/CharUnits.h | 11 + include/clang/AST/Comment.h | 87 ++- include/clang/AST/CommentCommandTraits.h | 34 +- include/clang/AST/CommentCommands.td | 92 +++- .../AST/CommentHTMLNamedCharacterReferences.td | 177 +++++++ include/clang/AST/CommentLexer.h | 13 +- include/clang/AST/CommentParser.h | 9 +- include/clang/AST/CommentSema.h | 31 +- include/clang/AST/CommentVisitor.h | 4 + include/clang/AST/Decl.h | 327 ++++++------ include/clang/AST/DeclAccessPair.h | 1 + include/clang/AST/DeclBase.h | 129 ++--- include/clang/AST/DeclCXX.h | 587 +++++++++++---------- include/clang/AST/DeclContextInternals.h | 24 +- include/clang/AST/DeclFriend.h | 50 +- include/clang/AST/DeclLookups.h | 1 + include/clang/AST/DeclObjC.h | 339 ++++++++++-- include/clang/AST/DeclOpenMP.h | 83 +++ include/clang/AST/DeclTemplate.h | 114 ++-- include/clang/AST/DeclVisitor.h | 43 +- include/clang/AST/DeclarationName.h | 85 ++- include/clang/AST/DependentDiagnostic.h | 22 +- include/clang/AST/EvaluatedExprVisitor.h | 23 +- include/clang/AST/Expr.h | 367 ++++++++----- include/clang/AST/ExprCXX.h | 257 +++++---- include/clang/AST/ExprObjC.h | 126 +++-- include/clang/AST/ExternalASTSource.h | 28 +- include/clang/AST/LambdaMangleContext.h | 4 +- include/clang/AST/Makefile | 25 +- include/clang/AST/Mangle.h | 2 +- include/clang/AST/NSAPI.h | 14 +- include/clang/AST/NestedNameSpecifier.h | 2 +- include/clang/AST/OperationKinds.h | 5 +- include/clang/AST/PrettyPrinter.h | 19 +- include/clang/AST/RecursiveASTVisitor.h | 36 +- include/clang/AST/Stmt.h | 229 ++++---- include/clang/AST/StmtCXX.h | 38 +- include/clang/AST/StmtGraphTraits.h | 2 +- include/clang/AST/StmtObjC.h | 37 +- include/clang/AST/TemplateBase.h | 87 +-- include/clang/AST/TemplateName.h | 24 +- include/clang/AST/Type.h | 200 ++++--- include/clang/AST/TypeLoc.h | 93 ++-- include/clang/AST/TypeLocVisitor.h | 2 +- include/clang/AST/TypeOrdering.h | 2 +- include/clang/AST/UnresolvedSet.h | 11 +- include/clang/AST/VTTBuilder.h | 9 - include/clang/AST/VTableBuilder.h | 23 +- 63 files changed, 3287 insertions(+), 1647 deletions(-) create mode 100644 include/clang/AST/ASTTypeTraits.h create mode 100644 include/clang/AST/ASTUnresolvedSet.h create mode 100644 include/clang/AST/AttrIterator.h create mode 100644 include/clang/AST/CommentHTMLNamedCharacterReferences.td create mode 100644 include/clang/AST/DeclOpenMP.h (limited to 'include/clang/AST') diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h index 1b6e90c..ec8faa4 100644 --- a/include/clang/AST/APValue.h +++ b/include/clang/AST/APValue.h @@ -15,8 +15,8 @@ #define LLVM_CLANG_AST_APVALUE_H #include "clang/Basic/LLVM.h" -#include "llvm/ADT/APSInt.h" #include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" diff --git a/include/clang/AST/AST.h b/include/clang/AST/AST.h index 164c5fb..6db351d 100644 --- a/include/clang/AST/AST.h +++ b/include/clang/AST/AST.h @@ -22,7 +22,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" -#include "clang/AST/Type.h" #include "clang/AST/StmtVisitor.h" +#include "clang/AST/Type.h" #endif diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index 37b0740..ae77943 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -17,9 +17,9 @@ namespace clang { class ASTContext; class CXXRecordDecl; + class Decl; class DeclGroupRef; class HandleTagDeclDefinition; - class PPMutationListener; class ASTMutationListener; class ASTDeserializationListener; // layering violation because void* is ugly class SemaConsumer; // layering violation required for safe SemaConsumer @@ -112,11 +112,6 @@ public: /// it was actually used. virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {} - /// \brief If the consumer is interested in preprocessor entities getting - /// modified after their initial creation, it should return a pointer to - /// a PPMutationListener here. - virtual PPMutationListener *GetPPMutationListener() { return 0; } - /// \brief If the consumer is interested in entities getting modified after /// their initial creation, it should return a pointer to /// an ASTMutationListener here. @@ -130,6 +125,14 @@ public: /// PrintStats - If desired, print any statistics. virtual void PrintStats() {} + + /// \brief This callback is called for each function if the Parser was + /// initialized with \c SkipFunctionBodies set to \c true. + /// + /// \return \c true if the function's body should be skipped. The function + /// body may be parsed anyway if it is needed (for instance, if it contains + /// the code completion point or is constexpr). + virtual bool shouldSkipFunctionBody(Decl *D) { return true; } }; } // end namespace clang. diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index f0934b7..d4878a9 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -15,21 +15,23 @@ #ifndef LLVM_CLANG_AST_ASTCONTEXT_H #define LLVM_CLANG_AST_ASTCONTEXT_H -#include "clang/Basic/AddressSpaces.h" -#include "clang/Basic/IdentifierTable.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/OperatorKinds.h" -#include "clang/Basic/PartialDiagnostic.h" -#include "clang/Basic/VersionTuple.h" +#include "clang/AST/ASTTypeTraits.h" +#include "clang/AST/CanonicalType.h" +#include "clang/AST/CommentCommandTraits.h" #include "clang/AST/Decl.h" #include "clang/AST/LambdaMangleContext.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/AST/RawCommentList.h" +#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" -#include "clang/AST/CanonicalType.h" -#include "clang/AST/RawCommentList.h" -#include "clang/AST/CommentCommandTraits.h" +#include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -57,28 +59,12 @@ namespace clang { class TargetInfo; class CXXABI; // Decls - class DeclContext; - class CXXConversionDecl; - class CXXMethodDecl; - class CXXRecordDecl; - class Decl; - class FieldDecl; class MangleContext; class ObjCIvarDecl; - class ObjCIvarRefExpr; class ObjCPropertyDecl; - class ParmVarDecl; - class RecordDecl; - class StoredDeclsMap; - class TagDecl; - class TemplateTemplateParmDecl; - class TemplateTypeParmDecl; - class TranslationUnitDecl; - class TypeDecl; - class TypedefNameDecl; + class UnresolvedSetIterator; class UsingDecl; class UsingShadowDecl; - class UnresolvedSetIterator; namespace Builtin { class Context; } @@ -91,7 +77,7 @@ namespace clang { class ASTContext : public RefCountedBase { ASTContext &this_() { return *this; } - mutable std::vector Types; + mutable SmallVector Types; mutable llvm::FoldingSet ExtQualNodes; mutable llvm::FoldingSet ComplexTypes; mutable llvm::FoldingSet PointerTypes; @@ -233,6 +219,8 @@ class ASTContext : public RefCountedBase { QualType ObjCConstantStringType; mutable RecordDecl *CFConstantStringTypeDecl; + mutable QualType ObjCSuperType; + QualType ObjCNSStringType; /// \brief The typedef declaration for the Objective-C "instancetype" type. @@ -343,7 +331,10 @@ class ASTContext : public RefCountedBase { /// \brief Mapping from each declaration context to its corresponding lambda /// mangling context. llvm::DenseMap LambdaMangleContexts; - + + llvm::DenseMap UnnamedMangleContexts; + llvm::DenseMap UnnamedMangleNumbers; + /// \brief Mapping that stores parameterIndex values for ParmVarDecls when /// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex. typedef llvm::DenseMap ParameterIndexTable; @@ -393,6 +384,58 @@ public: OwningPtr ExternalSource; ASTMutationListener *Listener; + /// \brief Contains parents of a node. + typedef llvm::SmallVector ParentVector; + + /// \brief Maps from a node to its parents. + typedef llvm::DenseMap ParentMap; + + /// \brief Returns the parents of the given node. + /// + /// Note that this will lazily compute the parents of all nodes + /// and store them for later retrieval. Thus, the first call is O(n) + /// in the number of AST nodes. + /// + /// Caveats and FIXMEs: + /// Calculating the parent map over all AST nodes will need to load the + /// full AST. This can be undesirable in the case where the full AST is + /// expensive to create (for example, when using precompiled header + /// preambles). Thus, there are good opportunities for optimization here. + /// One idea is to walk the given node downwards, looking for references + /// to declaration contexts - once a declaration context is found, compute + /// the parent map for the declaration context; if that can satisfy the + /// request, loading the whole AST can be avoided. Note that this is made + /// more complex by statements in templates having multiple parents - those + /// problems can be solved by building closure over the templated parts of + /// the AST, which also avoids touching large parts of the AST. + /// Additionally, we will want to add an interface to already give a hint + /// where to search for the parents, for example when looking at a statement + /// inside a certain function. + /// + /// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc, + /// NestedNameSpecifier or NestedNameSpecifierLoc. + template + ParentVector getParents(const NodeT &Node) { + return getParents(ast_type_traits::DynTypedNode::create(Node)); + } + + ParentVector getParents(const ast_type_traits::DynTypedNode &Node) { + assert(Node.getMemoizationData() && + "Invariant broken: only nodes that support memoization may be " + "used in the parent map."); + if (!AllParents) { + // We always need to run over the whole translation unit, as + // hasAncestor can escape any subtree. + AllParents.reset( + ParentMapASTVisitor::buildMap(*getTranslationUnitDecl())); + } + ParentMap::const_iterator I = AllParents->find(Node.getMemoizationData()); + if (I == AllParents->end()) { + return ParentVector(); + } + return I->second; + } + const clang::PrintingPolicy &getPrintingPolicy() const { return PrintingPolicy; } @@ -713,6 +756,10 @@ public: CanQualType PseudoObjectTy, ARCUnbridgedCastTy; CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy; CanQualType ObjCBuiltinBoolTy; + CanQualType OCLImage1dTy, OCLImage1dArrayTy, OCLImage1dBufferTy; + CanQualType OCLImage2dTy, OCLImage2dArrayTy; + CanQualType OCLImage3dTy; + CanQualType OCLSamplerTy, OCLEventTy; // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand. mutable QualType AutoDeductTy; // Deduction against 'auto'. @@ -755,7 +802,7 @@ public: ASTMutationListener *getASTMutationListener() const { return Listener; } void PrintStats() const; - const std::vector& getTypes() const { return Types; } + const SmallVectorImpl& getTypes() const { return Types; } /// \brief Retrieve the declaration for the 128-bit signed integer type. TypedefDecl *getInt128Decl() const; @@ -857,12 +904,17 @@ public: return cudaConfigureCallDecl; } - /// Builds the struct used for __block variables. - QualType BuildByRefType(StringRef DeclName, QualType Ty) const; - /// Returns true iff we need copy/dispose helpers for the given type. - bool BlockRequiresCopying(QualType Ty) const; - + bool BlockRequiresCopying(QualType Ty, const VarDecl *D); + + + /// Returns true, if given type has a known lifetime. HasByrefExtendedLayout is set + /// to false in this case. If HasByrefExtendedLayout returns true, byref variable + /// has extended lifetime. + bool getByrefLifetime(QualType Ty, + Qualifiers::ObjCLifetime &Lifetime, + bool &HasByrefExtendedLayout) const; + /// \brief Return the uniqued reference to the type for an lvalue reference /// to the specified type. QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true) @@ -941,8 +993,7 @@ public: } /// \brief Return a normal function type with a typed argument list. - QualType getFunctionType(QualType ResultTy, - const QualType *Args, unsigned NumArgs, + QualType getFunctionType(QualType ResultTy, ArrayRef Args, const FunctionProtoType::ExtProtoInfo &EPI) const; /// \brief Return the unique reference to the type for the specified type @@ -1025,7 +1076,7 @@ public: const TemplateArgument *Args) const; QualType getPackExpansionType(QualType Pattern, - llvm::Optional NumExpansions); + Optional NumExpansions); QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl = 0) const; @@ -1094,6 +1145,14 @@ public: /// defined in as defined by the target. QualType getWIntType() const { return WIntTy; } + /// \brief Return a type compatible with "intptr_t" (C99 7.18.1.4), + /// as defined by the target. + QualType getIntPtrType() const; + + /// \brief Return a type compatible with "uintptr_t" (C99 7.18.1.4), + /// as defined by the target. + QualType getUIntPtrType() const; + /// \brief Return the unique type for "ptrdiff_t" (C99 7.17) defined in /// . Pointer - pointer requires this (C99 6.5.6p9). QualType getPointerDiffType() const; @@ -1104,7 +1163,11 @@ public: /// \brief Return the C structure type used to represent constant CFStrings. QualType getCFConstantStringType() const; - + + /// \brief Returns the C struct type for objc_super + QualType getObjCSuperType() const; + void setObjCSuperType(QualType ST) { ObjCSuperType = ST; } + /// Get the structure type used to representation CFStrings, or NULL /// if it hasn't yet been built. QualType getRawCFConstantStringType() const { @@ -1545,14 +1608,27 @@ public: const ASTRecordLayout & getASTObjCImplementationLayout(const ObjCImplementationDecl *D) const; - /// \brief Get the key function for the given record decl, or NULL if there - /// isn't one. + /// \brief Get our current best idea for the key function of the + /// given record decl, or NULL if there isn't one. /// /// The key function is, according to the Itanium C++ ABI section 5.2.3: + /// ...the first non-pure virtual function that is not inline at the + /// point of class definition. /// - /// ...the first non-pure virtual function that is not inline at the point - /// of class definition. - const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD); + /// Other ABIs use the same idea. However, the ARM C++ ABI ignores + /// virtual functions that are defined 'inline', which means that + /// the result of this computation can change. + const CXXMethodDecl *getCurrentKeyFunction(const CXXRecordDecl *RD); + + /// \brief Observe that the given method cannot be a key function. + /// Checks the key-function cache for the method's class and clears it + /// if matches the given declaration. + /// + /// This is used in ABIs where out-of-line definitions marked + /// inline are not considered to be key functions. + /// + /// \param method should be the declaration from the class definition + void setNonKeyFunction(const CXXMethodDecl *method); /// Get the offset of a FieldDecl or IndirectFieldDecl, in bits. uint64_t getFieldOffset(const ValueDecl *FD) const; @@ -1885,8 +1961,8 @@ public: // Type Iterators. //===--------------------------------------------------------------------===// - typedef std::vector::iterator type_iterator; - typedef std::vector::const_iterator const_type_iterator; + typedef SmallVectorImpl::iterator type_iterator; + typedef SmallVectorImpl::const_iterator const_type_iterator; type_iterator types_begin() { return Types.begin(); } type_iterator types_end() { return Types.end(); } @@ -1943,7 +2019,7 @@ public: /// \brief Returns the Objective-C interface that \p ND belongs to if it is /// an Objective-C method/property/ivar etc. that is part of an interface, /// otherwise returns null. - ObjCInterfaceDecl *getObjContainingInterface(NamedDecl *ND) const; + const ObjCInterfaceDecl *getObjContainingInterface(const NamedDecl *ND) const; /// \brief Set the copy inialization expression of a block var decl. void setBlockVarCopyInits(VarDecl*VD, Expr* Init); @@ -1993,6 +2069,9 @@ public: /// it is not used. bool DeclMustBeEmitted(const Decl *D); + void addUnnamedTag(const TagDecl *Tag); + int getUnnamedTagManglingNumber(const TagDecl *Tag) const; + /// \brief Retrieve the lambda mangling number for a lambda expression. unsigned getLambdaManglingNumber(CXXMethodDecl *CallOperator); @@ -2077,7 +2156,8 @@ private: bool EncodingProperty = false, bool StructField = false, bool EncodeBlockParameters = false, - bool EncodeClassNames = false) const; + bool EncodeClassNames = false, + bool EncodePointerToObjCTypedef = false) const; // Adds the encoding of the structure's members. void getObjCEncodingForStructureImpl(RecordDecl *RD, std::string &S, @@ -2109,8 +2189,81 @@ private: friend class DeclContext; friend class DeclarationNameTable; void ReleaseDeclContextMaps(); + + /// \brief A \c RecursiveASTVisitor that builds a map from nodes to their + /// parents as defined by the \c RecursiveASTVisitor. + /// + /// Note that the relationship described here is purely in terms of AST + /// traversal - there are other relationships (for example declaration context) + /// in the AST that are better modeled by special matchers. + /// + /// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes. + class ParentMapASTVisitor : public RecursiveASTVisitor { + public: + /// \brief Builds and returns the translation unit's parent map. + /// + /// The caller takes ownership of the returned \c ParentMap. + static ParentMap *buildMap(TranslationUnitDecl &TU) { + ParentMapASTVisitor Visitor(new ParentMap); + Visitor.TraverseDecl(&TU); + return Visitor.Parents; + } + + private: + typedef RecursiveASTVisitor VisitorBase; + + ParentMapASTVisitor(ParentMap *Parents) : Parents(Parents) { + } + + bool shouldVisitTemplateInstantiations() const { + return true; + } + bool shouldVisitImplicitCode() const { + return true; + } + // Disables data recursion. We intercept Traverse* methods in the RAV, which + // are not triggered during data recursion. + bool shouldUseDataRecursionFor(clang::Stmt *S) const { + return false; + } + + template + bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *)) { + if (Node == NULL) + return true; + if (ParentStack.size() > 0) + // FIXME: Currently we add the same parent multiple times, for example + // when we visit all subexpressions of template instantiations; this is + // suboptimal, bug benign: the only way to visit those is with + // hasAncestor / hasParent, and those do not create new matches. + // The plan is to enable DynTypedNode to be storable in a map or hash + // map. The main problem there is to implement hash functions / + // comparison operators for all types that DynTypedNode supports that + // do not have pointer identity. + (*Parents)[Node].push_back(ParentStack.back()); + ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node)); + bool Result = (this ->* traverse) (Node); + ParentStack.pop_back(); + return Result; + } + + bool TraverseDecl(Decl *DeclNode) { + return TraverseNode(DeclNode, &VisitorBase::TraverseDecl); + } + + bool TraverseStmt(Stmt *StmtNode) { + return TraverseNode(StmtNode, &VisitorBase::TraverseStmt); + } + + ParentMap *Parents; + llvm::SmallVector ParentStack; + + friend class RecursiveASTVisitor; + }; + + llvm::OwningPtr AllParents; }; - + /// \brief Utility function for constructing a nullary selector. static inline Selector GetNullarySelector(StringRef name, ASTContext& Ctx) { IdentifierInfo* II = &Ctx.Idents.get(name); @@ -2132,8 +2285,8 @@ static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) { /// This placement form of operator new uses the ASTContext's allocator for /// obtaining memory. /// -/// IMPORTANT: These are also declared in clang/AST/Attr.h! Any changes here -/// need to also be made there. +/// IMPORTANT: These are also declared in clang/AST/AttrIterator.h! Any changes +/// here need to also be made there. /// /// We intentionally avoid using a nothrow specification here so that the calls /// to this operator will not perform a null check on the result -- the diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index 46a9881..1672ab2 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -48,6 +48,9 @@ namespace clang { /// \brief Whether to perform a minimal import. bool Minimal; + + /// \brief Whether the last diagnostic came from the "from" context. + bool LastDiagFromFrom; /// \brief Mapping from the already-imported types in the "from" context /// to the corresponding types in the "to" context. diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index 56d1526..6b70285 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -16,18 +16,19 @@ #include "clang/Basic/SourceLocation.h" namespace clang { - class Decl; - class DeclContext; - class TagDecl; class CXXRecordDecl; class ClassTemplateDecl; class ClassTemplateSpecializationDecl; + class Decl; + class DeclContext; class FunctionDecl; class FunctionTemplateDecl; class ObjCCategoryDecl; - class ObjCInterfaceDecl; class ObjCContainerDecl; + class ObjCInterfaceDecl; class ObjCPropertyDecl; + class TagDecl; + class VarDecl; /// \brief An abstract interface that should be implemented by listeners /// that want to be notified when an AST entity gets modified after its diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h new file mode 100644 index 0000000..4688b12 --- /dev/null +++ b/include/clang/AST/ASTTypeTraits.h @@ -0,0 +1,211 @@ +//===--- ASTTypeTraits.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Provides a dynamically typed node container that can be used to store +// an AST base node at runtime in the same storage in a type safe way. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_AST_TYPE_TRAITS_H +#define LLVM_CLANG_AST_AST_TYPE_TRAITS_H + +#include "clang/AST/Decl.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/TypeLoc.h" +#include "llvm/Support/AlignOf.h" + +namespace clang { +namespace ast_type_traits { + +/// \brief A dynamically typed AST node container. +/// +/// Stores an AST node in a type safe way. This allows writing code that +/// works with different kinds of AST nodes, despite the fact that they don't +/// have a common base class. +/// +/// Use \c create(Node) to create a \c DynTypedNode from an AST node, +/// and \c get() to retrieve the node as type T if the types match. +/// +/// See \c NodeTypeTag for which node base types are currently supported; +/// You can create DynTypedNodes for all nodes in the inheritance hierarchy of +/// the supported base types. +class DynTypedNode { +public: + /// \brief Creates a \c DynTypedNode from \c Node. + template + static DynTypedNode create(const T &Node) { + return BaseConverter::create(Node); + } + + /// \brief Retrieve the stored node as type \c T. + /// + /// Returns NULL if the stored node does not have a type that is + /// convertible to \c T. + /// + /// For types that have identity via their pointer in the AST + /// (like \c Stmt and \c Decl) the returned pointer points to the + /// referenced AST node. + /// For other types (like \c QualType) the value is stored directly + /// in the \c DynTypedNode, and the returned pointer points at + /// the storage inside DynTypedNode. For those nodes, do not + /// use the pointer outside the scope of the DynTypedNode. + template + const T *get() const { + return BaseConverter::get(Tag, Storage.buffer); + } + + /// \brief Returns a pointer that identifies the stored AST node. + /// + /// Note that this is not supported by all AST nodes. For AST nodes + /// that don't have a pointer-defined identity inside the AST, this + /// method returns NULL. + const void *getMemoizationData() const; + +private: + /// \brief Takes care of converting from and to \c T. + template struct BaseConverter; + + /// \brief Supported base node types. + enum NodeTypeTag { + NT_Decl, + NT_Stmt, + NT_NestedNameSpecifier, + NT_NestedNameSpecifierLoc, + NT_QualType, + NT_Type, + NT_TypeLoc + } Tag; + + /// \brief Stores the data of the node. + /// + /// Note that we can store \c Decls and \c Stmts by pointer as they are + /// guaranteed to be unique pointers pointing to dedicated storage in the + /// AST. \c QualTypes on the other hand do not have storage or unique + /// pointers and thus need to be stored by value. + llvm::AlignedCharArrayUnion Storage; +}; + +// FIXME: Pull out abstraction for the following. +template struct DynTypedNode::BaseConverter >::type> { + static const T *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_Decl) + return dyn_cast(*reinterpret_cast(Storage)); + return NULL; + } + static DynTypedNode create(const Decl &Node) { + DynTypedNode Result; + Result.Tag = NT_Decl; + new (Result.Storage.buffer) const Decl*(&Node); + return Result; + } +}; +template struct DynTypedNode::BaseConverter >::type> { + static const T *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_Stmt) + return dyn_cast(*reinterpret_cast(Storage)); + return NULL; + } + static DynTypedNode create(const Stmt &Node) { + DynTypedNode Result; + Result.Tag = NT_Stmt; + new (Result.Storage.buffer) const Stmt*(&Node); + return Result; + } +}; +template struct DynTypedNode::BaseConverter >::type> { + static const T *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_Type) + return dyn_cast(*reinterpret_cast(Storage)); + return NULL; + } + static DynTypedNode create(const Type &Node) { + DynTypedNode Result; + Result.Tag = NT_Type; + new (Result.Storage.buffer) const Type*(&Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter { + static const NestedNameSpecifier *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_NestedNameSpecifier) + return *reinterpret_cast(Storage); + return NULL; + } + static DynTypedNode create(const NestedNameSpecifier &Node) { + DynTypedNode Result; + Result.Tag = NT_NestedNameSpecifier; + new (Result.Storage.buffer) const NestedNameSpecifier*(&Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter { + static const NestedNameSpecifierLoc *get(NodeTypeTag Tag, + const char Storage[]) { + if (Tag == NT_NestedNameSpecifierLoc) + return reinterpret_cast(Storage); + return NULL; + } + static DynTypedNode create(const NestedNameSpecifierLoc &Node) { + DynTypedNode Result; + Result.Tag = NT_NestedNameSpecifierLoc; + new (Result.Storage.buffer) NestedNameSpecifierLoc(Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter { + static const QualType *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_QualType) + return reinterpret_cast(Storage); + return NULL; + } + static DynTypedNode create(const QualType &Node) { + DynTypedNode Result; + Result.Tag = NT_QualType; + new (Result.Storage.buffer) QualType(Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter { + static const TypeLoc *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_TypeLoc) + return reinterpret_cast(Storage); + return NULL; + } + static DynTypedNode create(const TypeLoc &Node) { + DynTypedNode Result; + Result.Tag = NT_TypeLoc; + new (Result.Storage.buffer) TypeLoc(Node); + return Result; + } +}; +// The only operation we allow on unsupported types is \c get. +// This allows to conveniently use \c DynTypedNode when having an arbitrary +// AST node that is not supported, but prevents misuse - a user cannot create +// a DynTypedNode from arbitrary types. +template struct DynTypedNode::BaseConverter { + static const T *get(NodeTypeTag Tag, const char Storage[]) { return NULL; } +}; + +inline const void *DynTypedNode::getMemoizationData() const { + switch (Tag) { + case NT_Decl: return BaseConverter::get(Tag, Storage.buffer); + case NT_Stmt: return BaseConverter::get(Tag, Storage.buffer); + default: return NULL; + }; +} + +} // end namespace ast_type_traits +} // end namespace clang + +#endif // LLVM_CLANG_AST_AST_TYPE_TRAITS_H diff --git a/include/clang/AST/ASTUnresolvedSet.h b/include/clang/AST/ASTUnresolvedSet.h new file mode 100644 index 0000000..c709895 --- /dev/null +++ b/include/clang/AST/ASTUnresolvedSet.h @@ -0,0 +1,86 @@ +//===-- ASTUnresolvedSet.h - Unresolved sets of declarations ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides an UnresolvedSet-like class, whose contents are +// allocated using the allocator associated with an ASTContext. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ASTUNRESOLVEDSET_H +#define LLVM_CLANG_AST_ASTUNRESOLVEDSET_H + +#include "clang/AST/ASTVector.h" +#include "clang/AST/UnresolvedSet.h" + +namespace clang { + +/// \brief An UnresolvedSet-like class which uses the ASTContext's allocator. +class ASTUnresolvedSet { + typedef ASTVector DeclsTy; + DeclsTy Decls; + + ASTUnresolvedSet(const ASTUnresolvedSet &) LLVM_DELETED_FUNCTION; + void operator=(const ASTUnresolvedSet &) LLVM_DELETED_FUNCTION; + +public: + ASTUnresolvedSet() {} + ASTUnresolvedSet(ASTContext &C, unsigned N) : Decls(C, N) {} + + typedef UnresolvedSetIterator iterator; + typedef UnresolvedSetIterator const_iterator; + + iterator begin() { return iterator(Decls.begin()); } + iterator end() { return iterator(Decls.end()); } + + const_iterator begin() const { return const_iterator(Decls.begin()); } + const_iterator end() const { return const_iterator(Decls.end()); } + + void addDecl(ASTContext &C, NamedDecl *D) { + addDecl(C, D, AS_none); + } + + void addDecl(ASTContext &C, NamedDecl *D, AccessSpecifier AS) { + Decls.push_back(DeclAccessPair::make(D, AS), C); + } + + /// Replaces the given declaration with the new one, once. + /// + /// \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->getDecl() == Old) + return (I->setDecl(New), true); + return false; + } + + void erase(unsigned I) { + Decls[I] = Decls.back(); + Decls.pop_back(); + } + + void clear() { Decls.clear(); } + + bool empty() const { return Decls.empty(); } + unsigned size() const { return Decls.size(); } + + void reserve(ASTContext &C, unsigned N) { + Decls.reserve(C, N); + } + + void append(ASTContext &C, iterator I, iterator E) { + Decls.append(C, I.ir, E.ir); + } + + DeclAccessPair &operator[](unsigned I) { return Decls[I]; } + const DeclAccessPair &operator[](unsigned I) const { return Decls[I]; } +}; + +} // namespace clang + +#endif diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h index 4ff5ea3..669e50d 100644 --- a/include/clang/AST/ASTVector.h +++ b/include/clang/AST/ASTVector.h @@ -18,12 +18,13 @@ #ifndef LLVM_CLANG_AST_VECTOR #define LLVM_CLANG_AST_VECTOR -#include "llvm/Support/type_traits.h" -#include "llvm/Support/Allocator.h" +#include "clang/AST/AttrIterator.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/type_traits.h" #include -#include #include +#include #ifdef _MSC_VER namespace std { @@ -50,6 +51,7 @@ namespace std { #endif namespace clang { + class ASTContext; template class ASTVector { @@ -59,7 +61,9 @@ class ASTVector { public: // Default ctor - Initialize to empty. - explicit ASTVector(ASTContext &C, unsigned N = 0) + ASTVector() : Begin(NULL), End(NULL), Capacity(NULL) { } + + ASTVector(ASTContext &C, unsigned N) : Begin(NULL), End(NULL), Capacity(NULL) { reserve(C, N); } diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 12a9855..27dcef2 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -14,9 +14,10 @@ #ifndef LLVM_CLANG_AST_ATTR_H #define LLVM_CLANG_AST_ATTR_H -#include "clang/Basic/LLVM.h" -#include "clang/Basic/AttrKinds.h" +#include "clang/AST/AttrIterator.h" #include "clang/AST/Type.h" +#include "clang/Basic/AttrKinds.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/VersionTuple.h" #include "llvm/ADT/SmallVector.h" @@ -26,7 +27,6 @@ #include "llvm/Support/raw_ostream.h" #include #include -#include namespace clang { class ASTContext; @@ -36,23 +36,6 @@ namespace clang { class QualType; class FunctionDecl; class TypeSourceInfo; -} - -// Defined in ASTContext.h -void *operator new(size_t Bytes, const clang::ASTContext &C, - size_t Alignment = 16); -// FIXME: Being forced to not have a default argument here due to redeclaration -// rules on default arguments sucks -void *operator new[](size_t Bytes, const clang::ASTContext &C, - size_t Alignment); - -// It is good practice to pair new/delete operators. Also, MSVC gives many -// warnings if a matching delete overload is not declared, even though the -// throw() spec guarantees it will not be implicitly called. -void operator delete(void *Ptr, const clang::ASTContext &C, size_t); -void operator delete[](void *Ptr, const clang::ASTContext &C, size_t); - -namespace clang { /// Attr - This represents one attribute. class Attr { @@ -61,10 +44,16 @@ private: unsigned AttrKind : 16; protected: + /// An index into the spelling list of an + /// attribute defined in Attr.td file. + unsigned SpellingListIndex : 4; + bool Inherited : 1; + bool IsPackExpansion : 1; + virtual ~Attr(); - + void* operator new(size_t bytes) throw() { llvm_unreachable("Attrs cannot be allocated with regular 'new'."); } @@ -84,14 +73,17 @@ public: } protected: - Attr(attr::Kind AK, SourceRange R) - : Range(R), AttrKind(AK), Inherited(false) {} + Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0) + : Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex), + Inherited(false), IsPackExpansion(false) {} public: attr::Kind getKind() const { return static_cast(AttrKind); } + + unsigned getSpellingListIndex() const { return SpellingListIndex; } SourceLocation getLocation() const { return Range.getBegin(); } SourceRange getRange() const { return Range; } @@ -99,21 +91,24 @@ public: bool isInherited() const { return Inherited; } + void setPackExpansion(bool PE) { IsPackExpansion = PE; } + bool isPackExpansion() const { return IsPackExpansion; } + // Clone this attribute. - virtual Attr* clone(ASTContext &C) const = 0; + virtual Attr *clone(ASTContext &C) const = 0; virtual bool isLateParsed() const { return false; } // Pretty print this attribute. - virtual void printPretty(llvm::raw_ostream &OS, + virtual void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const = 0; }; class InheritableAttr : public Attr { virtual void anchor(); protected: - InheritableAttr(attr::Kind AK, SourceRange R) - : Attr(AK, R) {} + InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0) + : Attr(AK, R, SpellingListIndex) {} public: void setInherited(bool I) { Inherited = I; } @@ -127,125 +122,35 @@ public: class InheritableParamAttr : public InheritableAttr { virtual void anchor(); protected: - InheritableParamAttr(attr::Kind AK, SourceRange R) - : InheritableAttr(AK, R) {} + InheritableParamAttr(attr::Kind AK, SourceRange R, + unsigned SpellingListIndex = 0) + : InheritableAttr(AK, R, SpellingListIndex) {} public: // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { + // Relies on relative order of enum emission with respect to MS inheritance + // attrs. return A->getKind() <= attr::LAST_INHERITABLE_PARAM; } }; -#include "clang/AST/Attrs.inc" - -/// AttrVec - A vector of Attr, which is how they are stored on the AST. -typedef SmallVector AttrVec; -typedef SmallVector ConstAttrVec; - -/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only -/// providing attributes that are of a specifc type. -template -class specific_attr_iterator { - typedef typename Container::const_iterator Iterator; - - /// Current - The current, underlying iterator. - /// In order to ensure we don't dereference an invalid iterator unless - /// specifically requested, we don't necessarily advance this all the - /// way. Instead, we advance it when an operation is requested; if the - /// operation is acting on what should be a past-the-end iterator, - /// then we offer no guarantees, but this way we do not dererence a - /// past-the-end iterator when we move to a past-the-end position. - mutable Iterator Current; - - void AdvanceToNext() const { - while (!isa(*Current)) - ++Current; - } - - void AdvanceToNext(Iterator I) const { - while (Current != I && !isa(*Current)) - ++Current; - } +class MSInheritanceAttr : public InheritableAttr { + virtual void anchor(); +protected: + MSInheritanceAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0) + : InheritableAttr(AK, R, SpellingListIndex) {} public: - typedef SpecificAttr* value_type; - typedef SpecificAttr* reference; - typedef SpecificAttr* pointer; - typedef std::forward_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; - - specific_attr_iterator() : Current() { } - explicit specific_attr_iterator(Iterator i) : Current(i) { } - - reference operator*() const { - AdvanceToNext(); - return cast(*Current); - } - pointer operator->() const { - AdvanceToNext(); - return cast(*Current); - } - - specific_attr_iterator& operator++() { - ++Current; - return *this; - } - specific_attr_iterator operator++(int) { - specific_attr_iterator Tmp(*this); - ++(*this); - return Tmp; - } - - friend bool operator==(specific_attr_iterator Left, - specific_attr_iterator Right) { - if (Left.Current < Right.Current) - Left.AdvanceToNext(Right.Current); - else - Right.AdvanceToNext(Left.Current); - return Left.Current == Right.Current; - } - friend bool operator!=(specific_attr_iterator Left, - specific_attr_iterator Right) { - return !(Left == Right); + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + // Relies on relative order of enum emission with respect to param attrs. + return (A->getKind() <= attr::LAST_MS_INHERITABLE && + A->getKind() > attr::LAST_INHERITABLE_PARAM); } }; -template -inline specific_attr_iterator - specific_attr_begin(const Container& container) { - return specific_attr_iterator(container.begin()); -} -template -inline specific_attr_iterator - specific_attr_end(const Container& container) { - return specific_attr_iterator(container.end()); -} - -template -inline bool hasSpecificAttr(const Container& container) { - return specific_attr_begin(container) != - specific_attr_end(container); -} -template -inline SpecificAttr *getSpecificAttr(const Container& container) { - specific_attr_iterator i = - specific_attr_begin(container); - if (i != specific_attr_end(container)) - return *i; - else - return 0; -} - -/// getMaxAlignment - Returns the highest alignment value found among -/// AlignedAttrs in an AttrVec, or 0 if there are none. -inline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) { - unsigned Align = 0; - specific_attr_iterator i(V.begin()), e(V.end()); - for(; i != e; ++i) - Align = std::max(Align, i->getAlignment(Ctx)); - return Align; -} +#include "clang/AST/Attrs.inc" } // end namespace clang diff --git a/include/clang/AST/AttrIterator.h b/include/clang/AST/AttrIterator.h new file mode 100644 index 0000000..8bd8fbe --- /dev/null +++ b/include/clang/AST/AttrIterator.h @@ -0,0 +1,142 @@ +//===--- AttrIterator.h - Classes for attribute iteration -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the Attr vector and specific_attr_iterator interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ATTRITERATOR_H +#define LLVM_CLANG_AST_ATTRITERATOR_H + +#include "clang/Basic/LLVM.h" +#include + +namespace clang { + class ASTContext; + class Attr; +} + +// Defined in ASTContext.h +void *operator new(size_t Bytes, const clang::ASTContext &C, + size_t Alignment = 16); +// FIXME: Being forced to not have a default argument here due to redeclaration +// rules on default arguments sucks +void *operator new[](size_t Bytes, const clang::ASTContext &C, + size_t Alignment); + +// It is good practice to pair new/delete operators. Also, MSVC gives many +// warnings if a matching delete overload is not declared, even though the +// throw() spec guarantees it will not be implicitly called. +void operator delete(void *Ptr, const clang::ASTContext &C, size_t); +void operator delete[](void *Ptr, const clang::ASTContext &C, size_t); + +namespace clang { + +/// AttrVec - A vector of Attr, which is how they are stored on the AST. +typedef SmallVector AttrVec; +typedef SmallVector ConstAttrVec; + +/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only +/// providing attributes that are of a specifc type. +template +class specific_attr_iterator { + typedef typename Container::const_iterator Iterator; + + /// Current - The current, underlying iterator. + /// In order to ensure we don't dereference an invalid iterator unless + /// specifically requested, we don't necessarily advance this all the + /// way. Instead, we advance it when an operation is requested; if the + /// operation is acting on what should be a past-the-end iterator, + /// then we offer no guarantees, but this way we do not dererence a + /// past-the-end iterator when we move to a past-the-end position. + mutable Iterator Current; + + void AdvanceToNext() const { + while (!isa(*Current)) + ++Current; + } + + void AdvanceToNext(Iterator I) const { + while (Current != I && !isa(*Current)) + ++Current; + } + +public: + typedef SpecificAttr* value_type; + typedef SpecificAttr* reference; + typedef SpecificAttr* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + specific_attr_iterator() : Current() { } + explicit specific_attr_iterator(Iterator i) : Current(i) { } + + reference operator*() const { + AdvanceToNext(); + return cast(*Current); + } + pointer operator->() const { + AdvanceToNext(); + return cast(*Current); + } + + specific_attr_iterator& operator++() { + ++Current; + return *this; + } + specific_attr_iterator operator++(int) { + specific_attr_iterator Tmp(*this); + ++(*this); + return Tmp; + } + + friend bool operator==(specific_attr_iterator Left, + specific_attr_iterator Right) { + assert((Left.Current == 0) == (Right.Current == 0)); + if (Left.Current < Right.Current) + Left.AdvanceToNext(Right.Current); + else + Right.AdvanceToNext(Left.Current); + return Left.Current == Right.Current; + } + friend bool operator!=(specific_attr_iterator Left, + specific_attr_iterator Right) { + return !(Left == Right); + } +}; + +template +inline specific_attr_iterator + specific_attr_begin(const Container& container) { + return specific_attr_iterator(container.begin()); +} +template +inline specific_attr_iterator + specific_attr_end(const Container& container) { + return specific_attr_iterator(container.end()); +} + +template +inline bool hasSpecificAttr(const Container& container) { + return specific_attr_begin(container) != + specific_attr_end(container); +} +template +inline SpecificAttr *getSpecificAttr(const Container& container) { + specific_attr_iterator i = + specific_attr_begin(container); + if (i != specific_attr_end(container)) + return *i; + else + return 0; +} + +} // end namespace clang + +#endif diff --git a/include/clang/AST/BuiltinTypes.def b/include/clang/AST/BuiltinTypes.def index ba322fb..488cace 100644 --- a/include/clang/AST/BuiltinTypes.def +++ b/include/clang/AST/BuiltinTypes.def @@ -154,6 +154,20 @@ BUILTIN_TYPE(ObjCClass, ObjCBuiltinClassTy) // type is a typedef of a PointerType to this. BUILTIN_TYPE(ObjCSel, ObjCBuiltinSelTy) +// OpenCL image types. +BUILTIN_TYPE(OCLImage1d, OCLImage1dTy) +BUILTIN_TYPE(OCLImage1dArray, OCLImage1dArrayTy) +BUILTIN_TYPE(OCLImage1dBuffer, OCLImage1dBufferTy) +BUILTIN_TYPE(OCLImage2d, OCLImage2dTy) +BUILTIN_TYPE(OCLImage2dArray, OCLImage2dArrayTy) +BUILTIN_TYPE(OCLImage3d, OCLImage3dTy) + +// OpenCL sampler_t. +BUILTIN_TYPE(OCLSampler, OCLSamplerTy) + +// OpenCL event_t. +BUILTIN_TYPE(OCLEvent, OCLEventTy) + // This represents the type of an expression whose type is // totally unknown, e.g. 'T::foo'. It is permitted for this to // appear in situations where the structure of the type is diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt index 4c4c0fb..ba54fa2 100644 --- a/include/clang/AST/CMakeLists.txt +++ b/include/clang/AST/CMakeLists.txt @@ -8,6 +8,11 @@ clang_tablegen(AttrImpl.inc -gen-clang-attr-impl SOURCE ../Basic/Attr.td TARGET ClangAttrImpl) +clang_tablegen(AttrDump.inc -gen-clang-attr-dump + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ + SOURCE ../Basic/Attr.td + TARGET ClangAttrDump) + clang_tablegen(StmtNodes.inc -gen-clang-stmt-nodes SOURCE ../Basic/StmtNodes.td TARGET ClangStmtNodes) @@ -28,7 +33,15 @@ clang_tablegen(CommentHTMLTagsProperties.inc -gen-clang-comment-html-tags-proper SOURCE CommentHTMLTags.td TARGET ClangCommentHTMLTagsProperties) +clang_tablegen(CommentHTMLNamedCharacterReferences.inc -gen-clang-comment-html-named-character-references + SOURCE CommentHTMLNamedCharacterReferences.td + TARGET ClangCommentHTMLNamedCharacterReferences) + clang_tablegen(CommentCommandInfo.inc -gen-clang-comment-command-info SOURCE CommentCommands.td TARGET ClangCommentCommandInfo) +clang_tablegen(CommentCommandList.inc -gen-clang-comment-command-list + SOURCE CommentCommands.td + TARGET ClangCommentCommandList) + diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index 87bdbe0..2983e04 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -14,17 +14,17 @@ #ifndef LLVM_CLANG_AST_CXXINHERITANCE_H #define LLVM_CLANG_AST_CXXINHERITANCE_H -#include "clang/AST/DeclarationName.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Type.h" #include "clang/AST/TypeOrdering.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" +#include #include #include -#include namespace clang { diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index ea307bf..9460757 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -351,15 +351,12 @@ namespace llvm { /// CanQual to a specific Type class. We're prefer isa/dyn_cast/cast/etc. /// to return smart pointer (proxies?). template -struct simplify_type > { +struct simplify_type< ::clang::CanQual > { typedef const T *SimpleType; - static SimpleType getSimplifiedValue(const ::clang::CanQual &Val) { + static SimpleType getSimplifiedValue(::clang::CanQual Val) { return Val.getTypePtr(); } }; -template -struct simplify_type< ::clang::CanQual > -: public simplify_type > {}; // Teach SmallPtrSet that CanQual is "basically a pointer". template @@ -514,55 +511,13 @@ struct CanProxyAdaptor LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass) }; -template<> -struct CanProxyAdaptor : public CanProxyBase { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, - getSizeModifier) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) -}; - -template<> -struct CanProxyAdaptor - : public CanProxyBase { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, - getSizeModifier) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize) -}; - -template<> -struct CanProxyAdaptor - : public CanProxyBase { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, - getSizeModifier) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) -}; - -template<> -struct CanProxyAdaptor - : public CanProxyBase { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, - getSizeModifier) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc) -}; - -template<> -struct CanProxyAdaptor - : public CanProxyBase { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc) -}; +// CanProxyAdaptors for arrays are intentionally unimplemented because +// they are not safe. +template<> struct CanProxyAdaptor; +template<> struct CanProxyAdaptor; +template<> struct CanProxyAdaptor; +template<> struct CanProxyAdaptor; +template<> struct CanProxyAdaptor; template<> struct CanProxyAdaptor @@ -746,6 +701,9 @@ CanQual CanQual::CreateUnsafe(QualType Other) { template template CanProxy CanQual::getAs() const { + ArrayType_cannot_be_used_with_getAs at; + (void)at; + if (Stored.isNull()) return CanProxy(); @@ -758,6 +716,9 @@ CanProxy CanQual::getAs() const { template template CanProxy CanQual::castAs() const { + ArrayType_cannot_be_used_with_getAs at; + (void)at; + assert(!Stored.isNull() && isa(Stored.getTypePtr())); return CanQual::CreateUnsafe(Stored); } diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h index 12e74b3..082c672 100644 --- a/include/clang/AST/CharUnits.h +++ b/include/clang/AST/CharUnits.h @@ -171,6 +171,17 @@ namespace clang { Align.Quantity)); } + /// Given that this is a non-zero alignment value, what is the + /// alignment at the given offset? + CharUnits alignmentAtOffset(CharUnits offset) { + // alignment: 0010000 + // offset: 1011100 + // lowBits: 0001011 + // result: 0000100 + QuantityType lowBits = (Quantity-1) & (offset.Quantity-1); + return CharUnits((lowBits + 1) & ~lowBits); + } + }; // class CharUnit } // namespace clang diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h index 316a180..c02a82f 100644 --- a/include/clang/AST/Comment.h +++ b/include/clang/AST/Comment.h @@ -14,10 +14,10 @@ #ifndef LLVM_CLANG_AST_COMMENT_H #define LLVM_CLANG_AST_COMMENT_H -#include "clang/Basic/SourceLocation.h" -#include "clang/AST/Type.h" #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/Type.h" +#include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" @@ -28,6 +28,26 @@ class TemplateParameterList; namespace comments { class FullComment; + +/// Describes the syntax that was used in a documentation command. +/// +/// Exact values of this enumeration are important because they used to select +/// parts of diagnostic messages. Audit diagnostics before changing or adding +/// a new value. +enum CommandMarkerKind { + /// Command started with a backslash character: + /// \code + /// \foo + /// \endcode + CMK_Backslash = 0, + + /// Command started with an 'at' character: + /// \code + /// @foo + /// \endcode + CMK_At = 1 +}; + /// Any part of the comment. /// Abstract class. class Comment { @@ -110,8 +130,12 @@ protected: unsigned : NumCommentBits; unsigned CommandID : 8; + + /// Describes the syntax that was used in a documentation command. + /// Contains values from CommandMarkerKind enum. + unsigned CommandMarker : 1; }; - enum { NumBlockCommandCommentBits = NumCommentBits + 8 }; + enum { NumBlockCommandCommentBits = NumCommentBits + 9 }; class ParamCommandCommentBitfields { friend class ParamCommandComment; @@ -171,8 +195,9 @@ public: const char *getCommentKindName() const; LLVM_ATTRIBUTE_USED void dump() const; + LLVM_ATTRIBUTE_USED void dumpColor() const; LLVM_ATTRIBUTE_USED void dump(const ASTContext &Context) const; - void dump(llvm::raw_ostream &OS, const CommandTraits *Traits, + void dump(raw_ostream &OS, const CommandTraits *Traits, const SourceManager *SM) const; SourceRange getSourceRange() const LLVM_READONLY { return Range; } @@ -282,14 +307,14 @@ public: protected: /// Command arguments. - llvm::ArrayRef Args; + ArrayRef Args; public: InlineCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, RenderKind RK, - llvm::ArrayRef Args) : + ArrayRef Args) : InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd), Args(Args) { InlineCommandCommentBits.RenderKind = RK; @@ -504,10 +529,10 @@ public: /// A single paragraph that contains inline content. class ParagraphComment : public BlockContentComment { - llvm::ArrayRef Content; + ArrayRef Content; public: - ParagraphComment(llvm::ArrayRef Content) : + ParagraphComment(ArrayRef Content) : BlockContentComment(ParagraphCommentKind, SourceLocation(), SourceLocation()), @@ -565,7 +590,7 @@ public: protected: /// Word-like arguments. - llvm::ArrayRef Args; + ArrayRef Args; /// Paragraph argument. ParagraphComment *Paragraph; @@ -573,21 +598,25 @@ protected: BlockCommandComment(CommentKind K, SourceLocation LocBegin, SourceLocation LocEnd, - unsigned CommandID) : + unsigned CommandID, + CommandMarkerKind CommandMarker) : BlockContentComment(K, LocBegin, LocEnd), Paragraph(NULL) { setLocation(getCommandNameBeginLoc()); BlockCommandCommentBits.CommandID = CommandID; + BlockCommandCommentBits.CommandMarker = CommandMarker; } public: BlockCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, - unsigned CommandID) : + unsigned CommandID, + CommandMarkerKind CommandMarker) : BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd), Paragraph(NULL) { setLocation(getCommandNameBeginLoc()); BlockCommandCommentBits.CommandID = CommandID; + BlockCommandCommentBits.CommandMarker = CommandMarker; } static bool classof(const Comment *C) { @@ -633,7 +662,7 @@ public: return Args[Idx].Range; } - void setArgs(llvm::ArrayRef A) { + void setArgs(ArrayRef A) { Args = A; if (Args.size() > 0) { SourceLocation NewLocEnd = Args.back().Range.getEnd(); @@ -656,6 +685,11 @@ public: if (NewLocEnd.isValid()) setSourceRange(SourceRange(getLocStart(), NewLocEnd)); } + + CommandMarkerKind getCommandMarker() const LLVM_READONLY { + return static_cast( + BlockCommandCommentBits.CommandMarker); + } }; /// Doxygen \\param command. @@ -669,9 +703,10 @@ public: ParamCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, - unsigned CommandID) : + unsigned CommandID, + CommandMarkerKind CommandMarker) : BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, - CommandID), + CommandID, CommandMarker), ParamIndex(InvalidParamIndex) { ParamCommandCommentBits.Direction = In; ParamCommandCommentBits.IsDirectionExplicit = false; @@ -746,13 +781,15 @@ private: /// For C: Position = { 0 } /// For TT: Position = { 1 } /// For T: Position = { 1, 0 } - llvm::ArrayRef Position; + ArrayRef Position; public: TParamCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, - unsigned CommandID) : - BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID) + unsigned CommandID, + CommandMarkerKind CommandMarker) : + BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID, + CommandMarker) { } static bool classof(const Comment *C) { @@ -826,14 +863,15 @@ class VerbatimBlockComment : public BlockCommandComment { protected: StringRef CloseName; SourceLocation CloseNameLocBegin; - llvm::ArrayRef Lines; + ArrayRef Lines; public: VerbatimBlockComment(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID) : BlockCommandComment(VerbatimBlockCommentKind, - LocBegin, LocEnd, CommandID) + LocBegin, LocEnd, CommandID, + CMK_At) // FIXME: improve source fidelity. { } static bool classof(const Comment *C) { @@ -853,7 +891,7 @@ public: CloseNameLocBegin = LocBegin; } - void setLines(llvm::ArrayRef L) { + void setLines(ArrayRef L) { Lines = L; } @@ -886,7 +924,8 @@ public: StringRef Text) : BlockCommandComment(VerbatimLineCommentKind, LocBegin, LocEnd, - CommandID), + CommandID, + CMK_At), // FIXME: improve source fidelity. Text(Text), TextBegin(TextBegin) { } @@ -1021,11 +1060,11 @@ struct DeclInfo { /// A full comment attached to a declaration, contains block content. class FullComment : public Comment { - llvm::ArrayRef Blocks; + ArrayRef Blocks; DeclInfo *ThisDeclInfo; public: - FullComment(llvm::ArrayRef Blocks, DeclInfo *D) : + FullComment(ArrayRef Blocks, DeclInfo *D) : Comment(FullCommentKind, SourceLocation(), SourceLocation()), Blocks(Blocks), ThisDeclInfo(D) { if (Blocks.empty()) @@ -1062,7 +1101,7 @@ public: return ThisDeclInfo; } - llvm::ArrayRef getBlocks() const { return Blocks; } + ArrayRef getBlocks() const { return Blocks; } }; } // end namespace comments diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h index 6d44c70..d1f5209 100644 --- a/include/clang/AST/CommentCommandTraits.h +++ b/include/clang/AST/CommentCommandTraits.h @@ -16,9 +16,10 @@ #ifndef LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H #define LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H +#include "clang/Basic/CommentOptions.h" #include "clang/Basic/LLVM.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/ErrorHandling.h" @@ -69,6 +70,9 @@ struct CommandInfo { /// True if this command is \\deprecated or an alias. unsigned IsDeprecatedCommand : 1; + /// \brief True if this is a \\headerfile-like command. + unsigned IsHeaderfileCommand : 1; + /// True if we don't want to warn about this command being passed an empty /// paragraph. Meaningful only for block commands. unsigned IsEmptyParagraphAllowed : 1; @@ -96,7 +100,17 @@ struct CommandInfo { /// \fn void f(int a); /// \endcode unsigned IsDeclarationCommand : 1; - + + /// \brief True if verbatim-like line command is a function declaration. + unsigned IsFunctionDeclarationCommand : 1; + + /// \brief True if block command is further describing a container API; such + /// as \@coclass, \@classdesign, etc. + unsigned IsRecordLikeDetailCommand : 1; + + /// \brief True if block command is a container API; such as \@interface. + unsigned IsRecordLikeDeclarationCommand : 1; + /// \brief True if this command is unknown. This \c CommandInfo object was /// created during parsing. unsigned IsUnknownCommand : 1; @@ -106,7 +120,17 @@ struct CommandInfo { /// in comments. class CommandTraits { public: - CommandTraits(llvm::BumpPtrAllocator &Allocator); + enum KnownCommandIDs { +#define COMMENT_COMMAND(NAME) KCI_##NAME, +#include "clang/AST/CommentCommandList.inc" +#undef COMMENT_COMMAND + KCI_Last + }; + + CommandTraits(llvm::BumpPtrAllocator &Allocator, + const CommentOptions &CommentOptions); + + void registerCommentOptions(const CommentOptions &CommentOptions); /// \returns a CommandInfo object for a given command name or /// NULL if no CommandInfo object exists for this command. @@ -122,6 +146,8 @@ public: const CommandInfo *registerUnknownCommand(StringRef CommandName); + const CommandInfo *registerBlockCommand(StringRef CommandName); + /// \returns a CommandInfo object for a given command name or /// NULL if \c Name is not a builtin command. static const CommandInfo *getBuiltinCommandInfo(StringRef Name); @@ -137,6 +163,8 @@ private: const CommandInfo *getRegisteredCommandInfo(StringRef Name) const; const CommandInfo *getRegisteredCommandInfo(unsigned CommandID) const; + CommandInfo *createCommandInfoWithName(StringRef CommandName); + unsigned NextID; /// Allocator for CommandInfo objects. diff --git a/include/clang/AST/CommentCommands.td b/include/clang/AST/CommentCommands.td index 3d8bad8..9587ace 100644 --- a/include/clang/AST/CommentCommands.td +++ b/include/clang/AST/CommentCommands.td @@ -1,3 +1,7 @@ +//===----------------------------------------------------------------------===// +// Define command classes. +//===----------------------------------------------------------------------===// + class Command { string Name = name; string EndCommandName = ""; @@ -12,6 +16,7 @@ class Command { bit IsParamCommand = 0; bit IsTParamCommand = 0; bit IsDeprecatedCommand = 0; + bit IsHeaderfileCommand = 0; bit IsEmptyParagraphAllowed = 0; @@ -19,6 +24,9 @@ class Command { bit IsVerbatimBlockEndCommand = 0; bit IsVerbatimLineCommand = 0; bit IsDeclarationCommand = 0; + bit IsFunctionDeclarationCommand = 0; + bit IsRecordLikeDetailCommand = 0; + bit IsRecordLikeDeclarationCommand = 0; } class InlineCommand : Command { @@ -29,6 +37,10 @@ class BlockCommand : Command { let IsBlockCommand = 1; } +class RecordLikeDetailCommand : BlockCommand { + let IsRecordLikeDetailCommand = 1; +} + class VerbatimBlockCommand : Command { let EndCommandName = name; let IsVerbatimBlockCommand = 1; @@ -54,6 +66,22 @@ class DeclarationVerbatimLineCommand : let IsDeclarationCommand = 1; } +class FunctionDeclarationVerbatimLineCommand : + VerbatimLineCommand { + let IsDeclarationCommand = 1; + let IsFunctionDeclarationCommand = 1; +} + +class RecordLikeDeclarationVerbatimLineCommand : + VerbatimLineCommand { + let IsDeclarationCommand = 1; + let IsRecordLikeDeclarationCommand = 1; +} + +//===----------------------------------------------------------------------===// +// InlineCommand +//===----------------------------------------------------------------------===// + def B : InlineCommand<"b">; def C : InlineCommand<"c">; def P : InlineCommand<"p">; @@ -61,19 +89,26 @@ def A : InlineCommand<"a">; def E : InlineCommand<"e">; def Em : InlineCommand<"em">; +//===----------------------------------------------------------------------===// +// BlockCommand +//===----------------------------------------------------------------------===// + def Brief : BlockCommand<"brief"> { let IsBriefCommand = 1; } def Short : BlockCommand<"short"> { let IsBriefCommand = 1; } +// Opposite of \brief, it is the default in our implementation. +def Details : BlockCommand<"details">; + def Returns : BlockCommand<"returns"> { let IsReturnsCommand = 1; } def Return : BlockCommand<"return"> { let IsReturnsCommand = 1; } def Result : BlockCommand<"result"> { let IsReturnsCommand = 1; } def Param : BlockCommand<"param"> { let IsParamCommand = 1; } -// Doxygen +// Doxygen command for template parameter documentation. def Tparam : BlockCommand<"tparam"> { let IsTParamCommand = 1; } -// HeaderDoc +// HeaderDoc command for template parameter documentation. def Templatefield : BlockCommand<"templatefield"> { let IsTParamCommand = 1; } def Deprecated : BlockCommand<"deprecated"> { @@ -81,12 +116,17 @@ def Deprecated : BlockCommand<"deprecated"> { let IsDeprecatedCommand = 1; } +def Headerfile : BlockCommand<"headerfile"> { let IsHeaderfileCommand = 1; } + +// We don't do any additional semantic analysis for the following +// BlockCommands. It might be a good idea to do something extra for them, but +// for now we model them as plain BlockCommands. +def Attention : BlockCommand<"attention">; def Author : BlockCommand<"author">; def Authors : BlockCommand<"authors">; def Bug : BlockCommand<"bug">; def Copyright : BlockCommand<"copyright">; def Date : BlockCommand<"date">; -def Details : BlockCommand<"details">; def Invariant : BlockCommand<"invariant">; def Note : BlockCommand<"note">; def Post : BlockCommand<"post">; @@ -99,6 +139,22 @@ def Since : BlockCommand<"since">; def Todo : BlockCommand<"todo">; def Version : BlockCommand<"version">; def Warning : BlockCommand<"warning">; +// HeaderDoc commands +def ClassDesign : RecordLikeDetailCommand<"classdesign">; +def CoClass : RecordLikeDetailCommand<"coclass">; +def Dependency : RecordLikeDetailCommand<"dependency">; +def Helper : RecordLikeDetailCommand<"helper">; +def HelperClass : RecordLikeDetailCommand<"helperclass">; +def Helps : RecordLikeDetailCommand<"helps">; +def InstanceSize : RecordLikeDetailCommand<"instancesize">; +def Ownership : RecordLikeDetailCommand<"ownership">; +def Performance : RecordLikeDetailCommand<"performance">; +def Security : RecordLikeDetailCommand<"security">; +def SuperClass : RecordLikeDetailCommand<"superclass">; + +//===----------------------------------------------------------------------===// +// VerbatimBlockCommand +//===----------------------------------------------------------------------===// defm Code : VerbatimBlockCommand<"code", "endcode">; defm Verbatim : VerbatimBlockCommand<"verbatim", "endverbatim">; @@ -111,11 +167,16 @@ defm Rtfonly : VerbatimBlockCommand<"rtfonly", "endrtfonly">; defm Dot : VerbatimBlockCommand<"dot", "enddot">; defm Msc : VerbatimBlockCommand<"msc", "endmsc">; -// These commands have special support in lexer. +// These three commands have special support in CommentLexer to recognize their +// names. def FDollar : VerbatimBlockCommand<"f$">; // Inline LaTeX formula defm FBracket : VerbatimBlockCommand<"f[", "f]">; // Displayed LaTeX formula defm FBrace : VerbatimBlockCommand<"f{", "f}">; // LaTeX environment +//===----------------------------------------------------------------------===// +// VerbatimLineCommand +//===----------------------------------------------------------------------===// + def Defgroup : VerbatimLineCommand<"defgroup">; def Ingroup : VerbatimLineCommand<"ingroup">; def Addtogroup : VerbatimLineCommand<"addtogroup">; @@ -131,6 +192,10 @@ def Mainpage : VerbatimLineCommand<"mainpage">; def Subpage : VerbatimLineCommand<"subpage">; def Ref : VerbatimLineCommand<"ref">; +//===----------------------------------------------------------------------===// +// DeclarationVerbatimLineCommand +//===----------------------------------------------------------------------===// + // Doxygen commands. def Fn : DeclarationVerbatimLineCommand<"fn">; def Namespace : DeclarationVerbatimLineCommand<"namespace">; @@ -140,17 +205,18 @@ def Typedef : DeclarationVerbatimLineCommand<"typedef">; def Var : DeclarationVerbatimLineCommand<"var">; // HeaderDoc commands. -def Class : DeclarationVerbatimLineCommand<"class">; -def Interface : DeclarationVerbatimLineCommand<"interface">; -def Protocol : DeclarationVerbatimLineCommand<"protocol">; +def Class : RecordLikeDeclarationVerbatimLineCommand<"class">; +def Interface : RecordLikeDeclarationVerbatimLineCommand<"interface">; +def Protocol : RecordLikeDeclarationVerbatimLineCommand<"protocol">; +def Struct : RecordLikeDeclarationVerbatimLineCommand<"struct">; +def Union : RecordLikeDeclarationVerbatimLineCommand<"union">; def Category : DeclarationVerbatimLineCommand<"category">; def Template : DeclarationVerbatimLineCommand<"template">; -def Function : DeclarationVerbatimLineCommand<"function">; -def Method : DeclarationVerbatimLineCommand<"method">; -def Callback : DeclarationVerbatimLineCommand<"callback">; +def Function : FunctionDeclarationVerbatimLineCommand<"function">; +def FunctionGroup : FunctionDeclarationVerbatimLineCommand<"functiongroup">; +def Method : FunctionDeclarationVerbatimLineCommand<"method">; +def MethodGroup : FunctionDeclarationVerbatimLineCommand<"methodgroup">; +def Callback : FunctionDeclarationVerbatimLineCommand<"callback">; def Const : DeclarationVerbatimLineCommand<"const">; def Constant : DeclarationVerbatimLineCommand<"constant">; -def Struct : DeclarationVerbatimLineCommand<"struct">; -def Union : DeclarationVerbatimLineCommand<"union">; def Enum : DeclarationVerbatimLineCommand<"enum">; - diff --git a/include/clang/AST/CommentHTMLNamedCharacterReferences.td b/include/clang/AST/CommentHTMLNamedCharacterReferences.td new file mode 100644 index 0000000..4493108 --- /dev/null +++ b/include/clang/AST/CommentHTMLNamedCharacterReferences.td @@ -0,0 +1,177 @@ +// HTML Named Character Reference +class NCR { + string Spelling = spelling; + int CodePoint = codePoint; +} + +// The list below includes named character references supported by Doxygen: +// http://www.stack.nl/~dimitri/doxygen/manual/htmlcmds.html +// +// It does not include all HTML 5 named character references. +// +// Corresponding code point values can be found here: +// http://www.w3.org/TR/2011/WD-html5-20110113/named-character-references.html + +def : NCR<"copy", 0x000A9>; +def : NCR<"COPY", 0x000A9>; +def : NCR<"trade", 0x02122>; +def : NCR<"TRADE", 0x02122>; +def : NCR<"reg", 0x000AE>; +def : NCR<"REG", 0x000AE>; +def : NCR<"lt", 0x0003C>; +def : NCR<"Lt", 0x0003C>; +def : NCR<"LT", 0x0003C>; +def : NCR<"gt", 0x0003E>; +def : NCR<"Gt", 0x0003E>; +def : NCR<"GT", 0x0003E>; +def : NCR<"amp", 0x00026>; +def : NCR<"AMP", 0x00026>; +def : NCR<"apos", 0x00027>; +def : NCR<"quot", 0x00022>; +def : NCR<"QUOT", 0x00022>; +def : NCR<"lsquo", 0x02018>; +def : NCR<"rsquo", 0x02019>; +def : NCR<"ldquo", 0x0201C>; +def : NCR<"rdquo", 0x0201D>; +def : NCR<"ndash", 0x02013>; +def : NCR<"mdash", 0x02014>; + +def : NCR<"Auml", 0x000C4>; +def : NCR<"Euml", 0x000CB>; +def : NCR<"Iuml", 0x000CF>; +def : NCR<"Ouml", 0x000D6>; +def : NCR<"Uuml", 0x000DC>; +def : NCR<"Yuml", 0x00178>; +def : NCR<"auml", 0x000E4>; +def : NCR<"euml", 0x000EB>; +def : NCR<"iuml", 0x000EF>; +def : NCR<"ouml", 0x000F6>; +def : NCR<"uuml", 0x000FC>; +def : NCR<"yuml", 0x000FF>; + +def : NCR<"Aacute", 0x000C1>; +def : NCR<"Eacute", 0x000C9>; +def : NCR<"Iacute", 0x000CD>; +def : NCR<"Oacute", 0x000D3>; +def : NCR<"Uacute", 0x000DA>; +def : NCR<"Yacute", 0x000DD>; +def : NCR<"aacute", 0x000E1>; +def : NCR<"eacute", 0x000E9>; +def : NCR<"iacute", 0x000ED>; +def : NCR<"oacute", 0x000F3>; +def : NCR<"uacute", 0x000FA>; +def : NCR<"yacute", 0x000FD>; + +def : NCR<"Agrave", 0x000C0>; +def : NCR<"Egrave", 0x000C8>; +def : NCR<"Igrave", 0x000CC>; +def : NCR<"Ograve", 0x000D2>; +def : NCR<"Ugrave", 0x000D9>; +// def : NCR<"Ygrave", 0x01EF2>; // Defined neither in Doxygen, nor in HTML5. +def : NCR<"agrave", 0x000E0>; +def : NCR<"egrave", 0x000E8>; +def : NCR<"igrave", 0x000EC>; +def : NCR<"ograve", 0x000F2>; +def : NCR<"ugrave", 0x000F9>; +def : NCR<"ygrave", 0x01EF3>; // Defined in Doxygen, not defined in HTML5. + +def : NCR<"Acirc", 0x000C2>; +def : NCR<"Ecirc", 0x000CA>; +def : NCR<"Icirc", 0x000CE>; +def : NCR<"Ocirc", 0x000D4>; +def : NCR<"Ucirc", 0x000DB>; +def : NCR<"Ycirc", 0x00176>; // Not defined in Doxygen, defined in HTML5. +def : NCR<"acirc", 0x000E2>; +def : NCR<"ecirc", 0x000EA>; +def : NCR<"icirc", 0x000EE>; +def : NCR<"ocirc", 0x000F4>; +def : NCR<"ucirc", 0x000FB>; +def : NCR<"ycirc", 0x00177>; + +def : NCR<"Atilde", 0x000C3>; +def : NCR<"Ntilde", 0x000D1>; +def : NCR<"Otilde", 0x000D5>; +def : NCR<"atilde", 0x000E3>; +def : NCR<"ntilde", 0x000F1>; +def : NCR<"otilde", 0x000F5>; + +def : NCR<"szlig", 0x000DF>; + +def : NCR<"ccedil", 0x000E7>; +def : NCR<"Ccedil", 0x000C7>; + +def : NCR<"aring", 0x000E5>; +def : NCR<"Aring", 0x000C5>; + +def : NCR<"nbsp", 0x000A0>; + +def : NCR<"Gamma", 0x00393>; +def : NCR<"Delta", 0x00394>; +def : NCR<"Theta", 0x00398>; +def : NCR<"Lambda", 0x0039B>; +def : NCR<"Xi", 0x0039E>; +def : NCR<"Pi", 0x003A0>; +def : NCR<"Sigma", 0x003A3>; +def : NCR<"Upsilon", 0x003A5>; +def : NCR<"Phi", 0x003A6>; +def : NCR<"Psi", 0x003A8>; +def : NCR<"Omega", 0x003A9>; + +def : NCR<"alpha", 0x003B1>; +def : NCR<"beta", 0x003B2>; +def : NCR<"gamma", 0x003B3>; +def : NCR<"delta", 0x003B4>; +def : NCR<"epsilon", 0x003B5>; +def : NCR<"zeta", 0x003B6>; +def : NCR<"eta", 0x003B7>; +def : NCR<"theta", 0x003B8>; +def : NCR<"iota", 0x003B9>; +def : NCR<"kappa", 0x003BA>; +def : NCR<"lambda", 0x003BB>; +def : NCR<"mu", 0x003BC>; +def : NCR<"nu", 0x003BD>; +def : NCR<"xi", 0x003BE>; +def : NCR<"pi", 0x003C0>; +def : NCR<"rho", 0x003C1>; +def : NCR<"sigma", 0x003C3>; +def : NCR<"tau", 0x003C4>; +def : NCR<"upsilon", 0x003C5>; +def : NCR<"phi", 0x003C6>; +def : NCR<"chi", 0x003C7>; +def : NCR<"psi", 0x003C8>; +def : NCR<"omega", 0x003C9>; +def : NCR<"sigmaf", 0x003C2>; + +def : NCR<"sect", 0x000A7>; +def : NCR<"deg", 0x000B0>; +def : NCR<"prime", 0x02032>; +def : NCR<"Prime", 0x02033>; +def : NCR<"infin", 0x0221E>; +def : NCR<"empty", 0x02205>; +def : NCR<"plusmn", 0x000B1>; +def : NCR<"times", 0x000D7>; +def : NCR<"minus", 0x02212>; +def : NCR<"sdot", 0x022C5>; +def : NCR<"part", 0x02202>; +def : NCR<"nabla", 0x02207>; +def : NCR<"radic", 0x0221A>; +def : NCR<"perp", 0x022A5>; +def : NCR<"sum", 0x02211>; +def : NCR<"int", 0x0222B>; +def : NCR<"prod", 0x0220F>; +def : NCR<"sim", 0x0223C>; +def : NCR<"asymp", 0x02248>; +def : NCR<"ne", 0x02260>; +def : NCR<"equiv", 0x02261>; +def : NCR<"prop", 0x0221D>; +def : NCR<"le", 0x02264>; +def : NCR<"ge", 0x02265>; +def : NCR<"larr", 0x02190>; +def : NCR<"rarr", 0x02192>; +def : NCR<"isin", 0x02208>; +def : NCR<"notin", 0x02209>; +def : NCR<"lceil", 0x02308>; +def : NCR<"rceil", 0x02309>; +def : NCR<"lfloor", 0x0230A>; +def : NCR<"rfloor", 0x0230B>; + diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h index f263697..4179f45 100644 --- a/include/clang/AST/CommentLexer.h +++ b/include/clang/AST/CommentLexer.h @@ -15,9 +15,9 @@ #define LLVM_CLANG_AST_COMMENT_LEXER_H #include "clang/Basic/SourceManager.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/raw_ostream.h" @@ -34,8 +34,9 @@ enum TokenKind { eof, newline, text, - unknown_command, // Command that does not have an ID. - command, // Command with an ID. + unknown_command, // Command that does not have an ID. + backslash_command, // Command with an ID, that used backslash marker. + at_command, // Command with an ID, that used 'at' marker. verbatim_block_begin, verbatim_block_line, verbatim_block_end, @@ -75,7 +76,7 @@ class Token { /// unused (command spelling can be found with CommandTraits). Otherwise, /// contains the length of the string that starts at TextPtr. unsigned IntVal; - + public: SourceLocation getLocation() const LLVM_READONLY { return Loc; } void setLocation(SourceLocation SL) { Loc = SL; } @@ -118,12 +119,12 @@ public: } unsigned getCommandID() const LLVM_READONLY { - assert(is(tok::command)); + assert(is(tok::backslash_command) || is(tok::at_command)); return IntVal; } void setCommandID(unsigned ID) { - assert(is(tok::command)); + assert(is(tok::backslash_command) || is(tok::at_command)); IntVal = ID; } diff --git a/include/clang/AST/CommentParser.h b/include/clang/AST/CommentParser.h index 19e1d57..d6a1072 100644 --- a/include/clang/AST/CommentParser.h +++ b/include/clang/AST/CommentParser.h @@ -14,10 +14,10 @@ #ifndef LLVM_CLANG_AST_COMMENT_PARSER_H #define LLVM_CLANG_AST_COMMENT_PARSER_H -#include "clang/Basic/Diagnostic.h" -#include "clang/AST/CommentLexer.h" #include "clang/AST/Comment.h" +#include "clang/AST/CommentLexer.h" #include "clang/AST/CommentSema.h" +#include "clang/Basic/Diagnostic.h" #include "llvm/Support/Allocator.h" namespace clang { @@ -86,6 +86,11 @@ class Parser { Tok = Toks[0]; } + bool isTokBlockCommand() { + return (Tok.is(tok::backslash_command) || Tok.is(tok::at_command)) && + Traits.getCommandInfo(Tok.getCommandID())->IsBlockCommand; + } + public: Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, DiagnosticsEngine &Diags, diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h index 0340b3c..15e454d 100644 --- a/include/clang/AST/CommentSema.h +++ b/include/clang/AST/CommentSema.h @@ -14,12 +14,12 @@ #ifndef LLVM_CLANG_AST_COMMENT_SEMA_H #define LLVM_CLANG_AST_COMMENT_SEMA_H +#include "clang/AST/Comment.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" -#include "clang/AST/Comment.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" namespace clang { @@ -60,6 +60,9 @@ class Sema { /// AST node for the \\returns command and its aliases. const BlockCommandComment *ReturnsCommand; + + /// AST node for the \\headerfile command. + const BlockCommandComment *HeaderfileCommand; DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { return Diags.Report(Loc, DiagID); @@ -93,7 +96,8 @@ public: BlockCommandComment *actOnBlockCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, - unsigned CommandID); + unsigned CommandID, + CommandMarkerKind CommandMarker); void actOnBlockCommandArgs(BlockCommandComment *Command, ArrayRef Args); @@ -103,7 +107,8 @@ public: ParamCommandComment *actOnParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, - unsigned CommandID); + unsigned CommandID, + CommandMarkerKind CommandMarker); void actOnParamCommandDirectionArg(ParamCommandComment *Command, SourceLocation ArgLocBegin, @@ -120,7 +125,8 @@ public: TParamCommandComment *actOnTParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, - unsigned CommandID); + unsigned CommandID, + CommandMarkerKind CommandMarker); void actOnTParamCommandParamNameArg(TParamCommandComment *Command, SourceLocation ArgLocBegin, @@ -192,13 +198,28 @@ public: void checkBlockCommandDuplicate(const BlockCommandComment *Command); void checkDeprecatedCommand(const BlockCommandComment *Comment); + + void checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment); + + void checkContainerDeclVerbatimLine(const BlockCommandComment *Comment); + + void checkContainerDecl(const BlockCommandComment *Comment); /// Resolve parameter names to parameter indexes in function declaration. /// Emit diagnostics about unknown parametrs. void resolveParamCommandIndexes(const FullComment *FC); bool isFunctionDecl(); + bool isAnyFunctionDecl(); + bool isFunctionPointerVarDecl(); + bool isObjCMethodDecl(); + bool isObjCPropertyDecl(); bool isTemplateOrSpecialization(); + bool isRecordLikeDecl(); + bool isClassOrStructDecl(); + bool isUnionDecl(); + bool isObjCInterfaceDecl(); + bool isObjCProtocolDecl(); ArrayRef getParamVars(); diff --git a/include/clang/AST/CommentVisitor.h b/include/clang/AST/CommentVisitor.h index 47867a6..21641bf 100644 --- a/include/clang/AST/CommentVisitor.h +++ b/include/clang/AST/CommentVisitor.h @@ -7,6 +7,9 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_COMMENTVISITOR_H +#define LLVM_CLANG_AST_COMMENTVISITOR_H + #include "clang/AST/Comment.h" #include "llvm/Support/ErrorHandling.h" @@ -64,3 +67,4 @@ class ConstCommentVisitor : } // end namespace comments } // end namespace clang +#endif diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 087a585..7927279 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -16,33 +16,34 @@ #include "clang/AST/APValue.h" #include "clang/AST/DeclBase.h" -#include "clang/AST/Redeclarable.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" +#include "clang/AST/Redeclarable.h" +#include "clang/AST/Type.h" #include "clang/Basic/Linkage.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/Support/Compiler.h" namespace clang { +struct ASTTemplateArgumentListInfo; class CXXTemporary; +class CompoundStmt; +class DependentFunctionTemplateSpecializationInfo; class Expr; class FunctionTemplateDecl; +class FunctionTemplateSpecializationInfo; +class LabelStmt; +class MemberSpecializationInfo; +class Module; +class NestedNameSpecifier; class Stmt; -class CompoundStmt; class StringLiteral; -class NestedNameSpecifier; -class TemplateParameterList; class TemplateArgumentList; -struct ASTTemplateArgumentListInfo; -class MemberSpecializationInfo; -class FunctionTemplateSpecializationInfo; -class DependentFunctionTemplateSpecializationInfo; +class TemplateParameterList; class TypeLoc; class UnresolvedSetImpl; -class LabelStmt; -class Module; - + /// \brief A container of type source information. /// /// A client can read the relevant info using TypeLoc wrappers, e.g: @@ -108,6 +109,7 @@ class NamedDecl : public Decl { private: NamedDecl *getUnderlyingDeclImpl(); + void verifyLinkage() const; protected: NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N) @@ -149,32 +151,29 @@ public: /// \brief Set the name of this declaration. void setDeclName(DeclarationName N) { Name = N; } - /// getQualifiedNameAsString - Returns human-readable qualified name for + /// printQualifiedName - Returns human-readable qualified name for /// declaration, like A::B::i, for i being member of namespace A::B. /// If declaration is not member of context which can be named (record, - /// namespace), it will return same result as getNameAsString(). + /// namespace), it will return same result as printName(). /// Creating this name is expensive, so it should be called only when /// performance doesn't matter. + void printQualifiedName(raw_ostream &OS) const; + void printQualifiedName(raw_ostream &OS, const PrintingPolicy &Policy) const; + + // FIXME: Remove string versions. std::string getQualifiedNameAsString() const; std::string getQualifiedNameAsString(const PrintingPolicy &Policy) const; /// getNameForDiagnostic - Appends a human-readable name for this - /// declaration into the given string. + /// declaration into the given stream. /// /// This is the method invoked by Sema when displaying a NamedDecl /// in a diagnostic. It does not necessarily produce the same - /// result as getNameAsString(); for example, class template + /// result as printName(); for example, class template /// specializations are printed with their template arguments. - /// - /// TODO: use an API that doesn't require so many temporary strings - virtual void getNameForDiagnostic(std::string &S, + virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, - bool Qualified) const { - if (Qualified) - S += getQualifiedNameAsString(Policy); - else - S += getNameAsString(); - } + bool Qualified) const; /// declarationReplaces - Determine whether this declaration, if /// known to be well-formed within its context, will replace the @@ -212,117 +211,40 @@ public: /// a C++ class. bool isCXXInstanceMember() const; - class LinkageInfo { - uint8_t linkage_ : 2; - uint8_t visibility_ : 2; - uint8_t explicit_ : 1; - - void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; } - public: - LinkageInfo() : linkage_(ExternalLinkage), visibility_(DefaultVisibility), - explicit_(false) {} - LinkageInfo(Linkage L, Visibility V, bool E) - : linkage_(L), visibility_(V), explicit_(E) { - assert(linkage() == L && visibility() == V && visibilityExplicit() == E && - "Enum truncated!"); - } - - static LinkageInfo external() { - return LinkageInfo(); - } - static LinkageInfo internal() { - return LinkageInfo(InternalLinkage, DefaultVisibility, false); - } - static LinkageInfo uniqueExternal() { - return LinkageInfo(UniqueExternalLinkage, DefaultVisibility, false); - } - static LinkageInfo none() { - return LinkageInfo(NoLinkage, DefaultVisibility, false); - } - - Linkage linkage() const { return (Linkage)linkage_; } - Visibility visibility() const { return (Visibility)visibility_; } - bool visibilityExplicit() const { return explicit_; } - - void setLinkage(Linkage L) { linkage_ = L; } - void mergeLinkage(Linkage L) { - setLinkage(minLinkage(linkage(), L)); - } - void mergeLinkage(LinkageInfo Other) { - mergeLinkage(Other.linkage()); - } - - // Merge the visibility V giving preference to explicit ones. - // This is used, for example, when merging the visibility of a class - // down to one of its members. If the member has no explicit visibility, - // the class visibility wins. - void mergeVisibility(Visibility V, bool E = false) { - // Never increase the visibility - if (visibility() < V) - return; - - // If we have an explicit visibility, keep it - if (visibilityExplicit()) - return; - - setVisibility(V, E); - } - // Merge the visibility V, keeping the most restrictive one. - // This is used for cases like merging the visibility of a template - // argument to an instantiation. If we already have a hidden class, - // no argument should give it default visibility. - void mergeVisibilityWithMin(Visibility V, bool E = false) { - // Never increase the visibility - if (visibility() < V) - return; - - // FIXME: this - // If this visibility is explicit, keep it. - if (visibilityExplicit() && !E) - return; - - // should be replaced with this - // Don't lose the explicit bit for nothing - // if (visibility() == V && visibilityExplicit()) - // return; - - setVisibility(V, E); - } - void mergeVisibility(LinkageInfo Other) { - mergeVisibility(Other.visibility(), Other.visibilityExplicit()); - } - void mergeVisibilityWithMin(LinkageInfo Other) { - mergeVisibilityWithMin(Other.visibility(), Other.visibilityExplicit()); - } - - void merge(LinkageInfo Other) { - mergeLinkage(Other); - mergeVisibility(Other); - } - void mergeWithMin(LinkageInfo Other) { - mergeLinkage(Other); - mergeVisibilityWithMin(Other); - } - }; - /// \brief Determine what kind of linkage this entity has. Linkage getLinkage() const; + /// \brief True if this decl has external linkage. + bool hasExternalLinkage() const { + return getLinkage() == ExternalLinkage; + } + + /// \brief True if this decl has external linkage. Don't cache the linkage, + /// because we are not finished setting up the redecl chain for the decl. + bool hasExternalLinkageUncached() const; + /// \brief Determines the visibility of this entity. Visibility getVisibility() const { - return getLinkageAndVisibility().visibility(); + return getLinkageAndVisibility().getVisibility(); } /// \brief Determines the linkage and visibility of this entity. LinkageInfo getLinkageAndVisibility() const; + /// Kinds of explicit visibility. + enum ExplicitVisibilityKind { + VisibilityForType, + VisibilityForValue + }; + /// \brief If visibility was explicitly specified for this /// declaration, return that visibility. - llvm::Optional getExplicitVisibility() const; + Optional + getExplicitVisibility(ExplicitVisibilityKind kind) const; - /// \brief Clear the linkage cache in response to a change - /// to the declaration. - void ClearLinkageCache(); + /// \brief True if the computed linkage is valid. Used for consistency + /// checking. Should always return true. + bool isLinkageValid() const; /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for /// the underlying named decl. @@ -538,9 +460,7 @@ public: /// \brief Determine whether this symbol is weakly-imported, /// or declared with the weak or weak-ref attr. - bool isWeak() const { - return hasAttr() || hasAttr() || isWeakImported(); - } + bool isWeak() const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -744,7 +664,6 @@ private: friend class ASTDeclReader; unsigned SClass : 3; - unsigned SClassAsWritten : 3; unsigned ThreadSpecified : 1; unsigned InitStyle : 2; @@ -811,14 +730,12 @@ protected: VarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, StorageClass SC, - StorageClass SCAsWritten) + QualType T, TypeSourceInfo *TInfo, StorageClass SC) : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Init() { assert(sizeof(VarDeclBitfields) <= sizeof(unsigned)); assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned)); AllBits = 0; VarDeclBits.SClass = SC; - VarDeclBits.SClassAsWritten = SCAsWritten; // Everything else is implicitly initialized to false. } @@ -841,23 +758,18 @@ public: static VarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, StorageClass SCAsWritten); + StorageClass S); static VarDecl *CreateDeserialized(ASTContext &C, unsigned ID); virtual SourceRange getSourceRange() const LLVM_READONLY; + /// \brief Returns the storage class as written in the source. For the + /// computed linkage of symbol, see getLinkage. StorageClass getStorageClass() const { return (StorageClass) VarDeclBits.SClass; } - StorageClass getStorageClassAsWritten() const { - return (StorageClass) VarDeclBits.SClassAsWritten; - } void setStorageClass(StorageClass SC); - void setStorageClassAsWritten(StorageClass SC) { - assert(isLegalForVariable(SC)); - VarDeclBits.SClassAsWritten = SC; - } void setThreadSpecified(bool T) { VarDeclBits.ThreadSpecified = T; } bool isThreadSpecified() const { @@ -882,8 +794,8 @@ public: return getStorageClass() == SC_Static && !isFileVarDecl(); } - /// hasExternStorage - Returns true if a variable has extern or - /// __private_extern__ storage. + /// \brief Returns true if a variable has extern or __private_extern__ + /// storage. bool hasExternalStorage() const { return getStorageClass() == SC_Extern || getStorageClass() == SC_PrivateExtern; @@ -894,6 +806,9 @@ public: /// as static variables declared within a function. bool hasGlobalStorage() const { return !hasLocalStorage(); } + /// Compute the language linkage. + LanguageLinkage getLanguageLinkage() const; + /// \brief Determines whether this variable is a variable with /// external, C linkage. bool isExternC() const; @@ -1087,8 +1002,7 @@ public: /// not a constant expression. Returns a pointer to the value if evaluation /// succeeded, 0 otherwise. APValue *evaluateValue() const; - APValue *evaluateValue( - llvm::SmallVectorImpl &Notes) const; + APValue *evaluateValue(SmallVectorImpl &Notes) const; /// \brief Return the already-evaluated value of this variable's /// initializer, or NULL if the value is not yet known. Returns pointer @@ -1220,7 +1134,7 @@ public: ImplicitParamDecl(DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType Type) : VarDecl(ImplicitParam, DC, IdLoc, IdLoc, Id, Type, - /*tinfo*/ 0, SC_None, SC_None) { + /*tinfo*/ 0, SC_None) { setImplicit(); } @@ -1239,8 +1153,8 @@ protected: ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, StorageClass SCAsWritten, Expr *DefArg) - : VarDecl(DK, DC, StartLoc, IdLoc, Id, T, TInfo, S, SCAsWritten) { + StorageClass S, Expr *DefArg) + : VarDecl(DK, DC, StartLoc, IdLoc, Id, T, TInfo, S) { assert(ParmVarDeclBits.HasInheritedDefaultArg == false); assert(ParmVarDeclBits.IsKNRPromoted == false); assert(ParmVarDeclBits.IsObjCMethodParam == false); @@ -1252,8 +1166,7 @@ public: SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, StorageClass SCAsWritten, - Expr *DefArg); + StorageClass S, Expr *DefArg); static ParmVarDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -1451,14 +1364,13 @@ private: /// DeclsInPrototypeScope - Array of pointers to NamedDecls for /// decls defined in the function prototype that are not parameters. E.g. /// 'enum Y' in 'void f(enum Y {AA} x) {}'. - llvm::ArrayRef DeclsInPrototypeScope; + ArrayRef DeclsInPrototypeScope; LazyDeclStmtPtr Body; // FIXME: This can be packed into the bitfields in Decl. // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum unsigned SClass : 2; - unsigned SClassAsWritten : 2; bool IsInline : 1; bool IsInlineSpecified : 1; bool IsVirtualAsWritten : 1; @@ -1473,6 +1385,10 @@ private: bool IsLateTemplateParsed : 1; bool IsConstexpr : 1; + /// \brief Indicates if the function was a definition but its body was + /// skipped. + unsigned HasSkippedBody : 1; + /// \brief End part of this FunctionDecl's source range. /// /// We could compute the full range in getSourceRange(). However, when we're @@ -1538,25 +1454,26 @@ private: void setInstantiationOfMemberFunction(ASTContext &C, FunctionDecl *FD, TemplateSpecializationKind TSK); - void setParams(ASTContext &C, llvm::ArrayRef NewParamInfo); + void setParams(ASTContext &C, ArrayRef NewParamInfo); protected: FunctionDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - StorageClass S, StorageClass SCAsWritten, bool isInlineSpecified, + StorageClass S, bool isInlineSpecified, bool isConstexprSpecified) : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo, StartLoc), DeclContext(DK), ParamInfo(0), Body(), - SClass(S), SClassAsWritten(SCAsWritten), + SClass(S), IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), IsDefaulted(false), IsExplicitlyDefaulted(false), HasImplicitReturnZero(false), IsLateTemplateParsed(false), - IsConstexpr(isConstexprSpecified), EndRangeLoc(NameInfo.getEndLoc()), + IsConstexpr(isConstexprSpecified), HasSkippedBody(false), + EndRangeLoc(NameInfo.getEndLoc()), TemplateOrSpecialization(), DNLoc(NameInfo.getInfo()) {} @@ -1580,14 +1497,13 @@ public: SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - StorageClass SC = SC_None, - StorageClass SCAsWritten = SC_None, + StorageClass SC, bool isInlineSpecified = false, bool hasWrittenPrototype = true, bool isConstexprSpecified = false) { DeclarationNameInfo NameInfo(N, NLoc); return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, - SC, SCAsWritten, + SC, isInlineSpecified, hasWrittenPrototype, isConstexprSpecified); } @@ -1596,10 +1512,9 @@ public: SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - StorageClass SC = SC_None, - StorageClass SCAsWritten = SC_None, - bool isInlineSpecified = false, - bool hasWrittenPrototype = true, + StorageClass SC, + bool isInlineSpecified, + bool hasWrittenPrototype, bool isConstexprSpecified = false); static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -1608,7 +1523,7 @@ public: return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } - virtual void getNameForDiagnostic(std::string &S, + virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const; @@ -1732,7 +1647,7 @@ public: /// Whether this is a (C++11) constexpr function or constexpr constructor. bool isConstexpr() const { return IsConstexpr; } - void setConstexpr(bool IC); + void setConstexpr(bool IC) { IsConstexpr = IC; } /// \brief Whether this function has been deleted. /// @@ -1776,6 +1691,9 @@ public: /// This function must be an allocation or deallocation function. bool isReservedGlobalPlacementOperator() const; + /// Compute the language linkage. + LanguageLinkage getLanguageLinkage() const; + /// \brief Determines whether this function is a function with /// external, C linkage. bool isExternC() const; @@ -1783,6 +1701,14 @@ public: /// \brief Determines whether this is a global function. bool isGlobal() const; + /// \brief Determines whether this function is known to be 'noreturn', through + /// an attribute on its declaration or its type. + bool isNoReturn() const; + + /// \brief True if the function was a definition but its body was skipped. + bool hasSkippedBody() const { return HasSkippedBody; } + void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; } + void setPreviousDeclaration(FunctionDecl * PrevDecl); virtual const FunctionDecl *getCanonicalDecl() const; @@ -1814,14 +1740,14 @@ public: assert(i < getNumParams() && "Illegal param #"); return ParamInfo[i]; } - void setParams(llvm::ArrayRef NewParamInfo) { + void setParams(ArrayRef NewParamInfo) { setParams(getASTContext(), NewParamInfo); } - const llvm::ArrayRef &getDeclsInPrototypeScope() const { + const ArrayRef &getDeclsInPrototypeScope() const { return DeclsInPrototypeScope; } - void setDeclsInPrototypeScope(llvm::ArrayRef NewDecls); + void setDeclsInPrototypeScope(ArrayRef NewDecls); /// getMinRequiredArguments - Returns the minimum number of arguments /// needed to call this function. This may be fewer than the number of @@ -1838,12 +1764,9 @@ public: return getType()->getAs()->getCallResultType(getASTContext()); } + /// \brief Returns the storage class as written in the source. For the + /// computed linkage of symbol, see getLinkage. StorageClass getStorageClass() const { return StorageClass(SClass); } - void setStorageClass(StorageClass SC); - - StorageClass getStorageClassAsWritten() const { - return StorageClass(SClassAsWritten); - } /// \brief Determine whether the "inline" keyword was specified for this /// function. @@ -1863,7 +1786,7 @@ public: /// \brief Determine whether this function should be inlined, because it is /// either marked "inline" or "constexpr" or is a member function of a class /// that was defined in the class body. - bool isInlined() const; + bool isInlined() const { return IsInline; } bool isInlineDefinitionExternallyVisible() const; @@ -1908,7 +1831,9 @@ public: /// \brief If this function is an instantiation of a member function of a /// class template specialization, retrieves the member specialization /// information. - MemberSpecializationInfo *getMemberSpecializationInfo() const; + MemberSpecializationInfo *getMemberSpecializationInfo() const { + return TemplateOrSpecialization.dyn_cast(); + } /// \brief Specify that this record is an instantiation of the /// member function FD. @@ -2472,6 +2397,12 @@ protected: /// possible in C++11 or Microsoft extensions mode. bool IsFixed : 1; + /// \brief Indicates whether it is possible for declarations of this kind + /// to have an out-of-date definition. + /// + /// This option is only enabled when modules are enabled. + bool MayHaveOutOfDateDef : 1; + private: SourceLocation RBraceLoc; @@ -2616,6 +2547,25 @@ public: bool isUnion() const { return getTagKind() == TTK_Union; } bool isEnum() const { return getTagKind() == TTK_Enum; } + /// Is this tag type named, either directly or via being defined in + /// a typedef of this type? + /// + /// C++11 [basic.link]p8: + /// A type is said to have linkage if and only if: + /// - it is a class or enumeration type that is named (or has a + /// name for linkage purposes) and the name has linkage; ... + /// C++11 [dcl.typedef]p9: + /// If the typedef declaration defines an unnamed class (or enum), + /// the first typedef-name declared by the declaration to be that + /// class type (or enum type) is used to denote the class type (or + /// enum type) for linkage purposes only. + /// + /// C does not have an analogous rule, but the same concept is + /// nonetheless useful in some places. + bool hasNameForLinkage() const { + return (getDeclName() || getTypedefNameForAnonDecl()); + } + TypedefNameDecl *getTypedefNameForAnonDecl() const { return hasExtInfo() ? 0 : TypedefNameDeclOrQualifier.get(); @@ -2906,6 +2856,10 @@ class RecordDecl : public TagDecl { /// HasObjectMember - This is true if this struct has at least one member /// containing an Objective-C object pointer type. bool HasObjectMember : 1; + + /// HasVolatileMember - This is true if struct has at least one member of + /// 'volatile' type. + bool HasVolatileMember : 1; /// \brief Whether the field declarations of this record have been loaded /// from external storage. To avoid unnecessary deserialization of @@ -2962,6 +2916,9 @@ public: bool hasObjectMember() const { return HasObjectMember; } void setHasObjectMember (bool val) { HasObjectMember = val; } + bool hasVolatileMember() const { return HasVolatileMember; } + void setHasVolatileMember (bool val) { HasVolatileMember = val; } + /// \brief Determines whether this declaration represents the /// injected class name. /// @@ -3161,7 +3118,7 @@ public: assert(i < getNumParams() && "Illegal param #"); return ParamInfo[i]; } - void setParams(llvm::ArrayRef NewParamInfo); + void setParams(ArrayRef NewParamInfo); /// hasCaptures - True if this block (or its nested blocks) captures /// anything of local storage from its enclosing scopes. @@ -3210,7 +3167,7 @@ public: /// /// An import declaration imports the named module (or submodule). For example: /// \code -/// @__experimental_modules_import std.vector; +/// @import std.vector; /// \endcode /// /// Import declarations can also be implicitly generated from @@ -3271,7 +3228,21 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Import; } }; - + +/// \brief Represents an empty-declaration. +class EmptyDecl : public Decl { + virtual void anchor(); + EmptyDecl(DeclContext *DC, SourceLocation L) + : Decl(Empty, DC, L) { } + +public: + static EmptyDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L); + static EmptyDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == Empty; } +}; /// Insertion operator for diagnostics. This allows sending NamedDecl's /// into a diagnostic with <<. @@ -3299,10 +3270,10 @@ void Redeclarable::setPreviousDeclaration(decl_type *PrevDecl) { // Point to previous. Make sure that this is actually the most recent // redeclaration, or we can build invalid chains. If the most recent // redeclaration is invalid, it won't be PrevDecl, but we want it anyway. - RedeclLink = PreviousDeclLink( - llvm::cast(PrevDecl->getMostRecentDecl())); First = PrevDecl->getFirstDeclaration(); assert(First->RedeclLink.NextIsLatest() && "Expected first"); + decl_type *MostRecent = First->RedeclLink.getNext(); + RedeclLink = PreviousDeclLink(cast(MostRecent)); } else { // Make this first. First = static_cast(this); @@ -3310,8 +3281,8 @@ void Redeclarable::setPreviousDeclaration(decl_type *PrevDecl) { // First one will point to this one as latest. First->RedeclLink = LatestDeclLink(static_cast(this)); - if (NamedDecl *ND = dyn_cast(static_cast(this))) - ND->ClearLinkageCache(); + assert(!isa(static_cast(this)) || + cast(static_cast(this))->isLinkageValid()); } // Inline function definitions. diff --git a/include/clang/AST/DeclAccessPair.h b/include/clang/AST/DeclAccessPair.h index 7ecd8f8..5731308 100644 --- a/include/clang/AST/DeclAccessPair.h +++ b/include/clang/AST/DeclAccessPair.h @@ -19,6 +19,7 @@ #define LLVM_CLANG_AST_DECLACCESSPAIR_H #include "clang/Basic/Specifiers.h" +#include "llvm/Support/DataTypes.h" namespace clang { diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 50e2027..852bb9a 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -14,38 +14,40 @@ #ifndef LLVM_CLANG_AST_DECLBASE_H #define LLVM_CLANG_AST_DECLBASE_H -#include "clang/AST/Attr.h" +#include "clang/AST/AttrIterator.h" #include "clang/AST/DeclarationName.h" -#include "clang/AST/Type.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/PrettyStackTrace.h" namespace clang { -class DeclContext; -class TranslationUnitDecl; -class NamespaceDecl; -class UsingDirectiveDecl; -class NamedDecl; -class FunctionDecl; +class ASTMutationListener; +class BlockDecl; class CXXRecordDecl; +class CompoundStmt; +class DeclContext; +class DeclarationName; +class DependentDiagnostic; class EnumDecl; -class ObjCMethodDecl; -class ObjCContainerDecl; -class ObjCInterfaceDecl; +class FunctionDecl; +class LinkageSpecDecl; +class Module; +class NamedDecl; +class NamespaceDecl; class ObjCCategoryDecl; -class ObjCProtocolDecl; -class ObjCImplementationDecl; class ObjCCategoryImplDecl; +class ObjCContainerDecl; class ObjCImplDecl; -class LinkageSpecDecl; -class BlockDecl; -class DeclarationName; -class CompoundStmt; +class ObjCImplementationDecl; +class ObjCInterfaceDecl; +class ObjCMethodDecl; +class ObjCProtocolDecl; +struct PrintingPolicy; +class Stmt; class StoredDeclsMap; -class DependentDiagnostic; -class ASTMutationListener; +class TranslationUnitDecl; +class UsingDirectiveDecl; } namespace llvm { @@ -133,7 +135,7 @@ public: /// or member ends up here. IDNS_Ordinary = 0x0020, - /// Objective C @protocol. + /// Objective C \@protocol. IDNS_ObjCProtocol = 0x0040, /// This declaration is a friend function. A friend function @@ -335,7 +337,10 @@ protected: static void *AllocateDeserializedDecl(const ASTContext &Context, unsigned ID, unsigned Size); - + + /// \brief Update a potentially out-of-date declaration. + void updateOutOfDate(IdentifierInfo &II) const; + public: /// \brief Source range that this declaration covers. @@ -455,9 +460,7 @@ public: /// getMaxAlignment - return the maximum alignment specified by attributes /// on this decl, 0 if there are none. - unsigned getMaxAlignment() const { - return hasAttrs() ? getMaxAttrAlignment(getAttrs(), getASTContext()) : 0; - } + unsigned getMaxAlignment() const; /// setInvalidDecl - Indicates the Decl had a semantic error. This /// allows for graceful error recovery. @@ -593,7 +596,18 @@ public: return 0; } - + +private: + Module *getOwningModuleSlow() const; + +public: + Module *getOwningModule() const { + if (!isFromASTFile()) + return 0; + + return getOwningModuleSlow(); + } + unsigned getIdentifierNamespace() const { return IdentifierNamespace; } @@ -851,6 +865,8 @@ public: unsigned Indentation = 0); // Debuggers don't usually respect default arguments. LLVM_ATTRIBUTE_USED void dump() const; + // Same as dump(), but forces color printing. + LLVM_ATTRIBUTE_USED void dumpColor() const; void dump(raw_ostream &Out) const; // Debuggers don't usually respect default arguments. LLVM_ATTRIBUTE_USED void dumpXML() const; @@ -891,29 +907,9 @@ public: virtual void print(raw_ostream &OS) const; }; -class DeclContextLookupResult - : public std::pair { -public: - DeclContextLookupResult(NamedDecl **I, NamedDecl **E) - : std::pair(I, E) {} - DeclContextLookupResult() - : std::pair() {} +typedef llvm::MutableArrayRef DeclContextLookupResult; - using std::pair::operator=; -}; - -class DeclContextLookupConstResult - : public std::pair { -public: - DeclContextLookupConstResult(std::pair R) - : std::pair(R) {} - DeclContextLookupConstResult(NamedDecl * const *I, NamedDecl * const *E) - : std::pair(I, E) {} - DeclContextLookupConstResult() - : std::pair() {} - - using std::pair::operator=; -}; +typedef ArrayRef DeclContextLookupConstResult; /// DeclContext - This is used only as base class of specific decl types that /// can act as declaration contexts. These decls are (only the top classes @@ -935,19 +931,26 @@ class DeclContext { /// \brief Whether this declaration context also has some external /// storage that contains additional declarations that are lexically /// part of this context. - mutable unsigned ExternalLexicalStorage : 1; + mutable bool ExternalLexicalStorage : 1; /// \brief Whether this declaration context also has some external /// storage that contains additional declarations that are visible /// in this context. - mutable unsigned ExternalVisibleStorage : 1; + mutable bool ExternalVisibleStorage : 1; + + /// \brief Whether this declaration context has had external visible + /// storage added since the last lookup. In this case, \c LookupPtr's + /// invariant may not hold and needs to be fixed before we perform + /// another lookup. + mutable bool NeedToReconcileExternalVisibleStorage : 1; /// \brief Pointer to the data structure used to lookup declarations /// within this context (or a DependentStoredDeclsMap if this is a /// dependent context), and a bool indicating whether we have lazily /// omitted any declarations from the map. We maintain the invariant - /// that, if the map contains an entry for a DeclarationName, then it - /// contains all relevant entries for that name. + /// that, if the map contains an entry for a DeclarationName (and we + /// haven't lazily omitted anything), then it contains all relevant + /// entries for that name. mutable llvm::PointerIntPair LookupPtr; protected: @@ -970,10 +973,11 @@ protected: static std::pair BuildDeclChain(ArrayRef Decls, bool FieldsAlreadyLoaded); - DeclContext(Decl::Kind K) - : DeclKind(K), ExternalLexicalStorage(false), - ExternalVisibleStorage(false), LookupPtr(0, false), FirstDecl(0), - LastDecl(0) { } + DeclContext(Decl::Kind K) + : DeclKind(K), ExternalLexicalStorage(false), + ExternalVisibleStorage(false), + NeedToReconcileExternalVisibleStorage(false), LookupPtr(0, false), + FirstDecl(0), LastDecl(0) {} public: ~DeclContext(); @@ -1086,6 +1090,10 @@ public: /// a C++ extern "C" linkage spec. bool isExternCContext() const; + /// \brief Determines whether this context is, or is nested within, + /// a C++ extern "C++" linkage spec. + bool isExternCXXContext() const; + /// \brief Determine whether this declaration context is equivalent /// to the declaration context DC. bool Equals(const DeclContext *DC) const { @@ -1160,7 +1168,7 @@ public: /// contexts that are semanticaly connected to this declaration context, /// in source order, including this context (which may be the only result, /// for non-namespace contexts). - void collectAllContexts(llvm::SmallVectorImpl &Contexts); + void collectAllContexts(SmallVectorImpl &Contexts); /// decl_iterator - Iterates through the declarations stored /// within this context. @@ -1423,7 +1431,7 @@ public: /// usual relationship between a DeclContext and the external source. /// See the ASTImporter for the (few, but important) use cases. void localUncachedLookup(DeclarationName Name, - llvm::SmallVectorImpl &Results); + SmallVectorImpl &Results); /// @brief Makes a declaration visible within this context. /// @@ -1473,9 +1481,9 @@ public: // Low-level accessors /// \brief Mark the lookup table as needing to be built. This should be - /// used only if setHasExternalLexicalStorage() has been called. + /// used only if setHasExternalLexicalStorage() has been called on any + /// decl context for which this is the primary context. void setMustBuildLookupTable() { - assert(ExternalLexicalStorage && "Requires external lexical storage"); LookupPtr.setInt(true); } @@ -1504,6 +1512,8 @@ public: /// declarations visible in this context. void setHasExternalVisibleStorage(bool ES = true) { ExternalVisibleStorage = ES; + if (ES && LookupPtr.getPointer()) + NeedToReconcileExternalVisibleStorage = true; } /// \brief Determine whether the given declaration is stored in the list of @@ -1519,6 +1529,7 @@ public: LLVM_ATTRIBUTE_USED void dumpDeclContext() const; private: + void reconcileExternalVisibleStorage(); void LoadLexicalDeclsFromExternalStorage() const; /// @brief Makes a declaration visible within this context, but diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 9cb56e2..05ff49c 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -15,11 +15,11 @@ #ifndef LLVM_CLANG_AST_DECLCXX_H #define LLVM_CLANG_AST_DECLCXX_H +#include "clang/AST/ASTUnresolvedSet.h" +#include "clang/AST/Decl.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/Decl.h" #include "clang/AST/TypeLoc.h" -#include "clang/AST/UnresolvedSet.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" @@ -69,17 +69,6 @@ public: } // end namespace clang namespace llvm { - /// Implement simplify_type for AnyFunctionDecl, so that we can dyn_cast from - /// AnyFunctionDecl to any function or function template declaration. - template<> struct simplify_type { - typedef ::clang::NamedDecl* SimpleType; - static SimpleType getSimplifiedValue(const ::clang::AnyFunctionDecl &Val) { - return Val; - } - }; - template<> struct simplify_type< ::clang::AnyFunctionDecl> - : public simplify_type {}; - // Provide PointerLikeTypeTraits for non-cvr pointers. template<> class PointerLikeTypeTraits< ::clang::AnyFunctionDecl> { @@ -272,32 +261,25 @@ class CXXRecordDecl : public RecordDecl { friend void TagDecl::startDefinition(); + /// Values used in DefinitionData fields to represent special members. + enum SpecialMemberFlags { + SMF_DefaultConstructor = 0x1, + SMF_CopyConstructor = 0x2, + SMF_MoveConstructor = 0x4, + SMF_CopyAssignment = 0x8, + SMF_MoveAssignment = 0x10, + SMF_Destructor = 0x20, + SMF_All = 0x3f + }; + struct DefinitionData { DefinitionData(CXXRecordDecl *D); - /// UserDeclaredConstructor - True when this class has a - /// user-declared constructor. + /// \brief True if this class has any user-declared constructors. bool UserDeclaredConstructor : 1; - /// UserDeclaredCopyConstructor - True when this class has a - /// user-declared copy constructor. - bool UserDeclaredCopyConstructor : 1; - - /// UserDeclareMoveConstructor - True when this class has a - /// user-declared move constructor. - bool UserDeclaredMoveConstructor : 1; - - /// UserDeclaredCopyAssignment - True when this class has a - /// user-declared copy assignment operator. - bool UserDeclaredCopyAssignment : 1; - - /// UserDeclareMoveAssignment - True when this class has a - /// user-declared move assignment. - bool UserDeclaredMoveAssignment : 1; - - /// UserDeclaredDestructor - True when this class has a - /// user-declared destructor. - bool UserDeclaredDestructor : 1; + /// The user-declared special members which this class has. + unsigned UserDeclaredSpecialMembers : 6; /// Aggregate - True when this class is an aggregate. bool Aggregate : 1; @@ -360,21 +342,46 @@ class CXXRecordDecl : public RecordDecl { /// \brief True if any field has an in-class initializer. bool HasInClassInitializer : 1; - /// HasTrivialDefaultConstructor - True when, if this class has a default - /// constructor, this default constructor is trivial. + /// \brief True if any field is of reference type, and does not have an + /// in-class initializer. In this case, value-initialization of this class + /// is illegal in C++98 even if the class has a trivial default constructor. + bool HasUninitializedReferenceMember : 1; + + /// \brief These flags are \c true if a defaulted corresponding special + /// member can't be fully analyzed without performing overload resolution. + /// @{ + bool NeedOverloadResolutionForMoveConstructor : 1; + bool NeedOverloadResolutionForMoveAssignment : 1; + bool NeedOverloadResolutionForDestructor : 1; + /// @} + + /// \brief These flags are \c true if an implicit defaulted corresponding + /// special member would be defined as deleted. + /// @{ + bool DefaultedMoveConstructorIsDeleted : 1; + bool DefaultedMoveAssignmentIsDeleted : 1; + bool DefaultedDestructorIsDeleted : 1; + /// @} + + /// \brief The trivial special members which this class has, per + /// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25, + /// C++11 [class.dtor]p5, or would have if the member were not suppressed. + /// + /// This excludes any user-declared but not user-provided special members + /// which have been declared but not yet defined. + unsigned HasTrivialSpecialMembers : 6; + + /// \brief The declared special members of this class which are known to be + /// non-trivial. /// - /// C++0x [class.ctor]p5 - /// A default constructor is trivial if it is not user-provided and if - /// -- its class has no virtual functions and no virtual base classes, - /// and - /// -- no non-static data member of its class has a - /// brace-or-equal-initializer, and - /// -- all the direct base classes of its class have trivial - /// default 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 - /// default constructor. - bool HasTrivialDefaultConstructor : 1; + /// This excludes any user-declared but not user-provided special members + /// which have been declared but not yet defined, and any implicit special + /// members which have not yet been declared. + unsigned DeclaredNonTrivialSpecialMembers : 6; + + /// HasIrrelevantDestructor - True when this class has a destructor with no + /// semantic effect. + bool HasIrrelevantDestructor : 1; /// HasConstexprNonCopyMoveConstructor - True when this class has at least /// one user-declared constexpr constructor which is neither the copy nor @@ -389,80 +396,6 @@ class CXXRecordDecl : public RecordDecl { /// default constructor (either user-declared or implicitly declared). bool HasConstexprDefaultConstructor : 1; - /// HasTrivialCopyConstructor - True when this class has a trivial copy - /// constructor. - /// - /// C++0x [class.copy]p13: - /// A copy/move constructor for class X is trivial if it is neither - /// user-provided and if - /// -- class X has no virtual functions and no virtual base classes, and - /// -- the constructor selected to copy/move each direct base class - /// subobject is trivial, and - /// -- for each non-static data member of X that is of class type (or an - /// array thereof), the constructor selected to copy/move that member - /// is trivial; - /// otherwise the copy/move constructor is non-trivial. - bool HasTrivialCopyConstructor : 1; - - /// HasTrivialMoveConstructor - True when this class has a trivial move - /// constructor. - /// - /// C++0x [class.copy]p13: - /// A copy/move constructor for class X is trivial if it is neither - /// user-provided and if - /// -- class X has no virtual functions and no virtual base classes, and - /// -- the constructor selected to copy/move each direct base class - /// subobject is trivial, and - /// -- for each non-static data member of X that is of class type (or an - /// array thereof), the constructor selected to copy/move that member - /// is trivial; - /// otherwise the copy/move constructor is non-trivial. - bool HasTrivialMoveConstructor : 1; - - /// HasTrivialCopyAssignment - True when this class has a trivial copy - /// assignment operator. - /// - /// C++0x [class.copy]p27: - /// A copy/move assignment operator for class X is trivial if it is - /// neither user-provided nor deleted and if - /// -- class X has no virtual functions and no virtual base classes, and - /// -- the assignment operator selected to copy/move each direct base - /// class subobject is trivial, and - /// -- for each non-static data member of X that is of class type (or an - /// array thereof), the assignment operator selected to copy/move - /// that member is trivial; - /// otherwise the copy/move assignment operator is non-trivial. - bool HasTrivialCopyAssignment : 1; - - /// HasTrivialMoveAssignment - True when this class has a trivial move - /// assignment operator. - /// - /// C++0x [class.copy]p27: - /// A copy/move assignment operator for class X is trivial if it is - /// neither user-provided nor deleted and if - /// -- class X has no virtual functions and no virtual base classes, and - /// -- the assignment operator selected to copy/move each direct base - /// class subobject is trivial, and - /// -- for each non-static data member of X that is of class type (or an - /// array thereof), the assignment operator selected to copy/move - /// that member is trivial; - /// otherwise the copy/move assignment operator is non-trivial. - bool HasTrivialMoveAssignment : 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; - - /// HasIrrelevantDestructor - True when this class has a destructor with no - /// semantic effect. - bool HasIrrelevantDestructor : 1; - /// HasNonLiteralTypeFieldsOrBases - True when this class contains at least /// one non-static data member or base class of non-literal or volatile /// type. @@ -472,27 +405,29 @@ class CXXRecordDecl : public RecordDecl { /// already computed and are available. bool ComputedVisibleConversions : 1; - /// \brief Whether we have a C++0x user-provided default constructor (not + /// \brief Whether we have a C++11 user-provided default constructor (not /// explicitly deleted or defaulted). bool UserProvidedDefaultConstructor : 1; - /// \brief Whether we have already declared the default constructor. - bool DeclaredDefaultConstructor : 1; + /// \brief The special members which have been declared for this class, + /// either by the user or implicitly. + unsigned DeclaredSpecialMembers : 6; - /// \brief Whether we have already declared the copy constructor. - bool DeclaredCopyConstructor : 1; + /// \brief Whether an implicit copy constructor would have a const-qualified + /// parameter. + bool ImplicitCopyConstructorHasConstParam : 1; - /// \brief Whether we have already declared the move constructor. - bool DeclaredMoveConstructor : 1; + /// \brief Whether an implicit copy assignment operator would have a + /// const-qualified parameter. + bool ImplicitCopyAssignmentHasConstParam : 1; - /// \brief Whether we have already declared the copy-assignment operator. - bool DeclaredCopyAssignment : 1; + /// \brief Whether any declared copy constructor has a const-qualified + /// parameter. + bool HasDeclaredCopyConstructorWithConstParam : 1; - /// \brief Whether we have already declared the move-assignment operator. - bool DeclaredMoveAssignment : 1; - - /// \brief Whether we have already declared a destructor within the class. - bool DeclaredDestructor : 1; + /// \brief Whether any declared copy assignment operator has either a + /// const-qualified reference parameter or a non-reference parameter. + bool HasDeclaredCopyAssignmentWithConstParam : 1; /// \brief Whether an implicit move constructor was attempted to be declared /// but would have been deleted. @@ -522,14 +457,14 @@ class CXXRecordDecl : public RecordDecl { /// of this C++ class (but not its inherited conversion /// functions). Each of the entries in this overload set is a /// CXXConversionDecl. - UnresolvedSet<4> Conversions; + ASTUnresolvedSet 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; + ASTUnresolvedSet VisibleConversions; /// Definition - The declaration which defines this record. CXXRecordDecl *Definition; @@ -636,6 +571,10 @@ class CXXRecordDecl : public RecordDecl { friend class DeclContext; friend class LambdaExpr; + /// \brief Called from setBases and addedMember to notify the class that a + /// direct or virtual base class or a member of class type has been added. + void addedClassSubobject(CXXRecordDecl *Base); + /// \brief Notify the class that member has been added. /// /// This routine helps maintain information about the class based on which @@ -646,9 +585,6 @@ class CXXRecordDecl : public RecordDecl { void markedVirtualFunctionPure(); friend void FunctionDecl::setPure(bool); - void markedConstructorConstexpr(CXXConstructorDecl *CD); - friend void FunctionDecl::setConstexpr(bool); - friend class ASTNodeImporter; protected: @@ -765,7 +701,8 @@ public: return reverse_base_class_const_iterator(vbases_begin()); } - /// \brief Determine whether this class has any dependent base classes. + /// \brief Determine whether this class has any dependent base classes which + /// are not the current instantiation. bool hasAnyDependentBases() const; /// Iterator access to method members. The method iterator visits @@ -805,47 +742,38 @@ public: return data().FirstFriend != 0; } + /// \brief \c true if we know for sure that this class has a single, + /// accessible, unambiguous move constructor that is not deleted. + bool hasSimpleMoveConstructor() const { + return !hasUserDeclaredMoveConstructor() && hasMoveConstructor(); + } + /// \brief \c true if we know for sure that this class has a single, + /// accessible, unambiguous move assignment operator that is not deleted. + bool hasSimpleMoveAssignment() const { + return !hasUserDeclaredMoveAssignment() && hasMoveAssignment(); + } + /// \brief \c true if we know for sure that this class has an accessible + /// destructor that is not deleted. + bool hasSimpleDestructor() const { + return !hasUserDeclaredDestructor() && + !data().DefaultedDestructorIsDeleted; + } + + /// \brief Determine whether this class has any default constructors. + bool hasDefaultConstructor() const { + return (data().DeclaredSpecialMembers & SMF_DefaultConstructor) || + needsImplicitDefaultConstructor(); + } + /// \brief Determine if we need to declare a default constructor for /// this class. /// /// This value is used for lazy creation of default constructors. bool needsImplicitDefaultConstructor() const { return !data().UserDeclaredConstructor && - !data().DeclaredDefaultConstructor; - } - - /// hasDeclaredDefaultConstructor - Whether this class's default constructor - /// has been declared (either explicitly or implicitly). - bool hasDeclaredDefaultConstructor() const { - return data().DeclaredDefaultConstructor; + !(data().DeclaredSpecialMembers & SMF_DefaultConstructor); } - /// hasConstCopyConstructor - Determines whether this class has a - /// copy constructor that accepts a const-qualified argument. - bool hasConstCopyConstructor() const; - - /// getCopyConstructor - Returns the copy constructor for this class - CXXConstructorDecl *getCopyConstructor(unsigned TypeQuals) const; - - /// getMoveConstructor - Returns the move constructor for this class - CXXConstructorDecl *getMoveConstructor() const; - - /// \brief Retrieve the copy-assignment operator for this class, if available. - /// - /// This routine attempts to find the copy-assignment operator for this - /// class, using a simplistic form of overload resolution. - /// - /// \param ArgIsConst Whether the argument to the copy-assignment operator - /// is const-qualified. - /// - /// \returns The copy-assignment operator that can be invoked, or NULL if - /// a unique copy-assignment operator could not be found. - CXXMethodDecl *getCopyAssignmentOperator(bool ArgIsConst) const; - - /// getMoveAssignmentOperator - Returns the move assignment operator for this - /// class - CXXMethodDecl *getMoveAssignmentOperator() const; - /// hasUserDeclaredConstructor - Whether this class has any /// user-declared constructors. When true, a default constructor /// will not be implicitly declared. @@ -863,35 +791,53 @@ public: /// user-declared copy constructor. When false, a copy constructor /// will be implicitly declared. bool hasUserDeclaredCopyConstructor() const { - return data().UserDeclaredCopyConstructor; + return data().UserDeclaredSpecialMembers & SMF_CopyConstructor; } - /// \brief Determine whether this class has had its copy constructor - /// declared, either via the user or via an implicit declaration. - /// - /// This value is used for lazy creation of copy constructors. - bool hasDeclaredCopyConstructor() const { - return data().DeclaredCopyConstructor; + /// \brief Determine whether this class needs an implicit copy + /// constructor to be lazily declared. + bool needsImplicitCopyConstructor() const { + return !(data().DeclaredSpecialMembers & SMF_CopyConstructor); + } + + /// \brief Determine whether we need to eagerly declare a defaulted copy + /// constructor for this class. + bool needsOverloadResolutionForCopyConstructor() const { + return data().HasMutableFields; + } + + /// \brief Determine whether an implicit copy constructor for this type + /// would have a parameter with a const-qualified reference type. + bool implicitCopyConstructorHasConstParam() const { + return data().ImplicitCopyConstructorHasConstParam; + } + + /// \brief Determine whether this class has a copy constructor with + /// a parameter type which is a reference to a const-qualified type. + bool hasCopyConstructorWithConstParam() const { + return data().HasDeclaredCopyConstructorWithConstParam || + (needsImplicitCopyConstructor() && + implicitCopyConstructorHasConstParam()); } /// hasUserDeclaredMoveOperation - Whether this class has a user- /// declared move constructor or assignment operator. When false, a /// move constructor and assignment operator may be implicitly declared. bool hasUserDeclaredMoveOperation() const { - return data().UserDeclaredMoveConstructor || - data().UserDeclaredMoveAssignment; + return data().UserDeclaredSpecialMembers & + (SMF_MoveConstructor | SMF_MoveAssignment); } /// \brief Determine whether this class has had a move constructor /// declared by the user. bool hasUserDeclaredMoveConstructor() const { - return data().UserDeclaredMoveConstructor; + return data().UserDeclaredSpecialMembers & SMF_MoveConstructor; } - /// \brief Determine whether this class has had a move constructor - /// declared. - bool hasDeclaredMoveConstructor() const { - return data().DeclaredMoveConstructor; + /// \brief Determine whether this class has a move constructor. + bool hasMoveConstructor() const { + return (data().DeclaredSpecialMembers & SMF_MoveConstructor) || + needsImplicitMoveConstructor(); } /// \brief Determine whether implicit move constructor generation for this @@ -908,44 +854,66 @@ public: /// \brief Determine whether this class should get an implicit move /// constructor or if any existing special member function inhibits this. - /// - /// Covers all bullets of C++0x [class.copy]p9 except the last, that the - /// constructor wouldn't be deleted, which is only looked up from a cached - /// result. bool needsImplicitMoveConstructor() const { return !hasFailedImplicitMoveConstructor() && - !hasDeclaredMoveConstructor() && + !(data().DeclaredSpecialMembers & SMF_MoveConstructor) && !hasUserDeclaredCopyConstructor() && !hasUserDeclaredCopyAssignment() && !hasUserDeclaredMoveAssignment() && - !hasUserDeclaredDestructor(); + !hasUserDeclaredDestructor() && + !data().DefaultedMoveConstructorIsDeleted; + } + + /// \brief Determine whether we need to eagerly declare a defaulted move + /// constructor for this class. + bool needsOverloadResolutionForMoveConstructor() const { + return data().NeedOverloadResolutionForMoveConstructor; } /// hasUserDeclaredCopyAssignment - Whether this class has a /// user-declared copy assignment operator. When false, a copy /// assigment operator will be implicitly declared. bool hasUserDeclaredCopyAssignment() const { - return data().UserDeclaredCopyAssignment; + return data().UserDeclaredSpecialMembers & SMF_CopyAssignment; } - /// \brief Determine whether this class has had its copy assignment operator - /// declared, either via the user or via an implicit declaration. - /// - /// This value is used for lazy creation of copy assignment operators. - bool hasDeclaredCopyAssignment() const { - return data().DeclaredCopyAssignment; + /// \brief Determine whether this class needs an implicit copy + /// assignment operator to be lazily declared. + bool needsImplicitCopyAssignment() const { + return !(data().DeclaredSpecialMembers & SMF_CopyAssignment); + } + + /// \brief Determine whether we need to eagerly declare a defaulted copy + /// assignment operator for this class. + bool needsOverloadResolutionForCopyAssignment() const { + return data().HasMutableFields; + } + + /// \brief Determine whether an implicit copy assignment operator for this + /// type would have a parameter with a const-qualified reference type. + bool implicitCopyAssignmentHasConstParam() const { + return data().ImplicitCopyAssignmentHasConstParam; + } + + /// \brief Determine whether this class has a copy assignment operator with + /// a parameter type which is a reference to a const-qualified type or is not + /// a reference.. + bool hasCopyAssignmentWithConstParam() const { + return data().HasDeclaredCopyAssignmentWithConstParam || + (needsImplicitCopyAssignment() && + implicitCopyAssignmentHasConstParam()); } /// \brief Determine whether this class has had a move assignment /// declared by the user. bool hasUserDeclaredMoveAssignment() const { - return data().UserDeclaredMoveAssignment; + return data().UserDeclaredSpecialMembers & SMF_MoveAssignment; } - /// hasDeclaredMoveAssignment - Whether this class has a - /// declared move assignment operator. - bool hasDeclaredMoveAssignment() const { - return data().DeclaredMoveAssignment; + /// \brief Determine whether this class has a move assignment operator. + bool hasMoveAssignment() const { + return (data().DeclaredSpecialMembers & SMF_MoveAssignment) || + needsImplicitMoveAssignment(); } /// \brief Determine whether implicit move assignment generation for this @@ -963,34 +931,44 @@ public: /// \brief Determine whether this class should get an implicit move /// assignment operator or if any existing special member function inhibits /// this. - /// - /// Covers all bullets of C++0x [class.copy]p20 except the last, that the - /// constructor wouldn't be deleted. bool needsImplicitMoveAssignment() const { return !hasFailedImplicitMoveAssignment() && - !hasDeclaredMoveAssignment() && + !(data().DeclaredSpecialMembers & SMF_MoveAssignment) && !hasUserDeclaredCopyConstructor() && !hasUserDeclaredCopyAssignment() && !hasUserDeclaredMoveConstructor() && - !hasUserDeclaredDestructor(); + !hasUserDeclaredDestructor() && + !data().DefaultedMoveAssignmentIsDeleted; + } + + /// \brief Determine whether we need to eagerly declare a move assignment + /// operator for this class. + bool needsOverloadResolutionForMoveAssignment() const { + return data().NeedOverloadResolutionForMoveAssignment; } /// hasUserDeclaredDestructor - Whether this class has a /// user-declared destructor. When false, a destructor will be /// implicitly declared. bool hasUserDeclaredDestructor() const { - return data().UserDeclaredDestructor; + return data().UserDeclaredSpecialMembers & SMF_Destructor; } - /// \brief Determine whether this class has had its destructor declared, - /// either via the user or via an implicit declaration. - /// - /// This value is used for lazy creation of destructors. - bool hasDeclaredDestructor() const { return data().DeclaredDestructor; } + /// \brief Determine whether this class needs an implicit destructor to + /// be lazily declared. + bool needsImplicitDestructor() const { + return !(data().DeclaredSpecialMembers & SMF_Destructor); + } + + /// \brief Determine whether we need to eagerly declare a destructor for this + /// class. + bool needsOverloadResolutionForDestructor() const { + return data().NeedOverloadResolutionForDestructor; + } /// \brief Determine whether this class describes a lambda function object. bool isLambda() const { return hasDefinition() && data().IsLambda; } - + /// \brief For a closure type, retrieve the mapping from captured /// variables and this to the non-static data members that store the /// values or references of the captures. @@ -1011,21 +989,12 @@ public: return isLambda() ? captures_begin() + getLambdaData().NumCaptures : NULL; } - /// getConversions - Retrieve the overload set containing all of the - /// conversion functions in this class. - UnresolvedSetImpl *getConversionFunctions() { - return &data().Conversions; - } - const UnresolvedSetImpl *getConversionFunctions() const { - return &data().Conversions; - } - - typedef UnresolvedSetImpl::iterator conversion_iterator; + typedef UnresolvedSetIterator conversion_iterator; conversion_iterator conversion_begin() const { - return getConversionFunctions()->begin(); + return data().Conversions.begin(); } conversion_iterator conversion_end() const { - return getConversionFunctions()->end(); + return data().Conversions.end(); } /// Removes a conversion function from this class. The conversion @@ -1035,7 +1004,8 @@ public: /// getVisibleConversionFunctions - get all conversion functions visible /// in current class; including conversion function templates. - const UnresolvedSetImpl *getVisibleConversionFunctions(); + std::pair + getVisibleConversionFunctions(); /// isAggregate - Whether this class is an aggregate (C++ /// [dcl.init.aggr]), which is a class with no user-declared @@ -1047,10 +1017,26 @@ public: /// for non-static data members. bool hasInClassInitializer() const { return data().HasInClassInitializer; } + /// \brief Whether this class or any of its subobjects has any members of + /// reference type which would make value-initialization ill-formed, per + /// C++03 [dcl.init]p5: + /// -- if T is a non-union class type without a user-declared constructor, + /// then every non-static data member and base-class component of T is + /// value-initialized + /// [...] + /// A program that calls for [...] value-initialization of an entity of + /// reference type is ill-formed. + bool hasUninitializedReferenceMember() const { + return !isUnion() && !hasUserDeclaredConstructor() && + data().HasUninitializedReferenceMember; + } + /// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class /// that is an aggregate that has no non-static non-POD data members, no /// reference data members, no user-defined copy assignment operator and no /// user-defined destructor. + /// + /// Note that this is the C++ TR1 definition of POD. bool isPOD() const { return data().PlainOldData; } /// \brief True if this class is C-like, without C++-specific features, e.g. @@ -1079,64 +1065,110 @@ public: /// mutable field. bool hasMutableFields() const { return data().HasMutableFields; } - /// hasTrivialDefaultConstructor - Whether this class has a trivial default - /// constructor (C++11 [class.ctor]p5). + /// \brief Determine whether this class has a trivial default constructor + /// (C++11 [class.ctor]p5). bool hasTrivialDefaultConstructor() const { - return data().HasTrivialDefaultConstructor && - (!data().UserDeclaredConstructor || - data().DeclaredDefaultConstructor); + return hasDefaultConstructor() && + (data().HasTrivialSpecialMembers & SMF_DefaultConstructor); + } + + /// \brief Determine whether this class has a non-trivial default constructor + /// (C++11 [class.ctor]p5). + bool hasNonTrivialDefaultConstructor() const { + return (data().DeclaredNonTrivialSpecialMembers & SMF_DefaultConstructor) || + (needsImplicitDefaultConstructor() && + !(data().HasTrivialSpecialMembers & SMF_DefaultConstructor)); } - /// hasConstexprNonCopyMoveConstructor - Whether this class has at least one - /// constexpr constructor other than the copy or move constructors. + /// \brief Determine whether this class has at least one constexpr constructor + /// other than the copy or move constructors. bool hasConstexprNonCopyMoveConstructor() const { return data().HasConstexprNonCopyMoveConstructor || - (!hasUserDeclaredConstructor() && + (needsImplicitDefaultConstructor() && defaultedDefaultConstructorIsConstexpr()); } - /// defaultedDefaultConstructorIsConstexpr - Whether a defaulted default - /// constructor for this class would be constexpr. + /// \brief Determine whether a defaulted default constructor for this class + /// would be constexpr. bool defaultedDefaultConstructorIsConstexpr() const { return data().DefaultedDefaultConstructorIsConstexpr && (!isUnion() || hasInClassInitializer()); } - /// hasConstexprDefaultConstructor - Whether this class has a constexpr - /// default constructor. + /// \brief Determine whether this class has a constexpr default constructor. bool hasConstexprDefaultConstructor() const { return data().HasConstexprDefaultConstructor || - (!data().UserDeclaredConstructor && + (needsImplicitDefaultConstructor() && defaultedDefaultConstructorIsConstexpr()); } - // hasTrivialCopyConstructor - Whether this class has a trivial copy - // constructor (C++ [class.copy]p6, C++0x [class.copy]p13) + /// \brief Determine whether this class has a trivial copy constructor + /// (C++ [class.copy]p6, C++11 [class.copy]p12) bool hasTrivialCopyConstructor() const { - return data().HasTrivialCopyConstructor; + return data().HasTrivialSpecialMembers & SMF_CopyConstructor; + } + + /// \brief Determine whether this class has a non-trivial copy constructor + /// (C++ [class.copy]p6, C++11 [class.copy]p12) + bool hasNonTrivialCopyConstructor() const { + return data().DeclaredNonTrivialSpecialMembers & SMF_CopyConstructor || + !hasTrivialCopyConstructor(); } - // hasTrivialMoveConstructor - Whether this class has a trivial move - // constructor (C++0x [class.copy]p13) + /// \brief Determine whether this class has a trivial move constructor + /// (C++11 [class.copy]p12) bool hasTrivialMoveConstructor() const { - return data().HasTrivialMoveConstructor; + return hasMoveConstructor() && + (data().HasTrivialSpecialMembers & SMF_MoveConstructor); } - // hasTrivialCopyAssignment - Whether this class has a trivial copy - // assignment operator (C++ [class.copy]p11, C++0x [class.copy]p27) + /// \brief Determine whether this class has a non-trivial move constructor + /// (C++11 [class.copy]p12) + bool hasNonTrivialMoveConstructor() const { + return (data().DeclaredNonTrivialSpecialMembers & SMF_MoveConstructor) || + (needsImplicitMoveConstructor() && + !(data().HasTrivialSpecialMembers & SMF_MoveConstructor)); + } + + /// \brief Determine whether this class has a trivial copy assignment operator + /// (C++ [class.copy]p11, C++11 [class.copy]p25) bool hasTrivialCopyAssignment() const { - return data().HasTrivialCopyAssignment; + return data().HasTrivialSpecialMembers & SMF_CopyAssignment; + } + + /// \brief Determine whether this class has a non-trivial copy assignment + /// operator (C++ [class.copy]p11, C++11 [class.copy]p25) + bool hasNonTrivialCopyAssignment() const { + return data().DeclaredNonTrivialSpecialMembers & SMF_CopyAssignment || + !hasTrivialCopyAssignment(); } - // hasTrivialMoveAssignment - Whether this class has a trivial move - // assignment operator (C++0x [class.copy]p27) + /// \brief Determine whether this class has a trivial move assignment operator + /// (C++11 [class.copy]p25) bool hasTrivialMoveAssignment() const { - return data().HasTrivialMoveAssignment; + return hasMoveAssignment() && + (data().HasTrivialSpecialMembers & SMF_MoveAssignment); + } + + /// \brief Determine whether this class has a non-trivial move assignment + /// operator (C++11 [class.copy]p25) + bool hasNonTrivialMoveAssignment() const { + return (data().DeclaredNonTrivialSpecialMembers & SMF_MoveAssignment) || + (needsImplicitMoveAssignment() && + !(data().HasTrivialSpecialMembers & SMF_MoveAssignment)); } - // hasTrivialDestructor - Whether this class has a trivial destructor - // (C++ [class.dtor]p3) - bool hasTrivialDestructor() const { return data().HasTrivialDestructor; } + /// \brief Determine whether this class has a trivial destructor + /// (C++ [class.dtor]p3) + bool hasTrivialDestructor() const { + return data().HasTrivialSpecialMembers & SMF_Destructor; + } + + /// \brief Determine whether this class has a non-trivial destructor + /// (C++ [class.dtor]p3) + bool hasNonTrivialDestructor() const { + return !(data().HasTrivialSpecialMembers & SMF_Destructor); + } // hasIrrelevantDestructor - Whether this class has a destructor which has no // semantic effect. Any such destructor will be trivial, public, defaulted @@ -1210,7 +1242,9 @@ public: /// \brief If this class is an instantiation of a member class of a /// class template specialization, retrieves the member specialization /// information. - MemberSpecializationInfo *getMemberSpecializationInfo() const; + MemberSpecializationInfo *getMemberSpecializationInfo() const { + return TemplateOrInstantiation.dyn_cast(); + } /// \brief Specify that this record is an instantiation of the /// member class RD. @@ -1256,6 +1290,10 @@ public: return dyn_cast(getDeclContext()); } + /// \brief Determine whether this dependent class is a current instantiation, + /// when viewed from within the given context. + bool isCurrentInstantiation(const DeclContext *CurContext) const; + /// \brief Determine whether this class is derived from the class \p Base. /// /// This routine only determines whether this class is derived from \p Base, @@ -1437,6 +1475,10 @@ public: return (PathAccess > DeclAccess ? PathAccess : DeclAccess); } + /// \brief Indicates that the declaration of a defaulted or deleted special + /// member function is now complete. + void finishedDefaultedOrDeletedMember(CXXMethodDecl *MD); + /// \brief Indicates that the definition of this class is now complete. virtual void completeDefinition(); @@ -1490,6 +1532,9 @@ public: getLambdaData().ContextDecl = ContextDecl; } + /// \brief Returns the inheritance model used for this record. + MSInheritanceModel getMSInheritanceModel() const; + /// \brief Determine whether this lambda expression was known to be dependent /// at the time it was created, even if its context does not appear to be /// dependent. @@ -1528,11 +1573,10 @@ protected: CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isStatic, StorageClass SCAsWritten, bool isInline, + StorageClass SC, bool isInline, bool isConstexpr, SourceLocation EndLocation) : FunctionDecl(DK, RD, StartLoc, NameInfo, T, TInfo, - (isStatic ? SC_Static : SC_None), - SCAsWritten, isInline, isConstexpr) { + SC, isInline, isConstexpr) { if (EndLocation.isValid()) setRangeEnd(EndLocation); } @@ -1542,15 +1586,14 @@ public: SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isStatic, - StorageClass SCAsWritten, + StorageClass SC, bool isInline, bool isConstexpr, SourceLocation EndLocation); static CXXMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - bool isStatic() const { return getStorageClass() == SC_Static; } + + bool isStatic() const; bool isInstance() const { return !isStatic(); } bool isConst() const { return getType()->castAs()->isConst(); } @@ -1958,7 +2001,7 @@ class CXXConstructorDecl : public CXXMethodDecl { QualType T, TypeSourceInfo *TInfo, bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared, bool isConstexpr) - : CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, false, + : CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, isConstexpr, SourceLocation()), IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false), CtorInitializers(0), NumCtorInitializers(0) { @@ -2077,7 +2120,7 @@ public: /// constructor (C++ [class.copy]p2, which can be used to copy the /// class. @p TypeQuals will be set to the qualifiers on the /// argument type. For example, @p TypeQuals would be set to @c - /// QualType::Const for the following copy constructor: + /// Qualifiers::Const for the following copy constructor: /// /// @code /// class X { @@ -2177,7 +2220,7 @@ class CXXDestructorDecl : public CXXMethodDecl { const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXDestructor, RD, StartLoc, NameInfo, T, TInfo, false, + : CXXMethodDecl(CXXDestructor, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, /*isConstexpr=*/false, SourceLocation()), ImplicitlyDefined(false), OperatorDelete(0) { setImplicit(isImplicitlyDeclared); @@ -2244,7 +2287,7 @@ class CXXConversionDecl : public CXXMethodDecl { QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicitSpecified, bool isConstexpr, SourceLocation EndLocation) - : CXXMethodDecl(CXXConversion, RD, StartLoc, NameInfo, T, TInfo, false, + : CXXMethodDecl(CXXConversion, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, isConstexpr, EndLocation), IsExplicitSpecified(isExplicitSpecified) { } diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index 39f04c6..84f3698 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -15,10 +15,10 @@ #define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H #include "clang/AST/Decl.h" -#include "clang/AST/DeclarationName.h" #include "clang/AST/DeclCXX.h" -#include "llvm/ADT/PointerUnion.h" +#include "clang/AST/DeclarationName.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" #include @@ -97,6 +97,22 @@ public: == Vec.end() && "list still contains decl"); } + /// \brief Remove any declarations which were imported from an external + /// AST source. + void removeExternalDecls() { + if (isNull()) { + // Nothing to do. + } else if (NamedDecl *Singleton = getAsDecl()) { + if (Singleton->isFromASTFile()) + *this = StoredDeclsList(); + } else { + DeclsTy &Vec = *getAsVector(); + Vec.erase(std::remove_if(Vec.begin(), Vec.end(), + std::mem_fun(&Decl::isFromASTFile)), + Vec.end()); + } + } + /// getLookupResult - Return an array of all the decls that this list /// represents. DeclContext::lookup_result getLookupResult() { @@ -117,7 +133,7 @@ public: DeclsTy &Vector = *getAsVector(); // Otherwise, we have a range result. - return DeclContext::lookup_result(&Vector[0], &Vector[0]+Vector.size()); + return DeclContext::lookup_result(Vector.begin(), Vector.end()); } /// HandleRedeclaration - If this is a redeclaration of an existing decl, @@ -186,7 +202,7 @@ public: // All other declarations go at the end of the list, but before any // tag declarations. But we can be clever about tag declarations // because there can only ever be one in a scope. - } else if (Vec.back()->hasTagIdentifierNamespace()) { + } else if (!Vec.empty() && Vec.back()->hasTagIdentifierNamespace()) { NamedDecl *TagD = Vec.back(); Vec.back() = D; Vec.push_back(TagD); diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 37e4586..253c23c 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -54,22 +54,40 @@ private: /// True if this 'friend' declaration is unsupported. Eventually we /// will support every possible friend declaration, but for now we /// silently ignore some and set this flag to authorize all access. - bool UnsupportedFriend; + bool UnsupportedFriend : 1; + + // The number of "outer" template parameter lists in non-templatic + // (currently unsupported) friend type declarations, such as + // template friend class A::B; + unsigned NumTPLists : 31; + + // The tail-allocated friend type template parameter lists (if any). + TemplateParameterList* const *getTPLists() const { + return reinterpret_cast(this + 1); + } + TemplateParameterList **getTPLists() { + return reinterpret_cast(this + 1); + } friend class CXXRecordDecl::friend_iterator; friend class CXXRecordDecl; FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend, - SourceLocation FriendL) + SourceLocation FriendL, + ArrayRef FriendTypeTPLists) : Decl(Decl::Friend, DC, L), Friend(Friend), NextFriend(), FriendLoc(FriendL), - UnsupportedFriend(false) { + UnsupportedFriend(false), + NumTPLists(FriendTypeTPLists.size()) { + for (unsigned i = 0; i < NumTPLists; ++i) + getTPLists()[i] = FriendTypeTPLists[i]; } - explicit FriendDecl(EmptyShell Empty) - : Decl(Decl::Friend, Empty), NextFriend() { } + FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists) + : Decl(Decl::Friend, Empty), NextFriend(), + NumTPLists(NumFriendTypeTPLists) { } FriendDecl *getNextFriend() { if (!NextFriend.isOffset()) @@ -81,8 +99,11 @@ private: public: static FriendDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_, - SourceLocation FriendL); - static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID); + SourceLocation FriendL, + ArrayRef FriendTypeTPLists + = ArrayRef()); + static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID, + unsigned FriendTypeNumTPLists); /// If this friend declaration names an (untemplated but possibly /// dependent) type, return the type; otherwise return null. This @@ -91,6 +112,13 @@ public: TypeSourceInfo *getFriendType() const { return Friend.dyn_cast(); } + unsigned getFriendTypeNumTemplateParameterLists() const { + return NumTPLists; + } + TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const { + assert(N < NumTPLists); + return getTPLists()[N]; + } /// If this friend declaration doesn't name a type, return the inner /// declaration. @@ -114,8 +142,12 @@ public: } return SourceRange(getFriendLoc(), ND->getLocEnd()); } - else if (TypeSourceInfo *TInfo = getFriendType()) - return SourceRange(getFriendLoc(), TInfo->getTypeLoc().getEndLoc()); + else if (TypeSourceInfo *TInfo = getFriendType()) { + SourceLocation StartL = (NumTPLists == 0) + ? getFriendLoc() + : getTPLists()[0]->getTemplateLoc(); + return SourceRange(StartL, TInfo->getTypeLoc().getEndLoc()); + } else return SourceRange(getFriendLoc(), getLocation()); } diff --git a/include/clang/AST/DeclLookups.h b/include/clang/AST/DeclLookups.h index 867b465..4477c25 100644 --- a/include/clang/AST/DeclLookups.h +++ b/include/clang/AST/DeclLookups.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_DECLLOOKUPS_H #define LLVM_CLANG_AST_DECLLOOKUPS_H +#include "clang/AST/ASTContext.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclContextInternals.h" #include "clang/AST/DeclarationName.h" diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 8b27dd8..c294922 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -159,6 +159,9 @@ private: /// method in the interface or its categories. unsigned IsOverriding : 1; + /// \brief Indicates if the method was a definition but its body was skipped. + unsigned HasSkippedBody : 1; + // Result type of this method. QualType MethodDeclType; @@ -238,7 +241,7 @@ private: IsDefined(isDefined), IsRedeclaration(0), HasRedeclaration(0), DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), RelatedResultType(HasRelatedResultType), - SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), + SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), HasSkippedBody(0), MethodDeclType(T), ResultTInfo(ResultTInfo), ParamsAndSelLocs(0), NumParams(0), DeclEndLoc(endLoc), Body(), SelfDecl(0), CmdDecl(0) { @@ -429,6 +432,10 @@ public: void getOverriddenMethods( SmallVectorImpl &Overridden) const; + /// \brief True if the method was a definition but its body was skipped. + bool hasSkippedBody() const { return HasSkippedBody; } + void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; } + /// \brief Returns the property associated with this method's selector. /// /// Note that even if this particular method is not marked as a property @@ -530,23 +537,29 @@ public: } // Get the local instance/class method declared in this interface. - ObjCMethodDecl *getMethod(Selector Sel, bool isInstance) const; - ObjCMethodDecl *getInstanceMethod(Selector Sel) const { - return getMethod(Sel, true/*isInstance*/); + ObjCMethodDecl *getMethod(Selector Sel, bool isInstance, + bool AllowHidden = false) const; + ObjCMethodDecl *getInstanceMethod(Selector Sel, + bool AllowHidden = false) const { + return getMethod(Sel, true/*isInstance*/, AllowHidden); } - ObjCMethodDecl *getClassMethod(Selector Sel) const { - return getMethod(Sel, false/*isInstance*/); + ObjCMethodDecl *getClassMethod(Selector Sel, bool AllowHidden = false) const { + return getMethod(Sel, false/*isInstance*/, AllowHidden); } + bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const; ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const; ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const; typedef llvm::DenseMap PropertyMap; - + + typedef llvm::SmallVector PropertyDeclOrder; + /// This routine collects list of properties to be implemented in the class. /// This includes, class's and its conforming protocols' properties. /// Note, the superclass's properties are not included in the list. - virtual void collectPropertiesToImplement(PropertyMap &PM) const {} + virtual void collectPropertiesToImplement(PropertyMap &PM, + PropertyDeclOrder &PO) const {} SourceLocation getAtStartLoc() const { return AtStart; } void setAtStartLoc(SourceLocation Loc) { AtStart = Loc; } @@ -641,6 +654,10 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// completed by the external AST source when required. mutable bool ExternallyCompleted : 1; + /// \brief Indicates that the ivar cache does not yet include ivars + /// declared in the implementation. + mutable bool IvarListMissingImplementation : 1; + /// \brief The location of the superclass, if any. SourceLocation SuperClassLoc; @@ -650,7 +667,8 @@ class ObjCInterfaceDecl : public ObjCContainerDecl SourceLocation EndLoc; DefinitionData() : Definition(), SuperClass(), CategoryList(), IvarList(), - ExternallyCompleted() { } + ExternallyCompleted(), + IvarListMissingImplementation(true) { } }; ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, @@ -661,11 +679,14 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// \brief Contains a pointer to the data associated with this class, /// which will be NULL if this class has not yet been defined. - DefinitionData *Data; + /// + /// The bit indicates when we don't need to check for out-of-date + /// declarations. It will be set unless modules are enabled. + llvm::PointerIntPair Data; DefinitionData &data() const { - assert(Data != 0 && "Declaration has no definition!"); - return *Data; + assert(Data.getPointer() && "Declaration has no definition!"); + return *Data.getPointer(); } /// \brief Allocate the definition data for this class. @@ -673,7 +694,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl typedef Redeclarable redeclarable_base; virtual ObjCInterfaceDecl *getNextRedeclaration() { - return RedeclLink.getNext(); + return RedeclLink.getNext(); } virtual ObjCInterfaceDecl *getPreviousDeclImpl() { return getPreviousDecl(); @@ -846,24 +867,38 @@ public: /// \brief Determine whether this particular declaration of this class is /// actually also a definition. bool isThisDeclarationADefinition() const { - return Data && Data->Definition == this; + return getDefinition() == this; } /// \brief Determine whether this class has been defined. - bool hasDefinition() const { return Data; } + bool hasDefinition() const { + // If the name of this class is out-of-date, bring it up-to-date, which + // might bring in a definition. + // Note: a null value indicates that we don't have a definition and that + // modules are enabled. + if (!Data.getOpaqueValue()) { + if (IdentifierInfo *II = getIdentifier()) { + if (II->isOutOfDate()) { + updateOutOfDate(*II); + } + } + } + + return Data.getPointer(); + } /// \brief Retrieve the definition of this class, or NULL if this class /// has been forward-declared (with \@class) but not yet defined (with /// \@interface). ObjCInterfaceDecl *getDefinition() { - return hasDefinition()? Data->Definition : 0; + return hasDefinition()? Data.getPointer()->Definition : 0; } /// \brief Retrieve the definition of this class, or NULL if this class /// has been forward-declared (with \@class) but not yet defined (with /// \@interface). const ObjCInterfaceDecl *getDefinition() const { - return hasDefinition()? Data->Definition : 0; + return hasDefinition()? Data.getPointer()->Definition : 0; } /// \brief Starts the definition of this Objective-C class, taking it from @@ -887,7 +922,166 @@ public: : superCls; } - ObjCCategoryDecl* getCategoryList() const { + /// \brief Iterator that walks over the list of categories, filtering out + /// those that do not meet specific criteria. + /// + /// This class template is used for the various permutations of category + /// and extension iterators. + template + class filtered_category_iterator { + ObjCCategoryDecl *Current; + + void findAcceptableCategory(); + + public: + typedef ObjCCategoryDecl * value_type; + typedef value_type reference; + typedef value_type pointer; + typedef std::ptrdiff_t difference_type; + typedef std::input_iterator_tag iterator_category; + + filtered_category_iterator() : Current(0) { } + explicit filtered_category_iterator(ObjCCategoryDecl *Current) + : Current(Current) + { + findAcceptableCategory(); + } + + reference operator*() const { return Current; } + pointer operator->() const { return Current; } + + filtered_category_iterator &operator++(); + + filtered_category_iterator operator++(int) { + filtered_category_iterator Tmp = *this; + ++(*this); + return Tmp; + } + + friend bool operator==(filtered_category_iterator X, + filtered_category_iterator Y) { + return X.Current == Y.Current; + } + + friend bool operator!=(filtered_category_iterator X, + filtered_category_iterator Y) { + return X.Current != Y.Current; + } + }; + +private: + /// \brief Test whether the given category is visible. + /// + /// Used in the \c visible_categories_iterator. + static bool isVisibleCategory(ObjCCategoryDecl *Cat); + +public: + /// \brief Iterator that walks over the list of categories and extensions + /// that are visible, i.e., not hidden in a non-imported submodule. + typedef filtered_category_iterator + visible_categories_iterator; + + /// \brief Retrieve an iterator to the beginning of the visible-categories + /// list. + visible_categories_iterator visible_categories_begin() const { + return visible_categories_iterator(getCategoryListRaw()); + } + + /// \brief Retrieve an iterator to the end of the visible-categories list. + visible_categories_iterator visible_categories_end() const { + return visible_categories_iterator(); + } + + /// \brief Determine whether the visible-categories list is empty. + bool visible_categories_empty() const { + return visible_categories_begin() == visible_categories_end(); + } + +private: + /// \brief Test whether the given category... is a category. + /// + /// Used in the \c known_categories_iterator. + static bool isKnownCategory(ObjCCategoryDecl *) { return true; } + +public: + /// \brief Iterator that walks over all of the known categories and + /// extensions, including those that are hidden. + typedef filtered_category_iterator known_categories_iterator; + + /// \brief Retrieve an iterator to the beginning of the known-categories + /// list. + known_categories_iterator known_categories_begin() const { + return known_categories_iterator(getCategoryListRaw()); + } + + /// \brief Retrieve an iterator to the end of the known-categories list. + known_categories_iterator known_categories_end() const { + return known_categories_iterator(); + } + + /// \brief Determine whether the known-categories list is empty. + bool known_categories_empty() const { + return known_categories_begin() == known_categories_end(); + } + +private: + /// \brief Test whether the given category is a visible extension. + /// + /// Used in the \c visible_extensions_iterator. + static bool isVisibleExtension(ObjCCategoryDecl *Cat); + +public: + /// \brief Iterator that walks over all of the visible extensions, skipping + /// any that are known but hidden. + typedef filtered_category_iterator + visible_extensions_iterator; + + /// \brief Retrieve an iterator to the beginning of the visible-extensions + /// list. + visible_extensions_iterator visible_extensions_begin() const { + return visible_extensions_iterator(getCategoryListRaw()); + } + + /// \brief Retrieve an iterator to the end of the visible-extensions list. + visible_extensions_iterator visible_extensions_end() const { + return visible_extensions_iterator(); + } + + /// \brief Determine whether the visible-extensions list is empty. + bool visible_extensions_empty() const { + return visible_extensions_begin() == visible_extensions_end(); + } + +private: + /// \brief Test whether the given category is an extension. + /// + /// Used in the \c known_extensions_iterator. + static bool isKnownExtension(ObjCCategoryDecl *Cat); + +public: + /// \brief Iterator that walks over all of the known extensions. + typedef filtered_category_iterator + known_extensions_iterator; + + /// \brief Retrieve an iterator to the beginning of the known-extensions + /// list. + known_extensions_iterator known_extensions_begin() const { + return known_extensions_iterator(getCategoryListRaw()); + } + + /// \brief Retrieve an iterator to the end of the known-extensions list. + known_extensions_iterator known_extensions_end() const { + return known_extensions_iterator(); + } + + /// \brief Determine whether the known-extensions list is empty. + bool known_extensions_empty() const { + return known_extensions_begin() == known_extensions_end(); + } + + /// \brief Retrieve the raw pointer to the start of the category/extension + /// list. + ObjCCategoryDecl* getCategoryListRaw() const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) return 0; @@ -898,16 +1092,17 @@ public: return data().CategoryList; } - void setCategoryList(ObjCCategoryDecl *category) { + /// \brief Set the raw pointer to the start of the category/extension + /// list. + void setCategoryListRaw(ObjCCategoryDecl *category) { data().CategoryList = category; } - ObjCCategoryDecl* getFirstClassExtension() const; - ObjCPropertyDecl *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const; - virtual void collectPropertiesToImplement(PropertyMap &PM) const; + virtual void collectPropertiesToImplement(PropertyMap &PM, + PropertyDeclOrder &PO) const; /// isSuperClassOf - Return true if this class is the specified class or is a /// super class of the specified interface class. @@ -924,28 +1119,12 @@ public: /// isArcWeakrefUnavailable - Checks for a class or one of its super classes /// to be incompatible with __weak references. Returns true if it is. - bool isArcWeakrefUnavailable() const { - const ObjCInterfaceDecl *Class = this; - while (Class) { - if (Class->hasAttr()) - return true; - Class = Class->getSuperClass(); - } - return false; - } + bool isArcWeakrefUnavailable() const; /// isObjCRequiresPropertyDefs - Checks that a class or one of its super /// classes must not be auto-synthesized. Returns class decl. if it must not /// be; 0, otherwise. - const ObjCInterfaceDecl *isObjCRequiresPropertyDefs() const { - const ObjCInterfaceDecl *Class = this; - while (Class) { - if (Class->hasAttr()) - return Class; - Class = Class->getSuperClass(); - } - return 0; - } + const ObjCInterfaceDecl *isObjCRequiresPropertyDefs() const; ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName, ObjCInterfaceDecl *&ClassDeclared); @@ -992,7 +1171,7 @@ public: /// ObjCInterfaceDecl node. This is for legacy objective-c \@implementation /// declaration without an \@interface declaration. bool isImplicitInterfaceDecl() const { - return hasDefinition() ? Data->Definition->isImplicit() : isImplicit(); + return hasDefinition() ? data().Definition->isImplicit() : isImplicit(); } /// ClassImplementsProtocol - Checks that 'lProto' protocol @@ -1169,12 +1348,17 @@ class ObjCProtocolDecl : public ObjCContainerDecl, /// \brief Referenced protocols ObjCProtocolList ReferencedProtocols; }; - - DefinitionData *Data; + + /// \brief Contains a pointer to the data associated with this class, + /// which will be NULL if this class has not yet been defined. + /// + /// The bit indicates when we don't need to check for out-of-date + /// declarations. It will be set unless modules are enabled. + llvm::PointerIntPair Data; DefinitionData &data() const { - assert(Data && "Objective-C protocol has no definition!"); - return *Data; + assert(Data.getPointer() && "Objective-C protocol has no definition!"); + return *Data.getPointer(); } ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id, @@ -1193,7 +1377,7 @@ class ObjCProtocolDecl : public ObjCContainerDecl, virtual ObjCProtocolDecl *getMostRecentDeclImpl() { return getMostRecentDecl(); } - + public: static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, @@ -1244,7 +1428,7 @@ public: /// implements. void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num, const SourceLocation *Locs, ASTContext &C) { - assert(Data && "Protocol is not defined"); + assert(hasDefinition() && "Protocol is not defined"); data().ReferencedProtocols.set(List, Num, Locs, C); } @@ -1261,16 +1445,30 @@ public: } /// \brief Determine whether this protocol has a definition. - bool hasDefinition() const { return Data != 0; } + bool hasDefinition() const { + // If the name of this protocol is out-of-date, bring it up-to-date, which + // might bring in a definition. + // Note: a null value indicates that we don't have a definition and that + // modules are enabled. + if (!Data.getOpaqueValue()) { + if (IdentifierInfo *II = getIdentifier()) { + if (II->isOutOfDate()) { + updateOutOfDate(*II); + } + } + } + + return Data.getPointer(); + } /// \brief Retrieve the definition of this protocol, if any. ObjCProtocolDecl *getDefinition() { - return Data? Data->Definition : 0; + return hasDefinition()? Data.getPointer()->Definition : 0; } /// \brief Retrieve the definition of this protocol, if any. const ObjCProtocolDecl *getDefinition() const { - return Data? Data->Definition : 0; + return hasDefinition()? Data.getPointer()->Definition : 0; } /// \brief Determine whether this particular declaration is also the @@ -1303,7 +1501,8 @@ public: return getFirstDeclaration(); } - virtual void collectPropertiesToImplement(PropertyMap &PM) const; + virtual void collectPropertiesToImplement(PropertyMap &PM, + PropertyDeclOrder &PO) const; static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCProtocol; } @@ -1360,6 +1559,7 @@ class ObjCCategoryDecl : public ObjCContainerDecl { CategoryNameLoc(CategoryNameLoc), IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) { } + public: static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC, @@ -1403,8 +1603,13 @@ public: ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; } + /// \brief Retrieve the pointer to the next stored category (or extension), + /// which may be hidden. + ObjCCategoryDecl *getNextClassCategoryRaw() const { + return NextClassCategory; + } + bool IsClassExtension() const { return getIdentifier() == 0; } - const ObjCCategoryDecl *getNextClassExtension() const; typedef specific_decl_iterator ivar_iterator; ivar_iterator ivar_begin() const { @@ -1847,7 +2052,7 @@ public: PropertyAttributesAsWritten = PRVal; } - void makeitReadWriteAttribute(void) { + void makeitReadWriteAttribute() { PropertyAttributes &= ~OBJC_PR_readonly; PropertyAttributes |= OBJC_PR_readwrite; } @@ -2039,5 +2244,33 @@ public: friend class ASTDeclReader; }; +template +void +ObjCInterfaceDecl::filtered_category_iterator:: +findAcceptableCategory() { + while (Current && !Filter(Current)) + Current = Current->getNextClassCategoryRaw(); +} + +template +inline ObjCInterfaceDecl::filtered_category_iterator & +ObjCInterfaceDecl::filtered_category_iterator::operator++() { + Current = Current->getNextClassCategoryRaw(); + findAcceptableCategory(); + return *this; +} + +inline bool ObjCInterfaceDecl::isVisibleCategory(ObjCCategoryDecl *Cat) { + return !Cat->isHidden(); +} + +inline bool ObjCInterfaceDecl::isVisibleExtension(ObjCCategoryDecl *Cat) { + return Cat->IsClassExtension() && !Cat->isHidden(); +} + +inline bool ObjCInterfaceDecl::isKnownExtension(ObjCCategoryDecl *Cat) { + return Cat->IsClassExtension(); +} + } // end namespace clang #endif diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h new file mode 100644 index 0000000..ca92040 --- /dev/null +++ b/include/clang/AST/DeclOpenMP.h @@ -0,0 +1,83 @@ +//===--- OpenMP.h - Classes for representing OpenMP directives ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file defines OpenMP nodes. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_OPENMP_H +#define LLVM_CLANG_AST_OPENMP_H + +#include "clang/AST/DeclBase.h" +#include "llvm/ADT/ArrayRef.h" + +namespace clang { + +class DeclRefExpr; + +/// \brief This represents '#pragma omp threadprivate ...' directive. +/// For example, in the following, both 'a' and 'A::b' are threadprivate: +/// +/// \code +/// int a; +/// #pragma omp threadprivate(a) +/// struct A { +/// static int b; +/// #pragma omp threadprivate(b) +/// }; +/// \endcode +/// +class OMPThreadPrivateDecl : public Decl { + friend class ASTDeclReader; + unsigned NumVars; + + virtual void anchor(); + + OMPThreadPrivateDecl(Kind DK, DeclContext *DC, SourceLocation L) : + Decl(DK, DC, L), NumVars(0) { } + + ArrayRef getVars() const { + return ArrayRef( + reinterpret_cast(this + 1), + NumVars); + } + + llvm::MutableArrayRef getVars() { + return llvm::MutableArrayRef( + reinterpret_cast(this + 1), + NumVars); + } + + void setVars(ArrayRef VL); + +public: + static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + ArrayRef VL); + static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C, + unsigned ID, unsigned N); + + typedef llvm::MutableArrayRef::iterator varlist_iterator; + typedef ArrayRef::iterator varlist_const_iterator; + + unsigned varlist_size() const { return NumVars; } + bool varlist_empty() const { return NumVars == 0; } + varlist_iterator varlist_begin() { return getVars().begin(); } + varlist_iterator varlist_end() { return getVars().end(); } + varlist_const_iterator varlist_begin() const { return getVars().begin(); } + varlist_const_iterator varlist_end() const { return getVars().end(); } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == OMPThreadPrivate; } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 8620116..425a617 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -84,6 +84,13 @@ public: unsigned size() const { return NumParams; } + llvm::ArrayRef asArray() { + return llvm::ArrayRef(begin(), size()); + } + llvm::ArrayRef asArray() const { + return llvm::ArrayRef(begin(), size()); + } + NamedDecl* getParam(unsigned Idx) { assert(Idx < size() && "Template parameter index out-of-range"); return begin()[Idx]; @@ -193,6 +200,11 @@ public: /// \brief Retrieve the template argument at a given index. const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); } + /// \brief Produce this as an array ref. + llvm::ArrayRef asArray() const { + return llvm::ArrayRef(data(), size()); + } + /// \brief Retrieve the number of template arguments in this /// template argument list. unsigned size() const { return NumArguments; } @@ -324,6 +336,23 @@ public: return getTemplateSpecializationKind() == TSK_ExplicitSpecialization; } + /// \brief True if this declaration is an explicit specialization, + /// explicit instantiation declaration, or explicit instantiation + /// definition. + bool isExplicitInstantiationOrSpecialization() const { + switch (getTemplateSpecializationKind()) { + case TSK_ExplicitSpecialization: + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + return true; + + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + return false; + } + llvm_unreachable("bad template specialization kind"); + } + /// \brief Set the template specialization kind. void setTemplateSpecializationKind(TemplateSpecializationKind TSK) { assert(TSK != TSK_Undeclared && @@ -390,6 +419,10 @@ public: return (TemplateSpecializationKind)(MemberAndTSK.getInt() + 1); } + bool isExplicitSpecialization() const { + return getTemplateSpecializationKind() == TSK_ExplicitSpecialization; + } + /// \brief Set the template specialization kind. void setTemplateSpecializationKind(TemplateSpecializationKind TSK) { assert(TSK != TSK_Undeclared && @@ -425,18 +458,19 @@ public: /// }; /// \endcode class DependentFunctionTemplateSpecializationInfo { + struct CA { + /// The number of potential template candidates. + unsigned NumTemplates; + + /// The number of template arguments. + unsigned NumArgs; + }; + union { // Force sizeof to be a multiple of sizeof(void*) so that the // trailing data is aligned. void *Aligner; - - struct { - /// The number of potential template candidates. - unsigned NumTemplates; - - /// The number of template arguments. - unsigned NumArgs; - } d; + struct CA d; }; /// The locations of the left and right angle brackets. @@ -552,7 +586,7 @@ protected: }; template - SpecIterator + static SpecIterator makeSpecIterator(llvm::FoldingSetVector &Specs, bool isEnd) { return SpecIterator(isEnd ? Specs.end() : Specs.begin()); } @@ -576,14 +610,14 @@ protected: /// \brief Pointer to the common data shared by all declarations of this /// template. - CommonBase *Common; + mutable CommonBase *Common; /// \brief Retrieves the "common" pointer shared by all (re-)declarations of /// the same template. Calling this routine may implicitly allocate memory /// for the common pointer. - CommonBase *getCommonPtr(); + CommonBase *getCommonPtr() const; - virtual CommonBase *newCommon(ASTContext &C) = 0; + virtual CommonBase *newCommon(ASTContext &C) const = 0; // Construct a template decl with name, parameters, and templated element. RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, @@ -618,7 +652,7 @@ public: /// template<> template /// struct X::Inner { /* ... */ }; /// \endcode - bool isMemberSpecialization() { + bool isMemberSpecialization() const { return getCommonPtr()->InstantiatedFromMember.getInt(); } @@ -665,7 +699,7 @@ public: /// template /// void X::f(T, U); /// \endcode - RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() { + RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() const { return getCommonPtr()->InstantiatedFromMember.getPointer(); } @@ -729,9 +763,9 @@ protected: TemplateParameterList *Params, NamedDecl *Decl) : RedeclarableTemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { } - CommonBase *newCommon(ASTContext &C); + CommonBase *newCommon(ASTContext &C) const; - Common *getCommonPtr() { + Common *getCommonPtr() const { return static_cast(RedeclarableTemplateDecl::getCommonPtr()); } @@ -740,7 +774,7 @@ protected: /// \brief Retrieve the set of function template specializations of this /// function template. llvm::FoldingSetVector & - getSpecializations() { + getSpecializations() const { return getCommonPtr()->Specializations; } @@ -798,11 +832,11 @@ public: typedef SpecIterator spec_iterator; - spec_iterator spec_begin() { + spec_iterator spec_begin() const { return makeSpecIterator(getSpecializations(), false); } - spec_iterator spec_end() { + spec_iterator spec_end() const { return makeSpecIterator(getSpecializations(), true); } @@ -1205,7 +1239,7 @@ public: unsigned P, IdentifierInfo *Id, TemplateParameterList *Params, - llvm::ArrayRef Expansions); + ArrayRef Expansions); static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -1399,7 +1433,7 @@ public: static ClassTemplateSpecializationDecl * CreateDeserialized(ASTContext &C, unsigned ID); - virtual void getNameForDiagnostic(std::string &S, + virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const; @@ -1433,6 +1467,23 @@ public: return getSpecializationKind() == TSK_ExplicitSpecialization; } + /// \brief True if this declaration is an explicit specialization, + /// explicit instantiation declaration, or explicit instantiation + /// definition. + bool isExplicitInstantiationOrSpecialization() const { + switch (getTemplateSpecializationKind()) { + case TSK_ExplicitSpecialization: + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + return true; + + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + return false; + } + llvm_unreachable("bad template specialization kind"); + } + void setSpecializationKind(TemplateSpecializationKind TSK) { SpecializationKind = TSK; } @@ -1464,8 +1515,7 @@ public: = SpecializedTemplate.dyn_cast()) return PartialSpec->PartialSpecialization; - return const_cast( - SpecializedTemplate.get()); + return SpecializedTemplate.get(); } /// \brief Retrieve the class template or class template partial @@ -1477,8 +1527,7 @@ public: = SpecializedTemplate.dyn_cast()) return PartialSpec->PartialSpecialization; - return const_cast( - SpecializedTemplate.get()); + return SpecializedTemplate.get(); } /// \brief Retrieve the set of template arguments that should be used @@ -1780,10 +1829,11 @@ protected: }; /// \brief Load any lazily-loaded specializations from the external source. - void LoadLazySpecializations(); + void LoadLazySpecializations() const; /// \brief Retrieve the set of specializations of this class template. - llvm::FoldingSetVector &getSpecializations(); + llvm::FoldingSetVector & + getSpecializations() const; /// \brief Retrieve the set of partial specializations of this class /// template. @@ -1798,9 +1848,9 @@ protected: : RedeclarableTemplateDecl(ClassTemplate, 0, SourceLocation(), DeclarationName(), 0, 0) { } - CommonBase *newCommon(ASTContext &C); + CommonBase *newCommon(ASTContext &C) const; - Common *getCommonPtr() { + Common *getCommonPtr() const { return static_cast(RedeclarableTemplateDecl::getCommonPtr()); } @@ -1925,11 +1975,11 @@ public: typedef SpecIterator spec_iterator; - spec_iterator spec_begin() { + spec_iterator spec_begin() const { return makeSpecIterator(getSpecializations(), false); } - spec_iterator spec_end() { + spec_iterator spec_end() const { return makeSpecIterator(getSpecializations(), true); } @@ -2063,7 +2113,7 @@ protected: TemplateParameterList *Params, NamedDecl *Decl) : RedeclarableTemplateDecl(TypeAliasTemplate, DC, L, Name, Params, Decl) { } - CommonBase *newCommon(ASTContext &C); + CommonBase *newCommon(ASTContext &C) const; Common *getCommonPtr() { return static_cast(RedeclarableTemplateDecl::getCommonPtr()); diff --git a/include/clang/AST/DeclVisitor.h b/include/clang/AST/DeclVisitor.h index 62654b8..4eaae35 100644 --- a/include/clang/AST/DeclVisitor.h +++ b/include/clang/AST/DeclVisitor.h @@ -14,21 +14,28 @@ #define LLVM_CLANG_AST_DECLVISITOR_H #include "clang/AST/Decl.h" -#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" namespace clang { +namespace declvisitor { -#define DISPATCH(NAME, CLASS) \ - return static_cast(this)-> Visit##NAME(static_cast(D)) +template struct make_ptr { typedef T *type; }; +template struct make_const_ptr { typedef const T *type; }; /// \brief A simple visitor class that helps create declaration visitors. -template -class DeclVisitor { +template