diff options
author | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
commit | c72c57c9e9b69944e3e009cd5e209634839581d3 (patch) | |
tree | 4fc2f184c499d106f29a386c452b49e5197bf63d /include/clang | |
parent | 5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff) | |
download | FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz |
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'include/clang')
264 files changed, 10579 insertions, 4857 deletions
diff --git a/include/clang/ARCMigrate/ARCMT.h b/include/clang/ARCMigrate/ARCMT.h index cce8661..c167d3c 100644 --- a/include/clang/ARCMigrate/ARCMT.h +++ b/include/clang/ARCMigrate/ARCMT.h @@ -11,8 +11,8 @@ #define LLVM_CLANG_ARCMIGRATE_ARCMT_H #include "clang/ARCMigrate/FileRemapper.h" -#include "clang/Frontend/CompilerInvocation.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Frontend/CompilerInvocation.h" namespace clang { class ASTContext; diff --git a/include/clang/ARCMigrate/ARCMTActions.h b/include/clang/ARCMigrate/ARCMTActions.h index e075252..2daaf73 100644 --- a/include/clang/ARCMigrate/ARCMTActions.h +++ b/include/clang/ARCMigrate/ARCMTActions.h @@ -10,8 +10,8 @@ #ifndef LLVM_CLANG_ARCMIGRATE_ARCMT_ACTION_H #define LLVM_CLANG_ARCMIGRATE_ARCMT_ACTION_H -#include "clang/Frontend/FrontendAction.h" #include "clang/ARCMigrate/FileRemapper.h" +#include "clang/Frontend/FrontendAction.h" #include "llvm/ADT/OwningPtr.h" namespace clang { diff --git a/include/clang/ARCMigrate/FileRemapper.h b/include/clang/ARCMigrate/FileRemapper.h index fe7cfad..94c9e8f 100644 --- a/include/clang/ARCMigrate/FileRemapper.h +++ b/include/clang/ARCMigrate/FileRemapper.h @@ -11,9 +11,9 @@ #define LLVM_CLANG_ARCMIGRATE_FILEREMAPPER_H #include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" namespace llvm { 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> { ASTContext &this_() { return *this; } - mutable std::vector<Type*> Types; + mutable SmallVector<Type *, 0> Types; mutable llvm::FoldingSet<ExtQuals> ExtQualNodes; mutable llvm::FoldingSet<ComplexType> ComplexTypes; mutable llvm::FoldingSet<PointerType> PointerTypes; @@ -233,6 +219,8 @@ class ASTContext : public RefCountedBase<ASTContext> { 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<ASTContext> { /// \brief Mapping from each declaration context to its corresponding lambda /// mangling context. llvm::DenseMap<const DeclContext *, LambdaMangleContext> LambdaMangleContexts; - + + llvm::DenseMap<const DeclContext *, unsigned> UnnamedMangleContexts; + llvm::DenseMap<const TagDecl *, unsigned> UnnamedMangleNumbers; + /// \brief Mapping that stores parameterIndex values for ParmVarDecls when /// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex. typedef llvm::DenseMap<const VarDecl *, unsigned> ParameterIndexTable; @@ -393,6 +384,58 @@ public: OwningPtr<ExternalASTSource> ExternalSource; ASTMutationListener *Listener; + /// \brief Contains parents of a node. + typedef llvm::SmallVector<ast_type_traits::DynTypedNode, 1> ParentVector; + + /// \brief Maps from a node to its parents. + typedef llvm::DenseMap<const void *, ParentVector> 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 <typename NodeT> + 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<Type*>& getTypes() const { return Types; } + const SmallVectorImpl<Type *>& 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<QualType> 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<unsigned> NumExpansions); + Optional<unsigned> NumExpansions); QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl = 0) const; @@ -1094,6 +1145,14 @@ public: /// defined in <stddef.h> 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 /// <stddef.h>. 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<Type*>::iterator type_iterator; - typedef std::vector<Type*>::const_iterator const_type_iterator; + typedef SmallVectorImpl<Type *>::iterator type_iterator; + typedef SmallVectorImpl<Type *>::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<ParentMapASTVisitor> { + 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<ParentMapASTVisitor> 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 <typename T> + 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<ast_type_traits::DynTypedNode, 16> ParentStack; + + friend class RecursiveASTVisitor<ParentMapASTVisitor>; + }; + + llvm::OwningPtr<ParentMap> 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/ASTMatchers/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h index bda53ea..4688b12 100644 --- a/include/clang/ASTMatchers/ASTTypeTraits.h +++ b/include/clang/AST/ASTTypeTraits.h @@ -1,4 +1,4 @@ -//===--- ASTMatchersTypeTraits.h --------------------------------*- C++ -*-===// +//===--- ASTTypeTraits.h ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,11 +12,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H -#define LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H +#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 { @@ -87,8 +88,9 @@ private: /// 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<Decl*, QualType, TypeLoc, NestedNameSpecifierLoc> - Storage; + llvm::AlignedCharArrayUnion<Decl *, Stmt *, NestedNameSpecifier, + NestedNameSpecifierLoc, QualType, Type, + TypeLoc> Storage; }; // FIXME: Pull out abstraction for the following. @@ -206,4 +208,4 @@ inline const void *DynTypedNode::getMemoizationData() const { } // end namespace ast_type_traits } // end namespace clang -#endif // LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H +#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<DeclAccessPair> 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 <algorithm> -#include <memory> #include <cstring> +#include <memory> #ifdef _MSC_VER namespace std { @@ -50,6 +51,7 @@ namespace std { #endif namespace clang { + class ASTContext; template<typename T> 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 <cassert> #include <cstring> -#include <algorithm> 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<attr::Kind>(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<Attr*, 2> AttrVec; -typedef SmallVector<const Attr*, 2> ConstAttrVec; - -/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only -/// providing attributes that are of a specifc type. -template <typename SpecificAttr, typename Container = AttrVec> -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<SpecificAttr>(*Current)) - ++Current; - } - - void AdvanceToNext(Iterator I) const { - while (Current != I && !isa<SpecificAttr>(*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<SpecificAttr>(*Current); - } - pointer operator->() const { - AdvanceToNext(); - return cast<SpecificAttr>(*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 <typename SpecificAttr, typename Container> -inline specific_attr_iterator<SpecificAttr, Container> - specific_attr_begin(const Container& container) { - return specific_attr_iterator<SpecificAttr, Container>(container.begin()); -} -template <typename SpecificAttr, typename Container> -inline specific_attr_iterator<SpecificAttr, Container> - specific_attr_end(const Container& container) { - return specific_attr_iterator<SpecificAttr, Container>(container.end()); -} - -template <typename SpecificAttr, typename Container> -inline bool hasSpecificAttr(const Container& container) { - return specific_attr_begin<SpecificAttr>(container) != - specific_attr_end<SpecificAttr>(container); -} -template <typename SpecificAttr, typename Container> -inline SpecificAttr *getSpecificAttr(const Container& container) { - specific_attr_iterator<SpecificAttr, Container> i = - specific_attr_begin<SpecificAttr>(container); - if (i != specific_attr_end<SpecificAttr>(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<AlignedAttr> 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 <iterator> + +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<Attr*, 2> AttrVec; +typedef SmallVector<const Attr*, 2> ConstAttrVec; + +/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only +/// providing attributes that are of a specifc type. +template <typename SpecificAttr, typename Container = AttrVec> +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<SpecificAttr>(*Current)) + ++Current; + } + + void AdvanceToNext(Iterator I) const { + while (Current != I && !isa<SpecificAttr>(*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<SpecificAttr>(*Current); + } + pointer operator->() const { + AdvanceToNext(); + return cast<SpecificAttr>(*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 <typename SpecificAttr, typename Container> +inline specific_attr_iterator<SpecificAttr, Container> + specific_attr_begin(const Container& container) { + return specific_attr_iterator<SpecificAttr, Container>(container.begin()); +} +template <typename SpecificAttr, typename Container> +inline specific_attr_iterator<SpecificAttr, Container> + specific_attr_end(const Container& container) { + return specific_attr_iterator<SpecificAttr, Container>(container.end()); +} + +template <typename SpecificAttr, typename Container> +inline bool hasSpecificAttr(const Container& container) { + return specific_attr_begin<SpecificAttr>(container) != + specific_attr_end<SpecificAttr>(container); +} +template <typename SpecificAttr, typename Container> +inline SpecificAttr *getSpecificAttr(const Container& container) { + specific_attr_iterator<SpecificAttr, Container> i = + specific_attr_begin<SpecificAttr>(container); + if (i != specific_attr_end<SpecificAttr>(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 <cassert> #include <list> #include <map> -#include <cassert> 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<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc. /// to return smart pointer (proxies?). template<typename T> -struct simplify_type<const ::clang::CanQual<T> > { +struct simplify_type< ::clang::CanQual<T> > { typedef const T *SimpleType; - static SimpleType getSimplifiedValue(const ::clang::CanQual<T> &Val) { + static SimpleType getSimplifiedValue(::clang::CanQual<T> Val) { return Val.getTypePtr(); } }; -template<typename T> -struct simplify_type< ::clang::CanQual<T> > -: public simplify_type<const ::clang::CanQual<T> > {}; // Teach SmallPtrSet that CanQual<T> is "basically a pointer". template<typename T> @@ -514,55 +511,13 @@ struct CanProxyAdaptor<MemberPointerType> LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass) }; -template<> -struct CanProxyAdaptor<ArrayType> : public CanProxyBase<ArrayType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, - getSizeModifier) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) -}; - -template<> -struct CanProxyAdaptor<ConstantArrayType> - : public CanProxyBase<ConstantArrayType> { - 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<IncompleteArrayType> - : public CanProxyBase<IncompleteArrayType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, - getSizeModifier) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) -}; - -template<> -struct CanProxyAdaptor<VariableArrayType> - : public CanProxyBase<VariableArrayType> { - 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<DependentSizedArrayType> - : public CanProxyBase<DependentSizedArrayType> { - 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<ArrayType>; +template<> struct CanProxyAdaptor<ConstantArrayType>; +template<> struct CanProxyAdaptor<IncompleteArrayType>; +template<> struct CanProxyAdaptor<VariableArrayType>; +template<> struct CanProxyAdaptor<DependentSizedArrayType>; template<> struct CanProxyAdaptor<DependentSizedExtVectorType> @@ -746,6 +701,9 @@ CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) { template<typename T> template<typename U> CanProxy<U> CanQual<T>::getAs() const { + ArrayType_cannot_be_used_with_getAs<U> at; + (void)at; + if (Stored.isNull()) return CanProxy<U>(); @@ -758,6 +716,9 @@ CanProxy<U> CanQual<T>::getAs() const { template<typename T> template<typename U> CanProxy<U> CanQual<T>::castAs() const { + ArrayType_cannot_be_used_with_getAs<U> at; + (void)at; + assert(!Stored.isNull() && isa<U>(Stored.getTypePtr())); return CanQual<U>::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<Argument> Args; + ArrayRef<Argument> Args; public: InlineCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, RenderKind RK, - llvm::ArrayRef<Argument> Args) : + ArrayRef<Argument> 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<InlineContentComment *> Content; + ArrayRef<InlineContentComment *> Content; public: - ParagraphComment(llvm::ArrayRef<InlineContentComment *> Content) : + ParagraphComment(ArrayRef<InlineContentComment *> Content) : BlockContentComment(ParagraphCommentKind, SourceLocation(), SourceLocation()), @@ -565,7 +590,7 @@ public: protected: /// Word-like arguments. - llvm::ArrayRef<Argument> Args; + ArrayRef<Argument> 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<Argument> A) { + void setArgs(ArrayRef<Argument> 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<CommandMarkerKind>( + 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<unsigned> Position; + ArrayRef<unsigned> 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<VerbatimBlockLineComment *> Lines; + ArrayRef<VerbatimBlockLineComment *> 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<VerbatimBlockLineComment *> L) { + void setLines(ArrayRef<VerbatimBlockLineComment *> 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<BlockContentComment *> Blocks; + ArrayRef<BlockContentComment *> Blocks; DeclInfo *ThisDeclInfo; public: - FullComment(llvm::ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) : + FullComment(ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) : Comment(FullCommentKind, SourceLocation(), SourceLocation()), Blocks(Blocks), ThisDeclInfo(D) { if (Blocks.empty()) @@ -1062,7 +1101,7 @@ public: return ThisDeclInfo; } - llvm::ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; } + ArrayRef<BlockContentComment *> 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> { string Name = name; string EndCommandName = ""; @@ -12,6 +16,7 @@ class Command<string name> { bit IsParamCommand = 0; bit IsTParamCommand = 0; bit IsDeprecatedCommand = 0; + bit IsHeaderfileCommand = 0; bit IsEmptyParagraphAllowed = 0; @@ -19,6 +24,9 @@ class Command<string name> { bit IsVerbatimBlockEndCommand = 0; bit IsVerbatimLineCommand = 0; bit IsDeclarationCommand = 0; + bit IsFunctionDeclarationCommand = 0; + bit IsRecordLikeDetailCommand = 0; + bit IsRecordLikeDeclarationCommand = 0; } class InlineCommand<string name> : Command<name> { @@ -29,6 +37,10 @@ class BlockCommand<string name> : Command<name> { let IsBlockCommand = 1; } +class RecordLikeDetailCommand<string name> : BlockCommand<name> { + let IsRecordLikeDetailCommand = 1; +} + class VerbatimBlockCommand<string name> : Command<name> { let EndCommandName = name; let IsVerbatimBlockCommand = 1; @@ -54,6 +66,22 @@ class DeclarationVerbatimLineCommand<string name> : let IsDeclarationCommand = 1; } +class FunctionDeclarationVerbatimLineCommand<string name> : + VerbatimLineCommand<name> { + let IsDeclarationCommand = 1; + let IsFunctionDeclarationCommand = 1; +} + +class RecordLikeDeclarationVerbatimLineCommand<string name> : + VerbatimLineCommand<name> { + 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, int codePoint> { + 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<BlockCommandComment::Argument> 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<const ParmVarDecl *> 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<Visibility> getExplicitVisibility() const; + Optional<Visibility> + 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<WeakAttr>() || hasAttr<WeakRefAttr>() || 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<PartialDiagnosticAt> &Notes) const; + APValue *evaluateValue(SmallVectorImpl<PartialDiagnosticAt> &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<NamedDecl*> DeclsInPrototypeScope; + ArrayRef<NamedDecl *> 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<ParmVarDecl *> NewParamInfo); + void setParams(ASTContext &C, ArrayRef<ParmVarDecl *> 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<ParmVarDecl *> NewParamInfo) { + void setParams(ArrayRef<ParmVarDecl *> NewParamInfo) { setParams(getASTContext(), NewParamInfo); } - const llvm::ArrayRef<NamedDecl*> &getDeclsInPrototypeScope() const { + const ArrayRef<NamedDecl *> &getDeclsInPrototypeScope() const { return DeclsInPrototypeScope; } - void setDeclsInPrototypeScope(llvm::ArrayRef<NamedDecl *> NewDecls); + void setDeclsInPrototypeScope(ArrayRef<NamedDecl *> 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<FunctionType>()->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<MemberSpecializationInfo*>(); + } /// \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<TypedefNameDecl*>(); @@ -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<ParmVarDecl *> NewParamInfo); + void setParams(ArrayRef<ParmVarDecl *> 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<decl_type>::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<decl_type>(PrevDecl->getMostRecentDecl())); First = PrevDecl->getFirstDeclaration(); assert(First->RedeclLink.NextIsLatest() && "Expected first"); + decl_type *MostRecent = First->RedeclLink.getNext(); + RedeclLink = PreviousDeclLink(cast<decl_type>(MostRecent)); } else { // Make this first. First = static_cast<decl_type*>(this); @@ -3310,8 +3281,8 @@ void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *PrevDecl) { // First one will point to this one as latest. First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this)); - if (NamedDecl *ND = dyn_cast<NamedDecl>(static_cast<decl_type*>(this))) - ND->ClearLinkageCache(); + assert(!isa<NamedDecl>(static_cast<decl_type*>(this)) || + cast<NamedDecl>(static_cast<decl_type*>(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<NamedDecl**,NamedDecl**> { -public: - DeclContextLookupResult(NamedDecl **I, NamedDecl **E) - : std::pair<NamedDecl**,NamedDecl**>(I, E) {} - DeclContextLookupResult() - : std::pair<NamedDecl**,NamedDecl**>() {} +typedef llvm::MutableArrayRef<NamedDecl*> DeclContextLookupResult; - using std::pair<NamedDecl**,NamedDecl**>::operator=; -}; - -class DeclContextLookupConstResult - : public std::pair<NamedDecl*const*, NamedDecl*const*> { -public: - DeclContextLookupConstResult(std::pair<NamedDecl**,NamedDecl**> R) - : std::pair<NamedDecl*const*, NamedDecl*const*>(R) {} - DeclContextLookupConstResult(NamedDecl * const *I, NamedDecl * const *E) - : std::pair<NamedDecl*const*, NamedDecl*const*>(I, E) {} - DeclContextLookupConstResult() - : std::pair<NamedDecl*const*, NamedDecl*const*>() {} - - using std::pair<NamedDecl*const*,NamedDecl*const*>::operator=; -}; +typedef ArrayRef<NamedDecl *> 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<StoredDeclsMap*, 1, bool> LookupPtr; protected: @@ -970,10 +973,11 @@ protected: static std::pair<Decl *, Decl *> BuildDeclChain(ArrayRef<Decl*> 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<DeclContext *> &Contexts); + void collectAllContexts(SmallVectorImpl<DeclContext *> &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<NamedDecl *> &Results); + SmallVectorImpl<NamedDecl *> &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<const ::clang::AnyFunctionDecl> { - typedef ::clang::NamedDecl* SimpleType; - static SimpleType getSimplifiedValue(const ::clang::AnyFunctionDecl &Val) { - return Val; - } - }; - template<> struct simplify_type< ::clang::AnyFunctionDecl> - : public simplify_type<const ::clang::AnyFunctionDecl> {}; - // 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<conversion_iterator, conversion_iterator> + 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<MemberSpecializationInfo *>(); + } /// \brief Specify that this record is an instantiation of the /// member class RD. @@ -1256,6 +1290,10 @@ public: return dyn_cast<FunctionDecl>(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<FunctionType>()->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 <algorithm> @@ -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 <class T> friend class A<T>::B; + unsigned NumTPLists : 31; + + // The tail-allocated friend type template parameter lists (if any). + TemplateParameterList* const *getTPLists() const { + return reinterpret_cast<TemplateParameterList* const *>(this + 1); + } + TemplateParameterList **getTPLists() { + return reinterpret_cast<TemplateParameterList**>(this + 1); + } friend class CXXRecordDecl::friend_iterator; friend class CXXRecordDecl; FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend, - SourceLocation FriendL) + SourceLocation FriendL, + ArrayRef<TemplateParameterList*> 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<TemplateParameterList*> FriendTypeTPLists + = ArrayRef<TemplateParameterList*>()); + 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<TypeSourceInfo*>(); } + 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<const ObjCMethodDecl *> &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<IdentifierInfo*, ObjCPropertyDecl*> PropertyMap; - + + typedef llvm::SmallVector<ObjCPropertyDecl*, 8> 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<DefinitionData *, 1, bool> 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<ObjCInterfaceDecl> 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<bool (*Filter)(ObjCCategoryDecl *)> + 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<isVisibleCategory> + 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<isKnownCategory> 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<isVisibleExtension> + 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<isKnownExtension> + 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<ArcWeakrefUnavailableAttr>()) - 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<ObjCRequiresPropertyDefsAttr>()) - 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<DefinitionData *, 1, bool> 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<ObjCIvarDecl> 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<bool (*Filter)(ObjCCategoryDecl *)> +void +ObjCInterfaceDecl::filtered_category_iterator<Filter>:: +findAcceptableCategory() { + while (Current && !Filter(Current)) + Current = Current->getNextClassCategoryRaw(); +} + +template<bool (*Filter)(ObjCCategoryDecl *)> +inline ObjCInterfaceDecl::filtered_category_iterator<Filter> & +ObjCInterfaceDecl::filtered_category_iterator<Filter>::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<const DeclRefExpr *> getVars() const { + return ArrayRef<const DeclRefExpr *>( + reinterpret_cast<const DeclRefExpr * const *>(this + 1), + NumVars); + } + + llvm::MutableArrayRef<DeclRefExpr *> getVars() { + return llvm::MutableArrayRef<DeclRefExpr *>( + reinterpret_cast<DeclRefExpr **>(this + 1), + NumVars); + } + + void setVars(ArrayRef<DeclRefExpr *> VL); + +public: + static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + ArrayRef<DeclRefExpr *> VL); + static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C, + unsigned ID, unsigned N); + + typedef llvm::MutableArrayRef<DeclRefExpr *>::iterator varlist_iterator; + typedef ArrayRef<const DeclRefExpr *>::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<NamedDecl*> asArray() { + return llvm::ArrayRef<NamedDecl*>(begin(), size()); + } + llvm::ArrayRef<const NamedDecl*> asArray() const { + return llvm::ArrayRef<const NamedDecl*>(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<TemplateArgument> asArray() const { + return llvm::ArrayRef<TemplateArgument>(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 <typename EntryType> - SpecIterator<EntryType> + static SpecIterator<EntryType> makeSpecIterator(llvm::FoldingSetVector<EntryType> &Specs, bool isEnd) { return SpecIterator<EntryType>(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<typename T> /// struct X<int>::Inner { /* ... */ }; /// \endcode - bool isMemberSpecialization() { + bool isMemberSpecialization() const { return getCommonPtr()->InstantiatedFromMember.getInt(); } @@ -665,7 +699,7 @@ public: /// template<typename U> /// void X<T>::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<Common *>(RedeclarableTemplateDecl::getCommonPtr()); } @@ -740,7 +774,7 @@ protected: /// \brief Retrieve the set of function template specializations of this /// function template. llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> & - getSpecializations() { + getSpecializations() const { return getCommonPtr()->Specializations; } @@ -798,11 +832,11 @@ public: typedef SpecIterator<FunctionTemplateSpecializationInfo> 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<TemplateParameterList*> Expansions); + ArrayRef<TemplateParameterList *> 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<SpecializedPartialSpecialization*>()) return PartialSpec->PartialSpecialization; - return const_cast<ClassTemplateDecl*>( - SpecializedTemplate.get<ClassTemplateDecl*>()); + return SpecializedTemplate.get<ClassTemplateDecl*>(); } /// \brief Retrieve the class template or class template partial @@ -1477,8 +1527,7 @@ public: = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) return PartialSpec->PartialSpecialization; - return const_cast<ClassTemplateDecl*>( - SpecializedTemplate.get<ClassTemplateDecl*>()); + return SpecializedTemplate.get<ClassTemplateDecl*>(); } /// \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<ClassTemplateSpecializationDecl> &getSpecializations(); + llvm::FoldingSetVector<ClassTemplateSpecializationDecl> & + 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<Common *>(RedeclarableTemplateDecl::getCommonPtr()); } @@ -1925,11 +1975,11 @@ public: typedef SpecIterator<ClassTemplateSpecializationDecl> 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<Common *>(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<ImplClass*>(this)-> Visit##NAME(static_cast<CLASS*>(D)) +template <typename T> struct make_ptr { typedef T *type; }; +template <typename T> struct make_const_ptr { typedef const T *type; }; /// \brief A simple visitor class that helps create declaration visitors. -template<typename ImplClass, typename RetTy=void> -class DeclVisitor { +template<template <typename> class Ptr, typename ImplClass, typename RetTy=void> +class Base { public: - RetTy Visit(Decl *D) { + +#define PTR(CLASS) typename Ptr<CLASS>::type +#define DISPATCH(NAME, CLASS) \ + return static_cast<ImplClass*>(this)->Visit##NAME(static_cast<PTR(CLASS)>(D)) + + RetTy Visit(PTR(Decl) D) { switch (D->getKind()) { #define DECL(DERIVED, BASE) \ case Decl::DERIVED: DISPATCH(DERIVED##Decl, DERIVED##Decl); @@ -41,13 +48,31 @@ public: // If the implementation chooses not to implement a certain visit // method, fall back to the parent. #define DECL(DERIVED, BASE) \ - RetTy Visit##DERIVED##Decl(DERIVED##Decl *D) { DISPATCH(BASE, BASE); } + RetTy Visit##DERIVED##Decl(PTR(DERIVED##Decl) D) { DISPATCH(BASE, BASE); } #include "clang/AST/DeclNodes.inc" - RetTy VisitDecl(Decl *D) { return RetTy(); } -}; + RetTy VisitDecl(PTR(Decl) D) { return RetTy(); } +#undef PTR #undef DISPATCH +}; + +} // end namespace declvisitor + +/// \brief A simple visitor class that helps create declaration visitors. +/// +/// This class does not preserve constness of Decl pointers (see also +/// ConstDeclVisitor). +template<typename ImplClass, typename RetTy=void> +class DeclVisitor + : public declvisitor::Base<declvisitor::make_ptr, ImplClass, RetTy> {}; + +/// \brief A simple visitor class that helps create declaration visitors. +/// +/// This class preserves constness of Decl pointers (see also DeclVisitor). +template<typename ImplClass, typename RetTy=void> +class ConstDeclVisitor + : public declvisitor::Base<declvisitor::make_const_ptr, ImplClass, RetTy> {}; } // end namespace clang diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index d991c73..f28882b 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -14,8 +14,6 @@ #define LLVM_CLANG_AST_DECLARATIONNAME_H #include "clang/Basic/IdentifierTable.h" -#include "clang/AST/Type.h" -#include "clang/AST/CanonicalType.h" #include "clang/Basic/PartialDiagnostic.h" #include "llvm/Support/Compiler.h" @@ -24,14 +22,20 @@ namespace llvm { } namespace clang { - class CXXSpecialName; - class CXXOperatorIdName; + class ASTContext; class CXXLiteralOperatorIdName; + class CXXOperatorIdName; + class CXXSpecialName; class DeclarationNameExtra; class IdentifierInfo; class MultiKeywordSelector; - class UsingDirectiveDecl; + class QualType; + class Type; class TypeSourceInfo; + class UsingDirectiveDecl; + + template <typename> class CanQual; + typedef CanQual<Type> CanQualType; /// DeclarationName - The name of a declaration. In the common case, /// this just stores an IdentifierInfo pointer to a normal @@ -349,23 +353,15 @@ public: /// getCXXConstructorName - Returns the name of a C++ constructor /// for the given Type. - DeclarationName getCXXConstructorName(CanQualType Ty) { - return getCXXSpecialName(DeclarationName::CXXConstructorName, - Ty.getUnqualifiedType()); - } + DeclarationName getCXXConstructorName(CanQualType Ty); /// getCXXDestructorName - Returns the name of a C++ destructor /// for the given Type. - DeclarationName getCXXDestructorName(CanQualType Ty) { - return getCXXSpecialName(DeclarationName::CXXDestructorName, - Ty.getUnqualifiedType()); - } + DeclarationName getCXXDestructorName(CanQualType Ty); /// getCXXConversionFunctionName - Returns the name of a C++ /// conversion function for the given Type. - DeclarationName getCXXConversionFunctionName(CanQualType Ty) { - return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty); - } + DeclarationName getCXXConversionFunctionName(CanQualType Ty); /// getCXXSpecialName - Returns a declaration name for special kind /// of C++ name, e.g., for a constructor, destructor, or conversion @@ -386,32 +382,35 @@ public: /// for a declaration name. Needs a DeclarationName in order /// to be interpreted correctly. struct DeclarationNameLoc { + // The source location for identifier stored elsewhere. + // struct {} Identifier; + + // Type info for constructors, destructors and conversion functions. + // Locations (if any) for the tilde (destructor) or operator keyword + // (conversion) are stored elsewhere. + struct NT { + TypeSourceInfo* TInfo; + }; + + // The location (if any) of the operator keyword is stored elsewhere. + struct CXXOpName { + unsigned BeginOpNameLoc; + unsigned EndOpNameLoc; + }; + + // The location (if any) of the operator keyword is stored elsewhere. + struct CXXLitOpName { + unsigned OpNameLoc; + }; + + // struct {} CXXUsingDirective; + // struct {} ObjCZeroArgSelector; + // struct {} ObjCOneArgSelector; + // struct {} ObjCMultiArgSelector; union { - // The source location for identifier stored elsewhere. - // struct {} Identifier; - - // Type info for constructors, destructors and conversion functions. - // Locations (if any) for the tilde (destructor) or operator keyword - // (conversion) are stored elsewhere. - struct { - TypeSourceInfo* TInfo; - } NamedType; - - // The location (if any) of the operator keyword is stored elsewhere. - struct { - unsigned BeginOpNameLoc; - unsigned EndOpNameLoc; - } CXXOperatorName; - - // The location (if any) of the operator keyword is stored elsewhere. - struct { - unsigned OpNameLoc; - } CXXLiteralOperatorName; - - // struct {} CXXUsingDirective; - // struct {} ObjCZeroArgSelector; - // struct {} ObjCOneArgSelector; - // struct {} ObjCMultiArgSelector; + struct NT NamedType; + struct CXXOpName CXXOperatorName; + struct CXXLitOpName CXXLiteralOperatorName; }; DeclarationNameLoc(DeclarationName Name); @@ -525,9 +524,7 @@ public: SourceLocation getEndLoc() const; /// getSourceRange - The range of the declaration name. SourceRange getSourceRange() const LLVM_READONLY { - SourceLocation BeginLoc = getBeginLoc(); - SourceLocation EndLoc = getEndLoc(); - return SourceRange(BeginLoc, EndLoc.isValid() ? EndLoc : BeginLoc); + return SourceRange(getLocStart(), getLocEnd()); } SourceLocation getLocStart() const LLVM_READONLY { return getBeginLoc(); diff --git a/include/clang/AST/DependentDiagnostic.h b/include/clang/AST/DependentDiagnostic.h index 948dcb4..004b45d 100644 --- a/include/clang/AST/DependentDiagnostic.h +++ b/include/clang/AST/DependentDiagnostic.h @@ -18,11 +18,11 @@ #ifndef LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H #define LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H -#include "clang/Basic/PartialDiagnostic.h" -#include "clang/Basic/SourceLocation.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclContextInternals.h" #include "clang/AST/Type.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" namespace clang { @@ -108,16 +108,14 @@ private: PartialDiagnostic Diag; - union { - struct { - unsigned Loc; - unsigned Access : 2; - unsigned IsMember : 1; - NamedDecl *TargetDecl; - CXXRecordDecl *NamingClass; - void *BaseObjectType; - } AccessData; - }; + struct { + unsigned Loc; + unsigned Access : 2; + unsigned IsMember : 1; + NamedDecl *TargetDecl; + CXXRecordDecl *NamingClass; + void *BaseObjectType; + } AccessData; }; /// diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h index d5e9c8c..eb186c2 100644 --- a/include/clang/AST/EvaluatedExprVisitor.h +++ b/include/clang/AST/EvaluatedExprVisitor.h @@ -15,10 +15,10 @@ #ifndef LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H #define LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H -#include "clang/AST/StmtVisitor.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/StmtVisitor.h" namespace clang { @@ -49,6 +49,9 @@ public: } void VisitChooseExpr(ChooseExpr *E) { + // Don't visit either child expression if the condition is dependent. + if (E->getCond()->isValueDependent()) + return; // Only the selected subexpression matters; the other one is not evaluated. return this->Visit(E->getChosenSubExpr(Context)); } @@ -58,17 +61,17 @@ public: // expressions. return this->Visit(E->getInit()); } - + void VisitCXXTypeidExpr(CXXTypeidExpr *E) { - // typeid(expression) is potentially evaluated when the argument is - // a glvalue of polymorphic type. (C++ 5.2.8p2-3) - if (!E->isTypeOperand() && E->Classify(Context).isGLValue()) - if (const RecordType *Record - = E->getExprOperand()->getType()->template getAs<RecordType>()) - if (cast<CXXRecordDecl>(Record->getDecl())->isPolymorphic()) - return this->Visit(E->getExprOperand()); + if (E->isPotentiallyEvaluated()) + return this->Visit(E->getExprOperand()); } - + + void VisitCallExpr(CallExpr *CE) { + if (!CE->isUnevaluatedBuiltinCall(Context)) + return static_cast<ImplClass*>(this)->VisitExpr(CE); + } + /// \brief The basis case walks all of the children of the statement or /// expression, assuming they are all potentially evaluated. void VisitStmt(Stmt *S) { diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index dc83654..36d70d8 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -15,38 +15,38 @@ #define LLVM_CLANG_AST_EXPR_H #include "clang/AST/APValue.h" +#include "clang/AST/ASTVector.h" #include "clang/AST/Decl.h" -#include "clang/AST/Stmt.h" -#include "clang/AST/Type.h" #include "clang/AST/DeclAccessPair.h" #include "clang/AST/OperationKinds.h" -#include "clang/AST/ASTVector.h" +#include "clang/AST/Stmt.h" #include "clang/AST/TemplateBase.h" -#include "clang/Basic/TargetInfo.h" +#include "clang/AST/Type.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/TypeTraits.h" -#include "llvm/ADT/APSInt.h" #include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" -#include <cctype> namespace clang { - class ASTContext; class APValue; - class CastExpr; - class Decl; - class IdentifierInfo; - class ParmVarDecl; - class NamedDecl; - class ValueDecl; + class ASTContext; class BlockDecl; class CXXBaseSpecifier; + class CXXMemberCallExpr; class CXXOperatorCallExpr; + class CastExpr; + class Decl; + class IdentifierInfo; class MaterializeTemporaryExpr; - class CXXMemberCallExpr; + class NamedDecl; class ObjCPropertyRefExpr; class OpaqueValueExpr; + class ParmVarDecl; + class TargetInfo; + class ValueDecl; /// \brief A simple array of base specifiers. typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath; @@ -60,18 +60,21 @@ struct SubobjectAdjustment { MemberPointerAdjustment } Kind; - union { - struct { - const CastExpr *BasePath; - const CXXRecordDecl *DerivedClass; - } DerivedToBase; - FieldDecl *Field; + struct DTB { + const CastExpr *BasePath; + const CXXRecordDecl *DerivedClass; + }; - struct { - const MemberPointerType *MPT; - Expr *RHS; - } Ptr; + struct P { + const MemberPointerType *MPT; + Expr *RHS; + }; + + union { + struct DTB DerivedToBase; + FieldDecl *Field; + struct P Ptr; }; SubobjectAdjustment(const CastExpr *BasePath, @@ -196,7 +199,7 @@ public: } /// \brief Whether this expression contains an unexpanded parameter - /// pack (for C++0x variadic templates). + /// pack (for C++11 variadic templates). /// /// Given the following function template: /// @@ -238,7 +241,7 @@ public: /// result of an r-value expression is a value detached from any /// specific storage. /// - /// C++0x divides the concept of "r-value" into pure r-values + /// C++11 divides the concept of "r-value" into pure r-values /// ("pr-values") and so-called expiring values ("x-values"), which /// identify specific objects that can be safely cannibalized for /// their resources. This is an unfortunate abuse of terminology on @@ -294,7 +297,7 @@ public: isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = 0) const; - /// \brief The return type of classify(). Represents the C++0x expression + /// \brief The return type of classify(). Represents the C++11 expression /// taxonomy. class Classification { public: @@ -357,10 +360,10 @@ public: } }; - /// \brief Classify - Classify this expression according to the C++0x + /// \brief Classify - Classify this expression according to the C++11 /// expression taxonomy. /// - /// C++0x defines ([basic.lval]) a new taxonomy of expressions to replace the + /// C++11 defines ([basic.lval]) a new taxonomy of expressions to replace the /// old lvalue vs rvalue. This function determines the type of expression this /// is. There are three expression types: /// - lvalues are classical lvalues as in C++03. @@ -374,7 +377,7 @@ public: } /// \brief ClassifyModifiable - Classify this expression according to the - /// C++0x expression taxonomy, and see if it is valid on the left side + /// C++11 expression taxonomy, and see if it is valid on the left side /// of an assignment. /// /// This function extends classify in that it also tests whether the @@ -490,7 +493,7 @@ public: /// constexpr. Return false if the function can never produce a constant /// expression, along with diagnostics describing why not. static bool isPotentialConstantExpr(const FunctionDecl *FD, - llvm::SmallVectorImpl< + SmallVectorImpl< PartialDiagnosticAt> &Diags); /// isConstantInitializer - Returns true if this expression can be emitted to @@ -510,7 +513,7 @@ public: /// foldable. If the expression is foldable, but not a constant expression, /// the notes will describes why it isn't a constant expression. If the /// expression *is* a constant expression, no notes will be produced. - llvm::SmallVectorImpl<PartialDiagnosticAt> *Diag; + SmallVectorImpl<PartialDiagnosticAt> *Diag; EvalStatus() : HasSideEffects(false), Diag(0) {} @@ -568,7 +571,11 @@ public: /// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded /// integer. This must be called on an expression that constant folds to an /// integer. - llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const; + llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, + SmallVectorImpl<PartialDiagnosticAt> *Diag=0) const; + + void EvaluateForOverflow(const ASTContext &Ctx, + SmallVectorImpl<PartialDiagnosticAt> *Diag) const; /// EvaluateAsLValue - Evaluate an expression to see if we can fold it to an /// lvalue with link time known address, with no side-effects. @@ -580,7 +587,7 @@ public: /// notes will be produced if the expression is not a constant expression. bool EvaluateAsInitializer(APValue &Result, const ASTContext &Ctx, const VarDecl *VD, - llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const; + SmallVectorImpl<PartialDiagnosticAt> &Notes) const; /// \brief Enumeration used to describe the kind of Null pointer constant /// returned from \c isNullPointerConstant(). @@ -598,8 +605,8 @@ public: /// \brief Expression is a Null pointer constant built from a literal zero. NPCK_ZeroLiteral, - /// \brief Expression is a C++0X nullptr. - NPCK_CXX0X_nullptr, + /// \brief Expression is a C++11 nullptr. + NPCK_CXX11_nullptr, /// \brief Expression is a GNU-style __null constant. NPCK_GNUNull @@ -728,7 +735,7 @@ public: return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx); } - static bool hasAnyTypeDependentArguments(llvm::ArrayRef<Expr *> Exprs); + static bool hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs); /// \brief For an expression of class type or pointer to class type, /// return the most derived class decl the expression is known to refer to. @@ -796,9 +803,11 @@ public: /// \brief Retrieve the location of this expression. SourceLocation getLocation() const { return Loc; } - SourceRange getSourceRange() const LLVM_READONLY { - if (SourceExpr) return SourceExpr->getSourceRange(); - return Loc; + SourceLocation getLocStart() const LLVM_READONLY { + return SourceExpr ? SourceExpr->getLocStart() : Loc; + } + SourceLocation getLocEnd() const LLVM_READONLY { + return SourceExpr ? SourceExpr->getLocEnd() : Loc; } SourceLocation getExprLoc() const LLVM_READONLY { if (SourceExpr) return SourceExpr->getExprLoc(); @@ -954,7 +963,6 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - SourceRange getSourceRange() const LLVM_READONLY; SourceLocation getLocStart() const LLVM_READONLY; SourceLocation getLocEnd() const LLVM_READONLY; @@ -1160,7 +1168,8 @@ public: static std::string ComputeName(IdentType IT, const Decl *CurrentDecl); - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } static bool classof(const Stmt *T) { return T->getStmtClass() == PredefinedExprClass; @@ -1211,8 +1220,8 @@ public: class APFloatStorage : private APNumericStorage { public: - llvm::APFloat getValue(bool IsIEEE) const { - return llvm::APFloat(getIntValue(), IsIEEE); + llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const { + return llvm::APFloat(Semantics, getIntValue()); } void setValue(ASTContext &C, const llvm::APFloat &Val) { setIntValue(C, Val.bitcastToAPInt()); @@ -1241,7 +1250,8 @@ public: /// \brief Returns a new empty integer literal. static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty); - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } /// \brief Retrieve the location of the literal. SourceLocation getLocation() const { return Loc; } @@ -1286,7 +1296,8 @@ public: return static_cast<CharacterKind>(CharacterLiteralBits.Kind); } - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } unsigned getValue() const { return Value; } @@ -1317,12 +1328,31 @@ public: static FloatingLiteral *Create(ASTContext &C, EmptyShell Empty); llvm::APFloat getValue() const { - return APFloatStorage::getValue(FloatingLiteralBits.IsIEEE); + return APFloatStorage::getValue(getSemantics()); } void setValue(ASTContext &C, const llvm::APFloat &Val) { + assert(&getSemantics() == &Val.getSemantics() && "Inconsistent semantics"); APFloatStorage::setValue(C, Val); } + /// Get a raw enumeration value representing the floating-point semantics of + /// this literal (32-bit IEEE, x87, ...), suitable for serialisation. + APFloatSemantics getRawSemantics() const { + return static_cast<APFloatSemantics>(FloatingLiteralBits.Semantics); + } + + /// Set the raw enumeration value representing the floating-point semantics of + /// this literal (32-bit IEEE, x87, ...), suitable for serialisation. + void setRawSemantics(APFloatSemantics Sem) { + FloatingLiteralBits.Semantics = Sem; + } + + /// Return the APFloat semantics this literal uses. + const llvm::fltSemantics &getSemantics() const; + + /// Set the APFloat semantics this literal uses. + void setSemantics(const llvm::fltSemantics &Sem); + bool isExact() const { return FloatingLiteralBits.IsExact; } void setExact(bool E) { FloatingLiteralBits.IsExact = E; } @@ -1334,7 +1364,8 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } static bool classof(const Stmt *T) { return T->getStmtClass() == FloatingLiteralClass; @@ -1365,7 +1396,9 @@ public: Expr *getSubExpr() { return cast<Expr>(Val); } void setSubExpr(Expr *E) { Val = E; } - SourceRange getSourceRange() const LLVM_READONLY { return Val->getSourceRange(); } + SourceLocation getLocStart() const LLVM_READONLY { return Val->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Val->getLocEnd(); } + static bool classof(const Stmt *T) { return T->getStmtClass() == ImaginaryLiteralClass; } @@ -1458,7 +1491,7 @@ public: getByteLength()); } - void outputString(raw_ostream &OS); + void outputString(raw_ostream &OS) const; uint32_t getCodeUnit(size_t i) const { assert(i < Length && "out of bounds access"); @@ -1491,7 +1524,7 @@ public: bool containsNonAsciiOrNull() const { StringRef Str = getString(); for (unsigned i = 0, e = Str.size(); i != e; ++i) - if (!isascii(Str[i]) || !Str[i]) + if (!isASCII(Str[i]) || !Str[i]) return true; return false; } @@ -1524,9 +1557,11 @@ public: tokloc_iterator tokloc_begin() const { return TokLocs; } tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]); + SourceLocation getLocStart() const LLVM_READONLY { return TokLocs[0]; } + SourceLocation getLocEnd() const LLVM_READONLY { + return TokLocs[NumConcatenated - 1]; } + static bool classof(const Stmt *T) { return T->getStmtClass() == StringLiteralClass; } @@ -1557,7 +1592,8 @@ public: Expr *getSubExpr() { return cast<Expr>(Val); } void setSubExpr(Expr *E) { Val = E; } - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(L, R); } + SourceLocation getLocStart() const LLVM_READONLY { return L; } + SourceLocation getLocEnd() const LLVM_READONLY { return R; } /// \brief Get the location of the left parentheses '('. SourceLocation getLParen() const { return L; } @@ -1669,11 +1705,11 @@ public: /// the given unary opcode. static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); - SourceRange getSourceRange() const LLVM_READONLY { - if (isPostfix()) - return SourceRange(Val->getLocStart(), Loc); - else - return SourceRange(Loc, Val->getLocEnd()); + SourceLocation getLocStart() const LLVM_READONLY { + return isPostfix() ? Val->getLocStart() : Loc; + } + SourceLocation getLocEnd() const LLVM_READONLY { + return isPostfix() ? Loc : Val->getLocEnd(); } SourceLocation getExprLoc() const LLVM_READONLY { return Loc; } @@ -1791,6 +1827,8 @@ public: /// contains the location of the period (if there is one) and the /// identifier. SourceRange getSourceRange() const LLVM_READONLY { return Range; } + SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } }; private: @@ -1870,9 +1908,8 @@ public: return NumExprs; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(OperatorLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == OffsetOfExprClass; @@ -1974,9 +2011,8 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(OpLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return OpLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == UnaryExprOrTypeTraitExprClass; @@ -2048,14 +2084,17 @@ public: return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS()); } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getLHS()->getLocStart(), RBracketLoc); + SourceLocation getLocStart() const LLVM_READONLY { + return getLHS()->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; } SourceLocation getRBracketLoc() const { return RBracketLoc; } void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } - SourceLocation getExprLoc() const LLVM_READONLY { return getBase()->getExprLoc(); } + SourceLocation getExprLoc() const LLVM_READONLY { + return getBase()->getExprLoc(); + } static bool classof(const Stmt *T) { return T->getStmtClass() == ArraySubscriptExprClass; @@ -2171,6 +2210,15 @@ public: return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs(); } + /// This method provides fast access to all the subexpressions of + /// a CallExpr without going through the slower virtual child_iterator + /// interface. This provides efficient reverse iteration of the + /// subexpressions. This is currently used for CFG construction. + ArrayRef<Stmt*> getRawSubExprs() { + return ArrayRef<Stmt*>(SubExprs, + getNumPreArgs() + PREARGS_START + getNumArgs()); + } + /// getNumCommas - Return the number of commas that must have been present in /// this function call. unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; } @@ -2179,6 +2227,10 @@ public: /// not, return 0. unsigned isBuiltinCall() const; + /// \brief Returns \c true if this is a call to a builtin which does not + /// evaluate side-effects within its arguments. + bool isUnevaluatedBuiltinCall(ASTContext &Ctx) const; + /// getCallReturnType - Get the return type of the call expr. This is not /// always the type of the expr itself, if the return type is a reference /// type. @@ -2187,7 +2239,6 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY; SourceLocation getLocStart() const LLVM_READONLY; SourceLocation getLocEnd() const LLVM_READONLY; @@ -2455,7 +2506,6 @@ public: SourceLocation getMemberLoc() const { return MemberLoc; } void setMemberLoc(SourceLocation L) { MemberLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY; SourceLocation getLocStart() const LLVM_READONLY; SourceLocation getLocEnd() const LLVM_READONLY; @@ -2534,13 +2584,19 @@ public: TInfoAndScope.setPointer(tinfo); } - SourceRange getSourceRange() const LLVM_READONLY { + SourceLocation getLocStart() const LLVM_READONLY { // FIXME: Init should never be null. if (!Init) - return SourceRange(); + return SourceLocation(); if (LParenLoc.isInvalid()) - return Init->getSourceRange(); - return SourceRange(LParenLoc, Init->getLocEnd()); + return Init->getLocStart(); + return LParenLoc; + } + SourceLocation getLocEnd() const LLVM_READONLY { + // FIXME: Init should never be null. + if (!Init) + return SourceLocation(); + return Init->getLocEnd(); } static bool classof(const Stmt *T) { @@ -2686,9 +2742,6 @@ public: static ImplicitCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize); - SourceRange getSourceRange() const LLVM_READONLY { - return getSubExpr()->getSourceRange(); - } SourceLocation getLocStart() const LLVM_READONLY { return getSubExpr()->getLocStart(); } @@ -2787,9 +2840,11 @@ public: SourceLocation getRParenLoc() const { return RPLoc; } void setRParenLoc(SourceLocation L) { RPLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(LPLoc, getSubExpr()->getSourceRange().getEnd()); + SourceLocation getLocStart() const LLVM_READONLY { return LPLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + return getSubExpr()->getLocEnd(); } + static bool classof(const Stmt *T) { return T->getStmtClass() == CStyleCastExprClass; } @@ -2845,7 +2900,7 @@ public: SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; assert(!isCompoundAssignmentOp() && - "Use ArithAssignBinaryOperator for compound assignments"); + "Use CompoundAssignOperator for compound assignments"); } /// \brief Construct an empty binary operator. @@ -2864,8 +2919,11 @@ public: Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } void setRHS(Expr *E) { SubExprs[RHS] = E; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getLHS()->getLocStart(), getRHS()->getLocEnd()); + SourceLocation getLocStart() const LLVM_READONLY { + return getLHS()->getLocStart(); + } + SourceLocation getLocEnd() const LLVM_READONLY { + return getRHS()->getLocEnd(); } /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it @@ -2902,6 +2960,33 @@ public: static bool isComparisonOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_NE; } bool isComparisonOp() const { return isComparisonOp(getOpcode()); } + static Opcode negateComparisonOp(Opcode Opc) { + switch (Opc) { + default: + llvm_unreachable("Not a comparsion operator."); + case BO_LT: return BO_GE; + case BO_GT: return BO_LE; + case BO_LE: return BO_GT; + case BO_GE: return BO_LT; + case BO_EQ: return BO_NE; + case BO_NE: return BO_EQ; + } + } + + static Opcode reverseComparisonOp(Opcode Opc) { + switch (Opc) { + default: + llvm_unreachable("Not a comparsion operator."); + case BO_LT: return BO_GT; + case BO_GT: return BO_LT; + case BO_LE: return BO_GE; + case BO_GE: return BO_LE; + case BO_EQ: + case BO_NE: + return Opc; + } + } + static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; } bool isLogicalOp() const { return isLogicalOp(getOpcode()); } @@ -3101,9 +3186,13 @@ public: Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd()); + SourceLocation getLocStart() const LLVM_READONLY { + return getCond()->getLocStart(); + } + SourceLocation getLocEnd() const LLVM_READONLY { + return getRHS()->getLocEnd(); } + static bool classof(const Stmt *T) { return T->getStmtClass() == ConditionalOperatorClass; } @@ -3182,9 +3271,13 @@ public: return cast<Expr>(SubExprs[RHS]); } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getCommon()->getLocStart(), getFalseExpr()->getLocEnd()); + SourceLocation getLocStart() const LLVM_READONLY { + return getCommon()->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { + return getFalseExpr()->getLocEnd(); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == BinaryConditionalOperatorClass; } @@ -3233,9 +3326,8 @@ public: SourceLocation getLabelLoc() const { return LabelLoc; } void setLabelLoc(SourceLocation L) { LabelLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(AmpAmpLoc, LabelLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return AmpAmpLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return LabelLoc; } LabelDecl *getLabel() const { return Label; } void setLabel(LabelDecl *L) { Label = L; } @@ -3274,9 +3366,8 @@ public: const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); } void setSubStmt(CompoundStmt *S) { SubStmt = S; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(LParenLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } SourceLocation getLParenLoc() const { return LParenLoc; } void setLParenLoc(SourceLocation L) { LParenLoc = L; } @@ -3322,9 +3413,9 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(BuiltinLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + static bool classof(const Stmt *T) { return T->getStmtClass() == ShuffleVectorExprClass; } @@ -3416,9 +3507,9 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(BuiltinLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + static bool classof(const Stmt *T) { return T->getStmtClass() == ChooseExprClass; } @@ -3452,9 +3543,9 @@ public: SourceLocation getTokenLocation() const { return TokenLoc; } void setTokenLocation(SourceLocation L) { TokenLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(TokenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return TokenLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return TokenLoc; } + static bool classof(const Stmt *T) { return T->getStmtClass() == GNUNullExprClass; } @@ -3497,9 +3588,9 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(BuiltinLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + static bool classof(const Stmt *T) { return T->getStmtClass() == VAArgExprClass; } @@ -3580,8 +3671,8 @@ public: ArrayRef<Expr*> initExprs, SourceLocation rbraceloc); /// \brief Build an empty initializer list. - explicit InitListExpr(ASTContext &C, EmptyShell Empty) - : Expr(InitListExprClass, Empty), InitExprs(C) { } + explicit InitListExpr(EmptyShell Empty) + : Expr(InitListExprClass, Empty) { } unsigned getNumInits() const { return InitExprs.size(); } @@ -3698,7 +3789,8 @@ public: InitListExprBits.InitializesStdInitializerList = ISIL; } - SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == InitListExprClass; @@ -3923,17 +4015,17 @@ public: return ArrayOrRange.Index; } - SourceLocation getStartLocation() const { + SourceLocation getLocStart() const LLVM_READONLY { if (Kind == FieldDesignator) return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc(); else return getLBracketLoc(); } - SourceLocation getEndLocation() const { + SourceLocation getLocEnd() const LLVM_READONLY { return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc(); } SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getStartLocation(), getEndLocation()); + return SourceRange(getLocStart(), getLocEnd()); } }; @@ -3984,9 +4076,9 @@ public: void setDesignators(ASTContext &C, const Designator *Desigs, unsigned NumDesigs); - Expr *getArrayIndex(const Designator& D); - Expr *getArrayRangeStart(const Designator& D); - Expr *getArrayRangeEnd(const Designator& D); + Expr *getArrayIndex(const Designator &D) const; + Expr *getArrayRangeStart(const Designator &D) const; + Expr *getArrayRangeEnd(const Designator &D) const; /// @brief Retrieve the location of the '=' that precedes the /// initializer value itself, if present. @@ -4034,7 +4126,8 @@ public: SourceRange getDesignatorsSourceRange() const; - SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == DesignatedInitExprClass; @@ -4069,9 +4162,8 @@ public: return T->getStmtClass() == ImplicitValueInitExprClass; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(); - } + SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } // Iterators child_range children() { return child_range(); } @@ -4107,9 +4199,9 @@ public: SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(LParenLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + static bool classof(const Stmt *T) { return T->getStmtClass() == ParenListExprClass; } @@ -4221,9 +4313,9 @@ public: const Expr *getResultExpr() const { return getAssocExpr(getResultIndex()); } Expr *getResultExpr() { return getAssocExpr(getResultIndex()); } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(GenericLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return GenericLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + static bool classof(const Stmt *T) { return T->getStmtClass() == GenericSelectionExprClass; } @@ -4286,9 +4378,10 @@ public: /// aggregate Constant of ConstantInt(s). void getEncodedElementAccess(SmallVectorImpl<unsigned> &Elts) const; - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getBase()->getLocStart(), AccessorLoc); + SourceLocation getLocStart() const LLVM_READONLY { + return getBase()->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return AccessorLoc; } /// isArrow - Return true if the base expression is a pointer to vector, /// return false if the base expression is a vector. @@ -4328,9 +4421,8 @@ public: const Stmt *getBody() const; Stmt *getBody(); - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getCaretLocation(), getBody()->getLocEnd()); - } + SourceLocation getLocStart() const LLVM_READONLY { return getCaretLocation(); } + SourceLocation getLocEnd() const LLVM_READONLY { return getBody()->getLocEnd(); } /// getFunctionType - Return the underlying function type for this block. const FunctionProtoType *getFunctionType() const; @@ -4377,9 +4469,8 @@ public: /// getRParenLoc - Return the location of final right parenthesis. SourceLocation getRParenLoc() const { return RParenLoc; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(BuiltinLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == AsTypeExprClass; @@ -4508,8 +4599,12 @@ public: SourceLocation getExprLoc() const LLVM_READONLY { return getSyntacticForm()->getExprLoc(); } - SourceRange getSourceRange() const LLVM_READONLY { - return getSyntacticForm()->getSourceRange(); + + SourceLocation getLocStart() const LLVM_READONLY { + return getSyntacticForm()->getLocStart(); + } + SourceLocation getLocEnd() const LLVM_READONLY { + return getSyntacticForm()->getLocEnd(); } child_range children() { @@ -4603,9 +4698,9 @@ public: SourceLocation getBuiltinLoc() const { return BuiltinLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(BuiltinLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + static bool classof(const Stmt *T) { return T->getStmtClass() == AtomicExprClass; } diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 9c759db..04f6fb6 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -16,8 +16,8 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" -#include "clang/AST/UnresolvedSet.h" #include "clang/AST/TemplateBase.h" +#include "clang/AST/UnresolvedSet.h" #include "clang/Basic/ExpressionTraits.h" #include "clang/Basic/Lambda.h" #include "clang/Basic/TypeTraits.h" @@ -30,6 +30,7 @@ class CXXDestructorDecl; class CXXMethodDecl; class CXXTemporary; class TemplateArgumentListInfo; +class UuidAttr; //===--------------------------------------------------------------------===// // C++ Expressions. @@ -83,6 +84,8 @@ public: /// bracket. SourceLocation getOperatorLoc() const { return getRParenLoc(); } + SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } SourceRange getSourceRange() const { return Range; } static bool classof(const Stmt *T) { @@ -176,14 +179,16 @@ class CXXNamedCastExpr : public ExplicitCastExpr { private: SourceLocation Loc; // the location of the casting op SourceLocation RParenLoc; // the location of the right parenthesis + SourceRange AngleBrackets; // range for '<' '>' protected: CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK, CastKind kind, Expr *op, unsigned PathSize, TypeSourceInfo *writtenTy, SourceLocation l, - SourceLocation RParenLoc) + SourceLocation RParenLoc, + SourceRange AngleBrackets) : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, writtenTy), Loc(l), - RParenLoc(RParenLoc) {} + RParenLoc(RParenLoc), AngleBrackets(AngleBrackets) {} explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize) : ExplicitCastExpr(SC, Shell, PathSize) { } @@ -200,9 +205,10 @@ public: /// \brief Retrieve the location of the closing parenthesis. SourceLocation getRParenLoc() const { return RParenLoc; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(Loc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceRange getAngleBrackets() const LLVM_READONLY { return AngleBrackets; } + static bool classof(const Stmt *T) { switch (T->getStmtClass()) { case CXXStaticCastExprClass: @@ -224,9 +230,10 @@ public: class CXXStaticCastExpr : public CXXNamedCastExpr { CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, - SourceLocation l, SourceLocation RParenLoc) + SourceLocation l, SourceLocation RParenLoc, + SourceRange AngleBrackets) : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize, - writtenTy, l, RParenLoc) {} + writtenTy, l, RParenLoc, AngleBrackets) {} explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize) : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { } @@ -236,7 +243,8 @@ public: ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *Path, TypeSourceInfo *Written, SourceLocation L, - SourceLocation RParenLoc); + SourceLocation RParenLoc, + SourceRange AngleBrackets); static CXXStaticCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize); @@ -254,9 +262,10 @@ public: class CXXDynamicCastExpr : public CXXNamedCastExpr { CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, - SourceLocation l, SourceLocation RParenLoc) + SourceLocation l, SourceLocation RParenLoc, + SourceRange AngleBrackets) : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize, - writtenTy, l, RParenLoc) {} + writtenTy, l, RParenLoc, AngleBrackets) {} explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize) : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { } @@ -266,7 +275,8 @@ public: ExprValueKind VK, CastKind Kind, Expr *Op, const CXXCastPath *Path, TypeSourceInfo *Written, SourceLocation L, - SourceLocation RParenLoc); + SourceLocation RParenLoc, + SourceRange AngleBrackets); static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context, unsigned pathSize); @@ -288,9 +298,10 @@ class CXXReinterpretCastExpr : public CXXNamedCastExpr { CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l, - SourceLocation RParenLoc) + SourceLocation RParenLoc, + SourceRange AngleBrackets) : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op, - pathSize, writtenTy, l, RParenLoc) {} + pathSize, writtenTy, l, RParenLoc, AngleBrackets) {} CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize) : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { } @@ -300,7 +311,8 @@ public: ExprValueKind VK, CastKind Kind, Expr *Op, const CXXCastPath *Path, TypeSourceInfo *WrittenTy, SourceLocation L, - SourceLocation RParenLoc); + SourceLocation RParenLoc, + SourceRange AngleBrackets); static CXXReinterpretCastExpr *CreateEmpty(ASTContext &Context, unsigned pathSize); @@ -317,9 +329,9 @@ public: class CXXConstCastExpr : public CXXNamedCastExpr { CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op, TypeSourceInfo *writtenTy, SourceLocation l, - SourceLocation RParenLoc) + SourceLocation RParenLoc, SourceRange AngleBrackets) : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op, - 0, writtenTy, l, RParenLoc) {} + 0, writtenTy, l, RParenLoc, AngleBrackets) {} explicit CXXConstCastExpr(EmptyShell Empty) : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { } @@ -328,7 +340,8 @@ public: static CXXConstCastExpr *Create(ASTContext &Context, QualType T, ExprValueKind VK, Expr *Op, TypeSourceInfo *WrittenTy, SourceLocation L, - SourceLocation RParenLoc); + SourceLocation RParenLoc, + SourceRange AngleBrackets); static CXXConstCastExpr *CreateEmpty(ASTContext &Context); static bool classof(const Stmt *T) { @@ -386,9 +399,6 @@ public: return getArg(0)->getLocStart(); } SourceLocation getLocEnd() const { return getRParenLoc(); } - SourceRange getSourceRange() const { - return SourceRange(getLocStart(), getLocEnd()); - } /// getUDSuffixLoc - Returns the location of a ud-suffix in the expression. @@ -424,7 +434,8 @@ public: bool getValue() const { return Value; } void setValue(bool V) { Value = V; } - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } @@ -449,7 +460,8 @@ public: explicit CXXNullPtrLiteralExpr(EmptyShell Empty) : Expr(CXXNullPtrLiteralExprClass, Empty) { } - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } @@ -531,6 +543,8 @@ public: Operand = E; } + SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } SourceRange getSourceRange() const LLVM_READONLY { return Range; } void setSourceRange(SourceRange R) { Range = R; } @@ -605,6 +619,8 @@ public: Operand = E; } + SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } SourceRange getSourceRange() const LLVM_READONLY { return Range; } void setSourceRange(SourceRange R) { Range = R; } @@ -653,7 +669,8 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } bool isImplicit() const { return Implicit; } void setImplicit(bool I) { Implicit = I; } @@ -702,10 +719,11 @@ public: /// this variable. bool isThrownVariableInScope() const { return IsThrownVariableInScope; } - SourceRange getSourceRange() const LLVM_READONLY { + SourceLocation getLocStart() const LLVM_READONLY { return ThrowLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { if (getSubExpr() == 0) - return SourceRange(ThrowLoc, ThrowLoc); - return SourceRange(ThrowLoc, getSubExpr()->getSourceRange().getEnd()); + return ThrowLoc; + return getSubExpr()->getLocEnd(); } static bool classof(const Stmt *T) { @@ -789,11 +807,12 @@ public: /// used. SourceLocation getUsedLocation() const { return Loc; } - SourceRange getSourceRange() const LLVM_READONLY { - // Default argument expressions have no representation in the - // source, so they have an empty source range. - return SourceRange(); - } + // Default argument expressions have no representation in the + // source, so they have an empty source range. + SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } + + SourceLocation getExprLoc() const LLVM_READONLY { return Loc; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDefaultArgExprClass; @@ -866,9 +885,10 @@ public: Expr *getSubExpr() { return cast<Expr>(SubExpr); } void setSubExpr(Expr *E) { SubExpr = E; } - SourceRange getSourceRange() const LLVM_READONLY { - return SubExpr->getSourceRange(); + SourceLocation getLocStart() const LLVM_READONLY { + return SubExpr->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd();} // Implement isa/cast/dyncast/etc. static bool classof(const Stmt *T) { @@ -1001,7 +1021,8 @@ public: Args[Arg] = ArgExpr; } - SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY; SourceRange getParenRange() const { return ParenRange; } void setParenRange(SourceRange Range) { ParenRange = Range; } @@ -1057,9 +1078,9 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(TyBeginLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return TyBeginLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXFunctionalCastExprClass; } @@ -1089,13 +1110,15 @@ public: ArrayRef<Expr *> Args, SourceRange parenRange, bool HadMultipleCandidates, - bool ZeroInitialization = false); + bool ListInitialization, + bool ZeroInitialization); explicit CXXTemporaryObjectExpr(EmptyShell Empty) : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { } TypeSourceInfo *getTypeSourceInfo() const { return Type; } - SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXTemporaryObjectExprClass; @@ -1111,7 +1134,7 @@ public: /// \code /// void low_pass_filter(std::vector<double> &values, double cutoff) { /// values.erase(std::remove_if(values.begin(), values.end(), -// [=](double value) { return value > cutoff; }); +/// [=](double value) { return value > cutoff; }); /// } /// \endcode /// @@ -1393,9 +1416,10 @@ public: return T->getStmtClass() == LambdaExprClass; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(IntroducerRange.getBegin(), ClosingBrace); + SourceLocation getLocStart() const LLVM_READONLY { + return IntroducerRange.getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return ClosingBrace; } child_range children() { return child_range(getStoredStmts(), getStoredStmts() + NumCaptures + 1); @@ -1434,7 +1458,8 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } - SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXScalarValueInitExprClass; @@ -1621,6 +1646,8 @@ public: SourceRange getSourceRange() const LLVM_READONLY { return Range; } + SourceLocation getLocStart() const LLVM_READONLY { return getStartLoc(); } + SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXNewExprClass; @@ -1688,9 +1715,8 @@ public: /// return an invalid type. QualType getDestroyedType() const; - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(Loc, Argument->getLocEnd()); - } + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY {return Argument->getLocEnd();} static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDeleteExprClass; @@ -1878,7 +1904,8 @@ public: DestroyedType = PseudoDestructorTypeStorage(Info); } - SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY {return Base->getLocStart();} + SourceLocation getLocEnd() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXPseudoDestructorExprClass; @@ -1925,7 +1952,8 @@ public: : Expr(UnaryTypeTraitExprClass, Empty), UTT(0), Value(false), QueriedType() { } - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc, RParen);} + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } UnaryTypeTrait getTrait() const { return static_cast<UnaryTypeTrait>(UTT); } @@ -1990,9 +2018,8 @@ public: : Expr(BinaryTypeTraitExprClass, Empty), BTT(0), Value(false), LhsType(), RhsType() { } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(Loc, RParen); - } + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } BinaryTypeTrait getTrait() const { return static_cast<BinaryTypeTrait>(BTT); @@ -2097,8 +2124,9 @@ public: return getTypeSourceInfos() + getNumArgs(); } - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc, RParenLoc); } - + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + static bool classof(const Stmt *T) { return T->getStmtClass() == TypeTraitExprClass; } @@ -2159,9 +2187,8 @@ public: virtual ~ArrayTypeTraitExpr() { } - virtual SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(Loc, RParen); - } + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } ArrayTypeTrait getTrait() const { return static_cast<ArrayTypeTrait>(ATT); } @@ -2221,9 +2248,8 @@ public: : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false), QueriedExpression() { } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(Loc, RParen); - } + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } ExpressionTrait getTrait() const { return static_cast<ExpressionTrait>(ET); } @@ -2411,7 +2437,7 @@ public: /// /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. - const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() { + const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { if (!hasExplicitTemplateArgs()) return 0; return &getExplicitTemplateArgs(); } @@ -2512,13 +2538,15 @@ public: /// that was looked in to find these results. CXXRecordDecl *getNamingClass() const { return NamingClass; } - SourceRange getSourceRange() const LLVM_READONLY { - SourceRange Range(getNameInfo().getSourceRange()); - if (getQualifierLoc()) - Range.setBegin(getQualifierLoc().getBeginLoc()); + SourceLocation getLocStart() const LLVM_READONLY { + if (NestedNameSpecifierLoc l = getQualifierLoc()) + return l.getBeginLoc(); + return getNameInfo().getLocStart(); + } + SourceLocation getLocEnd() const LLVM_READONLY { if (hasExplicitTemplateArgs()) - Range.setEnd(getRAngleLoc()); - return Range; + return getRAngleLoc(); + return getNameInfo().getLocEnd(); } child_range children() { return child_range(); } @@ -2647,7 +2675,7 @@ public: /// \brief Retrieves the optional explicit template arguments. /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. - const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() { + const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { if (!hasExplicitTemplateArgs()) return 0; return &getExplicitTemplateArgs(); } @@ -2666,11 +2694,13 @@ public: return getExplicitTemplateArgs().NumTemplateArgs; } - SourceRange getSourceRange() const LLVM_READONLY { - SourceRange Range(QualifierLoc.getBeginLoc(), getLocation()); + SourceLocation getLocStart() const LLVM_READONLY { + return QualifierLoc.getBeginLoc(); + } + SourceLocation getLocEnd() const LLVM_READONLY { if (hasExplicitTemplateArgs()) - Range.setEnd(getRAngleLoc()); - return Range; + return getRAngleLoc(); + return getLocation(); } static bool classof(const Stmt *T) { @@ -2740,9 +2770,10 @@ public: /// when modifying an existing AST to preserve its invariants. void setSubExpr(Expr *E) { SubExpr = E; } - SourceRange getSourceRange() const LLVM_READONLY { - return SubExpr->getSourceRange(); + SourceLocation getLocStart() const LLVM_READONLY { + return SubExpr->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd();} // Implement isa/cast/dyncast/etc. static bool classof(const Stmt *T) { @@ -2855,7 +2886,8 @@ public: *(arg_begin() + I) = E; } - SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXUnresolvedConstructExprClass; @@ -3061,7 +3093,7 @@ public: /// \brief Retrieves the optional explicit template arguments. /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. - const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() { + const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { if (!hasExplicitTemplateArgs()) return 0; return &getExplicitTemplateArgs(); } @@ -3089,20 +3121,18 @@ public: return getExplicitTemplateArgs().NumTemplateArgs; } - SourceRange getSourceRange() const LLVM_READONLY { - SourceRange Range; + SourceLocation getLocStart() const LLVM_READONLY { if (!isImplicitAccess()) - Range.setBegin(Base->getSourceRange().getBegin()); - else if (getQualifier()) - Range.setBegin(getQualifierLoc().getBeginLoc()); - else - Range.setBegin(MemberNameInfo.getBeginLoc()); + return Base->getLocStart(); + if (getQualifier()) + return getQualifierLoc().getBeginLoc(); + return MemberNameInfo.getBeginLoc(); + } + SourceLocation getLocEnd() const LLVM_READONLY { if (hasExplicitTemplateArgs()) - Range.setEnd(getRAngleLoc()); - else - Range.setEnd(MemberNameInfo.getEndLoc()); - return Range; + return getRAngleLoc(); + return MemberNameInfo.getEndLoc(); } static bool classof(const Stmt *T) { @@ -3226,16 +3256,17 @@ public: // expression refers to. SourceLocation getMemberLoc() const { return getNameLoc(); } - SourceRange getSourceRange() const LLVM_READONLY { - SourceRange Range = getMemberNameInfo().getSourceRange(); + SourceLocation getLocStart() const LLVM_READONLY { if (!isImplicitAccess()) - Range.setBegin(Base->getSourceRange().getBegin()); - else if (getQualifierLoc()) - Range.setBegin(getQualifierLoc().getBeginLoc()); - + return Base->getLocStart(); + if (NestedNameSpecifierLoc l = getQualifierLoc()) + return l.getBeginLoc(); + return getMemberNameInfo().getLocStart(); + } + SourceLocation getLocEnd() const LLVM_READONLY { if (hasExplicitTemplateArgs()) - Range.setEnd(getRAngleLoc()); - return Range; + return getRAngleLoc(); + return getMemberNameInfo().getLocEnd(); } static bool classof(const Stmt *T) { @@ -3277,6 +3308,8 @@ public: Expr *getOperand() const { return static_cast<Expr*>(Operand); } + SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } SourceRange getSourceRange() const LLVM_READONLY { return Range; } bool getValue() const { return Value; } @@ -3323,7 +3356,7 @@ class PackExpansionExpr : public Expr { public: PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc, - llvm::Optional<unsigned> NumExpansions) + Optional<unsigned> NumExpansions) : Expr(PackExpansionExprClass, T, Pattern->getValueKind(), Pattern->getObjectKind(), /*TypeDependent=*/true, /*ValueDependent=*/true, /*InstantiationDependent=*/true, @@ -3346,16 +3379,17 @@ public: /// \brief Determine the number of expansions that will be produced when /// this pack expansion is instantiated, if already known. - llvm::Optional<unsigned> getNumExpansions() const { + Optional<unsigned> getNumExpansions() const { if (NumExpansions) return NumExpansions - 1; - return llvm::Optional<unsigned>(); + return None; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(Pattern->getLocStart(), EllipsisLoc); + SourceLocation getLocStart() const LLVM_READONLY { + return Pattern->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return EllipsisLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == PackExpansionExprClass; @@ -3458,9 +3492,8 @@ public: return Length; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(OperatorLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == SizeOfPackExprClass; @@ -3500,7 +3533,8 @@ public: Param(param), Replacement(replacement), NameLoc(loc) {} SourceLocation getNameLoc() const { return NameLoc; } - SourceRange getSourceRange() const LLVM_READONLY { return NameLoc; } + SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return NameLoc; } Expr *getReplacement() const { return cast<Expr>(Replacement); } @@ -3561,7 +3595,8 @@ public: /// template arguments. TemplateArgument getArgumentPack() const; - SourceRange getSourceRange() const LLVM_READONLY { return NameLoc; } + SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return NameLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == SubstNonTypeTemplateParmPackExprClass; @@ -3606,7 +3641,7 @@ public: static FunctionParmPackExpr *Create(ASTContext &Context, QualType T, ParmVarDecl *ParamPack, SourceLocation NameLoc, - llvm::ArrayRef<Decl*> Params); + ArrayRef<Decl *> Params); static FunctionParmPackExpr *CreateEmpty(ASTContext &Context, unsigned NumParams); @@ -3628,7 +3663,8 @@ public: /// \brief Get an expansion of the parameter pack by index. ParmVarDecl *getExpansion(unsigned I) const { return begin()[I]; } - SourceRange getSourceRange() const LLVM_READONLY { return NameLoc; } + SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return NameLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == FunctionParmPackExprClass; @@ -3684,8 +3720,11 @@ public: return getValueKind() == VK_LValue; } - SourceRange getSourceRange() const LLVM_READONLY { - return Temporary->getSourceRange(); + SourceLocation getLocStart() const LLVM_READONLY { + return Temporary->getLocStart(); + } + SourceLocation getLocEnd() const LLVM_READONLY { + return Temporary->getLocEnd(); } static bool classof(const Stmt *T) { diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 27f5da0..dfd4527 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -44,9 +44,8 @@ public: SourceLocation getAtLoc() const { return AtLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(AtLoc, String->getLocEnd()); - } + SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return String->getLocEnd(); } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCStringLiteralClass; @@ -72,8 +71,9 @@ public: bool getValue() const { return Value; } void setValue(bool V) { Value = V; } - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } - + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } @@ -112,6 +112,8 @@ public: SourceLocation getAtLoc() const { return Range.getBegin(); } + SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } SourceRange getSourceRange() const LLVM_READONLY { return Range; } @@ -133,7 +135,7 @@ class ObjCArrayLiteral : public Expr { SourceRange Range; ObjCMethodDecl *ArrayWithObjectsMethod; - ObjCArrayLiteral(llvm::ArrayRef<Expr *> Elements, + ObjCArrayLiteral(ArrayRef<Expr *> Elements, QualType T, ObjCMethodDecl * Method, SourceRange SR); @@ -142,12 +144,14 @@ class ObjCArrayLiteral : public Expr { public: static ObjCArrayLiteral *Create(ASTContext &C, - llvm::ArrayRef<Expr *> Elements, + ArrayRef<Expr *> Elements, QualType T, ObjCMethodDecl * Method, SourceRange SR); static ObjCArrayLiteral *CreateEmpty(ASTContext &C, unsigned NumElements); + SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } SourceRange getSourceRange() const LLVM_READONLY { return Range; } static bool classof(const Stmt *T) { @@ -202,12 +206,18 @@ struct ObjCDictionaryElement { /// \brief The number of elements this pack expansion will expand to, if /// this is a pack expansion and is known. - llvm::Optional<unsigned> NumExpansions; + Optional<unsigned> NumExpansions; /// \brief Determines whether this dictionary element is a pack expansion. bool isPackExpansion() const { return EllipsisLoc.isValid(); } }; +} // end namespace clang + +namespace llvm { +template <> struct isPodLike<clang::ObjCDictionaryElement> : llvm::true_type {}; +} +namespace clang { /// ObjCDictionaryLiteral - AST node to represent objective-c dictionary /// literals; as in: @{@"name" : NSUserName(), @"date" : [NSDate date] }; class ObjCDictionaryLiteral : public Expr { @@ -296,8 +306,7 @@ public: ObjCDictionaryElement getKeyValueElement(unsigned Index) const { assert((Index < NumElements) && "Arg access out of range!"); const KeyValuePair &KV = getKeyValues()[Index]; - ObjCDictionaryElement Result = { KV.Key, KV.Value, SourceLocation(), - llvm::Optional<unsigned>() }; + ObjCDictionaryElement Result = { KV.Key, KV.Value, SourceLocation(), None }; if (HasPackExpansions) { const ExpansionData &Expansion = getExpansionData()[Index]; Result.EllipsisLoc = Expansion.EllipsisLoc; @@ -310,6 +319,8 @@ public: ObjCMethodDecl *getDictWithObjectsMethod() const { return DictWithObjectsMethod; } + SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } SourceRange getSourceRange() const LLVM_READONLY { return Range; } static bool classof(const Stmt *T) { @@ -360,9 +371,8 @@ public: EncodedType = EncType; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(AtLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCEncodeExprClass; @@ -393,9 +403,8 @@ public: void setAtLoc(SourceLocation L) { AtLoc = L; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(AtLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } /// getNumArgs - Return the number of actual arguments to this call. unsigned getNumArgs() const { return SelName.getNumArgs(); } @@ -408,9 +417,13 @@ public: child_range children() { return child_range(); } }; -/// ObjCProtocolExpr used for protocol expression in Objective-C. This is used -/// as: @protocol(foo), as in: -/// obj conformsToProtocol:@protocol(foo)] +/// ObjCProtocolExpr used for protocol expression in Objective-C. +/// +/// This is used as: \@protocol(foo), as in: +/// \code +/// [obj conformsToProtocol:@protocol(foo)] +/// \endcode +/// /// The return type is "Protocol*". class ObjCProtocolExpr : public Expr { ObjCProtocolDecl *TheProtocol; @@ -433,9 +446,8 @@ public: void setAtLoc(SourceLocation L) { AtLoc = L; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(AtLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCProtocolExprClass; @@ -453,18 +465,23 @@ class ObjCIvarRefExpr : public Expr { ObjCIvarDecl *D; Stmt *Base; SourceLocation Loc; + /// OpLoc - This is the location of '.' or '->' + SourceLocation OpLoc; + bool IsArrow:1; // True if this is "X->F", false if this is "X.F". bool IsFreeIvar:1; // True if ivar reference has no base (self assumed). public: ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, - SourceLocation l, Expr *base, + SourceLocation l, SourceLocation oploc, + Expr *base, bool arrow = false, bool freeIvar = false) : Expr(ObjCIvarRefExprClass, t, VK_LValue, OK_Ordinary, /*TypeDependent=*/false, base->isValueDependent(), base->isInstantiationDependent(), base->containsUnexpandedParameterPack()), - D(d), Base(base), Loc(l), IsArrow(arrow), IsFreeIvar(freeIvar) {} + D(d), Base(base), Loc(l), OpLoc(oploc), + IsArrow(arrow), IsFreeIvar(freeIvar) {} explicit ObjCIvarRefExpr(EmptyShell Empty) : Expr(ObjCIvarRefExprClass, Empty) {} @@ -485,10 +502,13 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return isFreeIvar() ? SourceRange(Loc) - : SourceRange(getBase()->getLocStart(), Loc); + SourceLocation getLocStart() const LLVM_READONLY { + return isFreeIvar() ? Loc : getBase()->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + + SourceLocation getOpLoc() const { return OpLoc; } + void setOpLoc(SourceLocation L) { OpLoc = L; } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCIvarRefExprClass; @@ -697,11 +717,10 @@ public: bool isSuperReceiver() const { return Receiver.is<const Type*>(); } bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange((isObjectReceiver() ? getBase()->getLocStart() - : getReceiverLocation()), - IdLoc); + SourceLocation getLocStart() const LLVM_READONLY { + return isObjectReceiver() ? getBase()->getLocStart() :getReceiverLocation(); } + SourceLocation getLocEnd() const LLVM_READONLY { return IdLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCPropertyRefExprClass; @@ -796,10 +815,12 @@ public: SourceLocation getRBracket() const { return RBracket; } void setRBracket(SourceLocation RB) { RBracket = RB; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(SubExprs[BASE]->getLocStart(), RBracket); + + SourceLocation getLocStart() const LLVM_READONLY { + return SubExprs[BASE]->getLocStart(); } - + SourceLocation getLocEnd() const LLVM_READONLY { return RBracket; } + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCSubscriptRefExprClass; } @@ -1335,9 +1356,8 @@ public: LBracLoc = R.getBegin(); RBracLoc = R.getEnd(); } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(LBracLoc, RBracLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return LBracLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RBracLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCMessageExprClass; @@ -1372,16 +1392,20 @@ class ObjCIsaExpr : public Expr { /// IsaMemberLoc - This is the location of the 'isa'. SourceLocation IsaMemberLoc; + + /// OpLoc - This is the location of '.' or '->' + SourceLocation OpLoc; /// IsArrow - True if this is "X->F", false if this is "X.F". bool IsArrow; public: - ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty) + ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, SourceLocation oploc, + QualType ty) : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary, /*TypeDependent=*/false, base->isValueDependent(), base->isInstantiationDependent(), /*ContainsUnexpandedParameterPack=*/false), - Base(base), IsaMemberLoc(l), IsArrow(isarrow) {} + Base(base), IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {} /// \brief Build an empty expression. explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) { } @@ -1396,10 +1420,19 @@ public: /// location of 'F'. SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; } void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; } + + SourceLocation getOpLoc() const { return OpLoc; } + void setOpLoc(SourceLocation L) { OpLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getBase()->getLocStart(), IsaMemberLoc); + SourceLocation getLocStart() const LLVM_READONLY { + return getBase()->getLocStart(); + } + + SourceLocation getBaseLocEnd() const LLVM_READONLY { + return getBase()->getLocEnd(); } + + SourceLocation getLocEnd() const LLVM_READONLY { return IsaMemberLoc; } SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; } @@ -1469,9 +1502,11 @@ public: child_range children() { return child_range(&Operand, &Operand+1); } // Source locations are determined by the subexpression. - SourceRange getSourceRange() const LLVM_READONLY { - return Operand->getSourceRange(); + SourceLocation getLocStart() const LLVM_READONLY { + return Operand->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Operand->getLocEnd();} + SourceLocation getExprLoc() const LLVM_READONLY { return getSubExpr()->getExprLoc(); } @@ -1520,8 +1555,9 @@ public: /// \brief The location of the bridge keyword. SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(LParenLoc, getSubExpr()->getLocEnd()); + SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + return getSubExpr()->getLocEnd(); } static bool classof(const Stmt *T) { diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index db2bddb..81fcf24 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -14,8 +14,8 @@ #ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H #define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H -#include "clang/AST/DeclBase.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/DeclBase.h" #include "llvm/ADT/DenseMap.h" namespace clang { @@ -24,7 +24,10 @@ class ASTConsumer; class CXXBaseSpecifier; class DeclarationName; class ExternalSemaSource; // layering violation required for downcasting +class FieldDecl; +class Module; class NamedDecl; +class RecordDecl; class Selector; class Stmt; class TagDecl; @@ -115,23 +118,28 @@ public: /// The default implementation of this method is a no-op. virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); - /// \brief Finds all declarations with the given name in the - /// given context. - /// - /// Generally the final step of this method is either to call - /// SetExternalVisibleDeclsForName or to recursively call lookup on - /// the DeclContext after calling SetExternalVisibleDecls. + /// \brief Update an out-of-date identifier. + virtual void updateOutOfDateIdentifier(IdentifierInfo &II) { } + + /// \brief Find all declarations with the given name in the given context, + /// and add them to the context by calling SetExternalVisibleDeclsForName + /// or SetNoExternalVisibleDeclsForName. + /// \return \c true if any declarations might have been found, \c false if + /// we definitely have no declarations with tbis name. /// - /// The default implementation of this method is a no-op. - virtual DeclContextLookupResult + /// The default implementation of this method is a no-op returning \c false. + virtual bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); /// \brief Ensures that the table of all visible declarations inside this /// context is up to date. /// - /// The default implementation of this functino is a no-op. + /// The default implementation of this function is a no-op. virtual void completeVisibleDeclsMap(const DeclContext *DC); + /// \brief Retrieve the module that corresponds to the given module ID. + virtual Module *getModule(unsigned ID) { return 0; } + /// \brief Finds all declarations lexically contained within the given /// DeclContext, after applying an optional filter predicate. /// diff --git a/include/clang/AST/LambdaMangleContext.h b/include/clang/AST/LambdaMangleContext.h index 3e2fbad..bbaee26 100644 --- a/include/clang/AST/LambdaMangleContext.h +++ b/include/clang/AST/LambdaMangleContext.h @@ -14,7 +14,9 @@ #ifndef LLVM_CLANG_LAMBDAMANGLECONTEXT_H #define LLVM_CLANG_LAMBDAMANGLECONTEXT_H +#include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" namespace clang { @@ -23,7 +25,7 @@ class FunctionProtoType; /// \brief Keeps track of the mangled names of lambda expressions within a /// particular context. -class LambdaMangleContext { +class LambdaMangleContext : public RefCountedBase<LambdaMangleContext> { llvm::DenseMap<const FunctionProtoType *, unsigned> ManglingNumbers; public: diff --git a/include/clang/AST/Makefile b/include/clang/AST/Makefile index 7fb33f2..ae84bcf 100644 --- a/include/clang/AST/Makefile +++ b/include/clang/AST/Makefile @@ -1,8 +1,12 @@ CLANG_LEVEL := ../../.. TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic -BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc \ +BUILT_SOURCES = Attrs.inc AttrImpl.inc AttrDump.inc \ + StmtNodes.inc DeclNodes.inc \ CommentNodes.inc CommentHTMLTags.inc \ - CommentHTMLTagsProperties.inc CommentCommandInfo.inc + CommentHTMLTagsProperties.inc \ + CommentHTMLNamedCharacterReferences.inc \ + CommentCommandInfo.inc \ + CommentCommandList.inc TABLEGEN_INC_FILES_COMMON = 1 @@ -20,6 +24,12 @@ $(ObjDir)/AttrImpl.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \ $(Verb) $(ClangTableGen) -gen-clang-attr-impl -o $(call SYSPATH, $@) \ -I $(PROJ_SRC_DIR)/../../ $< +$(ObjDir)/AttrDump.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \ + $(ObjDir)/.dir + $(Echo) "Building Clang attribute dumper with tblgen" + $(Verb) $(ClangTableGen) -gen-clang-attr-dump -o $(call SYSPATH, $@) \ + -I $(PROJ_SRC_DIR)/../../ $< + $(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(CLANG_TBLGEN) \ $(ObjDir)/.dir $(Echo) "Building Clang statement node tables with tblgen" @@ -45,8 +55,19 @@ $(ObjDir)/CommentHTMLTagsProperties.inc.tmp : $(PROJ_SRC_DIR)/CommentHTMLTags.td $(Echo) "Building Clang comment HTML tag properties with tblgen" $(Verb) $(ClangTableGen) -gen-clang-comment-html-tags-properties -o $(call SYSPATH, $@) $< +$(ObjDir)/CommentHTMLNamedCharacterReferences.inc.tmp : \ + $(PROJ_SRC_DIR)/CommentHTMLNamedCharacterReferences.td \ + $(CLANG_TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang named character reference translation function with tblgen" + $(Verb) $(ClangTableGen) -gen-clang-comment-html-named-character-references -o $(call SYSPATH, $@) $< + $(ObjDir)/CommentCommandInfo.inc.tmp : $(PROJ_SRC_DIR)/CommentCommands.td \ $(CLANG_TBLGEN) $(ObjDir)/.dir $(Echo) "Building Clang comment command info with tblgen" $(Verb) $(ClangTableGen) -gen-clang-comment-command-info -o $(call SYSPATH, $@) $< +$(ObjDir)/CommentCommandList.inc.tmp : $(PROJ_SRC_DIR)/CommentCommands.td \ + $(CLANG_TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang list of comment commands with tblgen" + $(Verb) $(ClangTableGen) -gen-clang-comment-command-list -o $(call SYSPATH, $@) $< + diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h index a0dffb9..94faa19 100644 --- a/include/clang/AST/Mangle.h +++ b/include/clang/AST/Mangle.h @@ -17,8 +17,8 @@ #include "clang/AST/Type.h" #include "clang/Basic/ABI.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/raw_ostream.h" namespace clang { diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h index f9fd1f9..0b21b03 100644 --- a/include/clang/AST/NSAPI.h +++ b/include/clang/AST/NSAPI.h @@ -52,7 +52,7 @@ public: Selector getNSStringSelector(NSStringMethodKind MK) const; /// \brief Return NSStringMethodKind if \param Sel is such a selector. - llvm::Optional<NSStringMethodKind> getNSStringMethodKind(Selector Sel) const; + Optional<NSStringMethodKind> getNSStringMethodKind(Selector Sel) const; /// \brief Returns true if the expression \param E is a reference of /// "NSUTF8StringEncoding" enum constant. @@ -84,7 +84,7 @@ public: Selector getNSArraySelector(NSArrayMethodKind MK) const; /// \brief Return NSArrayMethodKind if \p Sel is such a selector. - llvm::Optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel); + Optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel); /// \brief Enumerates the NSDictionary methods used to generate literals. enum NSDictionaryMethodKind { @@ -96,17 +96,17 @@ public: NSDict_dictionaryWithObjectsAndKeys, NSDict_initWithDictionary, NSDict_initWithObjectsAndKeys, + NSDict_initWithObjectsForKeys, NSDict_objectForKey, NSMutableDict_setObjectForKey }; - static const unsigned NumNSDictionaryMethods = 10; + static const unsigned NumNSDictionaryMethods = 11; /// \brief The Objective-C NSDictionary selectors. Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const; /// \brief Return NSDictionaryMethodKind if \p Sel is such a selector. - llvm::Optional<NSDictionaryMethodKind> - getNSDictionaryMethodKind(Selector Sel); + Optional<NSDictionaryMethodKind> getNSDictionaryMethodKind(Selector Sel); /// \brief Returns selector for "objectForKeyedSubscript:". Selector getObjectForKeyedSubscriptSelector() const { @@ -170,12 +170,12 @@ public: } /// \brief Return NSNumberLiteralMethodKind if \p Sel is such a selector. - llvm::Optional<NSNumberLiteralMethodKind> + Optional<NSNumberLiteralMethodKind> getNSNumberLiteralMethodKind(Selector Sel) const; /// \brief Determine the appropriate NSNumber factory method kind for a /// literal of the given type. - llvm::Optional<NSNumberLiteralMethodKind> + Optional<NSNumberLiteralMethodKind> getNSNumberFactoryMethodKind(QualType T) const; /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c. diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index bf9e1cb..58f3986 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -117,7 +117,7 @@ public: /// \brief Builds a nested name specifier that names a namespace. static NestedNameSpecifier *Create(const ASTContext &Context, NestedNameSpecifier *Prefix, - NamespaceDecl *NS); + const NamespaceDecl *NS); /// \brief Builds a nested name specifier that names a namespace alias. static NestedNameSpecifier *Create(const ASTContext &Context, diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index 18169fd..5e41d95 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -292,7 +292,10 @@ enum CastKind { // Convert a builtin function to a function pointer; only allowed in the // callee of a call expression. - CK_BuiltinFnToFnPtr + CK_BuiltinFnToFnPtr, + + // Convert a zero value for OpenCL event_t initialization. + CK_ZeroToOCLEvent }; static const CastKind CK_Invalid = static_cast<CastKind>(-1); diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index 7babc1b..e3c09e7 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -14,14 +14,15 @@ #ifndef LLVM_CLANG_AST_PRETTY_PRINTER_H #define LLVM_CLANG_AST_PRETTY_PRINTER_H -#include "clang/Basic/LangOptions.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" namespace clang { +class LangOptions; +class SourceManager; class Stmt; class TagDecl; -class LangOptions; class PrinterHelper { public: @@ -39,8 +40,7 @@ struct PrintingPolicy { SuppressUnwrittenScope(false), SuppressInitializers(false), ConstantArraySizeAsWritten(false), AnonymousTagLocations(true), SuppressStrongLifetime(false), Bool(LO.Bool), - TerseOutput(false), SuppressAttributes(false), - DumpSourceManager(0) { } + TerseOutput(false), PolishForDeclaration(false) { } /// \brief What language we're printing. LangOptions LangOpts; @@ -142,15 +142,10 @@ struct PrintingPolicy { /// only the requested declaration. unsigned TerseOutput : 1; - /// \brief When true, do not print attributes attached to the declaration. + /// \brief When true, do certain refinement needed for producing proper + /// declaration tag; such as, do not print attributes attached to the declaration. /// - unsigned SuppressAttributes : 1; - - /// \brief If we are "dumping" rather than "pretty-printing", this points to - /// a SourceManager which will be used to dump SourceLocations. Dumping - /// involves printing the internal details of the AST and pretty-printing - /// involves printing something similar to source code. - SourceManager *DumpSourceManager; + unsigned PolishForDeclaration : 1; }; } // end namespace clang diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index f96e067..0191964 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -18,6 +18,7 @@ #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" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -464,20 +465,15 @@ template<typename Derived> bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, bool &EnqueueChildren) { -// The cast for DISPATCH_WALK is needed for older versions of g++, but causes -// problems for MSVC. So we'll skip the cast entirely for MSVC. -#if defined(_MSC_VER) - #define GCC_CAST(CLASS) -#else - #define GCC_CAST(CLASS) (bool (RecursiveASTVisitor::*)(CLASS*)) -#endif - // Dispatch to the corresponding WalkUpFrom* function only if the derived // class didn't override Traverse* (and thus the traversal is trivial). #define DISPATCH_WALK(NAME, CLASS, VAR) \ - if (&RecursiveASTVisitor::Traverse##NAME == \ - GCC_CAST(CLASS)&Derived::Traverse##NAME) \ - return getDerived().WalkUpFrom##NAME(static_cast<CLASS*>(VAR)); \ + { \ + bool (Derived::*DerivedFn)(CLASS*) = &Derived::Traverse##NAME; \ + bool (Derived::*BaseFn)(CLASS*) = &RecursiveASTVisitor::Traverse##NAME; \ + if (DerivedFn == BaseFn) \ + return getDerived().WalkUpFrom##NAME(static_cast<CLASS*>(VAR)); \ + } \ EnqueueChildren = false; \ return getDerived().Traverse##NAME(static_cast<CLASS*>(VAR)); @@ -516,7 +512,6 @@ bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, } #undef DISPATCH_WALK -#undef GCC_CAST return true; } @@ -600,7 +595,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) { #define ABSTRACT_TYPELOC(CLASS, BASE) #define TYPELOC(CLASS, BASE) \ case TypeLoc::CLASS: \ - return getDerived().Traverse##CLASS##TypeLoc(*cast<CLASS##TypeLoc>(&TL)); + return getDerived().Traverse##CLASS##TypeLoc(TL.castAs<CLASS##TypeLoc>()); #include "clang/AST/TypeLocNodes.def" } @@ -1263,6 +1258,8 @@ DEF_TRAVERSE_DECL(BlockDecl, { return true; }) +DEF_TRAVERSE_DECL(EmptyDecl, { }) + DEF_TRAVERSE_DECL(FileScopeAsmDecl, { TRY_TO(TraverseStmt(D->getAsmString())); }) @@ -1393,6 +1390,14 @@ DEF_TRAVERSE_DECL(UsingDirectiveDecl, { DEF_TRAVERSE_DECL(UsingShadowDecl, { }) +DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, { + for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(), + E = D->varlist_end(); + I != E; ++I) { + TRY_TO(TraverseStmt(*I)); + } + }) + // A helper method for TemplateDecl's children. template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( @@ -1716,7 +1721,7 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { // FunctionNoProtoType or FunctionProtoType, or a typedef. This // also covers the return type and the function parameters, // including exception specifications. - if (clang::TypeSourceInfo *TSI = D->getTypeSourceInfo()) { + if (TypeSourceInfo *TSI = D->getTypeSourceInfo()) { TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); } @@ -2106,8 +2111,7 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { if (S->hasExplicitParameters() && S->hasExplicitResultType()) { // Visit the whole type. TRY_TO(TraverseTypeLoc(TL)); - } else if (isa<FunctionProtoTypeLoc>(TL)) { - FunctionProtoTypeLoc Proto = cast<FunctionProtoTypeLoc>(TL); + } else if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) { if (S->hasExplicitParameters()) { // Visit parameters. for (unsigned I = 0, N = Proto.getNumArgs(); I != N; ++I) { diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index a9bbb48..cf8fc24 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -14,16 +14,14 @@ #ifndef LLVM_CLANG_AST_STMT_H #define LLVM_CLANG_AST_STMT_H +#include "clang/AST/DeclGroup.h" +#include "clang/AST/StmtIterator.h" +#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" -#include "clang/AST/PrettyPrinter.h" -#include "clang/AST/StmtIterator.h" -#include "clang/AST/DeclGroup.h" -#include "clang/AST/Attr.h" -#include "clang/Lex/Token.h" -#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ErrorHandling.h" #include <string> namespace llvm { @@ -32,15 +30,19 @@ namespace llvm { namespace clang { class ASTContext; - class Expr; + class Attr; class Decl; - class ParmVarDecl; - class QualType; + class Expr; class IdentifierInfo; class LabelDecl; + class ParmVarDecl; + class PrinterHelper; + struct PrintingPolicy; + class QualType; class SourceManager; class StringLiteral; class SwitchStmt; + class Token; class VarDecl; //===--------------------------------------------------------------------===// @@ -172,11 +174,20 @@ protected: unsigned Kind : 2; }; + enum APFloatSemantics { + IEEEhalf, + IEEEsingle, + IEEEdouble, + x87DoubleExtended, + IEEEquad, + PPCDoubleDouble + }; + class FloatingLiteralBitfields { friend class FloatingLiteral; unsigned : NumExprBits; - unsigned IsIEEE : 1; // Distinguishes between PPC128 and IEEE128. + unsigned Semantics : 3; // Provides semantics for APFloat construction unsigned IsExact : 1; }; @@ -302,14 +313,10 @@ public: // Only allow allocation of Stmts using the allocator in ASTContext // or by doing a placement new. void* operator new(size_t bytes, ASTContext& C, - unsigned alignment = 8) throw() { - return ::operator new(bytes, C, alignment); - } + unsigned alignment = 8) throw(); void* operator new(size_t bytes, ASTContext* C, - unsigned alignment = 8) throw() { - return ::operator new(bytes, *C, alignment); - } + unsigned alignment = 8) throw(); void* operator new(size_t bytes, void* mem) throw() { return mem; @@ -360,16 +367,14 @@ public: static void EnableStatistics(); static void PrintStats(); - /// dump - This does a local dump of the specified AST fragment. It dumps the - /// specified node and a few nodes underneath it, but not the whole subtree. - /// This is useful in a debugger. + /// \brief Dumps the specified AST fragment and all subtrees to + /// \c llvm::errs(). LLVM_ATTRIBUTE_USED void dump() const; LLVM_ATTRIBUTE_USED void dump(SourceManager &SM) const; void dump(raw_ostream &OS, SourceManager &SM) const; - /// dumpAll - This does a dump of the specified AST fragment and all subtrees. - void dumpAll() const; - void dumpAll(SourceManager &SM) const; + /// dumpColor - same as dump(), but forces color highlighting. + LLVM_ATTRIBUTE_USED void dumpColor() const; /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST /// back to its original source language syntax. @@ -470,9 +475,8 @@ public: SourceLocation getEndLoc() const { return EndLoc; } void setEndLoc(SourceLocation L) { EndLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(StartLoc, EndLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return StartLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == DeclStmtClass; @@ -526,7 +530,8 @@ public: bool hasLeadingEmptyMacro() const { return HasLeadingEmptyMacro; } - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(SemiLoc); } + SourceLocation getLocStart() const LLVM_READONLY { return SemiLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return SemiLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == NullStmtClass; @@ -544,7 +549,7 @@ class CompoundStmt : public Stmt { Stmt** Body; SourceLocation LBracLoc, RBracLoc; public: - CompoundStmt(ASTContext &C, Stmt **StmtStart, unsigned NumStmts, + CompoundStmt(ASTContext &C, ArrayRef<Stmt*> Stmts, SourceLocation LB, SourceLocation RB); // \brief Build an empty compound statment with a location. @@ -598,9 +603,8 @@ public: return const_reverse_body_iterator(body_begin()); } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(LBracLoc, RBracLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return LBracLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RBracLoc; } SourceLocation getLBracLoc() const { return LBracLoc; } void setLBracLoc(SourceLocation L) { LBracLoc = L; } @@ -627,8 +631,14 @@ protected: // A pointer to the following CaseStmt or DefaultStmt class, // used by SwitchStmt. SwitchCase *NextSwitchCase; + SourceLocation KeywordLoc; + SourceLocation ColonLoc; - SwitchCase(StmtClass SC) : Stmt(SC), NextSwitchCase(0) {} + SwitchCase(StmtClass SC, SourceLocation KWLoc, SourceLocation ColonLoc) + : Stmt(SC), NextSwitchCase(0), KeywordLoc(KWLoc), ColonLoc(ColonLoc) {} + + SwitchCase(StmtClass SC, EmptyShell) + : Stmt(SC), NextSwitchCase(0) {} public: const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; } @@ -637,12 +647,18 @@ public: void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; } + SourceLocation getKeywordLoc() const { return KeywordLoc; } + void setKeywordLoc(SourceLocation L) { KeywordLoc = L; } + SourceLocation getColonLoc() const { return ColonLoc; } + void setColonLoc(SourceLocation L) { ColonLoc = L; } + Stmt *getSubStmt(); const Stmt *getSubStmt() const { return const_cast<SwitchCase*>(this)->getSubStmt(); } - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(); } + SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } + SourceLocation getLocEnd() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == CaseStmtClass || @@ -654,26 +670,22 @@ class CaseStmt : public SwitchCase { enum { LHS, RHS, SUBSTMT, END_EXPR }; Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for // GNU "case 1 ... 4" extension - SourceLocation CaseLoc; SourceLocation EllipsisLoc; - SourceLocation ColonLoc; public: CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc, SourceLocation ellipsisLoc, SourceLocation colonLoc) - : SwitchCase(CaseStmtClass) { + : SwitchCase(CaseStmtClass, caseLoc, colonLoc) { SubExprs[SUBSTMT] = 0; SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs); SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs); - CaseLoc = caseLoc; EllipsisLoc = ellipsisLoc; - ColonLoc = colonLoc; } /// \brief Build an empty switch case statement. - explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass) { } + explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass, Empty) { } - SourceLocation getCaseLoc() const { return CaseLoc; } - void setCaseLoc(SourceLocation L) { CaseLoc = L; } + SourceLocation getCaseLoc() const { return KeywordLoc; } + void setCaseLoc(SourceLocation L) { KeywordLoc = L; } SourceLocation getEllipsisLoc() const { return EllipsisLoc; } void setEllipsisLoc(SourceLocation L) { EllipsisLoc = L; } SourceLocation getColonLoc() const { return ColonLoc; } @@ -695,15 +707,16 @@ public: void setLHS(Expr *Val) { SubExprs[LHS] = reinterpret_cast<Stmt*>(Val); } void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); } - - SourceRange getSourceRange() const LLVM_READONLY { + SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { // Handle deeply nested case statements with iteration instead of recursion. const CaseStmt *CS = this; while (const CaseStmt *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt())) CS = CS2; - return SourceRange(CaseLoc, CS->getSubStmt()->getLocEnd()); + return CS->getSubStmt()->getLocEnd(); } + static bool classof(const Stmt *T) { return T->getStmtClass() == CaseStmtClass; } @@ -716,28 +729,26 @@ public: class DefaultStmt : public SwitchCase { Stmt* SubStmt; - SourceLocation DefaultLoc; - SourceLocation ColonLoc; public: DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) : - SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL), - ColonLoc(CL) {} + SwitchCase(DefaultStmtClass, DL, CL), SubStmt(substmt) {} /// \brief Build an empty default statement. - explicit DefaultStmt(EmptyShell) : SwitchCase(DefaultStmtClass) { } + explicit DefaultStmt(EmptyShell Empty) + : SwitchCase(DefaultStmtClass, Empty) { } Stmt *getSubStmt() { return SubStmt; } const Stmt *getSubStmt() const { return SubStmt; } void setSubStmt(Stmt *S) { SubStmt = S; } - SourceLocation getDefaultLoc() const { return DefaultLoc; } - void setDefaultLoc(SourceLocation L) { DefaultLoc = L; } + SourceLocation getDefaultLoc() const { return KeywordLoc; } + void setDefaultLoc(SourceLocation L) { KeywordLoc = L; } SourceLocation getColonLoc() const { return ColonLoc; } void setColonLoc(SourceLocation L) { ColonLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(DefaultLoc, SubStmt->getLocEnd()); - } + SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();} + static bool classof(const Stmt *T) { return T->getStmtClass() == DefaultStmtClass; } @@ -746,6 +757,11 @@ public: child_range children() { return child_range(&SubStmt, &SubStmt+1); } }; +inline SourceLocation SwitchCase::getLocEnd() const { + if (const CaseStmt *CS = dyn_cast<CaseStmt>(this)) + return CS->getLocEnd(); + return cast<DefaultStmt>(this)->getLocEnd(); +} /// LabelStmt - Represents a label, which has a substatement. For example: /// foo: return; @@ -771,9 +787,9 @@ public: void setIdentLoc(SourceLocation L) { IdentLoc = L; } void setSubStmt(Stmt *SS) { SubStmt = SS; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(IdentLoc, SubStmt->getLocEnd()); - } + SourceLocation getLocStart() const LLVM_READONLY { return IdentLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();} + child_range children() { return child_range(&SubStmt, &SubStmt+1); } static bool classof(const Stmt *T) { @@ -819,9 +835,9 @@ public: Stmt *getSubStmt() { return SubStmt; } const Stmt *getSubStmt() const { return SubStmt; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(AttrLoc, SubStmt->getLocEnd()); - } + SourceLocation getLocStart() const LLVM_READONLY { return AttrLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();} + child_range children() { return child_range(&SubStmt, &SubStmt + 1); } static bool classof(const Stmt *T) { @@ -879,11 +895,12 @@ public: SourceLocation getElseLoc() const { return ElseLoc; } void setElseLoc(SourceLocation L) { ElseLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { + SourceLocation getLocStart() const LLVM_READONLY { return IfLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { if (SubExprs[ELSE]) - return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd()); + return SubExprs[ELSE]->getLocEnd(); else - return SourceRange(IfLoc, SubExprs[THEN]->getLocEnd()); + return SubExprs[THEN]->getLocEnd(); } // Iterators over subexpressions. The iterators will include iterating @@ -977,9 +994,11 @@ public: return (bool) AllEnumCasesCovered; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd()); + SourceLocation getLocStart() const LLVM_READONLY { return SwitchLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + return SubExprs[BODY]->getLocEnd(); } + // Iterators child_range children() { return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); @@ -1031,9 +1050,11 @@ public: SourceLocation getWhileLoc() const { return WhileLoc; } void setWhileLoc(SourceLocation L) { WhileLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd()); + SourceLocation getLocStart() const LLVM_READONLY { return WhileLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + return SubExprs[BODY]->getLocEnd(); } + static bool classof(const Stmt *T) { return T->getStmtClass() == WhileStmtClass; } @@ -1079,9 +1100,9 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(DoLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return DoLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + static bool classof(const Stmt *T) { return T->getStmtClass() == DoStmtClass; } @@ -1150,9 +1171,11 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); + SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + return SubExprs[BODY]->getLocEnd(); } + static bool classof(const Stmt *T) { return T->getStmtClass() == ForStmtClass; } @@ -1184,9 +1207,9 @@ public: SourceLocation getLabelLoc() const { return LabelLoc; } void setLabelLoc(SourceLocation L) { LabelLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(GotoLoc, LabelLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return GotoLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return LabelLoc; } + static bool classof(const Stmt *T) { return T->getStmtClass() == GotoStmtClass; } @@ -1227,9 +1250,8 @@ public: return const_cast<IndirectGotoStmt*>(this)->getConstantTarget(); } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(GotoLoc, Target->getLocEnd()); - } + SourceLocation getLocStart() const LLVM_READONLY { return GotoLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return Target->getLocEnd(); } static bool classof(const Stmt *T) { return T->getStmtClass() == IndirectGotoStmtClass; @@ -1253,9 +1275,8 @@ public: SourceLocation getContinueLoc() const { return ContinueLoc; } void setContinueLoc(SourceLocation L) { ContinueLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(ContinueLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return ContinueLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return ContinueLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == ContinueStmtClass; @@ -1278,7 +1299,8 @@ public: SourceLocation getBreakLoc() const { return BreakLoc; } void setBreakLoc(SourceLocation L) { BreakLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(BreakLoc); } + SourceLocation getLocStart() const LLVM_READONLY { return BreakLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return BreakLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == BreakStmtClass; @@ -1329,7 +1351,10 @@ public: const VarDecl *getNRVOCandidate() const { return NRVOCandidate; } void setNRVOCandidate(const VarDecl *Var) { NRVOCandidate = Var; } - SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY { return RetLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + return RetExpr ? RetExpr->getLocEnd() : RetLoc; + } static bool classof(const Stmt *T) { return T->getStmtClass() == ReturnStmtClass; @@ -1381,7 +1406,8 @@ public: bool isVolatile() const { return IsVolatile; } void setVolatile(bool V) { IsVolatile = V; } - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(); } + SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } //===--- Asm String Analysis ---===// @@ -1636,9 +1662,8 @@ public: return Clobbers[i]; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(AsmLoc, RParenLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == GCCAsmStmtClass; @@ -1648,7 +1673,7 @@ public: /// This represents a Microsoft inline-assembly statement extension. /// class MSAsmStmt : public AsmStmt { - SourceLocation AsmLoc, LBraceLoc, EndLoc; + SourceLocation LBraceLoc, EndLoc; std::string AsmStr; unsigned NumAsmToks; @@ -1717,9 +1742,9 @@ public: StringRef getClobber(unsigned i) const { return Clobbers[i]; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(AsmLoc, EndLoc); - } + SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; } + static bool classof(const Stmt *T) { return T->getStmtClass() == MSAsmStmtClass; } @@ -1748,9 +1773,9 @@ public: SourceLocation ExceptLoc, Expr *FilterExpr, Stmt *Block); - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getExceptLoc(), getEndLoc()); - } + + SourceLocation getLocStart() const LLVM_READONLY { return getExceptLoc(); } + SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } SourceLocation getExceptLoc() const { return Loc; } SourceLocation getEndLoc() const { return getBlock()->getLocEnd(); } @@ -1760,7 +1785,7 @@ public: } CompoundStmt *getBlock() const { - return llvm::cast<CompoundStmt>(Children[BLOCK]); + return cast<CompoundStmt>(Children[BLOCK]); } child_range children() { @@ -1789,14 +1814,13 @@ public: SourceLocation FinallyLoc, Stmt *Block); - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getFinallyLoc(), getEndLoc()); - } + SourceLocation getLocStart() const LLVM_READONLY { return getFinallyLoc(); } + SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } SourceLocation getFinallyLoc() const { return Loc; } SourceLocation getEndLoc() const { return Block->getLocEnd(); } - CompoundStmt *getBlock() const { return llvm::cast<CompoundStmt>(Block); } + CompoundStmt *getBlock() const { return cast<CompoundStmt>(Block); } child_range children() { return child_range(&Block,&Block+1); @@ -1831,9 +1855,8 @@ public: Stmt *TryBlock, Stmt *Handler); - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getTryLoc(), getEndLoc()); - } + SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); } + SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } SourceLocation getTryLoc() const { return TryLoc; } SourceLocation getEndLoc() const { return Children[HANDLER]->getLocEnd(); } @@ -1841,7 +1864,7 @@ public: bool getIsCXXTry() const { return IsCXXTry; } CompoundStmt* getTryBlock() const { - return llvm::cast<CompoundStmt>(Children[TRY]); + return cast<CompoundStmt>(Children[TRY]); } Stmt *getHandler() const { return Children[HANDLER]; } diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index f4e4dcd..0112bef 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -14,6 +14,9 @@ #ifndef LLVM_CLANG_AST_STMTCXX_H #define LLVM_CLANG_AST_STMTCXX_H +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Expr.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Stmt.h" #include "llvm/Support/Compiler.h" @@ -38,8 +41,9 @@ public: CXXCatchStmt(EmptyShell Empty) : Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {} - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(CatchLoc, HandlerBlock->getLocEnd()); + SourceLocation getLocStart() const LLVM_READONLY { return CatchLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + return HandlerBlock->getLocEnd(); } SourceLocation getCatchLoc() const { return CatchLoc; } @@ -62,8 +66,7 @@ class CXXTryStmt : public Stmt { SourceLocation TryLoc; unsigned NumHandlers; - CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers, - unsigned numHandlers); + CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef<Stmt*> handlers); CXXTryStmt(EmptyShell Empty, unsigned numHandlers) : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { } @@ -77,15 +80,13 @@ class CXXTryStmt : public Stmt { public: static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc, - Stmt *tryBlock, Stmt **handlers, - unsigned numHandlers); + Stmt *tryBlock, ArrayRef<Stmt*> handlers); static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty, unsigned numHandlers); - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getTryLoc(), getEndLoc()); - } + SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); } + SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } SourceLocation getTryLoc() const { return TryLoc; } SourceLocation getEndLoc() const { @@ -93,18 +94,18 @@ public: } CompoundStmt *getTryBlock() { - return llvm::cast<CompoundStmt>(getStmts()[0]); + return cast<CompoundStmt>(getStmts()[0]); } const CompoundStmt *getTryBlock() const { - return llvm::cast<CompoundStmt>(getStmts()[0]); + return cast<CompoundStmt>(getStmts()[0]); } unsigned getNumHandlers() const { return NumHandlers; } CXXCatchStmt *getHandler(unsigned i) { - return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]); + return cast<CXXCatchStmt>(getStmts()[i + 1]); } const CXXCatchStmt *getHandler(unsigned i) const { - return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]); + return cast<CXXCatchStmt>(getStmts()[i + 1]); } static bool classof(const Stmt *T) { @@ -188,9 +189,11 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); + SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + return SubExprs[BODY]->getLocEnd(); } + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXForRangeStmtClass; } @@ -272,9 +275,8 @@ public: return reinterpret_cast<CompoundStmt *>(SubStmt); } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(KeywordLoc, SubStmt->getLocEnd()); - } + SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();} child_range children() { return child_range(&SubStmt, &SubStmt+1); diff --git a/include/clang/AST/StmtGraphTraits.h b/include/clang/AST/StmtGraphTraits.h index 25d0152..a3e9e1e 100644 --- a/include/clang/AST/StmtGraphTraits.h +++ b/include/clang/AST/StmtGraphTraits.h @@ -16,8 +16,8 @@ #define LLVM_CLANG_AST_STMT_GRAPHTRAITS_H #include "clang/AST/Stmt.h" -#include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/GraphTraits.h" namespace llvm { diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h index d7a73a7..e97c1a5 100644 --- a/include/clang/AST/StmtObjC.h +++ b/include/clang/AST/StmtObjC.h @@ -55,9 +55,11 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); + SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + return SubExprs[BODY]->getLocEnd(); } + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCForCollectionStmtClass; } @@ -102,9 +104,8 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(AtCatchLoc, Body->getLocEnd()); - } + SourceLocation getLocStart() const LLVM_READONLY { return AtCatchLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return Body->getLocEnd(); } bool hasEllipsis() const { return getCatchParamDecl() == 0; } @@ -131,8 +132,9 @@ public: Stmt *getFinallyBody() { return AtFinallyStmt; } void setFinallyBody(Stmt *S) { AtFinallyStmt = S; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(AtFinallyLoc, AtFinallyStmt->getLocEnd()); + SourceLocation getLocStart() const LLVM_READONLY { return AtFinallyLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + return AtFinallyStmt->getLocEnd(); } SourceLocation getAtFinallyLoc() const { return AtFinallyLoc; } @@ -236,7 +238,8 @@ public: getStmts()[1 + NumCatchStmts] = S; } - SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY { return AtTryLoc; } + SourceLocation getLocEnd() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtTryStmtClass; @@ -292,8 +295,9 @@ public: } void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(AtSynchronizedLoc, getSynchBody()->getLocEnd()); + SourceLocation getLocStart() const LLVM_READONLY { return AtSynchronizedLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + return getSynchBody()->getLocEnd(); } static bool classof(const Stmt *T) { @@ -324,11 +328,9 @@ public: SourceLocation getThrowLoc() { return AtThrowLoc; } void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; } - SourceRange getSourceRange() const LLVM_READONLY { - if (Throw) - return SourceRange(AtThrowLoc, Throw->getLocEnd()); - else - return SourceRange(AtThrowLoc); + SourceLocation getLocStart() const LLVM_READONLY { return AtThrowLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + return Throw ? Throw->getLocEnd() : AtThrowLoc; } static bool classof(const Stmt *T) { @@ -355,9 +357,8 @@ public: Stmt *getSubStmt() { return SubStmt; } void setSubStmt(Stmt *S) { SubStmt = S; } - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(AtLoc, SubStmt->getLocEnd()); - } + SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();} SourceLocation getAtLoc() const { return AtLoc; } void setAtLoc(SourceLocation Loc) { AtLoc = Loc; } diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 1c0abde..70b934f 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -15,8 +15,8 @@ #ifndef LLVM_CLANG_AST_TEMPLATEBASE_H #define LLVM_CLANG_AST_TEMPLATEBASE_H -#include "clang/AST/Type.h" #include "clang/AST/TemplateName.h" +#include "clang/AST/Type.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" @@ -72,35 +72,39 @@ private: /// \brief The kind of template argument we're storing. unsigned Kind; + struct DA { + ValueDecl *D; + bool ForRefParam; + }; + struct I { + // We store a decomposed APSInt with the data allocated by ASTContext if + // BitWidth > 64. The memory may be shared between multiple + // TemplateArgument instances. + union { + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + const uint64_t *pVal; ///< Used to store the >64 bits integer value. + }; + unsigned BitWidth : 31; + unsigned IsUnsigned : 1; + void *Type; + }; + struct A { + const TemplateArgument *Args; + unsigned NumArgs; + }; + struct TA { + void *Name; + unsigned NumExpansions; + }; union { + struct DA DeclArg; + struct I Integer; + struct A Args; + struct TA TemplateArg; uintptr_t TypeOrValue; - struct { - ValueDecl *D; - bool ForRefParam; - } DeclArg; - struct { - // We store a decomposed APSInt with the data allocated by ASTContext if - // BitWidth > 64. The memory may be shared between multiple - // TemplateArgument instances. - union { - uint64_t VAL; ///< Used to store the <= 64 bits integer value. - const uint64_t *pVal; ///< Used to store the >64 bits integer value. - }; - unsigned BitWidth : 31; - unsigned IsUnsigned : 1; - void *Type; - } Integer; - struct { - const TemplateArgument *Args; - unsigned NumArgs; - } Args; - struct { - void *Name; - unsigned NumExpansions; - } TemplateArg; }; - TemplateArgument(TemplateName, bool); // DO NOT USE + TemplateArgument(TemplateName, bool) LLVM_DELETED_FUNCTION; public: /// \brief Construct an empty, invalid template argument. @@ -158,7 +162,7 @@ public: /// /// \param NumExpansions The number of expansions that will be generated by /// instantiating - TemplateArgument(TemplateName Name, llvm::Optional<unsigned> NumExpansions) + TemplateArgument(TemplateName Name, Optional<unsigned> NumExpansions) : Kind(TemplateExpansion) { TemplateArg.Name = Name.getAsVoidPointer(); @@ -261,7 +265,7 @@ public: /// \brief Retrieve the number of expansions that a template template argument /// expansion will produce, if known. - llvm::Optional<unsigned> getNumTemplateExpansions() const; + Optional<unsigned> getNumTemplateExpansions() const; /// \brief Retrieve the template argument as an integral value. // FIXME: Provide a way to read the integral data without copying the value. @@ -317,6 +321,12 @@ public: return Args.NumArgs; } + /// \brief Return the array of arguments in this template argument pack. + llvm::ArrayRef<TemplateArgument> getPackAsArray() const { + assert(Kind == Pack); + return llvm::ArrayRef<TemplateArgument>(Args.Args, Args.NumArgs); + } + /// \brief Determines whether two template arguments are superficially the /// same. bool structurallyEquals(const TemplateArgument &Other) const; @@ -335,17 +345,20 @@ public: /// Location information for a TemplateArgument. struct TemplateArgumentLocInfo { private: + + struct T { + // FIXME: We'd like to just use the qualifier in the TemplateName, + // but template arguments get canonicalized too quickly. + NestedNameSpecifier *Qualifier; + void *QualifierLocData; + unsigned TemplateNameLoc; + unsigned EllipsisLoc; + }; + union { + struct T Template; Expr *Expression; TypeSourceInfo *Declarator; - struct { - // FIXME: We'd like to just use the qualifier in the TemplateName, - // but template arguments get canonicalized too quickly. - NestedNameSpecifier *Qualifier; - void *QualifierLocData; - unsigned TemplateNameLoc; - unsigned EllipsisLoc; - } Template; }; public: @@ -490,7 +503,7 @@ public: /// \param NumExpansions Will be set to the number of expansions that will /// be generated from this pack expansion, if known a priori. TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis, - llvm::Optional<unsigned> &NumExpansions, + Optional<unsigned> &NumExpansions, ASTContext &Context) const; }; diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index 7dc75b1..0b9d4c8 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -15,9 +15,9 @@ #define LLVM_CLANG_AST_TEMPLATENAME_H #include "clang/Basic/LLVM.h" +#include "clang/Basic/OperatorKinds.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerUnion.h" -#include "clang/Basic/OperatorKinds.h" namespace clang { @@ -46,16 +46,17 @@ protected: SubstTemplateTemplateParmPack }; - union { - struct { - /// \brief A Kind. - unsigned Kind : 2; - - /// \brief The number of stored templates or template arguments, - /// depending on which subclass we have. - unsigned Size : 30; - } Bits; + struct BitsTag { + /// \brief A Kind. + unsigned Kind : 2; + /// \brief The number of stored templates or template arguments, + /// depending on which subclass we have. + unsigned Size : 30; + }; + + union { + struct BitsTag Bits; void *PointerAlignment; }; @@ -308,6 +309,9 @@ public: void print(raw_ostream &OS, const PrintingPolicy &Policy, bool SuppressNNS = false) const; + /// \brief Debugging aid that dumps the template name. + void dump(raw_ostream &OS) const; + /// \brief Debugging aid that dumps the template name to standard /// error. void dump() const; diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 6900a7d..23fa3e8 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -14,24 +14,24 @@ #ifndef LLVM_CLANG_AST_TYPE_H #define LLVM_CLANG_AST_TYPE_H +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/TemplateName.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/Linkage.h" #include "clang/Basic/PartialDiagnostic.h" -#include "clang/Basic/Visibility.h" #include "clang/Basic/Specifiers.h" -#include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/TemplateName.h" -#include "llvm/Support/type_traits.h" -#include "llvm/Support/ErrorHandling.h" +#include "clang/Basic/Visibility.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/Twine.h" -#include "clang/Basic/LLVM.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/type_traits.h" namespace clang { enum { @@ -784,8 +784,8 @@ public: /// Executing \c getUnqualifiedType() on the type \c DifferenceType will /// desugar until we hit the type \c Integer, which has no qualifiers on it. /// - /// The resulting type might still be qualified if it's an array - /// type. To strip qualifiers even from within an array type, use + /// The resulting type might still be qualified if it's sugar for an array + /// type. To strip qualifiers even from within a sugared array type, use /// ASTContext::getUnqualifiedArrayType. inline QualType getUnqualifiedType() const; @@ -795,8 +795,8 @@ public: /// Like getUnqualifiedType(), but also returns the set of /// qualifiers that were built up. /// - /// The resulting type might still be qualified if it's an array - /// type. To strip qualifiers even from within an array type, use + /// The resulting type might still be qualified if it's sugar for an array + /// type. To strip qualifiers even from within a sugared array type, use /// ASTContext::getUnqualifiedArrayType. inline SplitQualType getSplitUnqualifiedType() const; @@ -979,10 +979,6 @@ public: /// type other than void. bool isCForbiddenLValueType() const; - /// \brief Determine whether this type has trivial copy/move-assignment - /// semantics. - bool hasTrivialAssignment(ASTContext &Context, bool Copying) const; - private: // These methods are implemented in a separate translation unit; // "static"-ize them to avoid creating temporary QualTypes in the @@ -1002,14 +998,12 @@ private: namespace llvm { /// Implement simplify_type for QualType, so that we can dyn_cast from QualType /// to a specific Type class. -template<> struct simplify_type<const ::clang::QualType> { +template<> struct simplify_type< ::clang::QualType> { typedef const ::clang::Type *SimpleType; - static SimpleType getSimplifiedValue(const ::clang::QualType &Val) { + static SimpleType getSimplifiedValue(::clang::QualType Val) { return Val.getTypePtr(); } }; -template<> struct simplify_type< ::clang::QualType> - : public simplify_type<const ::clang::QualType> {}; // Teach SmallPtrSet that QualType is "basically a pointer". template<> @@ -1195,13 +1189,9 @@ private: /// (for C++0x variadic templates). unsigned ContainsUnexpandedParameterPack : 1; - /// \brief Nonzero if the cache (i.e. the bitfields here starting - /// with 'Cache') is valid. If so, then this is a - /// LangOptions::VisibilityMode+1. - mutable unsigned CacheValidAndVisibility : 2; - - /// \brief True if the visibility was set explicitly in the source code. - mutable unsigned CachedExplicitVisibility : 1; + /// \brief True if the cache (i.e. the bitfields here starting with + /// 'Cache') is valid. + mutable unsigned CacheValid : 1; /// \brief Linkage of this type. mutable unsigned CachedLinkage : 2; @@ -1213,15 +1203,7 @@ private: mutable unsigned FromAST : 1; bool isCacheValid() const { - return (CacheValidAndVisibility != 0); - } - Visibility getVisibility() const { - assert(isCacheValid() && "getting linkage from invalid cache"); - return static_cast<Visibility>(CacheValidAndVisibility-1); - } - bool isVisibilityExplicit() const { - assert(isCacheValid() && "getting linkage from invalid cache"); - return CachedExplicitVisibility; + return CacheValid; } Linkage getLinkage() const { assert(isCacheValid() && "getting linkage from invalid cache"); @@ -1278,11 +1260,6 @@ protected: /// C++ 8.3.5p4: The return type, the parameter type list and the /// cv-qualifier-seq, [...], are part of the function type. unsigned TypeQuals : 3; - - /// \brief The ref-qualifier associated with a \c FunctionProtoType. - /// - /// This is a value of type \c RefQualifierKind. - unsigned RefQualifier : 2; }; class ObjCObjectTypeBitfields { @@ -1382,8 +1359,7 @@ protected: TypeBits.InstantiationDependent = Dependent || InstantiationDependent; TypeBits.VariablyModified = VariablyModified; TypeBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; - TypeBits.CacheValidAndVisibility = 0; - TypeBits.CachedExplicitVisibility = false; + TypeBits.CacheValid = false; TypeBits.CachedLocalOrUnnamed = false; TypeBits.CachedLinkage = NoLinkage; TypeBits.FromAST = false; @@ -1584,6 +1560,20 @@ public: bool isNullPtrType() const; // C++0x nullptr_t bool isAtomicType() const; // C11 _Atomic() + bool isImage1dT() const; // OpenCL image1d_t + bool isImage1dArrayT() const; // OpenCL image1d_array_t + bool isImage1dBufferT() const; // OpenCL image1d_buffer_t + bool isImage2dT() const; // OpenCL image2d_t + bool isImage2dArrayT() const; // OpenCL image2d_array_t + bool isImage3dT() const; // OpenCL image3d_t + + bool isImageType() const; // Any OpenCL image type + + bool isSamplerT() const; // OpenCL sampler_t + bool isEventT() const; // OpenCL event_t + + bool isOpenCLSpecificType() const; // Any OpenCL specific type + /// Determines if this type, which must satisfy /// isObjCLifetimeType(), is implicitly __unsafe_unretained rather /// than implicitly __strong. @@ -1770,16 +1760,21 @@ public: Linkage getLinkage() const; /// \brief Determine the visibility of this type. - Visibility getVisibility() const; + Visibility getVisibility() const { + return getLinkageAndVisibility().getVisibility(); + } /// \brief Return true if the visibility was explicitly set is the code. - bool isVisibilityExplicit() const; + bool isVisibilityExplicit() const { + return getLinkageAndVisibility().isVisibilityExplicit(); + } /// \brief Determine the linkage and visibility of this type. - std::pair<Linkage,Visibility> getLinkageAndVisibility() const; + LinkageInfo getLinkageAndVisibility() const; - /// \brief Note that the linkage is no longer known. - void ClearLinkageCache(); + /// \brief True if the computed linkage is valid. Used for consistency + /// checking. Should always return true. + bool isLinkageValid() const; const char *getTypeClassName() const; @@ -2097,6 +2092,14 @@ public: } }; +/// The inheritance model to use for this member pointer. +enum MSInheritanceModel { + MSIM_Single, + MSIM_Multiple, + MSIM_Virtual, + MSIM_Unspecified +}; + /// MemberPointerType - C++ 8.3.3 - Pointers to members /// class MemberPointerType : public Type, public llvm::FoldingSetNode { @@ -2132,6 +2135,10 @@ public: return !PointeeType->isFunctionProtoType(); } + /// Returns the number of pointer and integer slots used to represent this + /// member pointer in the MS C++ ABI. + std::pair<unsigned, unsigned> getMSMemberPointerSlots() const; + const Type *getClass() const { return Class; } bool isSugared() const { return false; } @@ -2686,8 +2693,7 @@ class FunctionType : public Type { protected: FunctionType(TypeClass tc, QualType res, - unsigned typeQuals, RefQualifierKind RefQualifier, - QualType Canonical, bool Dependent, + unsigned typeQuals, QualType Canonical, bool Dependent, bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack, ExtInfo Info) @@ -2696,20 +2702,18 @@ protected: ResultType(res) { FunctionTypeBits.ExtInfo = Info.Bits; FunctionTypeBits.TypeQuals = typeQuals; - FunctionTypeBits.RefQualifier = static_cast<unsigned>(RefQualifier); } unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; } - RefQualifierKind getRefQualifier() const { - return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier); - } - public: QualType getResultType() const { return ResultType; } bool getHasRegParm() const { return getExtInfo().getHasRegParm(); } unsigned getRegParmType() const { return getExtInfo().getRegParm(); } + /// \brief Determine whether this function type includes the GNU noreturn + /// attribute. The C++11 [[noreturn]] attribute does not affect the function + /// type. bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); } CallingConv getCallConv() const { return getExtInfo().getCC(); } ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); } @@ -2735,7 +2739,7 @@ public: /// no information available about its arguments. class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info) - : FunctionType(FunctionNoProto, Result, 0, RQ_None, Canonical, + : FunctionType(FunctionNoProto, Result, 0, Canonical, /*Dependent=*/false, /*InstantiationDependent=*/false, Result->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false, Info) {} @@ -2804,11 +2808,11 @@ private: return false; } - FunctionProtoType(QualType result, const QualType *args, unsigned numArgs, + FunctionProtoType(QualType result, ArrayRef<QualType> args, QualType canonical, const ExtProtoInfo &epi); /// NumArgs - The number of arguments this function has, not counting '...'. - unsigned NumArgs : 17; + unsigned NumArgs : 15; /// NumExceptions - The number of types in the exception spec, if any. unsigned NumExceptions : 9; @@ -2825,6 +2829,11 @@ private: /// HasTrailingReturn - Whether this function has a trailing return type. unsigned HasTrailingReturn : 1; + /// \brief The ref-qualifier associated with a \c FunctionProtoType. + /// + /// This is a value of type \c RefQualifierKind. + unsigned RefQualifier : 2; + // ArgInfo - There is an variable size array after the class in memory that // holds the argument types. @@ -2864,6 +2873,9 @@ public: assert(i < NumArgs && "Invalid argument number!"); return arg_type_begin()[i]; } + ArrayRef<QualType> getArgTypes() const { + return ArrayRef<QualType>(arg_type_begin(), arg_type_end()); + } ExtProtoInfo getExtProtoInfo() const { ExtProtoInfo EPI; @@ -2972,7 +2984,7 @@ public: /// \brief Retrieve the ref-qualifier associated with this function type. RefQualifierKind getRefQualifier() const { - return FunctionType::getRefQualifier(); + return static_cast<RefQualifierKind>(RefQualifier); } typedef const QualType *arg_type_iterator; @@ -3005,9 +3017,6 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - // FIXME: Remove the string version. - void printExceptionSpecification(std::string &S, - const PrintingPolicy &Policy) const; void printExceptionSpecification(raw_ostream &OS, const PrintingPolicy &Policy) const; @@ -3323,7 +3332,8 @@ public: attr_stdcall, attr_thiscall, attr_pascal, - attr_pnaclcall + attr_pnaclcall, + attr_inteloclbicc }; private: @@ -3648,21 +3658,6 @@ public: /// \brief Print a template argument list, including the '<' and '>' /// enclosing the template arguments. - // FIXME: remove the string ones. - static std::string PrintTemplateArgumentList(const TemplateArgument *Args, - unsigned NumArgs, - const PrintingPolicy &Policy, - bool SkipBrackets = false); - - static std::string PrintTemplateArgumentList(const TemplateArgumentLoc *Args, - unsigned NumArgs, - const PrintingPolicy &Policy); - - static std::string PrintTemplateArgumentList(const TemplateArgumentListInfo &, - const PrintingPolicy &Policy); - - /// \brief Print a template argument list, including the '<' and '>' - /// enclosing the template arguments. static void PrintTemplateArgumentList(raw_ostream &OS, const TemplateArgument *Args, unsigned NumArgs, @@ -4125,7 +4120,7 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode { unsigned NumExpansions; PackExpansionType(QualType Pattern, QualType Canon, - llvm::Optional<unsigned> NumExpansions) + Optional<unsigned> NumExpansions) : Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(), /*InstantiationDependent=*/true, /*VariableModified=*/Pattern->isVariablyModifiedType(), @@ -4143,11 +4138,11 @@ public: /// \brief Retrieve the number of expansions that this pack expansion will /// generate, if known. - llvm::Optional<unsigned> getNumExpansions() const { + Optional<unsigned> getNumExpansions() const { if (NumExpansions) return NumExpansions - 1; - return llvm::Optional<unsigned>(); + return None; } bool isSugared() const { return false; } @@ -4158,9 +4153,9 @@ public: } static void Profile(llvm::FoldingSetNodeID &ID, QualType Pattern, - llvm::Optional<unsigned> NumExpansions) { + Optional<unsigned> NumExpansions) { ID.AddPointer(Pattern.getAsOpaquePtr()); - ID.AddBoolean(NumExpansions); + ID.AddBoolean(NumExpansions.hasValue()); if (NumExpansions) ID.AddInteger(*NumExpansions); } @@ -4887,6 +4882,49 @@ inline bool Type::isObjCSelType() const { inline bool Type::isObjCBuiltinType() const { return isObjCIdType() || isObjCClassType() || isObjCSelType(); } + +inline bool Type::isImage1dT() const { + return isSpecificBuiltinType(BuiltinType::OCLImage1d); +} + +inline bool Type::isImage1dArrayT() const { + return isSpecificBuiltinType(BuiltinType::OCLImage1dArray); +} + +inline bool Type::isImage1dBufferT() const { + return isSpecificBuiltinType(BuiltinType::OCLImage1dBuffer); +} + +inline bool Type::isImage2dT() const { + return isSpecificBuiltinType(BuiltinType::OCLImage2d); +} + +inline bool Type::isImage2dArrayT() const { + return isSpecificBuiltinType(BuiltinType::OCLImage2dArray); +} + +inline bool Type::isImage3dT() const { + return isSpecificBuiltinType(BuiltinType::OCLImage3d); +} + +inline bool Type::isSamplerT() const { + return isSpecificBuiltinType(BuiltinType::OCLSampler); +} + +inline bool Type::isEventT() const { + return isSpecificBuiltinType(BuiltinType::OCLEvent); +} + +inline bool Type::isImageType() const { + return isImage3dT() || + isImage2dT() || isImage2dArrayT() || + isImage1dT() || isImage1dArrayT() || isImage1dBufferT(); +} + +inline bool Type::isOpenCLSpecificType() const { + return isSamplerT() || isEventT() || isImageType(); +} + inline bool Type::isTemplateTypeParmType() const { return isa<TemplateTypeParmType>(CanonicalType); } diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 8a04bd8..11cad9b 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -14,9 +14,9 @@ #ifndef LLVM_CLANG_AST_TYPELOC_H #define LLVM_CLANG_AST_TYPELOC_H -#include "clang/AST/Type.h" #include "clang/AST/Decl.h" #include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" #include "clang/Basic/Specifiers.h" #include "llvm/Support/Compiler.h" @@ -44,6 +44,29 @@ protected: void *Data; public: + /// \brief Convert to the specified TypeLoc type, asserting that this TypeLoc + /// is of the desired type. + template<typename T> + T castAs() const { + assert(T::isKind(*this)); + T t; + TypeLoc& tl = t; + tl = *this; + return t; + } + + /// \brief Convert to the specified TypeLoc type, returning a null TypeLoc if + /// this TypeLoc is not of the desired type. + template<typename T> + T getAs() const { + if (!T::isKind(*this)) + return T(); + T t; + TypeLoc& tl = t; + tl = *this; + return t; + } + /// The kinds of TypeLocs. Equivalent to the Type::TypeClass enum, /// except it also defines a Qualified enum that corresponds to the /// QualifiedLoc class. @@ -119,11 +142,7 @@ public: /// \brief Skips past any qualifiers, if this is qualified. UnqualTypeLoc getUnqualifiedLoc() const; // implemented in this header - TypeLoc IgnoreParens() const { - if (isa<ParenTypeLoc>(this)) - return IgnoreParensImpl(*this); - return *this; - } + TypeLoc IgnoreParens() const; /// \brief Initializes this to state that every location in this /// type is the given location. @@ -160,6 +179,10 @@ public: } private: + static bool isKind(const TypeLoc&) { + return true; + } + static void initializeImpl(ASTContext &Context, TypeLoc TL, SourceLocation Loc); static TypeLoc getNextTypeLocImpl(TypeLoc TL); @@ -187,8 +210,10 @@ public: return (TypeLocClass) getTypePtr()->getTypeClass(); } - static bool classof(const TypeLoc *TL) { - return !TL->getType().hasLocalQualifiers(); +private: + friend class TypeLoc; + static bool isKind(const TypeLoc &TL) { + return !TL.getType().hasLocalQualifiers(); } }; @@ -231,15 +256,17 @@ public: getFullDataSizeForType(getType().getLocalUnqualifiedType()); } - static bool classof(const TypeLoc *TL) { - return TL->getType().hasLocalQualifiers(); +private: + friend class TypeLoc; + static bool isKind(const TypeLoc &TL) { + return TL.getType().hasLocalQualifiers(); } }; inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const { - if (isa<QualifiedTypeLoc>(this)) - return cast<QualifiedTypeLoc>(this)->getUnqualifiedLoc(); - return cast<UnqualTypeLoc>(*this); + if (QualifiedTypeLoc Loc = getAs<QualifiedTypeLoc>()) + return Loc.getUnqualifiedLoc(); + return castAs<UnqualTypeLoc>(); } /// A metaprogramming base class for TypeLoc classes which correspond @@ -280,24 +307,22 @@ class ConcreteTypeLoc : public Base { return static_cast<const Derived*>(this); } -public: - unsigned getLocalDataSize() const { - return sizeof(LocalData) + asDerived()->getExtraLocalDataSize(); - } - // Give a default implementation that's useful for leaf types. - unsigned getFullDataSize() const { - return asDerived()->getLocalDataSize() + getInnerTypeSize(); + friend class TypeLoc; + static bool isKind(const TypeLoc &TL) { + return Derived::classofType(TL.getTypePtr()); } static bool classofType(const Type *Ty) { return TypeClass::classof(Ty); } - static bool classof(const TypeLoc *TL) { - return Derived::classofType(TL->getTypePtr()); +public: + unsigned getLocalDataSize() const { + return sizeof(LocalData) + asDerived()->getExtraLocalDataSize(); } - static bool classof(const UnqualTypeLoc *TL) { - return Derived::classofType(TL->getTypePtr()); + // Give a default implementation that's useful for leaf types. + unsigned getFullDataSize() const { + return asDerived()->getLocalDataSize() + getInnerTypeSize(); } TypeLoc getNextTypeLoc() const { @@ -362,18 +387,19 @@ private: /// information. See the note on ConcreteTypeLoc. template <class Base, class Derived, class TypeClass> class InheritingConcreteTypeLoc : public Base { -public: + friend class TypeLoc; static bool classofType(const Type *Ty) { return TypeClass::classof(Ty); } - static bool classof(const TypeLoc *TL) { - return Derived::classofType(TL->getTypePtr()); + static bool isKind(const TypeLoc &TL) { + return Derived::classofType(TL.getTypePtr()); } - static bool classof(const UnqualTypeLoc *TL) { - return Derived::classofType(TL->getTypePtr()); + static bool isKind(const UnqualTypeLoc &TL) { + return Derived::classofType(TL.getTypePtr()); } +public: const TypeClass *getTypePtr() const { return cast<TypeClass>(Base::getTypePtr()); } @@ -406,7 +432,9 @@ public: setNameLoc(Loc); } - static bool classof(const TypeLoc *TL); +private: + friend class TypeLoc; + static bool isKind(const TypeLoc &TL); }; @@ -899,6 +927,11 @@ public: } }; +inline TypeLoc TypeLoc::IgnoreParens() const { + if (ParenTypeLoc::isKind(*this)) + return IgnoreParensImpl(*this); + return *this; +} struct PointerLikeLocInfo { SourceLocation StarLoc; diff --git a/include/clang/AST/TypeLocVisitor.h b/include/clang/AST/TypeLocVisitor.h index 50fc439..db5775a 100644 --- a/include/clang/AST/TypeLocVisitor.h +++ b/include/clang/AST/TypeLocVisitor.h @@ -21,7 +21,7 @@ namespace clang { #define DISPATCH(CLASSNAME) \ return static_cast<ImplClass*>(this)-> \ - Visit##CLASSNAME(cast<CLASSNAME>(TyLoc)) + Visit##CLASSNAME(TyLoc.castAs<CLASSNAME>()) template<typename ImplClass, typename RetTy=void> class TypeLocVisitor { diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h index 7cf0d5e..59b59f5 100644 --- a/include/clang/AST/TypeOrdering.h +++ b/include/clang/AST/TypeOrdering.h @@ -16,8 +16,8 @@ #ifndef LLVM_CLANG_TYPE_ORDERING_H #define LLVM_CLANG_TYPE_ORDERING_H -#include "clang/AST/Type.h" #include "clang/AST/CanonicalType.h" +#include "clang/AST/Type.h" #include <functional> namespace clang { diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h index 9f11ee5..d26065e 100644 --- a/include/clang/AST/UnresolvedSet.h +++ b/include/clang/AST/UnresolvedSet.h @@ -15,9 +15,11 @@ #ifndef LLVM_CLANG_AST_UNRESOLVEDSET_H #define LLVM_CLANG_AST_UNRESOLVEDSET_H -#include <iterator> -#include "llvm/ADT/SmallVector.h" #include "clang/AST/DeclAccessPair.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include <iterator> namespace clang { @@ -25,12 +27,13 @@ namespace clang { /// non-const iterator. class UnresolvedSetIterator { private: - typedef SmallVectorImpl<DeclAccessPair> DeclsTy; + typedef llvm::MutableArrayRef<DeclAccessPair> DeclsTy; typedef DeclsTy::iterator IteratorTy; IteratorTy ir; friend class UnresolvedSetImpl; + friend class ASTUnresolvedSet; friend class OverloadExpr; explicit UnresolvedSetIterator(DeclsTy::iterator ir) : ir(ir) {} explicit UnresolvedSetIterator(DeclsTy::const_iterator ir) : @@ -87,7 +90,7 @@ public: /// UnresolvedSet - A set of unresolved declarations. class UnresolvedSetImpl { - typedef UnresolvedSetIterator::DeclsTy DeclsTy; + typedef SmallVectorImpl<DeclAccessPair> DeclsTy; // Don't allow direct construction, and only permit subclassing by // UnresolvedSet. diff --git a/include/clang/AST/VTTBuilder.h b/include/clang/AST/VTTBuilder.h index 6756dd1..f24bb3f 100644 --- a/include/clang/AST/VTTBuilder.h +++ b/include/clang/AST/VTTBuilder.h @@ -102,9 +102,6 @@ class VTTBuilder { bool GenerateDefinition; /// AddVTablePointer - Add a vtable pointer to the VTT currently being built. - /// - /// \param AddressPoints - If the vtable is a construction vtable, this has - /// the address points for it. void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex, const CXXRecordDecl *VTableClass); @@ -117,9 +114,6 @@ class VTTBuilder { /// /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base /// or a direct or indirect base of a virtual base. - /// - /// \param AddressPoints - If the vtable is a construction vtable, this has - /// the address points for it. void LayoutSecondaryVirtualPointers(BaseSubobject Base, bool BaseIsMorallyVirtual, uint64_t VTableIndex, @@ -128,9 +122,6 @@ class VTTBuilder { /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers /// for the given base subobject. - /// - /// \param AddressPoints - If the vtable is a construction vtable, this has - /// the address points for it. void LayoutSecondaryVirtualPointers(BaseSubobject Base, uint64_t VTableIndex); diff --git a/include/clang/AST/VTableBuilder.h b/include/clang/AST/VTableBuilder.h index a6aa40b..bcbe875 100644 --- a/include/clang/AST/VTableBuilder.h +++ b/include/clang/AST/VTableBuilder.h @@ -215,12 +215,15 @@ private: /// Address points - Address points for all vtables. AddressPointsMapTy AddressPoints; + bool IsMicrosoftABI; + public: VTableLayout(uint64_t NumVTableComponents, const VTableComponent *VTableComponents, uint64_t NumVTableThunks, const VTableThunkTy *VTableThunks, - const AddressPointsMapTy &AddressPoints); + const AddressPointsMapTy &AddressPoints, + bool IsMicrosoftABI); ~VTableLayout(); uint64_t getNumVTableComponents() const { @@ -252,7 +255,8 @@ public: "Did not find address point!"); uint64_t AddressPoint = AddressPoints.lookup(Base); - assert(AddressPoint && "Address point must not be zero!"); + assert(AddressPoint != 0 || IsMicrosoftABI); + (void)IsMicrosoftABI; return AddressPoint; } @@ -271,6 +275,8 @@ public: typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy; private: + bool IsMicrosoftABI; + /// MethodVTableIndices - Contains the index (relative to the vtable address /// point) where the function pointer for a virtual function is stored. typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy; @@ -306,10 +312,21 @@ private: /// given record decl. void ComputeVTableRelatedInformation(const CXXRecordDecl *RD); + /// ErrorUnsupported - Print out an error that the v-table layout code + /// doesn't support the particular C++ feature yet. + void ErrorUnsupported(StringRef Feature, SourceLocation Location); + public: - VTableContext(ASTContext &Context) : Context(Context) {} + VTableContext(ASTContext &Context); ~VTableContext(); + bool isMicrosoftABI() const { + // FIXME: Currently, this method is only used in the VTableContext and + // VTableBuilder code which is ABI-specific. Probably we can remove it + // when we add a layer of abstraction for vtable generation. + return IsMicrosoftABI; + } + const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) { ComputeVTableRelatedInformation(RD); assert(VTableLayouts.count(RD) && "No layout for this record decl!"); diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h index 30b4050..870a39b 100644 --- a/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/include/clang/ASTMatchers/ASTMatchFinder.h @@ -56,6 +56,10 @@ namespace ast_matchers { /// that will trigger the callbacks specified via addMatcher(...) when a match /// is found. /// +/// The order of matches is guaranteed to be equivalent to doing a pre-order +/// traversal on the AST, and applying the matchers in the order in which they +/// were added to the MatchFinder. +/// /// See ASTMatchers.h for more information about how to create matchers. /// /// Not intended to be subclassed. @@ -130,11 +134,17 @@ public: /// \brief Creates a clang ASTConsumer that finds all matches. clang::ASTConsumer *newASTConsumer(); - /// \brief Finds all matches on the given \c Node. + /// \brief Calls the registered callbacks on all matches on the given \p Node. + /// + /// Note that there can be multiple matches on a single node, for + /// example when using decl(forEachDescendant(stmt())). /// /// @{ - void findAll(const Decl &Node, ASTContext &Context); - void findAll(const Stmt &Node, ASTContext &Context); + template <typename T> void match(const T &Node, ASTContext &Context) { + match(clang::ast_type_traits::DynTypedNode::create(Node), Context); + } + void match(const clang::ast_type_traits::DynTypedNode &Node, + ASTContext &Context); /// @} /// \brief Registers a callback to notify the end of parsing. @@ -154,6 +164,75 @@ private: ParsingDoneTestCallback *ParsingDone; }; +/// \brief Returns the results of matching \p Matcher on \p Node. +/// +/// Collects the \c BoundNodes of all callback invocations when matching +/// \p Matcher on \p Node and returns the collected results. +/// +/// Multiple results occur when using matchers like \c forEachDescendant, +/// which generate a result for each sub-match. +/// +/// \see selectFirst +/// @{ +template <typename MatcherT, typename NodeT> +SmallVector<BoundNodes, 1> +match(MatcherT Matcher, const NodeT &Node, ASTContext &Context); + +template <typename MatcherT> +SmallVector<BoundNodes, 1> +match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node, + ASTContext &Context); +/// @} + +/// \brief Returns the first result of type \c NodeT bound to \p BoundTo. +/// +/// Returns \c NULL if there is no match, or if the matching node cannot be +/// casted to \c NodeT. +/// +/// This is useful in combanation with \c match(): +/// \code +/// Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"), +/// Node, Context)); +/// \endcode +template <typename NodeT> +NodeT * +selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) { + for (SmallVectorImpl<BoundNodes>::const_iterator I = Results.begin(), + E = Results.end(); + I != E; ++I) { + if (NodeT *Node = I->getNodeAs<NodeT>(BoundTo)) + return Node; + } + return NULL; +} + +namespace internal { +class CollectMatchesCallback : public MatchFinder::MatchCallback { +public: + virtual void run(const MatchFinder::MatchResult &Result) { + Nodes.push_back(Result.Nodes); + } + SmallVector<BoundNodes, 1> Nodes; +}; +} + +template <typename MatcherT> +SmallVector<BoundNodes, 1> +match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node, + ASTContext &Context) { + internal::CollectMatchesCallback Callback; + MatchFinder Finder; + Finder.addMatcher(Matcher, &Callback); + Finder.match(Node, Context); + return Callback.Nodes; +} + +template <typename MatcherT, typename NodeT> +SmallVector<BoundNodes, 1> +match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) { + return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context); +} + } // end namespace ast_matchers } // end namespace clang diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index a70dd5c..f10addc 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -142,7 +142,7 @@ inline internal::PolymorphicMatcherWithParam0<internal::TrueMatcher> anything() /// friend X; /// }; /// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, Decl> decl; +const internal::VariadicAllOfMatcher<Decl> decl; /// \brief Matches a declaration of anything that could have a name. /// @@ -192,6 +192,69 @@ const internal::VariadicDynCastAllOfMatcher< Decl, ClassTemplateSpecializationDecl> classTemplateSpecializationDecl; +/// \brief Matches C++ access specifier declarations. +/// +/// Given +/// \code +/// class C { +/// public: +/// int a; +/// }; +/// \endcode +/// accessSpecDecl() +/// matches 'public:' +const internal::VariadicDynCastAllOfMatcher< + Decl, + AccessSpecDecl> accessSpecDecl; + +/// \brief Matches public C++ declarations. +/// +/// Given +/// \code +/// class C { +/// public: int a; +/// protected: int b; +/// private: int c; +/// }; +/// \endcode +/// fieldDecl(isPublic()) +/// matches 'int a;' +AST_MATCHER(Decl, isPublic) { + return Node.getAccess() == AS_public; +} + +/// \brief Matches protected C++ declarations. +/// +/// Given +/// \code +/// class C { +/// public: int a; +/// protected: int b; +/// private: int c; +/// }; +/// \endcode +/// fieldDecl(isProtected()) +/// matches 'int b;' +AST_MATCHER(Decl, isProtected) { + return Node.getAccess() == AS_protected; +} + +/// \brief Matches private C++ declarations. +/// +/// Given +/// \code +/// class C { +/// public: int a; +/// protected: int b; +/// private: int c; +/// }; +/// \endcode +/// fieldDecl(isPrivate()) +/// matches 'int c;' +AST_MATCHER(Decl, isPrivate) { + return Node.getAccess() == AS_private; +} + /// \brief Matches classTemplateSpecializations that have at least one /// TemplateArgument matching the given InnerMatcher. /// @@ -453,7 +516,7 @@ const internal::VariadicDynCastAllOfMatcher< /// \endcode /// stmt() /// matches both the compound statement '{ ++a; }' and '++a'. -const internal::VariadicDynCastAllOfMatcher<Stmt, Stmt> stmt; +const internal::VariadicAllOfMatcher<Stmt> stmt; /// \brief Matches declaration statements. /// @@ -922,6 +985,16 @@ const internal::VariadicDynCastAllOfMatcher< Stmt, UserDefinedLiteral> userDefinedLiteral; +/// \brief Matches compound (i.e. non-scalar) literals +/// +/// Example match: {1}, (1, 2) +/// \code +/// int array[4] = {1}; vector int myvec = (vector int)(1, 2); +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CompoundLiteralExpr> compoundLiteralExpr; + /// \brief Matches nullptr literal. const internal::VariadicDynCastAllOfMatcher< Stmt, @@ -1090,10 +1163,36 @@ const internal::VariadicDynCastAllOfMatcher< const internal::VariadicAllOfMatcher<QualType> qualType; /// \brief Matches \c Types in the clang AST. -const internal::VariadicDynCastAllOfMatcher<Type, Type> type; +const internal::VariadicAllOfMatcher<Type> type; /// \brief Matches \c TypeLocs in the clang AST. -const internal::VariadicDynCastAllOfMatcher<TypeLoc, TypeLoc> typeLoc; +const internal::VariadicAllOfMatcher<TypeLoc> typeLoc; + +/// \brief Matches if any of the given matchers matches. +/// +/// Unlike \c anyOf, \c eachOf will generate a match result for each +/// matching submatcher. +/// +/// For example, in: +/// \code +/// class A { int a; int b; }; +/// \endcode +/// The matcher: +/// \code +/// recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")), +/// has(fieldDecl(hasName("b")).bind("v")))) +/// \endcode +/// will generate two results binding "v", the first of which binds +/// the field declaration of \c a, the second the field declaration of +/// \c b. +/// +/// Usable as: Any Matcher +template <typename M1, typename M2> +internal::PolymorphicMatcherWithParam2<internal::EachOfMatcher, M1, M2> +eachOf(const M1 &P1, const M2 &P2) { + return internal::PolymorphicMatcherWithParam2<internal::EachOfMatcher, M1, + M2>(P1, P2); +} /// \brief Various overloads for the anyOf matcher. /// @{ @@ -1139,18 +1238,40 @@ anyOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) { /// \brief Matches if all given matchers match. /// /// Usable as: Any Matcher -template<typename M1, typename M2> +template <typename M1, typename M2> internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M1, M2> allOf(const M1 &P1, const M2 &P2) { - return internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, - M1, M2>(P1, P2); + return internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M1, M2>( + P1, P2); } -template<typename M1, typename M2, typename M3> -internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M1, +template <typename M1, typename M2, typename M3> +internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M1, internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M2, M3> > allOf(const M1 &P1, const M2 &P2, const M3 &P3) { return allOf(P1, allOf(P2, P3)); } +template <typename M1, typename M2, typename M3, typename M4> +internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M1, + internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M2, internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M3, M4> > > +allOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) { + return allOf(P1, allOf(P2, P3, P4)); +} +template <typename M1, typename M2, typename M3, typename M4, typename M5> +internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M1, + internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M2, + internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M3, + internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M4, + M5> > > > +allOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) { + return allOf(P1, allOf(P2, P3, P4, P5)); +} /// @} @@ -1198,7 +1319,7 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) { /// alignof. inline internal::Matcher<Stmt> alignOfExpr( const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) { - return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf( + return stmt(unaryExprOrTypeTraitExpr(allOf( ofKind(UETT_AlignOf), InnerMatcher))); } @@ -1206,8 +1327,8 @@ inline internal::Matcher<Stmt> alignOfExpr( /// sizeof. inline internal::Matcher<Stmt> sizeOfExpr( const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) { - return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf( - ofKind(UETT_SizeOf), InnerMatcher))); + return stmt(unaryExprOrTypeTraitExpr( + allOf(ofKind(UETT_SizeOf), InnerMatcher))); } /// \brief Matches NamedDecl nodes that have the specified name. @@ -1228,8 +1349,8 @@ inline internal::Matcher<Stmt> sizeOfExpr( AST_MATCHER_P(NamedDecl, hasName, std::string, Name) { assert(!Name.empty()); const std::string FullNameString = "::" + Node.getQualifiedNameAsString(); - const llvm::StringRef FullName = FullNameString; - const llvm::StringRef Pattern = Name; + const StringRef FullName = FullNameString; + const StringRef Pattern = Name; if (Pattern.startswith("::")) { return FullName == Pattern; } else { @@ -1237,8 +1358,8 @@ AST_MATCHER_P(NamedDecl, hasName, std::string, Name) { } } -/// \brief Matches NamedDecl nodes whose full names partially match the -/// given RegExp. +/// \brief Matches NamedDecl nodes whose fully qualified names contain +/// a substring matched by the given RegExp. /// /// Supports specifying enclosing namespaces or classes by /// prefixing the name with '<enclosing>::'. Does not match typedefs @@ -1263,18 +1384,26 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { /// \brief Matches overloaded operator names. /// /// Matches overloaded operator names specified in strings without the -/// "operator" prefix, such as "<<", for OverloadedOperatorCall's. +/// "operator" prefix: e.g. "<<". /// -/// Example matches a << b -/// (matcher == operatorCallExpr(hasOverloadedOperatorName("<<"))) +/// Given: /// \code -/// a << b; -/// c && d; // assuming both operator<< -/// // and operator&& are overloaded somewhere. +/// class A { int operator*(); }; +/// const A &operator<<(const A &a, const A &b); +/// A a; +/// a << a; // <-- This matches /// \endcode -AST_MATCHER_P(CXXOperatorCallExpr, - hasOverloadedOperatorName, std::string, Name) { - return getOperatorSpelling(Node.getOperator()) == Name; +/// +/// \c operatorCallExpr(hasOverloadedOperatorName("<<"))) matches the specified +/// line and \c recordDecl(hasMethod(hasOverloadedOperatorName("*"))) matches +/// the declaration of \c A. +/// +/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<CXXMethodDecl> +inline internal::PolymorphicMatcherWithParam1< + internal::HasOverloadedOperatorNameMatcher, StringRef> +hasOverloadedOperatorName(const StringRef Name) { + return internal::PolymorphicMatcherWithParam1< + internal::HasOverloadedOperatorNameMatcher, StringRef>(Name); } /// \brief Matches C++ classes that are directly or indirectly derived from @@ -1324,6 +1453,27 @@ inline internal::Matcher<CXXRecordDecl> isSameOrDerivedFrom( return isSameOrDerivedFrom(hasName(BaseName)); } +/// \brief Matches the first method of a class or struct that satisfies \c +/// InnerMatcher. +/// +/// Given: +/// \code +/// class A { void func(); }; +/// class B { void member(); }; +/// \code +/// +/// \c recordDecl(hasMethod(hasName("func"))) matches the declaration of \c A +/// but not \c B. +AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>, + InnerMatcher) { + for (CXXRecordDecl::method_iterator I = Node.method_begin(), + E = Node.method_end(); + I != E; ++I) + if (InnerMatcher.matches(**I, Finder, Builder)) + return true; + return false; +} + /// \brief Matches AST nodes that have child AST nodes that match the /// provided matcher. /// @@ -1424,6 +1574,29 @@ forEachDescendant( DescendantT>(DescendantMatcher); } +/// \brief Matches if the node or any descendant matches. +/// +/// Generates results for each match. +/// +/// For example, in: +/// \code +/// class A { class B {}; class C {}; }; +/// \endcode +/// The matcher: +/// \code +/// recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("m"))) +/// \endcode +/// will generate results for \c A, \c B and \c C. +/// +/// Usable as: Any Matcher +template <typename T> +internal::PolymorphicMatcherWithParam2< + internal::EachOfMatcher, internal::Matcher<T>, + internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher, T> > +findAll(const internal::Matcher<T> &Matcher) { + return eachOf(Matcher, forEachDescendant(Matcher)); +} + /// \brief Matches AST nodes that have a parent that matches the provided /// matcher. /// @@ -1480,8 +1653,13 @@ unless(const M &InnerMatcher) { /// \brief Matches a type if the declaration of the type matches the given /// matcher. /// +/// In addition to being usable as Matcher<TypedefType>, also usable as +/// Matcher<T> for any T supporting the getDecl() member function. e.g. various +/// subtypes of clang::Type. +/// /// Usable as: Matcher<QualType>, Matcher<CallExpr>, Matcher<CXXConstructExpr>, -/// Matcher<MemberExpr> +/// Matcher<MemberExpr>, Matcher<TypedefType>, +/// Matcher<TemplateSpecializationType> inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, internal::Matcher<Decl> > hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) { @@ -1501,9 +1679,8 @@ inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, /// FIXME: Overload to allow directly matching types? AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>, InnerMatcher) { - const Expr *ExprNode = const_cast<CXXMemberCallExpr&>(Node) - .getImplicitObjectArgument() - ->IgnoreParenImpCasts(); + const Expr *ExprNode = Node.getImplicitObjectArgument() + ->IgnoreParenImpCasts(); return (ExprNode != NULL && InnerMatcher.matches(*ExprNode, Finder, Builder)); } @@ -1541,7 +1718,7 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>, /// \endcode inline internal::Matcher<CallExpr> callee( const internal::Matcher<Decl> &InnerMatcher) { - return internal::Matcher<CallExpr>(hasDeclaration(InnerMatcher)); + return callExpr(hasDeclaration(InnerMatcher)); } /// \brief Matches if the expression's or declaration's type matches a type @@ -1579,11 +1756,10 @@ AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<QualType>, /// /// Usable as: Matcher<Expr>, Matcher<ValueDecl> inline internal::PolymorphicMatcherWithParam1< - internal::matcher_hasTypeMatcher, + internal::matcher_hasType0Matcher, internal::Matcher<QualType> > hasType(const internal::Matcher<Decl> &InnerMatcher) { - return hasType(internal::Matcher<QualType>( - hasDeclaration(InnerMatcher))); + return hasType(qualType(hasDeclaration(InnerMatcher))); } /// \brief Matches if the matched type is represented by the given string. @@ -1618,8 +1794,7 @@ AST_MATCHER_P( /// \brief Overloaded to match the pointee type's declaration. inline internal::Matcher<QualType> pointsTo( const internal::Matcher<Decl> &InnerMatcher) { - return pointsTo(internal::Matcher<QualType>( - hasDeclaration(InnerMatcher))); + return pointsTo(qualType(hasDeclaration(InnerMatcher))); } /// \brief Matches if the matched type is a reference type and the referenced @@ -1640,17 +1815,32 @@ AST_MATCHER_P(QualType, references, internal::Matcher<QualType>, InnerMatcher.matches(Node->getPointeeType(), Finder, Builder)); } +/// \brief Matches QualTypes whose canonical type matches InnerMatcher. +/// +/// Given: +/// \code +/// typedef int &int_ref; +/// int a; +/// int_ref b = a; +/// \code +/// +/// \c varDecl(hasType(qualType(referenceType()))))) will not match the +/// declaration of b but \c +/// varDecl(hasType(qualType(hasCanonicalType(referenceType())))))) does. +AST_MATCHER_P(QualType, hasCanonicalType, internal::Matcher<QualType>, + InnerMatcher) { + return InnerMatcher.matches(Node.getCanonicalType(), Finder, Builder); +} + /// \brief Overloaded to match the referenced type's declaration. inline internal::Matcher<QualType> references( const internal::Matcher<Decl> &InnerMatcher) { - return references(internal::Matcher<QualType>( - hasDeclaration(InnerMatcher))); + return references(qualType(hasDeclaration(InnerMatcher))); } AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument, internal::Matcher<Expr>, InnerMatcher) { - const Expr *ExprNode = - const_cast<CXXMemberCallExpr&>(Node).getImplicitObjectArgument(); + const Expr *ExprNode = Node.getImplicitObjectArgument(); return (ExprNode != NULL && InnerMatcher.matches(*ExprNode, Finder, Builder)); } @@ -1705,8 +1895,7 @@ AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>, AST_MATCHER_P(DeclRefExpr, throughUsingDecl, internal::Matcher<UsingShadowDecl>, InnerMatcher) { const NamedDecl *FoundDecl = Node.getFoundDecl(); - if (const UsingShadowDecl *UsingDecl = - llvm::dyn_cast<UsingShadowDecl>(FoundDecl)) + if (const UsingShadowDecl *UsingDecl = dyn_cast<UsingShadowDecl>(FoundDecl)) return InnerMatcher.matches(*UsingDecl, Finder, Builder); return false; } @@ -1974,6 +2163,19 @@ AST_MATCHER_P(FunctionDecl, hasAnyParameter, return false; } +/// \brief Matches \c FunctionDecls that have a specific parameter count. +/// +/// Given +/// \code +/// void f(int i) {} +/// void g(int i, int j) {} +/// \endcode +/// functionDecl(parameterCountIs(2)) +/// matches g(int i, int j) {} +AST_MATCHER_P(FunctionDecl, parameterCountIs, unsigned, N) { + return Node.getNumParams() == N; +} + /// \brief Matches the return type of a function declaration. /// /// Given: @@ -2279,10 +2481,13 @@ AST_MATCHER_P(ConditionalOperator, hasFalseExpression, /// \endcode /// /// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl> -inline internal::PolymorphicMatcherWithParam0<internal::IsDefinitionMatcher> -isDefinition() { - return internal::PolymorphicMatcherWithParam0< - internal::IsDefinitionMatcher>(); +AST_POLYMORPHIC_MATCHER(isDefinition) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of<TagDecl, NodeType>::value) || + (llvm::is_base_of<VarDecl, NodeType>::value) || + (llvm::is_base_of<FunctionDecl, NodeType>::value), + is_definition_requires_isThisDeclarationADefinition_method); + return Node.isThisDeclarationADefinition(); } /// \brief Matches the class declaration that the given method declaration @@ -2324,8 +2529,8 @@ AST_MATCHER_P(CXXMethodDecl, ofClass, /// \endcode /// memberExpr(isArrow()) /// matches this->x, x, y.x, a, this->b -inline internal::Matcher<MemberExpr> isArrow() { - return makeMatcher(new internal::IsArrowMatcher()); +AST_MATCHER(MemberExpr, isArrow) { + return Node.isArrow(); } /// \brief Matches QualType nodes that are of integer type. @@ -2357,8 +2562,25 @@ AST_MATCHER(QualType, isInteger) { /// matches "void b(int const)", "void c(const int)" and /// "void e(int const) {}". It does not match d as there /// is no top-level const on the parameter type "const int *". -inline internal::Matcher<QualType> isConstQualified() { - return makeMatcher(new internal::IsConstQualifiedMatcher()); +AST_MATCHER(QualType, isConstQualified) { + return Node.isConstQualified(); +} + +/// \brief Matches QualType nodes that have local CV-qualifiers attached to +/// the node, not hidden within a typedef. +/// +/// Given +/// \code +/// typedef const int const_int; +/// const_int i; +/// int *const j; +/// int *volatile k; +/// int m; +/// \endcode +/// \c varDecl(hasType(hasLocalQualifiers())) matches only \c j and \c k. +/// \c i is const-qualified but the qualifier is not local. +AST_MATCHER(QualType, hasLocalQualifiers) { + return Node.hasLocalQualifiers(); } /// \brief Matches a member expression where the member is matched by a @@ -2454,11 +2676,14 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl, /// does not match, as X<A> is an explicit template specialization. /// /// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl> -inline internal::PolymorphicMatcherWithParam0< - internal::IsTemplateInstantiationMatcher> -isTemplateInstantiation() { - return internal::PolymorphicMatcherWithParam0< - internal::IsTemplateInstantiationMatcher>(); +AST_POLYMORPHIC_MATCHER(isTemplateInstantiation) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, NodeType>::value) || + (llvm::is_base_of<VarDecl, NodeType>::value) || + (llvm::is_base_of<CXXRecordDecl, NodeType>::value), + requires_getTemplateSpecializationKind_method); + return (Node.getTemplateSpecializationKind() == TSK_ImplicitInstantiation || + Node.getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDefinition); } /// \brief Matches explicit template specializations of function, class, or @@ -2473,11 +2698,12 @@ isTemplateInstantiation() { /// matches the specialization A<int>(). /// /// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl> -inline internal::PolymorphicMatcherWithParam0< - internal::IsExplicitTemplateSpecializationMatcher> -isExplicitTemplateSpecialization() { - return internal::PolymorphicMatcherWithParam0< - internal::IsExplicitTemplateSpecializationMatcher>(); +AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, NodeType>::value) || + (llvm::is_base_of<VarDecl, NodeType>::value) || + (llvm::is_base_of<CXXRecordDecl, NodeType>::value), + requires_getTemplateSpecializationKind_method); + return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization); } /// \brief Matches \c TypeLocs for which the given inner @@ -2685,6 +2911,32 @@ AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType); /// matches "int (*f)(int)" and the type of "g". AST_TYPE_MATCHER(FunctionType, functionType); +/// \brief Matches \c ParenType nodes. +/// +/// Given +/// \code +/// int (*ptr_to_array)[4]; +/// int *array_of_ptrs[4]; +/// \endcode +/// +/// \c varDecl(hasType(pointsTo(parenType()))) matches \c ptr_to_array but not +/// \c array_of_ptrs. +AST_TYPE_MATCHER(ParenType, parenType); + +/// \brief Matches \c ParenType nodes where the inner type is a specific type. +/// +/// Given +/// \code +/// int (*ptr_to_array)[4]; +/// int (*ptr_to_func)(int); +/// \endcode +/// +/// \c varDecl(hasType(pointsTo(parenType(innerType(functionType()))))) matches +/// \c ptr_to_func but not \c ptr_to_array. +/// +/// Usable as: Matcher<ParenType> +AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType); + /// \brief Matches block pointer types, i.e. types syntactically represented as /// "void (^)(int)". /// @@ -2713,18 +2965,56 @@ AST_TYPE_MATCHER(MemberPointerType, memberPointerType); /// matches "int *a" AST_TYPE_MATCHER(PointerType, pointerType); -/// \brief Matches reference types. +/// \brief Matches both lvalue and rvalue reference types. /// /// Given /// \code /// int *a; /// int &b = *a; -/// int c = 5; +/// int &&c = 1; +/// auto &d = b; +/// auto &&e = c; +/// auto &&f = 2; +/// int g = 5; /// \endcode -/// pointerType() -/// matches "int &b" +/// +/// \c referenceType() matches the types of \c b, \c c, \c d, \c e, and \c f. AST_TYPE_MATCHER(ReferenceType, referenceType); +/// \brief Matches lvalue reference types. +/// +/// Given: +/// \code +/// int *a; +/// int &b = *a; +/// int &&c = 1; +/// auto &d = b; +/// auto &&e = c; +/// auto &&f = 2; +/// int g = 5; +/// \endcode +/// +/// \c lValueReferenceType() matches the types of \c b, \c d, and \c e. \c e is +/// matched since the type is deduced as int& by reference collapsing rules. +AST_TYPE_MATCHER(LValueReferenceType, lValueReferenceType); + +/// \brief Matches rvalue reference types. +/// +/// Given: +/// \code +/// int *a; +/// int &b = *a; +/// int &&c = 1; +/// auto &d = b; +/// auto &&e = c; +/// auto &&f = 2; +/// int g = 5; +/// \endcode +/// +/// \c rValueReferenceType() matches the types of \c c and \c f. \c e is not +/// matched as it is deduced to int& by reference collapsing rules. +AST_TYPE_MATCHER(RValueReferenceType, rValueReferenceType); + /// \brief Narrows PointerType (and similar) matchers to those where the /// \c pointee matches a given matcher. /// @@ -2751,11 +3041,116 @@ AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee); /// matches "typedef int X" AST_TYPE_MATCHER(TypedefType, typedefType); -/// \brief Matches \c TypedefTypes referring to a specific -/// \c TypedefNameDecl. -AST_MATCHER_P(TypedefType, hasDecl, - internal::Matcher<TypedefNameDecl>, InnerMatcher) { - return InnerMatcher.matches(*Node.getDecl(), Finder, Builder); +/// \brief Matches template specialization types. +/// +/// Given +/// \code +/// template <typename T> +/// class C { }; +/// +/// template class C<int>; // A +/// C<char> var; // B +/// \code +/// +/// \c templateSpecializationType() matches the type of the explicit +/// instantiation in \c A and the type of the variable declaration in \c B. +AST_TYPE_MATCHER(TemplateSpecializationType, templateSpecializationType); + +/// \brief Matches record types (e.g. structs, classes). +/// +/// Given +/// \code +/// class C {}; +/// struct S {}; +/// +/// C c; +/// S s; +/// \code +/// +/// \c recordType() matches the type of the variable declarations of both \c c +/// and \c s. +AST_TYPE_MATCHER(RecordType, recordType); + +/// \brief Matches types specified with an elaborated type keyword or with a +/// qualified name. +/// +/// Given +/// \code +/// namespace N { +/// namespace M { +/// class D {}; +/// } +/// } +/// class C {}; +/// +/// class C c; +/// N::M::D d; +/// \code +/// +/// \c elaboratedType() matches the type of the variable declarations of both +/// \c c and \c d. +AST_TYPE_MATCHER(ElaboratedType, elaboratedType); + +/// \brief Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier, +/// matches \c InnerMatcher if the qualifier exists. +/// +/// Given +/// \code +/// namespace N { +/// namespace M { +/// class D {}; +/// } +/// } +/// N::M::D d; +/// \code +/// +/// \c elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))) +/// matches the type of the variable declaration of \c d. +AST_MATCHER_P(ElaboratedType, hasQualifier, + internal::Matcher<NestedNameSpecifier>, InnerMatcher) { + if (const NestedNameSpecifier *Qualifier = Node.getQualifier()) + return InnerMatcher.matches(*Qualifier, Finder, Builder); + + return false; +} + +/// \brief Matches ElaboratedTypes whose named type matches \c InnerMatcher. +/// +/// Given +/// \code +/// namespace N { +/// namespace M { +/// class D {}; +/// } +/// } +/// N::M::D d; +/// \code +/// +/// \c elaboratedType(namesType(recordType( +/// hasDeclaration(namedDecl(hasName("D")))))) matches the type of the variable +/// declaration of \c d. +AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>, + InnerMatcher) { + return InnerMatcher.matches(Node.getNamedType(), Finder, Builder); +} + +/// \brief Matches declarations whose declaration context, interpreted as a +/// Decl, matches \c InnerMatcher. +/// +/// Given +/// \code +/// namespace N { +/// namespace M { +/// class D {}; +/// } +/// } +/// \code +/// +/// \c recordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the +/// declaration of \c class \c D. +AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) { + return InnerMatcher.matches(*Decl::castFromDeclContext(Node.getDeclContext()), + Finder, Builder); } /// \brief Matches nested name specifiers. @@ -2828,10 +3223,13 @@ AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc, /// \endcode /// nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A")))) and /// matches "A::" -inline internal::Matcher<NestedNameSpecifier> hasPrefix( - const internal::Matcher<NestedNameSpecifier> &InnerMatcher) { - return internal::makeMatcher( - new internal::NestedNameSpecifierPrefixMatcher(InnerMatcher)); +AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix, + internal::Matcher<NestedNameSpecifier>, InnerMatcher, + 0) { + NestedNameSpecifier *NextNode = Node.getPrefix(); + if (NextNode == NULL) + return false; + return InnerMatcher.matches(*NextNode, Finder, Builder); } /// \brief Matches on the prefix of a \c NestedNameSpecifierLoc. @@ -2843,10 +3241,13 @@ inline internal::Matcher<NestedNameSpecifier> hasPrefix( /// \endcode /// nestedNameSpecifierLoc(hasPrefix(loc(specifiesType(asString("struct A"))))) /// matches "A::" -inline internal::Matcher<NestedNameSpecifierLoc> hasPrefix( - const internal::Matcher<NestedNameSpecifierLoc> &InnerMatcher) { - return internal::makeMatcher( - new internal::NestedNameSpecifierLocPrefixMatcher(InnerMatcher)); +AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix, + internal::Matcher<NestedNameSpecifierLoc>, InnerMatcher, + 1) { + NestedNameSpecifierLoc NextNode = Node.getPrefix(); + if (!NextNode) + return false; + return InnerMatcher.matches(NextNode, Finder, Builder); } /// \brief Matches nested name specifiers that specify a namespace matching the @@ -2866,6 +3267,26 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace, return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder); } +/// \brief Overloads for the \c equalsNode matcher. +/// FIXME: Implement for other node types. +/// @{ + +/// \brief Matches if a node equals another node. +/// +/// \c Decl has pointer identity in the AST. +AST_MATCHER_P_OVERLOAD(Decl, equalsNode, Decl*, Other, 0) { + return &Node == Other; +} +/// \brief Matches if a node equals another node. +/// +/// \c Stmt has pointer identity in the AST. +/// +AST_MATCHER_P_OVERLOAD(Stmt, equalsNode, Stmt*, Other, 1) { + return &Node == Other; +} + +/// @} + } // end namespace ast_matchers } // end namespace clang diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index e5365ff..30691ad 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -35,13 +35,13 @@ #ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H #define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H -#include "clang/AST/Decl.h" +#include "clang/AST/ASTTypeTraits.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/Decl.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" +#include "clang/AST/Stmt.h" #include "clang/AST/Type.h" -#include "clang/ASTMatchers/ASTTypeTraits.h" #include "llvm/ADT/VariadicFunction.h" #include "llvm/Support/type_traits.h" #include <map> @@ -193,7 +193,7 @@ class ASTMatchFinder; /// current node and doesn't care about its children or descendants, /// implement SingleNodeMatcherInterface instead. template <typename T> -class MatcherInterface : public llvm::RefCountedBaseVPTR { +class MatcherInterface : public RefCountedBaseVPTR { public: virtual ~MatcherInterface() {} @@ -343,7 +343,7 @@ private: const Matcher<Base> From; }; - llvm::IntrusiveRefCntPtr< MatcherInterface<T> > Implementation; + IntrusiveRefCntPtr< MatcherInterface<T> > Implementation; }; // class Matcher /// \brief A convenient helper for creating a Matcher<T> without specifying @@ -353,6 +353,61 @@ inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) { return Matcher<T>(Implementation); } +/// \brief Metafunction to determine if type T has a member called getDecl. +template <typename T> struct has_getDecl { + struct Default { int getDecl; }; + struct Derived : T, Default { }; + + template<typename C, C> struct CheckT; + + // If T::getDecl exists, an ambiguity arises and CheckT will + // not be instantiable. This makes f(...) the only available + // overload. + template<typename C> + static char (&f(CheckT<int Default::*, &C::getDecl>*))[1]; + template<typename C> static char (&f(...))[2]; + + static bool const value = sizeof(f<Derived>(0)) == 2; +}; + +/// \brief Matches overloaded operators with a specific name. +/// +/// The type argument ArgT is not used by this matcher but is used by +/// PolymorphicMatcherWithParam1 and should be StringRef. +template <typename T, typename ArgT> +class HasOverloadedOperatorNameMatcher : public SingleNodeMatcherInterface<T> { + TOOLING_COMPILE_ASSERT((llvm::is_same<T, CXXOperatorCallExpr>::value || + llvm::is_same<T, CXXMethodDecl>::value), + unsupported_class_for_matcher); + TOOLING_COMPILE_ASSERT((llvm::is_same<ArgT, StringRef>::value), + argument_type_must_be_StringRef); +public: + explicit HasOverloadedOperatorNameMatcher(const StringRef Name) + : SingleNodeMatcherInterface<T>(), Name(Name) {} + + virtual bool matchesNode(const T &Node) const LLVM_OVERRIDE { + return matchesSpecialized(Node); + } + +private: + + /// \brief CXXOperatorCallExpr exist only for calls to overloaded operators + /// so this function returns true if the call is to an operator of the given + /// name. + bool matchesSpecialized(const CXXOperatorCallExpr &Node) const { + return getOperatorSpelling(Node.getOperator()) == Name; + } + + /// \brief Returns true only if CXXMethodDecl represents an overloaded + /// operator and has the given operator name. + bool matchesSpecialized(const CXXMethodDecl &Node) const { + return Node.isOverloadedOperator() && + getOperatorSpelling(Node.getOverloadedOperator()) == Name; + } + + std::string Name; +}; + /// \brief Matches declarations for QualType and CallExpr. /// /// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but @@ -373,16 +428,36 @@ public: } private: - /// \brief Extracts the CXXRecordDecl of a QualType and returns whether the - /// inner matcher matches on it. + /// \brief If getDecl exists as a member of U, returns whether the inner + /// matcher matches Node.getDecl(). + template <typename U> + bool matchesSpecialized( + const U &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, + typename llvm::enable_if<has_getDecl<U>, int>::type = 0) const { + return matchesDecl(Node.getDecl(), Finder, Builder); + } + + /// \brief Extracts the CXXRecordDecl or EnumDecl of a QualType and returns + /// whether the inner matcher matches on it. bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { /// FIXME: Add other ways to convert... if (Node.isNull()) return false; + if (const EnumType *AsEnum = dyn_cast<EnumType>(Node.getTypePtr())) + return matchesDecl(AsEnum->getDecl(), Finder, Builder); return matchesDecl(Node->getAsCXXRecordDecl(), Finder, Builder); } + /// \brief Gets the TemplateDecl from a TemplateSpecializationType + /// and returns whether the inner matches on it. + bool matchesSpecialized(const TemplateSpecializationType &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return matchesDecl(Node.getTemplateName().getAsTemplateDecl(), + Finder, Builder); + } + /// \brief Extracts the Decl of the callee of a CallExpr and returns whether /// the inner matcher matches on it. bool matchesSpecialized(const CallExpr &Node, ASTMatchFinder *Finder, @@ -537,6 +612,8 @@ public: Matcher, Builder, MatchMode); } + virtual ASTContext &getASTContext() const = 0; + protected: virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node, const DynTypedMatcher &Matcher, @@ -672,7 +749,7 @@ public: virtual bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { - const To *InnerMatchValue = llvm::dyn_cast<To>(&Node); + const To *InnerMatchValue = dyn_cast<To>(&Node); return InnerMatchValue != NULL && InnerMatcher.matches(*InnerMatchValue, Finder, Builder); } @@ -828,21 +905,56 @@ private: /// used. They will always be instantiated with types convertible to /// Matcher<T>. template <typename T, typename MatcherT1, typename MatcherT2> +class EachOfMatcher : public MatcherInterface<T> { +public: + EachOfMatcher(const Matcher<T> &InnerMatcher1, + const Matcher<T> &InnerMatcher2) + : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) { + } + + virtual bool matches(const T &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + BoundNodesTreeBuilder Builder1; + bool Matched1 = InnerMatcher1.matches(Node, Finder, &Builder1); + if (Matched1) + Builder->addMatch(Builder1.build()); + + BoundNodesTreeBuilder Builder2; + bool Matched2 = InnerMatcher2.matches(Node, Finder, &Builder2); + if (Matched2) + Builder->addMatch(Builder2.build()); + + return Matched1 || Matched2; + } + +private: + const Matcher<T> InnerMatcher1; + const Matcher<T> InnerMatcher2; +}; + +/// \brief Matches nodes of type T for which at least one of the two provided +/// matchers matches. +/// +/// Type arguments MatcherT1 and MatcherT2 are +/// required by PolymorphicMatcherWithParam2 but not actually +/// used. They will always be instantiated with types convertible to +/// Matcher<T>. +template <typename T, typename MatcherT1, typename MatcherT2> class AnyOfMatcher : public MatcherInterface<T> { public: AnyOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T> &InnerMatcher2) - : InnerMatcher1(InnerMatcher1), InnertMatcher2(InnerMatcher2) {} + : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {} virtual bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return InnerMatcher1.matches(Node, Finder, Builder) || - InnertMatcher2.matches(Node, Finder, Builder); + InnerMatcher2.matches(Node, Finder, Builder); } private: const Matcher<T> InnerMatcher1; - const Matcher<T> InnertMatcher2; + const Matcher<T> InnerMatcher2; }; /// \brief Creates a Matcher<T> that matches if all inner matchers match. @@ -989,69 +1101,6 @@ private: const ValueT ExpectedValue; }; -template <typename T> -class IsDefinitionMatcher : public SingleNodeMatcherInterface<T> { - TOOLING_COMPILE_ASSERT( - (llvm::is_base_of<TagDecl, T>::value) || - (llvm::is_base_of<VarDecl, T>::value) || - (llvm::is_base_of<FunctionDecl, T>::value), - is_definition_requires_isThisDeclarationADefinition_method); -public: - virtual bool matchesNode(const T &Node) const { - return Node.isThisDeclarationADefinition(); - } -}; - -/// \brief Matches on template instantiations for FunctionDecl, VarDecl or -/// CXXRecordDecl nodes. -template <typename T> -class IsTemplateInstantiationMatcher : public MatcherInterface<T> { - TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, T>::value) || - (llvm::is_base_of<VarDecl, T>::value) || - (llvm::is_base_of<CXXRecordDecl, T>::value), - requires_getTemplateSpecializationKind_method); - public: - virtual bool matches(const T& Node, - ASTMatchFinder* Finder, - BoundNodesTreeBuilder* Builder) const { - return (Node.getTemplateSpecializationKind() == - TSK_ImplicitInstantiation || - Node.getTemplateSpecializationKind() == - TSK_ExplicitInstantiationDefinition); - } -}; - -/// \brief Matches on explicit template specializations for FunctionDecl, -/// VarDecl or CXXRecordDecl nodes. -template <typename T> -class IsExplicitTemplateSpecializationMatcher : public MatcherInterface<T> { - TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, T>::value) || - (llvm::is_base_of<VarDecl, T>::value) || - (llvm::is_base_of<CXXRecordDecl, T>::value), - requires_getTemplateSpecializationKind_method); - public: - virtual bool matches(const T& Node, - ASTMatchFinder* Finder, - BoundNodesTreeBuilder* Builder) const { - return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization); - } -}; - -class IsArrowMatcher : public SingleNodeMatcherInterface<MemberExpr> { -public: - virtual bool matchesNode(const MemberExpr &Node) const { - return Node.isArrow(); - } -}; - -class IsConstQualifiedMatcher - : public SingleNodeMatcherInterface<QualType> { - public: - virtual bool matchesNode(const QualType& Node) const { - return Node.isConstQualified(); - } -}; - /// \brief A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a /// variadic functor that takes a number of Matcher<TargetT> and returns a /// Matcher<SourceT> that matches TargetT nodes that are matched by all of the @@ -1115,50 +1164,6 @@ private: const Matcher<T> InnerMatcher; }; -/// \brief Matches \c NestedNameSpecifiers with a prefix matching another -/// \c Matcher<NestedNameSpecifier>. -class NestedNameSpecifierPrefixMatcher - : public MatcherInterface<NestedNameSpecifier> { -public: - explicit NestedNameSpecifierPrefixMatcher( - const Matcher<NestedNameSpecifier> &InnerMatcher) - : InnerMatcher(InnerMatcher) {} - - virtual bool matches(const NestedNameSpecifier &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - NestedNameSpecifier *NextNode = Node.getPrefix(); - if (NextNode == NULL) - return false; - return InnerMatcher.matches(*NextNode, Finder, Builder); - } - -private: - const Matcher<NestedNameSpecifier> InnerMatcher; -}; - -/// \brief Matches \c NestedNameSpecifierLocs with a prefix matching another -/// \c Matcher<NestedNameSpecifierLoc>. -class NestedNameSpecifierLocPrefixMatcher - : public MatcherInterface<NestedNameSpecifierLoc> { -public: - explicit NestedNameSpecifierLocPrefixMatcher( - const Matcher<NestedNameSpecifierLoc> &InnerMatcher) - : InnerMatcher(InnerMatcher) {} - - virtual bool matches(const NestedNameSpecifierLoc &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - NestedNameSpecifierLoc NextNode = Node.getPrefix(); - if (!NextNode) - return false; - return InnerMatcher.matches(NextNode, Finder, Builder); - } - -private: - const Matcher<NestedNameSpecifierLoc> InnerMatcher; -}; - /// \brief Matches \c TypeLocs based on an inner matcher matching a certain /// \c QualType. /// diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h index 953abc2..f5ca26b 100644 --- a/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -49,21 +49,23 @@ /// /// The code should return true if 'Node' matches. #define AST_MATCHER(Type, DefineMatcher) \ + AST_MATCHER_OVERLOAD(Type, DefineMatcher, 0) + +#define AST_MATCHER_OVERLOAD(Type, DefineMatcher, OverloadId) \ namespace internal { \ - class matcher_##DefineMatcher##Matcher \ + class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface<Type> { \ - public: \ - explicit matcher_##DefineMatcher##Matcher() {} \ - virtual bool matches( \ - const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ + public: \ + explicit matcher_##DefineMatcher##OverloadId##Matcher() {} \ + virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ }; \ } \ inline internal::Matcher<Type> DefineMatcher() { \ return internal::makeMatcher( \ - new internal::matcher_##DefineMatcher##Matcher()); \ + new internal::matcher_##DefineMatcher##OverloadId##Matcher()); \ } \ - inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ + inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \ const Type &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const @@ -81,24 +83,29 @@ /// /// The code should return true if 'Node' matches. #define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) \ + AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, 0) + +#define AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, \ + OverloadId) \ namespace internal { \ - class matcher_##DefineMatcher##Matcher \ + class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface<Type> { \ - public: \ - explicit matcher_##DefineMatcher##Matcher( \ - const ParamType &A##Param) : Param(A##Param) {} \ - virtual bool matches( \ - const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ - private: \ + public: \ + explicit matcher_##DefineMatcher##OverloadId##Matcher( \ + const ParamType &A##Param) \ + : Param(A##Param) { \ + } \ + virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ + private: \ const ParamType Param; \ }; \ } \ inline internal::Matcher<Type> DefineMatcher(const ParamType &Param) { \ return internal::makeMatcher( \ - new internal::matcher_##DefineMatcher##Matcher(Param)); \ + new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \ } \ - inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ + inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \ const Type &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const @@ -116,33 +123,67 @@ /// Builder: a BoundNodesTreeBuilder*. /// /// The code should return true if 'Node' matches. -#define AST_MATCHER_P2( \ - Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) \ +#define AST_MATCHER_P2(Type, DefineMatcher, ParamType1, Param1, ParamType2, \ + Param2) \ + AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1, ParamType2, \ + Param2, 0) + +#define AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1, \ + ParamType2, Param2, OverloadId) \ namespace internal { \ - class matcher_##DefineMatcher##Matcher \ + class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface<Type> { \ - public: \ - matcher_##DefineMatcher##Matcher( \ - const ParamType1 &A##Param1, const ParamType2 &A##Param2) \ - : Param1(A##Param1), Param2(A##Param2) {} \ - virtual bool matches( \ - const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ - private: \ + public: \ + matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1, \ + const ParamType2 &A##Param2) \ + : Param1(A##Param1), Param2(A##Param2) { \ + } \ + virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ + private: \ const ParamType1 Param1; \ const ParamType2 Param2; \ }; \ } \ - inline internal::Matcher<Type> DefineMatcher( \ - const ParamType1 &Param1, const ParamType2 &Param2) { \ + inline internal::Matcher<Type> \ + DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \ return internal::makeMatcher( \ - new internal::matcher_##DefineMatcher##Matcher( \ - Param1, Param2)); \ + new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \ + Param2)); \ } \ - inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ + inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \ const Type &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const +/// \brief AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... } +/// defines a single-parameter function named DefineMatcher() that is +/// polymorphic in the return type. +/// +/// The variables are the same as for AST_MATCHER, but NodeType will be deduced +/// from the calling context. +#define AST_POLYMORPHIC_MATCHER(DefineMatcher) \ + AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, 0) + +#define AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, OverloadId) \ + namespace internal { \ + template <typename NodeType> \ + class matcher_##DefineMatcher##OverloadId##Matcher \ + : public MatcherInterface<NodeType> { \ + public: \ + virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ + }; \ + } \ + inline internal::PolymorphicMatcherWithParam0< \ + internal::matcher_##DefineMatcher##OverloadId##Matcher> DefineMatcher() {\ + return internal::PolymorphicMatcherWithParam0< \ + internal::matcher_##DefineMatcher##OverloadId##Matcher>(); \ + } \ + template <typename NodeType> \ + bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ + NodeType>::matches(const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const + /// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... } /// defines a single-parameter function named DefineMatcher() that is /// polymorphic in the return type. @@ -153,32 +194,36 @@ /// /// FIXME: Pull out common code with above macro? #define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) \ + AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param, 0) + +#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param, \ + OverloadId) \ namespace internal { \ template <typename NodeType, typename ParamT> \ - class matcher_##DefineMatcher##Matcher \ + class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface<NodeType> { \ - public: \ - explicit matcher_##DefineMatcher##Matcher( \ - const ParamType &A##Param) : Param(A##Param) {} \ - virtual bool matches( \ - const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ - private: \ + public: \ + explicit matcher_##DefineMatcher##OverloadId##Matcher( \ + const ParamType &A##Param) \ + : Param(A##Param) { \ + } \ + virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ + private: \ const ParamType Param; \ }; \ } \ inline internal::PolymorphicMatcherWithParam1< \ - internal::matcher_##DefineMatcher##Matcher, \ - ParamType > \ - DefineMatcher(const ParamType &Param) { \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType> \ + DefineMatcher(const ParamType &Param) { \ return internal::PolymorphicMatcherWithParam1< \ - internal::matcher_##DefineMatcher##Matcher, \ - ParamType >(Param); \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType>( \ + Param); \ } \ template <typename NodeType, typename ParamT> \ - bool internal::matcher_##DefineMatcher##Matcher<NodeType, ParamT>::matches( \ - const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const + bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ + NodeType, ParamT>::matches(const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const /// \brief AST_POLYMORPHIC_MATCHER_P2( /// DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... } @@ -188,35 +233,39 @@ /// The variables are the same as for AST_MATCHER_P2, with the /// addition of NodeType, which specifies the node type of the matcher /// Matcher<NodeType> returned by the function DefineMatcher(). -#define AST_POLYMORPHIC_MATCHER_P2( \ - DefineMatcher, ParamType1, Param1, ParamType2, Param2) \ +#define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ParamType1, Param1, \ + ParamType2, Param2) \ + AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1, \ + ParamType2, Param2, 0) + +#define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1, \ + ParamType2, Param2, OverloadId) \ namespace internal { \ template <typename NodeType, typename ParamT1, typename ParamT2> \ - class matcher_##DefineMatcher##Matcher \ + class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface<NodeType> { \ - public: \ - matcher_##DefineMatcher##Matcher( \ - const ParamType1 &A##Param1, const ParamType2 &A##Param2) \ - : Param1(A##Param1), Param2(A##Param2) {} \ - virtual bool matches( \ - const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ - private: \ + public: \ + matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1, \ + const ParamType2 &A##Param2) \ + : Param1(A##Param1), Param2(A##Param2) { \ + } \ + virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ + private: \ const ParamType1 Param1; \ const ParamType2 Param2; \ }; \ } \ inline internal::PolymorphicMatcherWithParam2< \ - internal::matcher_##DefineMatcher##Matcher, \ - ParamType1, ParamType2 > \ - DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ + ParamType2> \ + DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \ return internal::PolymorphicMatcherWithParam2< \ - internal::matcher_##DefineMatcher##Matcher, \ - ParamType1, ParamType2 >( \ - Param1, Param2); \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ + ParamType2>(Param1, Param2); \ } \ template <typename NodeType, typename ParamT1, typename ParamT2> \ - bool internal::matcher_##DefineMatcher##Matcher< \ + bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ NodeType, ParamT1, ParamT2>::matches( \ const NodeType &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const @@ -224,9 +273,9 @@ /// \brief Creates a variadic matcher for both a specific \c Type as well as /// the corresponding \c TypeLoc. #define AST_TYPE_MATCHER(NodeType, MatcherName) \ - const internal::VariadicDynCastAllOfMatcher<Type, NodeType> MatcherName; \ - const internal::VariadicDynCastAllOfMatcher<TypeLoc, \ - NodeType##Loc> MatcherName##Loc + const internal::VariadicDynCastAllOfMatcher<Type, NodeType> MatcherName +// FIXME: add a matcher for TypeLoc derived classes using its custom casting +// API (no longer dyn_cast) if/when we need such matching /// \brief AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines /// the matcher \c MatcherName that can be used to traverse from one \c Type @@ -236,54 +285,61 @@ /// \c SpecificType::FunctionName. The existance of such a function determines /// whether a corresponding matcher can be used on \c SpecificType. #define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) \ -class Polymorphic##MatcherName##TypeMatcher { \ -public: \ - Polymorphic##MatcherName##TypeMatcher( \ - const internal::Matcher<QualType> &InnerMatcher) \ - : InnerMatcher(InnerMatcher) {} \ - template <typename T> operator internal::Matcher<T>() { \ - return internal::Matcher<T>(new internal::TypeTraverseMatcher<T>( \ - InnerMatcher, &T::FunctionName)); \ + class Polymorphic##MatcherName##TypeMatcher { \ + public: \ + Polymorphic##MatcherName##TypeMatcher( \ + const internal::Matcher<QualType> &InnerMatcher) \ + : InnerMatcher(InnerMatcher) { \ + } \ + template <typename T> operator internal:: Matcher< T>() { \ + return internal::Matcher<T>(new internal::TypeTraverseMatcher<T>( \ + InnerMatcher, &T::FunctionName)); \ + } \ + private: \ + const internal::Matcher<QualType> InnerMatcher; \ } \ -private: \ - const internal::Matcher<QualType> InnerMatcher; \ -}; \ -class Variadic##MatcherName##TypeTraverseMatcher \ - : public llvm::VariadicFunction< \ - Polymorphic##MatcherName##TypeMatcher, \ - internal::Matcher<QualType>, \ - internal::makeTypeAllOfComposite< \ - Polymorphic##MatcherName##TypeMatcher, QualType> > { \ -public: \ - Variadic##MatcherName##TypeTraverseMatcher() {} \ -}; \ -const Variadic##MatcherName##TypeTraverseMatcher MatcherName + ; \ + class Variadic##MatcherName##TypeTraverseMatcher \ + : public llvm::VariadicFunction< \ + Polymorphic##MatcherName##TypeMatcher, internal::Matcher<QualType>, \ + internal::makeTypeAllOfComposite< \ + Polymorphic##MatcherName##TypeMatcher, QualType> > { \ + public: \ + Variadic##MatcherName##TypeTraverseMatcher() { \ + } \ + } \ + ; \ + const Variadic##MatcherName##TypeTraverseMatcher MatcherName /// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works /// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs. #define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) \ -class Polymorphic##MatcherName##TypeLocMatcher { \ -public: \ - Polymorphic##MatcherName##TypeLocMatcher( \ - const internal::Matcher<TypeLoc> &InnerMatcher) \ - : InnerMatcher(InnerMatcher) {} \ - template <typename T> operator internal::Matcher<T>() { \ - return internal::Matcher<T>(new internal::TypeLocTraverseMatcher<T>( \ - InnerMatcher, &T::FunctionName##Loc)); \ + class Polymorphic##MatcherName##TypeLocMatcher { \ + public: \ + Polymorphic##MatcherName##TypeLocMatcher( \ + const internal::Matcher<TypeLoc> &InnerMatcher) \ + : InnerMatcher(InnerMatcher) { \ + } \ + template <typename T> operator internal:: Matcher< T>() { \ + return internal::Matcher<T>( \ + new internal::TypeLocTraverseMatcher<T>(InnerMatcher, \ + &T::FunctionName##Loc)); \ + } \ + private: \ + const internal::Matcher<TypeLoc> InnerMatcher; \ + } \ + ; \ + class Variadic##MatcherName##TypeLocTraverseMatcher \ + : public llvm::VariadicFunction< \ + Polymorphic##MatcherName##TypeLocMatcher, internal::Matcher<TypeLoc>,\ + internal::makeTypeAllOfComposite< \ + Polymorphic##MatcherName##TypeLocMatcher, TypeLoc> > { \ + public: \ + Variadic##MatcherName##TypeLocTraverseMatcher() { \ + } \ } \ -private: \ - const internal::Matcher<TypeLoc> InnerMatcher; \ -}; \ -class Variadic##MatcherName##TypeLocTraverseMatcher \ - : public llvm::VariadicFunction< \ - Polymorphic##MatcherName##TypeLocMatcher, \ - internal::Matcher<TypeLoc>, \ - internal::makeTypeAllOfComposite< \ - Polymorphic##MatcherName##TypeLocMatcher, TypeLoc> > { \ -public: \ - Variadic##MatcherName##TypeLocTraverseMatcher() {} \ -}; \ -const Variadic##MatcherName##TypeLocTraverseMatcher MatcherName##Loc; \ -AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type) + ; \ + const Variadic##MatcherName##TypeLocTraverseMatcher MatcherName##Loc; \ + AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type) #endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H diff --git a/include/clang/Analysis/Analyses/Dominators.h b/include/clang/Analysis/Analyses/Dominators.h index e9a431a..2a806c8 100644 --- a/include/clang/Analysis/Analyses/Dominators.h +++ b/include/clang/Analysis/Analyses/Dominators.h @@ -15,12 +15,11 @@ #define LLVM_CLANG_DOMINATORS_H #include "clang/Analysis/AnalysisContext.h" - -#include "llvm/Module.h" -#include "llvm/ADT/GraphTraits.h" #include "clang/Analysis/CFG.h" -#include "llvm/Analysis/Dominators.h" +#include "llvm/ADT/GraphTraits.h" #include "llvm/Analysis/DominatorInternals.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/IR/Module.h" namespace clang { diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h index 5cb9731..4bd989c 100644 --- a/include/clang/Analysis/Analyses/FormatString.h +++ b/include/clang/Analysis/Analyses/FormatString.h @@ -201,7 +201,7 @@ public: bool isPrintfKind() const { return IsPrintf; } - llvm::Optional<ConversionSpecifier> getStandardSpecifier() const; + Optional<ConversionSpecifier> getStandardSpecifier() const; protected: bool IsPrintf; @@ -361,7 +361,7 @@ public: bool hasStandardLengthModifier() const; - llvm::Optional<LengthModifier> getCorrectedLengthModifier() const; + Optional<LengthModifier> getCorrectedLengthModifier() const; bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const; diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h index c9f39b4..bbd2b02 100644 --- a/include/clang/Analysis/Analyses/LiveVariables.h +++ b/include/clang/Analysis/Analyses/LiveVariables.h @@ -14,8 +14,8 @@ #ifndef LLVM_CLANG_LIVEVARIABLES_H #define LLVM_CLANG_LIVEVARIABLES_H -#include "clang/Analysis/AnalysisContext.h" #include "clang/AST/Decl.h" +#include "clang/Analysis/AnalysisContext.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/ImmutableSet.h" diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h index ef6b821..8a888e6 100644 --- a/include/clang/Analysis/Analyses/ThreadSafety.h +++ b/include/clang/Analysis/Analyses/ThreadSafety.h @@ -29,24 +29,24 @@ namespace thread_safety { /// This enum distinguishes between different kinds of operations that may /// need to be protected by locks. We use this enum in error handling. enum ProtectedOperationKind { - POK_VarDereference, /// Dereferencing a variable (e.g. p in *p = 5;) - POK_VarAccess, /// Reading or writing a variable (e.g. x in x = 5;) - POK_FunctionCall /// Making a function call (e.g. fool()) + POK_VarDereference, ///< Dereferencing a variable (e.g. p in *p = 5;) + POK_VarAccess, ///< Reading or writing a variable (e.g. x in x = 5;) + POK_FunctionCall ///< Making a function call (e.g. fool()) }; /// This enum distinguishes between different kinds of lock actions. For /// example, it is an error to write a variable protected by shared version of a /// mutex. enum LockKind { - LK_Shared, /// Shared/reader lock of a mutex - LK_Exclusive /// Exclusive/writer lock of a mutex + LK_Shared, ///< Shared/reader lock of a mutex. + LK_Exclusive ///< Exclusive/writer lock of a mutex. }; /// This enum distinguishes between different ways to access (read or write) a /// variable. enum AccessKind { - AK_Read, /// Reading a variable - AK_Written /// Writing a variable + AK_Read, ///< Reading a variable. + AK_Written ///< Writing a variable. }; /// This enum distinguishes between different situations where we warn due to @@ -67,7 +67,8 @@ enum LockErrorKind { /// Handler class for thread safety warnings. class ThreadSafetyHandler { public: - typedef llvm::StringRef Name; + typedef StringRef Name; + ThreadSafetyHandler() : IssueBetaWarnings(false) { } virtual ~ThreadSafetyHandler(); /// Warn about lock expressions which fail to resolve to lockable objects. @@ -143,6 +144,12 @@ public: /// \param Loc -- The location of the function call. virtual void handleFunExcludesLock(Name FunName, Name LockName, SourceLocation Loc) {} + + bool issueBetaWarnings() { return IssueBetaWarnings; } + void setIssueBetaWarnings(bool b) { IssueBetaWarnings = b; } + +private: + bool IssueBetaWarnings; }; /// \brief Check a function's CFG for thread-safety violations. diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h index 45ce4de..e8810c3 100644 --- a/include/clang/Analysis/Analyses/UninitializedValues.h +++ b/include/clang/Analysis/Analyses/UninitializedValues.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_UNINIT_VALS_H #define LLVM_CLANG_UNINIT_VALS_H +#include "clang/AST/Stmt.h" #include "llvm/ADT/SmallVector.h" namespace clang { @@ -42,7 +43,7 @@ private: /// This use is always uninitialized if it occurs after any of these branches /// is taken. - llvm::SmallVector<Branch, 2> UninitBranches; + SmallVector<Branch, 2> UninitBranches; public: UninitUse(const Expr *User, bool AlwaysUninit) : @@ -71,7 +72,7 @@ public: !branch_empty() ? Sometimes : Maybe; } - typedef llvm::SmallVectorImpl<Branch>::const_iterator branch_iterator; + typedef SmallVectorImpl<Branch>::const_iterator branch_iterator; /// Branches which inevitably result in the variable being used uninitialized. branch_iterator branch_begin() const { return UninitBranches.begin(); } branch_iterator branch_end() const { return UninitBranches.end(); } diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index 5246678..46d7d07 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -18,11 +18,11 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" #include "clang/Analysis/CFG.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/Support/Allocator.h" namespace clang { @@ -133,7 +133,21 @@ public: void registerForcedBlockExpression(const Stmt *stmt); const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt); + /// \brief Get the body of the Declaration. Stmt *getBody() const; + + /// \brief Get the body of the Declaration. + /// \param[out] IsAutosynthesized Specifies if the body is auto-generated + /// by the BodyFarm. + Stmt *getBody(bool &IsAutosynthesized) const; + + /// \brief Checks if the body of the Decl is generated by the BodyFarm. + /// + /// Note, the lookup is not free. We are going to call getBody behind + /// the scenes. + /// \sa getBody + bool isBodyAutosynthesized() const; + CFG *getCFG(); CFGStmtMap *getCFGStmtMap(); @@ -242,6 +256,8 @@ public: virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; + LLVM_ATTRIBUTE_USED void dumpStack() const; + public: static void ProfileCommon(llvm::FoldingSetNodeID &ID, ContextKind ck, @@ -396,7 +412,8 @@ public: bool addImplicitDtors = false, bool addInitializers = false, bool addTemporaryDtors = false, - bool synthesizeBodies = false); + bool synthesizeBodies = false, + bool addStaticInitBranches = false); ~AnalysisDeclContextManager(); diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index 8cc5d81..ee0be73 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -15,15 +15,16 @@ #ifndef LLVM_CLANG_CFG_H #define LLVM_CLANG_CFG_H -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/GraphTraits.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/Casting.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/DenseMap.h" #include "clang/AST/Stmt.h" #include "clang/Analysis/Support/BumpVector.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" #include <bitset> #include <cassert> #include <iterator> @@ -48,7 +49,6 @@ class CFGElement { public: enum Kind { // main kind - Invalid, Statement, Initializer, // dtor kind @@ -69,8 +69,31 @@ protected: : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3), Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {} -public: CFGElement() {} +public: + + /// \brief Convert to the specified CFGElement type, asserting that this + /// CFGElement is of the desired type. + template<typename T> + T castAs() const { + assert(T::isKind(*this)); + T t; + CFGElement& e = t; + e = *this; + return t; + } + + /// \brief Convert to the specified CFGElement type, returning None if this + /// CFGElement is not of the desired type. + template<typename T> + Optional<T> getAs() const { + if (!T::isKind(*this)) + return None; + T t; + CFGElement& e = t; + e = *this; + return t; + } Kind getKind() const { unsigned x = Data2.getInt(); @@ -78,16 +101,6 @@ public: x |= Data1.getInt(); return (Kind) x; } - - bool isValid() const { return getKind() != Invalid; } - - operator bool() const { return isValid(); } - - template<class ElemTy> const ElemTy *getAs() const { - if (llvm::isa<ElemTy>(this)) - return static_cast<const ElemTy*>(this); - return 0; - } }; class CFGStmt : public CFGElement { @@ -98,8 +111,11 @@ public: return static_cast<const Stmt *>(Data1.getPointer()); } - static bool classof(const CFGElement *E) { - return E->getKind() == Statement; +private: + friend class CFGElement; + CFGStmt() {} + static bool isKind(const CFGElement &E) { + return E.getKind() == Statement; } }; @@ -114,8 +130,11 @@ public: return static_cast<CXXCtorInitializer*>(Data1.getPointer()); } - static bool classof(const CFGElement *E) { - return E->getKind() == Initializer; +private: + friend class CFGElement; + CFGInitializer() {} + static bool isKind(const CFGElement &E) { + return E.getKind() == Initializer; } }; @@ -123,6 +142,7 @@ public: /// by compiler on various occasions. class CFGImplicitDtor : public CFGElement { protected: + CFGImplicitDtor() {} CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = 0) : CFGElement(kind, data1, data2) { assert(kind >= DTOR_BEGIN && kind <= DTOR_END); @@ -132,8 +152,10 @@ public: const CXXDestructorDecl *getDestructorDecl(ASTContext &astContext) const; bool isNoReturn(ASTContext &astContext) const; - static bool classof(const CFGElement *E) { - Kind kind = E->getKind(); +private: + friend class CFGElement; + static bool isKind(const CFGElement &E) { + Kind kind = E.getKind(); return kind >= DTOR_BEGIN && kind <= DTOR_END; } }; @@ -155,8 +177,11 @@ public: return static_cast<Stmt*>(Data2.getPointer()); } - static bool classof(const CFGElement *elem) { - return elem->getKind() == AutomaticObjectDtor; +private: + friend class CFGElement; + CFGAutomaticObjDtor() {} + static bool isKind(const CFGElement &elem) { + return elem.getKind() == AutomaticObjectDtor; } }; @@ -171,8 +196,11 @@ public: return static_cast<const CXXBaseSpecifier*>(Data1.getPointer()); } - static bool classof(const CFGElement *E) { - return E->getKind() == BaseDtor; +private: + friend class CFGElement; + CFGBaseDtor() {} + static bool isKind(const CFGElement &E) { + return E.getKind() == BaseDtor; } }; @@ -187,8 +215,11 @@ public: return static_cast<const FieldDecl*>(Data1.getPointer()); } - static bool classof(const CFGElement *E) { - return E->getKind() == MemberDtor; +private: + friend class CFGElement; + CFGMemberDtor() {} + static bool isKind(const CFGElement &E) { + return E.getKind() == MemberDtor; } }; @@ -203,8 +234,11 @@ public: return static_cast<const CXXBindTemporaryExpr *>(Data1.getPointer()); } - static bool classof(const CFGElement *E) { - return E->getKind() == TemporaryDtor; +private: + friend class CFGElement; + CFGTemporaryDtor() {} + static bool isKind(const CFGElement &E) { + return E.getKind() == TemporaryDtor; } }; @@ -535,7 +569,7 @@ public: // the elements beginning at the last position in prepared space. iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt, BumpVectorContext &C) { - return iterator(Elements.insert(I.base(), Cnt, CFGElement(), C)); + return iterator(Elements.insert(I.base(), Cnt, CFGAutomaticObjDtor(0, 0), C)); } iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S) { *I = CFGAutomaticObjDtor(VD, S); @@ -567,6 +601,7 @@ public: bool AddInitializers; bool AddImplicitDtors; bool AddTemporaryDtors; + bool AddStaticInitBranches; bool alwaysAdd(const Stmt *stmt) const { return alwaysAddMask[stmt->getStmtClass()]; @@ -587,7 +622,8 @@ public: ,AddEHEdges(false) ,AddInitializers(false) ,AddImplicitDtors(false) - ,AddTemporaryDtors(false) {} + ,AddTemporaryDtors(false) + ,AddStaticInitBranches(false) {} }; /// \brief Provides a custom implementation of the iterator class to have the @@ -718,7 +754,7 @@ public: for (const_iterator I=begin(), E=end(); I != E; ++I) for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end(); BI != BE; ++BI) { - if (const CFGStmt *stmt = BI->getAs<CFGStmt>()) + if (Optional<CFGStmt> stmt = BI->getAs<CFGStmt>()) O(const_cast<Stmt*>(stmt->getStmt())); } } @@ -807,17 +843,10 @@ namespace llvm { /// Implement simplify_type for CFGTerminator, so that we can dyn_cast from /// CFGTerminator to a specific Stmt class. -template <> struct simplify_type<const ::clang::CFGTerminator> { - typedef const ::clang::Stmt *SimpleType; - static SimpleType getSimplifiedValue(const ::clang::CFGTerminator &Val) { - return Val.getStmt(); - } -}; - template <> struct simplify_type< ::clang::CFGTerminator> { typedef ::clang::Stmt *SimpleType; - static SimpleType getSimplifiedValue(const ::clang::CFGTerminator &Val) { - return const_cast<SimpleType>(Val.getStmt()); + static SimpleType getSimplifiedValue(::clang::CFGTerminator Val) { + return Val.getStmt(); } }; diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h index 509de7b..5015eb6 100644 --- a/include/clang/Analysis/CallGraph.h +++ b/include/clang/Analysis/CallGraph.h @@ -39,15 +39,9 @@ class CallGraph : public RecursiveASTVisitor<CallGraph> { /// FunctionMap owns all CallGraphNodes. FunctionMapTy FunctionMap; - /// This is a virtual root node that has edges to all the global functions - - /// 'main' or functions accessible from other translation units. + /// This is a virtual root node that has edges to all the functions. CallGraphNode *Root; - /// The list of nodes that have no parent. These are unreachable from Root. - /// Declarations can get to this list due to impressions in the graph, for - /// example, we do not track functions whose addresses were taken. - llvm::SetVector<CallGraphNode *> ParentlessNodes; - public: CallGraph(); ~CallGraph(); @@ -91,34 +85,35 @@ public: /// failing to add a call edge due to the analysis imprecision. typedef llvm::SetVector<CallGraphNode *>::iterator nodes_iterator; typedef llvm::SetVector<CallGraphNode *>::const_iterator const_nodes_iterator; - nodes_iterator parentless_begin() { return ParentlessNodes.begin(); } - nodes_iterator parentless_end() { return ParentlessNodes.end(); } - const_nodes_iterator - parentless_begin() const { return ParentlessNodes.begin(); } - const_nodes_iterator - parentless_end() const { return ParentlessNodes.end(); } void print(raw_ostream &os) const; void dump() const; void viewGraph() const; + void addNodesForBlocks(DeclContext *D); + /// Part of recursive declaration visitation. We recursively visit all the - /// Declarations to collect the root functions. + /// declarations to collect the root functions. bool VisitFunctionDecl(FunctionDecl *FD) { // We skip function template definitions, as their semantics is // only determined when they are instantiated. - if (includeInGraph(FD)) + if (includeInGraph(FD)) { + // Add all blocks declared inside this function to the graph. + addNodesForBlocks(FD); // If this function has external linkage, anything could call it. // Note, we are not precise here. For example, the function could have // its address taken. addNodeForDecl(FD, FD->isGlobal()); + } return true; } /// Part of recursive declaration visitation. bool VisitObjCMethodDecl(ObjCMethodDecl *MD) { - if (includeInGraph(MD)) + if (includeInGraph(MD)) { + addNodesForBlocks(MD); addNodeForDecl(MD, true); + } return true; } @@ -144,15 +139,13 @@ private: Decl *FD; /// \brief The list of functions called from this node. - // Small vector might be more efficient since we are only tracking functions - // whose definition is in the current TU. - llvm::SmallVector<CallRecord, 5> CalledFunctions; + SmallVector<CallRecord, 5> CalledFunctions; public: CallGraphNode(Decl *D) : FD(D) {} - typedef llvm::SmallVector<CallRecord, 5>::iterator iterator; - typedef llvm::SmallVector<CallRecord, 5>::const_iterator const_iterator; + typedef SmallVector<CallRecord, 5>::iterator iterator; + typedef SmallVector<CallRecord, 5>::const_iterator const_iterator; /// Iterators through all the callees/children of the node. inline iterator begin() { return CalledFunctions.begin(); } @@ -165,13 +158,10 @@ public: void addCallee(CallGraphNode *N, CallGraph *CG) { CalledFunctions.push_back(N); - CG->ParentlessNodes.remove(N); } Decl *getDecl() const { return FD; } - StringRef getName() const; - void print(raw_ostream &os) const; void dump() const; }; @@ -203,7 +193,7 @@ template <> struct GraphTraits<const clang::CallGraphNode*> { typedef NodeType::const_iterator ChildIteratorType; static NodeType *getEntryNode(const clang::CallGraphNode *CGN) { return CGN; } static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();} - static inline ChildIteratorType child_end (NodeType *N) { return N->end(); } + static inline ChildIteratorType child_end(NodeType *N) { return N->end(); } }; template <> struct GraphTraits<clang::CallGraph*> diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h index 017da63..0f5e7bf 100644 --- a/include/clang/Analysis/FlowSensitive/DataflowSolver.h +++ b/include/clang/Analysis/FlowSensitive/DataflowSolver.h @@ -14,12 +14,12 @@ #ifndef LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER #define LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER +#include "functional" // STL #include "clang/Analysis/CFG.h" -#include "clang/Analysis/ProgramPoint.h" #include "clang/Analysis/FlowSensitive/DataflowValues.h" +#include "clang/Analysis/ProgramPoint.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" -#include "functional" // STL namespace clang { diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 9479978..333329d 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -17,15 +17,16 @@ #include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/CFG.h" -#include "llvm/Support/DataTypes.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/Support/Casting.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/DataTypes.h" #include <cassert> -#include <utility> #include <string> +#include <utility> namespace clang { @@ -71,9 +72,8 @@ private: llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag; - ProgramPoint(); - protected: + ProgramPoint() {} ProgramPoint(const void *P, Kind k, const LocationContext *l, @@ -110,6 +110,29 @@ public: getLocationContext(), tag); } + /// \brief Convert to the specified ProgramPoint type, asserting that this + /// ProgramPoint is of the desired type. + template<typename T> + T castAs() const { + assert(T::isKind(*this)); + T t; + ProgramPoint& PP = t; + PP = *this; + return t; + } + + /// \brief Convert to the specified ProgramPoint type, returning None if this + /// ProgramPoint is not of the desired type. + template<typename T> + Optional<T> getAs() const { + if (!T::isKind(*this)) + return None; + T t; + ProgramPoint& PP = t; + PP = *this; + return t; + } + Kind getKind() const { unsigned x = Tag.getInt(); x <<= 2; @@ -179,13 +202,16 @@ public: return reinterpret_cast<const CFGBlock*>(getData1()); } - const CFGElement getFirstElement() const { + Optional<CFGElement> getFirstElement() const { const CFGBlock *B = getBlock(); - return B->empty() ? CFGElement() : B->front(); + return B->empty() ? Optional<CFGElement>() : B->front(); } - static bool classof(const ProgramPoint* Location) { - return Location->getKind() == BlockEntranceKind; +private: + friend class ProgramPoint; + BlockEntrance() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == BlockEntranceKind; } }; @@ -202,8 +228,11 @@ public: return getBlock()->getTerminator(); } - static bool classof(const ProgramPoint* Location) { - return Location->getKind() == BlockExitKind; +private: + friend class ProgramPoint; + BlockExit() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == BlockExitKind; } }; @@ -218,10 +247,14 @@ public: const Stmt *getStmt() const { return (const Stmt*) getData1(); } template <typename T> - const T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); } + const T* getStmtAs() const { return dyn_cast<T>(getStmt()); } - static bool classof(const ProgramPoint* Location) { - unsigned k = Location->getKind(); +protected: + StmtPoint() {} +private: + friend class ProgramPoint; + static bool isKind(const ProgramPoint &Location) { + unsigned k = Location.getKind(); return k >= PreStmtKind && k <= MaxPostStmtKind; } }; @@ -235,13 +268,17 @@ public: const Stmt *getSubStmt() const { return (const Stmt*) getData2(); } - static bool classof(const ProgramPoint* Location) { - return Location->getKind() == PreStmtKind; +private: + friend class ProgramPoint; + PreStmt() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == PreStmtKind; } }; class PostStmt : public StmtPoint { protected: + PostStmt() {} PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L, const ProgramPointTag *tag = 0) : StmtPoint(S, data, k, L, tag) {} @@ -255,8 +292,10 @@ public: const ProgramPointTag *tag = 0) : StmtPoint(S, NULL, PostStmtKind, L, tag) {} - static bool classof(const ProgramPoint* Location) { - unsigned k = Location->getKind(); +private: + friend class ProgramPoint; + static bool isKind(const ProgramPoint &Location) { + unsigned k = Location.getKind(); return k >= MinPostStmtKind && k <= MaxPostStmtKind; } }; @@ -268,19 +307,25 @@ public: const ProgramPointTag *tag = 0) : PostStmt(S, PostConditionKind, L, tag) {} - static bool classof(const ProgramPoint* Location) { - return Location->getKind() == PostConditionKind; +private: + friend class ProgramPoint; + PostCondition() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == PostConditionKind; } }; class LocationCheck : public StmtPoint { protected: + LocationCheck() {} LocationCheck(const Stmt *S, const LocationContext *L, ProgramPoint::Kind K, const ProgramPointTag *tag) : StmtPoint(S, NULL, K, L, tag) {} - static bool classof(const ProgramPoint *location) { - unsigned k = location->getKind(); +private: + friend class ProgramPoint; + static bool isKind(const ProgramPoint &location) { + unsigned k = location.getKind(); return k == PreLoadKind || k == PreStoreKind; } }; @@ -291,8 +336,11 @@ public: const ProgramPointTag *tag = 0) : LocationCheck(S, L, PreLoadKind, tag) {} - static bool classof(const ProgramPoint *location) { - return location->getKind() == PreLoadKind; +private: + friend class ProgramPoint; + PreLoad() {} + static bool isKind(const ProgramPoint &location) { + return location.getKind() == PreLoadKind; } }; @@ -302,8 +350,11 @@ public: const ProgramPointTag *tag = 0) : LocationCheck(S, L, PreStoreKind, tag) {} - static bool classof(const ProgramPoint *location) { - return location->getKind() == PreStoreKind; +private: + friend class ProgramPoint; + PreStore() {} + static bool isKind(const ProgramPoint &location) { + return location.getKind() == PreStoreKind; } }; @@ -313,8 +364,11 @@ public: const ProgramPointTag *tag = 0) : PostStmt(S, PostLoadKind, L, tag) {} - static bool classof(const ProgramPoint* Location) { - return Location->getKind() == PostLoadKind; +private: + friend class ProgramPoint; + PostLoad() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == PostLoadKind; } }; @@ -331,16 +385,18 @@ public: setData2(Loc); } - static bool classof(const ProgramPoint* Location) { - return Location->getKind() == PostStoreKind; - } - /// \brief Returns the information about the location used in the store, /// how it was uttered in the code. const void *getLocationValue() const { return getData2(); } +private: + friend class ProgramPoint; + PostStore() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == PostStoreKind; + } }; class PostLValue : public PostStmt { @@ -349,8 +405,11 @@ public: const ProgramPointTag *tag = 0) : PostStmt(S, PostLValueKind, L, tag) {} - static bool classof(const ProgramPoint* Location) { - return Location->getKind() == PostLValueKind; +private: + friend class ProgramPoint; + PostLValue() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == PostLValueKind; } }; @@ -362,8 +421,11 @@ public: const ProgramPointTag *tag = 0) : StmtPoint(S, 0, PreStmtPurgeDeadSymbolsKind, L, tag) { } - static bool classof(const ProgramPoint* Location) { - return Location->getKind() == PreStmtPurgeDeadSymbolsKind; +private: + friend class ProgramPoint; + PreStmtPurgeDeadSymbols() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == PreStmtPurgeDeadSymbolsKind; } }; @@ -375,8 +437,11 @@ public: const ProgramPointTag *tag = 0) : StmtPoint(S, 0, PostStmtPurgeDeadSymbolsKind, L, tag) { } - static bool classof(const ProgramPoint* Location) { - return Location->getKind() == PostStmtPurgeDeadSymbolsKind; +private: + friend class ProgramPoint; + PostStmtPurgeDeadSymbols() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == PostStmtPurgeDeadSymbolsKind; } }; @@ -396,19 +461,40 @@ public: return static_cast<const CFGBlock*>(getData2()); } - static bool classof(const ProgramPoint* Location) { - return Location->getKind() == BlockEdgeKind; +private: + friend class ProgramPoint; + BlockEdge() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == BlockEdgeKind; } }; class PostInitializer : public ProgramPoint { public: - PostInitializer(const CXXCtorInitializer *I, + /// \brief Construct a PostInitializer point that represents a location after + /// CXXCtorInitializer expression evaluation. + /// + /// \param I The initializer. + /// \param Loc The location of the field being initialized. + PostInitializer(const CXXCtorInitializer *I, + const void *Loc, const LocationContext *L) - : ProgramPoint(I, PostInitializerKind, L) {} + : ProgramPoint(I, Loc, PostInitializerKind, L) {} + + const CXXCtorInitializer *getInitializer() const { + return static_cast<const CXXCtorInitializer *>(getData1()); + } - static bool classof(const ProgramPoint *Location) { - return Location->getKind() == PostInitializerKind; + /// \brief Returns the location of the field. + const void *getLocationValue() const { + return getData2(); + } + +private: + friend class ProgramPoint; + PostInitializer() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == PostInitializerKind; } }; @@ -426,9 +512,13 @@ public: return SourceLocation::getFromPtrEncoding(getData1()); } - static bool classof(const ProgramPoint *Location) { - return Location->getKind() >= MinImplicitCallKind && - Location->getKind() <= MaxImplicitCallKind; +protected: + ImplicitCallPoint() {} +private: + friend class ProgramPoint; + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() >= MinImplicitCallKind && + Location.getKind() <= MaxImplicitCallKind; } }; @@ -441,8 +531,11 @@ public: const LocationContext *L, const ProgramPointTag *Tag = 0) : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {} - static bool classof(const ProgramPoint *Location) { - return Location->getKind() == PreImplicitCallKind; +private: + friend class ProgramPoint; + PreImplicitCall() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == PreImplicitCallKind; } }; @@ -455,8 +548,11 @@ public: const LocationContext *L, const ProgramPointTag *Tag = 0) : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {} - static bool classof(const ProgramPoint *Location) { - return Location->getKind() == PostImplicitCallKind; +private: + friend class ProgramPoint; + PostImplicitCall() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == PostImplicitCallKind; } }; @@ -476,8 +572,11 @@ public: return static_cast<const StackFrameContext *>(getData2()); } - static bool classof(const ProgramPoint *Location) { - return Location->getKind() == CallEnterKind; +private: + friend class ProgramPoint; + CallEnter() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == CallEnterKind; } }; @@ -496,8 +595,11 @@ public: CallExitBegin(const StackFrameContext *L) : ProgramPoint(0, CallExitBeginKind, L, 0) {} - static bool classof(const ProgramPoint *Location) { - return Location->getKind() == CallExitBeginKind; +private: + friend class ProgramPoint; + CallExitBegin() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == CallExitBeginKind; } }; @@ -514,8 +616,11 @@ public: return static_cast<const StackFrameContext *>(getData1()); } - static bool classof(const ProgramPoint *Location) { - return Location->getKind() == CallExitEndKind; +private: + friend class ProgramPoint; + CallExitEnd() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == CallExitEndKind; } }; @@ -529,8 +634,11 @@ public: const void *getData() const { return getData1(); } - static bool classof(const ProgramPoint* Location) { - return Location->getKind() == EpsilonKind; +private: + friend class ProgramPoint; + EpsilonPoint() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == EpsilonKind; } }; @@ -544,7 +652,7 @@ public: virtual StringRef getTagDescription() const = 0; protected: - /// Used to implement 'classof' in subclasses. + /// Used to implement 'isKind' in subclasses. const void *getTagKind() { return TagKind; } private: diff --git a/include/clang/Analysis/Support/BlkExprDeclBitVector.h b/include/clang/Analysis/Support/BlkExprDeclBitVector.h index d25b848..35cc799 100644 --- a/include/clang/Analysis/Support/BlkExprDeclBitVector.h +++ b/include/clang/Analysis/Support/BlkExprDeclBitVector.h @@ -17,8 +17,8 @@ #ifndef LLVM_CLANG_STMTDECLBVDVAL_H #define LLVM_CLANG_STMTDECLBVDVAL_H -#include "clang/Analysis/CFG.h" #include "clang/AST/Decl.h" // for Decl* -> NamedDecl* conversion +#include "clang/Analysis/CFG.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h index 83532e6..387e779 100644 --- a/include/clang/Analysis/Support/BumpVector.h +++ b/include/clang/Analysis/Support/BumpVector.h @@ -19,9 +19,9 @@ #ifndef LLVM_CLANG_BUMP_VECTOR #define LLVM_CLANG_BUMP_VECTOR -#include "llvm/Support/type_traits.h" -#include "llvm/Support/Allocator.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/type_traits.h" #include <algorithm> #include <cstring> #include <iterator> diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h index c510e20..2bf3eda 100644 --- a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h +++ b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h @@ -17,10 +17,10 @@ #ifndef LLVM_CLANG_ANALYSIS_CFG_REC_STMT_DECL_VISITOR_H #define LLVM_CLANG_ANALYSIS_CFG_REC_STMT_DECL_VISITOR_H -#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h" #define DISPATCH_CASE(CLASS) \ case Decl::CLASS: \ @@ -63,6 +63,7 @@ public: DISPATCH_CASE(ImplicitParam) DISPATCH_CASE(EnumConstant) DISPATCH_CASE(Typedef) + DISPATCH_CASE(TypeAlias) DISPATCH_CASE(Record) // FIXME: Refine. VisitStructDecl? DISPATCH_CASE(CXXRecord) DISPATCH_CASE(Enum) @@ -82,6 +83,7 @@ public: DEFAULT_DISPATCH(ImplicitParam) DEFAULT_DISPATCH(EnumConstant) DEFAULT_DISPATCH(Typedef) + DEFAULT_DISPATCH(TypeAlias) DEFAULT_DISPATCH(Record) DEFAULT_DISPATCH(Enum) DEFAULT_DISPATCH(Field) diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index bfe8093..37aa332 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -29,8 +29,8 @@ class SubsetSubject<AttrSubject base, string description, code check> code CheckCode = check; } -// This is the type of a variable which C++0x defines [[aligned()]] as being -// a possible subject. +// This is the type of a variable which C++11 allows alignas(...) to appertain +// to. def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable", [{S->getStorageClass() != VarDecl::Register && S->getKind() != Decl::ImplicitParam && @@ -91,6 +91,12 @@ class Declspec<string name> : Spelling<name, "Declspec">; class CXX11<string namespace, string name> : Spelling<name, "CXX11"> { string Namespace = namespace; } +class Keyword<string name> : Spelling<name, "Keyword">; + +class Accessor<string name, list<Spelling> spellings> { + string Name = name; + list<Spelling> Spellings = spellings; +} class Attr { // The various ways in which an attribute can be spelled in source @@ -99,8 +105,10 @@ class Attr { list<AttrSubject> Subjects; // The arguments allowed on an attribute list<Argument> Args = []; - // Set to true for attributes with arguments which require delayed parsing. - bit LateParsed = 0; + // Accessors which should be generated for the attribute. + list<Accessor> Accessors = []; + // Set to true for attributes with arguments which require delayed parsing. + bit LateParsed = 0; // Set to false to prevent an attribute from being propagated from a template // to the instantiation. bit Clone = 1; @@ -114,7 +122,7 @@ class Attr { bit Ignored = 0; // Set to true if each of the spellings is a distinct attribute. bit DistinctSpellings = 0; - // Any additional text that should be included verbatim in the class. + // Any additional text that should be included verbatim in the class. code AdditionalMembers = [{}]; } @@ -125,6 +133,13 @@ class InheritableAttr : Attr; /// redeclarations, even when it's written on a parameter. class InheritableParamAttr : InheritableAttr; +/// An ignored attribute, which we parse but discard with no checking. +class IgnoredAttr : Attr { + let Ignored = 1; + let ASTNode = 0; + let SemaHandler = 0; +} + // // Attributes begin here // @@ -132,18 +147,24 @@ class InheritableParamAttr : InheritableAttr; def AddressSpace : Attr { let Spellings = [GNU<"address_space">]; let Args = [IntArgument<"AddressSpace">]; - let ASTNode = 0; + let ASTNode = 0; } def Alias : InheritableAttr { - let Spellings = [GNU<"alias">]; + let Spellings = [GNU<"alias">, CXX11<"gnu", "alias">]; let Args = [StringArgument<"Aliasee">]; } def Aligned : InheritableAttr { - let Spellings = [GNU<"aligned">, GNU<"align">]; + let Spellings = [GNU<"aligned">, Declspec<"align">, CXX11<"gnu", "aligned">, + Keyword<"alignas">, Keyword<"_Alignas">]; let Subjects = [NonBitField, NormalVar, Tag]; - let Args = [AlignedArgument<"Alignment">, BoolArgument<"IsMSDeclSpec">]; + let Args = [AlignedArgument<"Alignment">]; + let Accessors = [Accessor<"isGNU", [GNU<"aligned">, CXX11<"gnu","aligned">]>, + Accessor<"isC11", [Keyword<"_Alignas">]>, + Accessor<"isAlignas", [Keyword<"alignas">, + Keyword<"_Alignas">]>, + Accessor<"isDeclspec",[Declspec<"align">]>]; } def AlignMac68k : InheritableAttr { @@ -152,16 +173,16 @@ def AlignMac68k : InheritableAttr { } def AllocSize : Attr { - let Spellings = [GNU<"alloc_size">]; + let Spellings = [GNU<"alloc_size">, CXX11<"gnu", "alloc_size">]; let Args = [VariadicUnsignedArgument<"Args">]; } def AlwaysInline : InheritableAttr { - let Spellings = [GNU<"always_inline">]; + let Spellings = [GNU<"always_inline">, CXX11<"gnu", "always_inline">]; } def TLSModel : InheritableAttr { - let Spellings = [GNU<"tls_model">]; + let Spellings = [GNU<"tls_model">, CXX11<"gnu", "tls_model">]; let Subjects = [Var]; let Args = [StringArgument<"Model">]; } @@ -200,11 +221,8 @@ def Blocks : InheritableAttr { let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>]; } -def Bounded : Attr { +def Bounded : IgnoredAttr { let Spellings = [GNU<"bounded">]; - let ASTNode = 0; - let SemaHandler = 0; - let Ignored = 1; } def CarriesDependency : InheritableParamAttr { @@ -214,7 +232,8 @@ def CarriesDependency : InheritableParamAttr { } def CDecl : InheritableAttr { - let Spellings = [GNU<"cdecl">, GNU<"__cdecl">]; + let Spellings = [GNU<"cdecl">, CXX11<"gnu", "cdecl">, Keyword<"__cdecl">, + Keyword<"_cdecl">]; } // cf_audited_transfer indicates that the given function has been @@ -234,11 +253,6 @@ def CFUnknownTransfer : InheritableAttr { let Subjects = [Function]; } -def CFReturnsAutoreleased : Attr { - let Spellings = [GNU<"cf_returns_autoreleased">]; - let ASTNode = 0; -} - def CFReturnsRetained : InheritableAttr { let Spellings = [GNU<"cf_returns_retained">]; let Subjects = [ObjCMethod, Function]; @@ -255,24 +269,24 @@ def CFConsumed : InheritableParamAttr { } def Cleanup : InheritableAttr { - let Spellings = [GNU<"cleanup">]; + let Spellings = [GNU<"cleanup">, CXX11<"gnu", "cleanup">]; let Args = [FunctionArgument<"FunctionDecl">]; } def Cold : InheritableAttr { - let Spellings = [GNU<"cold">]; + let Spellings = [GNU<"cold">, CXX11<"gnu", "cold">]; } def Common : InheritableAttr { - let Spellings = [GNU<"common">]; + let Spellings = [GNU<"common">, CXX11<"gnu", "common">]; } def Const : InheritableAttr { - let Spellings = [GNU<"const">, GNU<"__const">]; + let Spellings = [GNU<"const">, GNU<"__const">, CXX11<"gnu", "const">]; } def Constructor : InheritableAttr { - let Spellings = [GNU<"constructor">]; + let Spellings = [GNU<"constructor">, CXX11<"gnu", "constructor">]; let Args = [IntArgument<"Priority">]; } @@ -301,23 +315,33 @@ def CUDAShared : InheritableAttr { let Spellings = [GNU<"shared">]; } +def C11NoReturn : InheritableAttr { + let Spellings = [Keyword<"_Noreturn">]; + let Subjects = [Function]; + let SemaHandler = 0; +} + +def CXX11NoReturn : InheritableAttr { + let Spellings = [CXX11<"","noreturn">, CXX11<"std","noreturn">]; + let Subjects = [Function]; +} + def OpenCLKernel : Attr { - let Spellings = [GNU<"opencl_kernel_function">]; + let Spellings = [Keyword<"__kernel">, Keyword<"kernel">]; } def OpenCLImageAccess : Attr { let Spellings = [GNU<"opencl_image_access">]; let Args = [IntArgument<"Access">]; - let ASTNode = 0; } def Deprecated : InheritableAttr { - let Spellings = [GNU<"deprecated">]; + let Spellings = [GNU<"deprecated">, CXX11<"gnu", "deprecated">]; let Args = [StringArgument<"Message">]; } def Destructor : InheritableAttr { - let Spellings = [GNU<"destructor">]; + let Spellings = [GNU<"destructor">, CXX11<"gnu", "destructor">]; let Args = [IntArgument<"Priority">]; } @@ -328,12 +352,13 @@ def ExtVectorType : Attr { } def FallThrough : Attr { - let Spellings = [CXX11<"clang","fallthrough">]; + let Spellings = [CXX11<"clang", "fallthrough">]; let Subjects = [NullStmt]; } def FastCall : InheritableAttr { - let Spellings = [GNU<"fastcall">, GNU<"__fastcall">]; + let Spellings = [GNU<"fastcall">, CXX11<"gnu", "fastcall">, + Keyword<"__fastcall">, Keyword<"_fastcall">]; } def Final : InheritableAttr { @@ -347,22 +372,22 @@ def MinSize : InheritableAttr { } def Format : InheritableAttr { - let Spellings = [GNU<"format">]; + let Spellings = [GNU<"format">, CXX11<"gnu", "format">]; let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">, IntArgument<"FirstArg">]; } def FormatArg : InheritableAttr { - let Spellings = [GNU<"format_arg">]; + let Spellings = [GNU<"format_arg">, CXX11<"gnu", "format_arg">]; let Args = [IntArgument<"FormatIdx">]; } def GNUInline : InheritableAttr { - let Spellings = [GNU<"gnu_inline">]; + let Spellings = [GNU<"gnu_inline">, CXX11<"gnu", "gnu_inline">]; } def Hot : InheritableAttr { - let Spellings = [GNU<"hot">]; + let Spellings = [GNU<"hot">, CXX11<"gnu", "hot">]; } def IBAction : InheritableAttr { @@ -379,7 +404,7 @@ def IBOutletCollection : InheritableAttr { } def Malloc : InheritableAttr { - let Spellings = [GNU<"malloc">]; + let Spellings = [GNU<"malloc">, CXX11<"gnu", "malloc">]; } def MaxFieldAlignment : InheritableAttr { @@ -389,7 +414,7 @@ def MaxFieldAlignment : InheritableAttr { } def MayAlias : InheritableAttr { - let Spellings = [GNU<"may_alias">]; + let Spellings = [GNU<"may_alias">, CXX11<"gnu", "may_alias">]; } def MSP430Interrupt : InheritableAttr { @@ -408,14 +433,19 @@ def MBlazeSaveVolatiles : InheritableAttr { let SemaHandler = 0; } +def Mips16 : InheritableAttr { + let Spellings = [GNU<"mips16">, CXX11<"gnu", "mips16">]; + let Subjects = [Function]; +} + def Mode : Attr { - let Spellings = [GNU<"mode">]; + let Spellings = [GNU<"mode">, CXX11<"gnu", "mode">]; let Args = [IdentifierArgument<"Mode">]; let ASTNode = 0; } def Naked : InheritableAttr { - let Spellings = [GNU<"naked">]; + let Spellings = [GNU<"naked">, CXX11<"gnu", "naked">]; } def NeonPolyVectorType : Attr { @@ -431,11 +461,11 @@ def NeonVectorType : Attr { } def ReturnsTwice : InheritableAttr { - let Spellings = [GNU<"returns_twice">]; + let Spellings = [GNU<"returns_twice">, CXX11<"gnu", "returns_twice">]; } def NoCommon : InheritableAttr { - let Spellings = [GNU<"nocommon">]; + let Spellings = [GNU<"nocommon">, CXX11<"gnu", "nocommon">]; } def NoDebug : InheritableAttr { @@ -443,11 +473,16 @@ def NoDebug : InheritableAttr { } def NoInline : InheritableAttr { - let Spellings = [GNU<"noinline">]; + let Spellings = [GNU<"noinline">, CXX11<"gnu", "noinline">]; +} + +def NoMips16 : InheritableAttr { + let Spellings = [GNU<"nomips16">, CXX11<"gnu", "nomips16">]; + let Subjects = [Function]; } def NonNull : InheritableAttr { - let Spellings = [GNU<"nonnull">]; + let Spellings = [GNU<"nonnull">, CXX11<"gnu", "nonnull">]; let Args = [VariadicUnsignedArgument<"Args">]; let AdditionalMembers = [{bool isNonNull(unsigned idx) const { @@ -460,19 +495,19 @@ def NonNull : InheritableAttr { } def NoReturn : InheritableAttr { - let Spellings = [GNU<"noreturn">, CXX11<"","noreturn">, - CXX11<"std","noreturn">]; + let Spellings = [GNU<"noreturn">, CXX11<"gnu", "noreturn">]; // FIXME: Does GCC allow this on the function instead? let Subjects = [Function]; } def NoInstrumentFunction : InheritableAttr { - let Spellings = [GNU<"no_instrument_function">]; + let Spellings = [GNU<"no_instrument_function">, + CXX11<"gnu", "no_instrument_function">]; let Subjects = [Function]; } def NoThrow : InheritableAttr { - let Spellings = [GNU<"nothrow">]; + let Spellings = [GNU<"nothrow">, CXX11<"gnu", "nothrow">]; } def NSBridged : InheritableAttr { @@ -563,26 +598,30 @@ def Ownership : InheritableAttr { } def Packed : InheritableAttr { - let Spellings = [GNU<"packed">]; + let Spellings = [GNU<"packed">, CXX11<"gnu", "packed">]; } def PnaclCall : InheritableAttr { let Spellings = [GNU<"pnaclcall">]; } +def IntelOclBicc : InheritableAttr { + let Spellings = [GNU<"intel_ocl_bicc">]; +} + def Pcs : InheritableAttr { - let Spellings = [GNU<"pcs">]; + let Spellings = [GNU<"pcs">, CXX11<"gnu", "pcs">]; let Args = [EnumArgument<"PCS", "PCSType", ["aapcs", "aapcs-vfp"], ["AAPCS", "AAPCS_VFP"]>]; } def Pure : InheritableAttr { - let Spellings = [GNU<"pure">]; + let Spellings = [GNU<"pure">, CXX11<"gnu", "pure">]; } def Regparm : InheritableAttr { - let Spellings = [GNU<"regparm">]; + let Spellings = [GNU<"regparm">, CXX11<"gnu", "regparm">]; let Args = [UnsignedArgument<"NumParams">]; } @@ -592,6 +631,11 @@ def ReqdWorkGroupSize : InheritableAttr { UnsignedArgument<"ZDim">]; } +def Endian : InheritableAttr { + let Spellings = [GNU<"endian">]; + let Args = [IdentifierArgument<"platform">]; +} + def WorkGroupSizeHint : InheritableAttr { let Spellings = [GNU<"work_group_size_hint">]; let Args = [UnsignedArgument<"XDim">, @@ -605,30 +649,32 @@ def InitPriority : InheritableAttr { } def Section : InheritableAttr { - let Spellings = [GNU<"section">]; + let Spellings = [GNU<"section">, CXX11<"gnu", "section">]; let Args = [StringArgument<"Name">]; } def Sentinel : InheritableAttr { - let Spellings = [GNU<"sentinel">]; + let Spellings = [GNU<"sentinel">, CXX11<"gnu", "sentinel">]; let Args = [DefaultIntArgument<"Sentinel", 0>, DefaultIntArgument<"NullPos", 0>]; } def StdCall : InheritableAttr { - let Spellings = [GNU<"stdcall">, GNU<"__stdcall">]; + let Spellings = [GNU<"stdcall">, CXX11<"gnu", "stdcall">, + Keyword<"__stdcall">, Keyword<"_stdcall">]; } def ThisCall : InheritableAttr { - let Spellings = [GNU<"thiscall">, GNU<"__thiscall">]; + let Spellings = [GNU<"thiscall">, CXX11<"gnu", "thiscall">, + Keyword<"__thiscall">, Keyword<"_thiscall">]; } def Pascal : InheritableAttr { - let Spellings = [GNU<"pascal">]; + let Spellings = [GNU<"pascal">, Keyword<"__pascal">, Keyword<"_pascal">]; } def TransparentUnion : InheritableAttr { - let Spellings = [GNU<"transparent_union">]; + let Spellings = [GNU<"transparent_union">, CXX11<"gnu", "transparent_union">]; } def Unavailable : InheritableAttr { @@ -659,11 +705,11 @@ def ObjCRequiresPropertyDefs : InheritableAttr { } def Unused : InheritableAttr { - let Spellings = [GNU<"unused">]; + let Spellings = [GNU<"unused">, CXX11<"gnu", "unused">]; } def Used : InheritableAttr { - let Spellings = [GNU<"used">]; + let Spellings = [GNU<"used">, CXX11<"gnu", "used">]; } def Uuid : InheritableAttr { @@ -673,21 +719,27 @@ def Uuid : InheritableAttr { } def VectorSize : Attr { - let Spellings = [GNU<"vector_size">]; + let Spellings = [GNU<"vector_size">, CXX11<"gnu", "vector_size">]; let Args = [ExprArgument<"NumBytes">]; let ASTNode = 0; } -def VecTypeHint : Attr { +def VecTypeHint : InheritableAttr { let Spellings = [GNU<"vec_type_hint">]; - let ASTNode = 0; - let SemaHandler = 0; - let Ignored = 1; + let Args = [TypeArgument<"TypeHint">, SourceLocArgument<"TypeLoc">]; } def Visibility : InheritableAttr { let Clone = 0; - let Spellings = [GNU<"visibility">]; + let Spellings = [GNU<"visibility">, CXX11<"gnu", "visibility">]; + let Args = [EnumArgument<"Visibility", "VisibilityType", + ["default", "hidden", "internal", "protected"], + ["Default", "Hidden", "Hidden", "Protected"]>]; +} + +def TypeVisibility : InheritableAttr { + let Clone = 0; + let Spellings = [GNU<"type_visibility">, CXX11<"clang", "type_visibility">]; let Args = [EnumArgument<"Visibility", "VisibilityType", ["default", "hidden", "internal", "protected"], ["Default", "Hidden", "Hidden", "Protected"]>]; @@ -699,11 +751,13 @@ def VecReturn : InheritableAttr { } def WarnUnusedResult : InheritableAttr { - let Spellings = [GNU<"warn_unused_result">]; + let Spellings = [GNU<"warn_unused_result">, + CXX11<"clang", "warn_unused_result">, + CXX11<"gnu", "warn_unused_result">]; } def Weak : InheritableAttr { - let Spellings = [GNU<"weak">]; + let Spellings = [GNU<"weak">, CXX11<"gnu", "weak">]; } def WeakImport : InheritableAttr { @@ -711,16 +765,27 @@ def WeakImport : InheritableAttr { } def WeakRef : InheritableAttr { - let Spellings = [GNU<"weakref">]; + let Spellings = [GNU<"weakref">, CXX11<"gnu", "weakref">]; } def X86ForceAlignArgPointer : InheritableAttr { let Spellings = []; } -// AddressSafety attribute (e.g. for AddressSanitizer) -def NoAddressSafetyAnalysis : InheritableAttr { - let Spellings = [GNU<"no_address_safety_analysis">]; +// Attribute to disable AddressSanitizer (or equivalent) checks. +def NoSanitizeAddress : InheritableAttr { + let Spellings = [GNU<"no_address_safety_analysis">, + GNU<"no_sanitize_address">]; +} + +// Attribute to disable ThreadSanitizer checks. +def NoSanitizeThread : InheritableAttr { + let Spellings = [GNU<"no_sanitize_thread">]; +} + +// Attribute to disable MemorySanitizer checks. +def NoSanitizeMemory : InheritableAttr { + let Spellings = [GNU<"no_sanitize_memory">]; } // C/C++ Thread safety attributes (e.g. for deadlock, data race checking) @@ -876,29 +941,41 @@ def DLLImport : InheritableAttr { } def ForceInline : InheritableAttr { - let Spellings = [Declspec<"__forceinline">]; + let Spellings = [Keyword<"__forceinline">]; } def Win64 : InheritableAttr { - let Spellings = [Declspec<"w64">]; + let Spellings = [Keyword<"__w64">]; } def Ptr32 : InheritableAttr { - let Spellings = [Declspec<"__ptr32">]; + let Spellings = [Keyword<"__ptr32">]; } def Ptr64 : InheritableAttr { - let Spellings = [Declspec<"__ptr64">]; + let Spellings = [Keyword<"__ptr64">]; } -def SingleInheritance : InheritableAttr { - let Spellings = [Declspec<"__single_inheritance">]; +class MSInheritanceAttr : InheritableAttr; + +def SingleInheritance : MSInheritanceAttr { + let Spellings = [Keyword<"__single_inheritance">]; +} + +def MultipleInheritance : MSInheritanceAttr { + let Spellings = [Keyword<"__multiple_inheritance">]; } -def MultipleInheritance : InheritableAttr { - let Spellings = [Declspec<"__multiple_inheritance">]; +def VirtualInheritance : MSInheritanceAttr { + let Spellings = [Keyword<"__virtual_inheritance">]; +} + +// This attribute doesn't have any spellings, but we can apply it implicitly to +// incomplete types that lack any of the other attributes. +def UnspecifiedInheritance : MSInheritanceAttr { + let Spellings = []; } -def VirtualInheritance : InheritableAttr { - let Spellings = [Declspec<"__virtual_inheritance">]; +def Unaligned : IgnoredAttr { + let Spellings = [Keyword<"__unaligned">]; } diff --git a/include/clang/Basic/AttrKinds.h b/include/clang/Basic/AttrKinds.h index 150a30e..bd090ec 100644 --- a/include/clang/Basic/AttrKinds.h +++ b/include/clang/Basic/AttrKinds.h @@ -24,6 +24,7 @@ enum Kind { #define ATTR(X) X, #define LAST_INHERITABLE_ATTR(X) X, LAST_INHERITABLE = X, #define LAST_INHERITABLE_PARAM_ATTR(X) X, LAST_INHERITABLE_PARAM = X, +#define LAST_MS_INHERITABLE_ATTR(X) X, LAST_MS_INHERITABLE = X, #include "clang/Basic/AttrList.inc" NUM_ATTRS }; diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index d48eadc..0a513ef 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -31,6 +31,7 @@ // F -> constant CFString // G -> id // H -> SEL +// M -> struct objc_super // a -> __builtin_va_list // A -> "reference" to __builtin_va_list // V -> Vector, followed by the number of elements and the base type. @@ -81,6 +82,7 @@ // through an ellipsis // e -> const, but only when -fmath-errno=0 // j -> returns_twice (like setjmp) +// u -> arguments are not evaluated for their side-effects // FIXME: gcc has nonnull #if defined(BUILTIN) && !defined(LIBBUILTIN) @@ -394,8 +396,8 @@ BUILTIN(__builtin_bswap32, "UiUi", "nc") BUILTIN(__builtin_bswap64, "ULLiULLi", "nc") // Random GCC builtins -BUILTIN(__builtin_constant_p, "i.", "nct") -BUILTIN(__builtin_classify_type, "i.", "nct") +BUILTIN(__builtin_constant_p, "i.", "nctu") +BUILTIN(__builtin_classify_type, "i.", "nctu") BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc") BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc") BUILTIN(__builtin_va_start, "vA.", "nt") @@ -453,17 +455,17 @@ BUILTIN(__builtin_dwarf_sp_column, "Ui", "n") BUILTIN(__builtin_extend_pointer, "ULLiv*", "n") // _Unwind_Word == uint64_t // GCC Object size checking builtins -BUILTIN(__builtin_object_size, "zvC*i", "n") +BUILTIN(__builtin_object_size, "zvC*i", "nu") BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "nF") -BUILTIN(__builtin___memccpy_chk, "v*v*vC*iz", "nF") +BUILTIN(__builtin___memccpy_chk, "v*v*vC*izz", "nF") BUILTIN(__builtin___memmove_chk, "v*v*vC*zz", "nF") BUILTIN(__builtin___mempcpy_chk, "v*v*vC*zz", "nF") BUILTIN(__builtin___memset_chk, "v*v*izz", "nF") BUILTIN(__builtin___stpcpy_chk, "c*c*cC*z", "nF") BUILTIN(__builtin___strcat_chk, "c*c*cC*z", "nF") BUILTIN(__builtin___strcpy_chk, "c*c*cC*z", "nF") -BUILTIN(__builtin___strlcat_chk, "c*c*cC*zz", "nF") -BUILTIN(__builtin___strlcpy_chk, "c*c*cC*zz", "nF") +BUILTIN(__builtin___strlcat_chk, "zc*cC*zz", "nF") +BUILTIN(__builtin___strlcpy_chk, "zc*cC*zz", "nF") BUILTIN(__builtin___strncat_chk, "c*c*cC*zz", "nF") BUILTIN(__builtin___strncpy_chk, "c*c*cC*zz", "nF") BUILTIN(__builtin___stpncpy_chk, "c*c*cC*zz", "nF") @@ -760,17 +762,16 @@ LIBBUILTIN(strlcpy, "zc*cC*z", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(strlcat, "zc*cC*z", "f", "string.h", ALL_LANGUAGES) // id objc_msgSend(id, SEL, ...) LIBBUILTIN(objc_msgSend, "GGH.", "f", "objc/message.h", OBJC_LANG) - // long double objc_msgSend_fpret(id self, SEL op, ...) LIBBUILTIN(objc_msgSend_fpret, "LdGH.", "f", "objc/message.h", OBJC_LANG) // _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...) LIBBUILTIN(objc_msgSend_fp2ret, "XLdGH.", "f", "objc/message.h", OBJC_LANG) -// id objc_msgSend_stret (id, SEL, ...) -LIBBUILTIN(objc_msgSend_stret, "GGH.", "f", "objc/message.h", OBJC_LANG) +// void objc_msgSend_stret (id, SEL, ...) +LIBBUILTIN(objc_msgSend_stret, "vGH.", "f", "objc/message.h", OBJC_LANG) // id objc_msgSendSuper(struct objc_super *super, SEL op, ...) -LIBBUILTIN(objc_msgSendSuper, "Gv*H.", "f", "objc/message.h", OBJC_LANG) +LIBBUILTIN(objc_msgSendSuper, "GM*H.", "f", "objc/message.h", OBJC_LANG) // void objc_msgSendSuper_stret(struct objc_super *super, SEL op, ...) -LIBBUILTIN(objc_msgSendSuper_stret, "vv*H.", "f", "objc/message.h", OBJC_LANG) +LIBBUILTIN(objc_msgSendSuper_stret, "vM*H.", "f", "objc/message.h", OBJC_LANG) // id objc_getClass(const char *name) LIBBUILTIN(objc_getClass, "GcC*", "f", "objc/runtime.h", OBJC_LANG) // id objc_getMetaClass(const char *name) @@ -833,6 +834,14 @@ LIBBUILTIN(ceil, "dd", "fc", "math.h", ALL_LANGUAGES) LIBBUILTIN(ceill, "LdLd", "fc", "math.h", ALL_LANGUAGES) LIBBUILTIN(ceilf, "ff", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(cimag, "dXd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cimagf, "fXf", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cimagl, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES) + +LIBBUILTIN(creal, "dXd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(crealf, "fXf", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(creall, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES) + LIBBUILTIN(copysign, "ddd", "fc", "math.h", ALL_LANGUAGES) LIBBUILTIN(copysignl, "LdLdLd", "fc", "math.h", ALL_LANGUAGES) LIBBUILTIN(copysignf, "fff", "fc", "math.h", ALL_LANGUAGES) @@ -917,5 +926,15 @@ LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES) // Annotation function BUILTIN(__builtin_annotation, "v.", "tn") +// Multiprecision Arithmetic Builtins. +BUILTIN(__builtin_addcs, "UsUsCUsCUsCUs*", "n") +BUILTIN(__builtin_addc, "UiUiCUiCUiCUi*", "n") +BUILTIN(__builtin_addcl, "ULiULiCULiCULiCULi*", "n") +BUILTIN(__builtin_addcll, "ULLiULLiCULLiCULLiCULLi*", "n") +BUILTIN(__builtin_subcs, "UsUsCUsCUsCUs*", "n") +BUILTIN(__builtin_subc, "UiUiCUiCUiCUi*", "n") +BUILTIN(__builtin_subcl, "ULiULiCULiCULiCULi*", "n") +BUILTIN(__builtin_subcll, "ULLiULLiCULLiCULLiCULLi*", "n") + #undef BUILTIN #undef LIBBUILTIN diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h index 257daf1..3b88e15 100644 --- a/include/clang/Basic/Builtins.h +++ b/include/clang/Basic/Builtins.h @@ -109,6 +109,12 @@ public: return strchr(GetRecord(ID).Attributes, 'j') != 0; } + /// \brief Returns true if this builtin does not perform the side-effects + /// of its arguments. + bool isUnevaluated(unsigned ID) const { + return strchr(GetRecord(ID).Attributes, 'u') != 0; + } + /// \brief Return true if this is a builtin for a libc/libm function, /// with a "__builtin_" prefix (e.g. __builtin_abs). bool isLibFunction(unsigned ID) const { diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 5b46f8e..d536821 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -624,6 +624,11 @@ BUILTIN(__builtin_ia32_rdrand16_step, "UiUs*", "") BUILTIN(__builtin_ia32_rdrand32_step, "UiUi*", "") BUILTIN(__builtin_ia32_rdrand64_step, "UiULLi*", "") +// RDSEED +BUILTIN(__builtin_ia32_rdseed16_step, "UiUs*", "") +BUILTIN(__builtin_ia32_rdseed32_step, "UiUi*", "") +BUILTIN(__builtin_ia32_rdseed64_step, "UiULLi*", "") + // BMI BUILTIN(__builtin_ia32_bextr_u32, "UiUiUi", "") BUILTIN(__builtin_ia32_bextr_u64, "ULLiULLiULLi", "") @@ -739,5 +744,6 @@ BUILTIN(__builtin_ia32_vfrczpd256, "V4dV4d", "") BUILTIN(__builtin_ia32_xbegin, "i", "") BUILTIN(__builtin_ia32_xend, "v", "") BUILTIN(__builtin_ia32_xabort, "vIc", "") +BUILTIN(__builtin_ia32_xtest, "i", "") #undef BUILTIN diff --git a/include/clang/Basic/CharInfo.h b/include/clang/Basic/CharInfo.h new file mode 100644 index 0000000..d0afda4 --- /dev/null +++ b/include/clang/Basic/CharInfo.h @@ -0,0 +1,198 @@ +//===--- clang/Basic/CharInfo.h - Classifying ASCII Characters ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_BASIC_CHARINFO_H +#define CLANG_BASIC_CHARINFO_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" + +namespace clang { +namespace charinfo { + extern const uint16_t InfoTable[256]; + + enum { + CHAR_HORZ_WS = 0x0001, // '\t', '\f', '\v'. Note, no '\0' + CHAR_VERT_WS = 0x0002, // '\r', '\n' + CHAR_SPACE = 0x0004, // ' ' + CHAR_DIGIT = 0x0008, // 0-9 + CHAR_XLETTER = 0x0010, // a-f,A-F + CHAR_UPPER = 0x0020, // A-Z + CHAR_LOWER = 0x0040, // a-z + CHAR_UNDER = 0x0080, // _ + CHAR_PERIOD = 0x0100, // . + CHAR_RAWDEL = 0x0200, // {}[]#<>%:;?*+-/^&|~!=,"' + CHAR_PUNCT = 0x0400 // `$@() + }; + + enum { + CHAR_XUPPER = CHAR_XLETTER | CHAR_UPPER, + CHAR_XLOWER = CHAR_XLETTER | CHAR_LOWER + }; +} // end namespace charinfo + +/// Returns true if this is an ASCII character. +LLVM_READNONE static inline bool isASCII(char c) { + return static_cast<unsigned char>(c) <= 127; +} + +/// Returns true if this is a valid first character of a C identifier, +/// which is [a-zA-Z_]. +LLVM_READONLY static inline bool isIdentifierHead(unsigned char c, + bool AllowDollar = false) { + using namespace charinfo; + if (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_UNDER)) + return true; + return AllowDollar && c == '$'; +} + +/// Returns true if this is a body character of a C identifier, +/// which is [a-zA-Z0-9_]. +LLVM_READONLY static inline bool isIdentifierBody(unsigned char c, + bool AllowDollar = false) { + using namespace charinfo; + if (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_DIGIT|CHAR_UNDER)) + return true; + return AllowDollar && c == '$'; +} + +/// Returns true if this character is horizontal ASCII whitespace: +/// ' ', '\\t', '\\f', '\\v'. +/// +/// Note that this returns false for '\\0'. +LLVM_READONLY static inline bool isHorizontalWhitespace(unsigned char c) { + using namespace charinfo; + return (InfoTable[c] & (CHAR_HORZ_WS|CHAR_SPACE)) != 0; +} + +/// Returns true if this character is vertical ASCII whitespace: '\\n', '\\r'. +/// +/// Note that this returns false for '\\0'. +LLVM_READONLY static inline bool isVerticalWhitespace(unsigned char c) { + using namespace charinfo; + return (InfoTable[c] & CHAR_VERT_WS) != 0; +} + +/// Return true if this character is horizontal or vertical ASCII whitespace: +/// ' ', '\\t', '\\f', '\\v', '\\n', '\\r'. +/// +/// Note that this returns false for '\\0'. +LLVM_READONLY static inline bool isWhitespace(unsigned char c) { + using namespace charinfo; + return (InfoTable[c] & (CHAR_HORZ_WS|CHAR_VERT_WS|CHAR_SPACE)) != 0; +} + +/// Return true if this character is an ASCII digit: [0-9] +LLVM_READONLY static inline bool isDigit(unsigned char c) { + using namespace charinfo; + return (InfoTable[c] & CHAR_DIGIT) != 0; +} + +/// Return true if this character is a lowercase ASCII letter: [a-z] +LLVM_READONLY static inline bool isLowercase(unsigned char c) { + using namespace charinfo; + return (InfoTable[c] & CHAR_LOWER) != 0; +} + +/// Return true if this character is an uppercase ASCII letter: [A-Z] +LLVM_READONLY static inline bool isUppercase(unsigned char c) { + using namespace charinfo; + return (InfoTable[c] & CHAR_UPPER) != 0; +} + +/// Return true if this character is an ASCII letter: [a-zA-Z] +LLVM_READONLY static inline bool isLetter(unsigned char c) { + using namespace charinfo; + return (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER)) != 0; +} + +/// Return true if this character is an ASCII letter or digit: [a-zA-Z0-9] +LLVM_READONLY static inline bool isAlphanumeric(unsigned char c) { + using namespace charinfo; + return (InfoTable[c] & (CHAR_DIGIT|CHAR_UPPER|CHAR_LOWER)) != 0; +} + +/// Return true if this character is an ASCII hex digit: [0-9a-fA-F] +LLVM_READONLY static inline bool isHexDigit(unsigned char c) { + using namespace charinfo; + return (InfoTable[c] & (CHAR_DIGIT|CHAR_XLETTER)) != 0; +} + +/// Return true if this character is an ASCII punctuation character. +/// +/// Note that '_' is both a punctuation character and an identifier character! +LLVM_READONLY static inline bool isPunctuation(unsigned char c) { + using namespace charinfo; + return (InfoTable[c] & (CHAR_UNDER|CHAR_PERIOD|CHAR_RAWDEL|CHAR_PUNCT)) != 0; +} + +/// Return true if this character is an ASCII printable character; that is, a +/// character that should take exactly one column to print in a fixed-width +/// terminal. +LLVM_READONLY static inline bool isPrintable(unsigned char c) { + using namespace charinfo; + return (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_PERIOD|CHAR_PUNCT| + CHAR_DIGIT|CHAR_UNDER|CHAR_RAWDEL|CHAR_SPACE)) != 0; +} + +/// Return true if this is the body character of a C preprocessing number, +/// which is [a-zA-Z0-9_.]. +LLVM_READONLY static inline bool isPreprocessingNumberBody(unsigned char c) { + using namespace charinfo; + return (InfoTable[c] & + (CHAR_UPPER|CHAR_LOWER|CHAR_DIGIT|CHAR_UNDER|CHAR_PERIOD)) != 0; +} + +/// Return true if this is the body character of a C++ raw string delimiter. +LLVM_READONLY static inline bool isRawStringDelimBody(unsigned char c) { + using namespace charinfo; + return (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_PERIOD| + CHAR_DIGIT|CHAR_UNDER|CHAR_RAWDEL)) != 0; +} + + +/// Converts the given ASCII character to its lowercase equivalent. +/// +/// If the character is not an uppercase character, it is returned as is. +LLVM_READONLY static inline char toLowercase(char c) { + if (isUppercase(c)) + return c + 'a' - 'A'; + return c; +} + +/// Converts the given ASCII character to its uppercase equivalent. +/// +/// If the character is not a lowercase character, it is returned as is. +LLVM_READONLY static inline char toUppercase(char c) { + if (isLowercase(c)) + return c + 'A' - 'a'; + return c; +} + + +/// Return true if this is a valid ASCII identifier. +/// +/// Note that this is a very simple check; it does not accept '$' or UCNs as +/// valid identifier characters. +LLVM_READONLY static inline bool isValidIdentifier(StringRef S) { + if (S.empty() || !isIdentifierHead(S[0])) + return false; + + for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) + if (!isIdentifierBody(*I)) + return false; + + return true; +} + +} // end namespace clang + +#endif diff --git a/include/clang/Basic/CommentOptions.h b/include/clang/Basic/CommentOptions.h new file mode 100644 index 0000000..79b9a6b --- /dev/null +++ b/include/clang/Basic/CommentOptions.h @@ -0,0 +1,34 @@ +//===--- CommentOptions.h - Options for parsing comments -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines the clang::CommentOptions interface. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_COMMENTOPTIONS_H +#define LLVM_CLANG_COMMENTOPTIONS_H + +#include <string> +#include <vector> + +namespace clang { + +/// \brief Options for controlling comment parsing. +struct CommentOptions { + typedef std::vector<std::string> BlockCommandNamesTy; + + /// \brief Command names to treat as block commands in comments. + /// Should not include the leading backslash. + BlockCommandNamesTy BlockCommandNames; +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Basic/ConvertUTF.h b/include/clang/Basic/ConvertUTF.h deleted file mode 100644 index cdc4269..0000000 --- a/include/clang/Basic/ConvertUTF.h +++ /dev/null @@ -1,203 +0,0 @@ -/*===--- ConvertUTF.h - Universal Character Names conversions ---------------=== - * - * The LLVM Compiler Infrastructure - * - * This file is distributed under the University of Illinois Open Source - * License. See LICENSE.TXT for details. - * - *==------------------------------------------------------------------------==*/ -/* - * Copyright 2001-2004 Unicode, Inc. - * - * Disclaimer - * - * This source code is provided as is by Unicode, Inc. No claims are - * made as to fitness for any particular purpose. No warranties of any - * kind are expressed or implied. The recipient agrees to determine - * applicability of information provided. If this file has been - * purchased on magnetic or optical media from Unicode, Inc., the - * sole remedy for any claim will be exchange of defective media - * within 90 days of receipt. - * - * Limitations on Rights to Redistribute This Code - * - * Unicode, Inc. hereby grants the right to freely use the information - * supplied in this file in the creation of products supporting the - * Unicode Standard, and to make copies of this file in any form - * for internal or external distribution as long as this notice - * remains attached. - */ - -/* --------------------------------------------------------------------- - - Conversions between UTF32, UTF-16, and UTF-8. Header file. - - Several funtions are included here, forming a complete set of - conversions between the three formats. UTF-7 is not included - here, but is handled in a separate source file. - - Each of these routines takes pointers to input buffers and output - buffers. The input buffers are const. - - Each routine converts the text between *sourceStart and sourceEnd, - putting the result into the buffer between *targetStart and - targetEnd. Note: the end pointers are *after* the last item: e.g. - *(sourceEnd - 1) is the last item. - - The return result indicates whether the conversion was successful, - and if not, whether the problem was in the source or target buffers. - (Only the first encountered problem is indicated.) - - After the conversion, *sourceStart and *targetStart are both - updated to point to the end of last text successfully converted in - the respective buffers. - - Input parameters: - sourceStart - pointer to a pointer to the source buffer. - The contents of this are modified on return so that - it points at the next thing to be converted. - targetStart - similarly, pointer to pointer to the target buffer. - sourceEnd, targetEnd - respectively pointers to the ends of the - two buffers, for overflow checking only. - - These conversion functions take a ConversionFlags argument. When this - flag is set to strict, both irregular sequences and isolated surrogates - will cause an error. When the flag is set to lenient, both irregular - sequences and isolated surrogates are converted. - - Whether the flag is strict or lenient, all illegal sequences will cause - an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>, - or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code - must check for illegal sequences. - - When the flag is set to lenient, characters over 0x10FFFF are converted - to the replacement character; otherwise (when the flag is set to strict) - they constitute an error. - - Output parameters: - The value "sourceIllegal" is returned from some routines if the input - sequence is malformed. When "sourceIllegal" is returned, the source - value will point to the illegal value that caused the problem. E.g., - in UTF-8 when a sequence is malformed, it points to the start of the - malformed sequence. - - Author: Mark E. Davis, 1994. - Rev History: Rick McGowan, fixes & updates May 2001. - Fixes & updates, Sept 2001. - ------------------------------------------------------------------------- */ - -#ifndef CLANG_BASIC_CONVERTUTF_H -#define CLANG_BASIC_CONVERTUTF_H - -/* --------------------------------------------------------------------- - The following 4 definitions are compiler-specific. - The C standard does not guarantee that wchar_t has at least - 16 bits, so wchar_t is no less portable than unsigned short! - All should be unsigned values to avoid sign extension during - bit mask & shift operations. ------------------------------------------------------------------------- */ - -typedef unsigned int UTF32; /* at least 32 bits */ -typedef unsigned short UTF16; /* at least 16 bits */ -typedef unsigned char UTF8; /* typically 8 bits */ -typedef unsigned char Boolean; /* 0 or 1 */ - -/* Some fundamental constants */ -#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD -#define UNI_MAX_BMP (UTF32)0x0000FFFF -#define UNI_MAX_UTF16 (UTF32)0x0010FFFF -#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF -#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF - -#define UNI_MAX_UTF8_BYTES_PER_CODE_POINT 4 - -typedef enum { - conversionOK, /* conversion successful */ - sourceExhausted, /* partial character in source, but hit end */ - targetExhausted, /* insuff. room in target for conversion */ - sourceIllegal /* source sequence is illegal/malformed */ -} ConversionResult; - -typedef enum { - strictConversion = 0, - lenientConversion -} ConversionFlags; - -/* This is for C++ and does no harm in C */ -#ifdef __cplusplus -extern "C" { -#endif - -ConversionResult ConvertUTF8toUTF16 ( - const UTF8** sourceStart, const UTF8* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF8toUTF32 ( - const UTF8** sourceStart, const UTF8* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); - -#ifdef CLANG_NEEDS_THESE_ONE_DAY -ConversionResult ConvertUTF16toUTF8 ( - const UTF16** sourceStart, const UTF16* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); -#endif - -ConversionResult ConvertUTF32toUTF8 ( - const UTF32** sourceStart, const UTF32* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF16toUTF32 ( - const UTF16** sourceStart, const UTF16* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF32toUTF16 ( - const UTF32** sourceStart, const UTF32* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); -#endif - -Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); - -Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd); - -unsigned getNumBytesForUTF8(UTF8 firstByte); - -#ifdef __cplusplus -} - -/*************************************************************************/ -/* Below are LLVM-specific wrappers of the functions above. */ - -#include "llvm/ADT/StringRef.h" - -namespace clang { - -/** - * Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on - * WideCharWidth. The converted data is written to ResultPtr, which needs to - * point to at least WideCharWidth * (Source.Size() + 1) bytes. On success, - * ResultPtr will point one after the end of the copied string. On failure, - * ResultPtr will not be changed, and ErrorPtr will be set to the location of - * the first character which could not be converted. - * \return true on success. - */ -bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source, - char *&ResultPtr, const UTF8 *&ErrorPtr); - -/** - * Convert an Unicode code point to UTF8 sequence. - * - * \param Source a Unicode code point. - * \param [in,out] ResultPtr pointer to the output buffer, needs to be at least - * \c UNI_MAX_UTF8_BYTES_PER_CODE_POINT bytes. On success \c ResultPtr is - * updated one past end of the converted sequence. - * - * \returns true on success. - */ -bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr); - -} - -#endif - -/* --------------------------------------------------------------------- */ diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td index 6f2bb35..45742bc 100644 --- a/include/clang/Basic/DeclNodes.td +++ b/include/clang/Basic/DeclNodes.td @@ -74,4 +74,6 @@ def StaticAssert : Decl; def Block : Decl, DeclContext; def ClassScopeFunctionSpecialization : Decl; def Import : Decl; +def OMPThreadPrivate : Decl; +def Empty : Decl; diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index e47f3e1..0327636 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -23,9 +23,8 @@ #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/type_traits.h" - -#include <vector> #include <list> +#include <vector> namespace clang { class DiagnosticConsumer; @@ -78,7 +77,7 @@ public: bool BeforePreviousInsertions = false) { FixItHint Hint; Hint.RemoveRange = - CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false); + CharSourceRange::getCharRange(InsertionLoc, InsertionLoc); Hint.CodeToInsert = Code; Hint.BeforePreviousInsertions = BeforePreviousInsertions; return Hint; @@ -91,7 +90,7 @@ public: bool BeforePreviousInsertions = false) { FixItHint Hint; Hint.RemoveRange = - CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false); + CharSourceRange::getCharRange(InsertionLoc, InsertionLoc); Hint.InsertFromRange = FromRange; Hint.BeforePreviousInsertions = BeforePreviousInsertions; return Hint; @@ -176,6 +175,7 @@ private: bool SuppressAllDiagnostics; // Suppress all diagnostics. bool ElideType; // Elide common types of templates. bool PrintTemplateTree; // Print a tree when comparing templates. + bool WarnOnSpellCheck; // Emit warning when spellcheck is initiated. bool ShowColors; // Color printing is enabled. OverloadsShown ShowOverloads; // Which overload candidates to show. unsigned ErrorLimit; // Cap of # errors emitted, 0 -> no limit. @@ -280,6 +280,10 @@ private: /// \brief Sticky flag set to \c true when an error is emitted. bool ErrorOccurred; + /// \brief Sticky flag set to \c true when an "uncompilable error" occurs. + /// I.e. an error that was not upgraded from a warning by -Werror. + bool UncompilableErrorOccurred; + /// \brief Sticky flag set to \c true when a fatal error is emitted. bool FatalErrorOccurred; @@ -432,8 +436,8 @@ public: /// /// If this and IgnoreAllWarnings are both set, then that one wins. void setEnableAllWarnings(bool Val) { EnableAllWarnings = Val; } - bool getEnableAllWarnngs() const { return EnableAllWarnings; } - + bool getEnableAllWarnings() const { return EnableAllWarnings; } + /// \brief When set to true, any warnings reported are issued as errors. void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; } bool getWarningsAsErrors() const { return WarningsAsErrors; } @@ -463,6 +467,10 @@ public: /// tree format. void setPrintTemplateTree(bool Val = false) { PrintTemplateTree = Val; } bool getPrintTemplateTree() { return PrintTemplateTree; } + + /// \brief Warn when spellchecking is initated, for testing. + void setWarnOnSpellCheck(bool Val = false) { WarnOnSpellCheck = Val; } + bool getWarnOnSpellCheck() { return WarnOnSpellCheck; } /// \brief Set color printing, so the type diffing will inject color markers /// into the output. @@ -559,6 +567,12 @@ public: SourceLocation Loc = SourceLocation()); bool hasErrorOccurred() const { return ErrorOccurred; } + + /// \brief Errors that actually prevent compilation, not those that are + /// upgraded from a warning by -Werror. + bool hasUncompilableErrorOccurred() const { + return UncompilableErrorOccurred; + } bool hasFatalErrorOccurred() const { return FatalErrorOccurred; } /// \brief Determine whether any kind of unrecoverable error has occurred. @@ -574,7 +588,7 @@ public: /// \brief Return an ID for a diagnostic with the specified message and level. /// - /// If this is the first request for this diagnosic, it is registered and + /// If this is the first request for this diagnostic, it is registered and /// created, otherwise the existing ID is returned. unsigned getCustomDiagID(Level L, StringRef Message) { return Diags->getCustomDiagID((DiagnosticIDs::Level)L, Message); @@ -598,6 +612,12 @@ public: ArgToStringCookie = Cookie; } + /// \brief Note that the prior diagnostic was emitted by some other + /// \c DiagnosticsEngine, and we may be attaching a note to that diagnostic. + void notePriorDiagnosticFrom(const DiagnosticsEngine &Other) { + LastDiagLevel = Other.LastDiagLevel; + } + /// \brief Reset the state of the diagnostic object to its initial /// configuration. void Reset(); diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td index d869c99..9be32af 100644 --- a/include/clang/Basic/DiagnosticASTKinds.td +++ b/include/clang/Basic/DiagnosticASTKinds.td @@ -106,6 +106,9 @@ def note_constexpr_calls_suppressed : Note< "(skipping %0 call%s0 in backtrace; use -fconstexpr-backtrace-limit=0 to " "see all)">; def note_constexpr_call_here : Note<"in call to '%0'">; +def warn_integer_constant_overflow : Warning< + "overflow in expression; result is %0 with type %1">, + InGroup<DiagGroup<"integer-overflow">>; // inline asm related. let CategoryName = "Inline Assembly Issue" in { @@ -135,7 +138,8 @@ def err_odr_function_type_inconsistent : Error< "external function %0 declared with incompatible types in different " "translation units (%1 vs. %2)">; def warn_odr_tag_type_inconsistent : Warning< - "type %0 has incompatible definitions in different translation units">; + "type %0 has incompatible definitions in different translation units">, + InGroup<DiagGroup<"odr">>; def note_odr_tag_kind_here: Note< "%0 is a %select{struct|interface|union|class|enum}1 here">; def note_odr_field : Note<"field %0 has type %1 here">; diff --git a/include/clang/Basic/DiagnosticCommentKinds.td b/include/clang/Basic/DiagnosticCommentKinds.td index e6dfe5b..3880e0e 100644 --- a/include/clang/Basic/DiagnosticCommentKinds.td +++ b/include/clang/Basic/DiagnosticCommentKinds.td @@ -44,18 +44,18 @@ def note_doc_html_end_tag : Note< // Commands def warn_doc_block_command_empty_paragraph : Warning< - "empty paragraph passed to '\\%0' command">, + "empty paragraph passed to '%select{\\|@}0%1' command">, InGroup<Documentation>, DefaultIgnore; def warn_doc_block_command_duplicate : Warning< - "duplicated command '\\%0'">, + "duplicated command '%select{\\|@}0%1'">, InGroup<Documentation>, DefaultIgnore; def note_doc_block_command_previous : Note< - "previous command '\\%0' here">; + "previous command '%select{\\|@}0%1' here">; def note_doc_block_command_previous_alias : Note< - "previous command '\\%0' (an alias of '\\%1') here">; + "previous command '%select{\\|@}0%1' (an alias of '\\%2') here">; // \param command @@ -69,10 +69,29 @@ def warn_doc_param_spaces_in_direction : Warning< InGroup<DocumentationPedantic>, DefaultIgnore; def warn_doc_param_not_attached_to_a_function_decl : Warning< - "'\\param' command used in a comment that is not attached to " + "'%select{\\|@}0param' command used in a comment that is not attached to " "a function declaration">, InGroup<Documentation>, DefaultIgnore; +def warn_doc_function_method_decl_mismatch : Warning< + "'%select{\\|@}0%select{function|functiongroup|method|methodgroup|callback}1' " + "command should be used in a comment attached to " + "%select{a function|a function|an Objective-C method|an Objective-C method|" + "a pointer to function}2 declaration">, + InGroup<Documentation>, DefaultIgnore; + +def warn_doc_api_container_decl_mismatch : Warning< + "'%select{\\|@}0%select{class|interface|protocol|struct|union}1' " + "command should not be used in a comment attached to a " + "non-%select{class|interface|protocol|struct|union}2 declaration">, + InGroup<Documentation>, DefaultIgnore; + +def warn_doc_container_decl_mismatch : Warning< + "'%select{\\|@}0%select{classdesign|coclass|dependency|helper" + "|helperclass|helps|instancesize|ownership|performance|security|superclass}1' " + "command should not be used in a comment attached to a non-container declaration">, + InGroup<Documentation>, DefaultIgnore; + def warn_doc_param_duplicate : Warning< "parameter '%0' is already documented">, InGroup<Documentation>, DefaultIgnore; @@ -87,10 +106,10 @@ def warn_doc_param_not_found : Warning< def note_doc_param_name_suggestion : Note< "did you mean '%0'?">; -// \tparam command +// tparam command def warn_doc_tparam_not_attached_to_a_template_decl : Warning< - "'\\tparam' command used in a comment that is not attached to " + "'%select{\\|@}0tparam' command used in a comment that is not attached to " "a template declaration">, InGroup<Documentation>, DefaultIgnore; @@ -111,14 +130,14 @@ def note_doc_tparam_name_suggestion : Note< // \returns command def warn_doc_returns_not_attached_to_a_function_decl : Warning< - "'\\%0' command used in a comment that is not attached to " + "'%select{\\|@}0%1' command used in a comment that is not attached to " "a function or method declaration">, InGroup<Documentation>, DefaultIgnore; def warn_doc_returns_attached_to_a_void_function : Warning< - "'\\%0' command used in a comment that is attached to a " + "'%select{\\|@}0%1' command used in a comment that is attached to a " "%select{function returning void|constructor|destructor|" - "method returning void}1">, + "method returning void}2">, InGroup<Documentation>, DefaultIgnore; // \deprecated command @@ -134,7 +153,7 @@ def note_add_deprecation_attr : Note< // verbatim block commands def warn_verbatim_block_end_without_start : Warning< - "'\\%0' command does not terminate a verbatim text block">, + "'%select{\\|@}0%1' command does not terminate a verbatim text block">, InGroup<Documentation>, DefaultIgnore; } // end of documentation issue category diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index a6ce9d4..7ff6ae1 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -41,6 +41,9 @@ def err_expected_colon : Error<"expected ':'">; def err_expected_colon_after_setter_name : Error< "method name referenced in property setter attribute " "must end with ':'">; +def err_expected_string_literal : Error<"expected string literal " + "%select{in %1|for diagnostic message in static_assert|" + "for optional message in 'availability' attribute}0">; def err_invalid_string_udl : Error< "string literal with user-defined suffix cannot be used here">; def err_invalid_character_udl : Error< @@ -49,8 +52,6 @@ def err_invalid_numeric_udl : Error< "numeric literal with user-defined suffix cannot be used here">; // Parse && Sema -def ext_no_declarators : ExtWarn<"declaration does not declare anything">, - InGroup<MissingDeclarations>; def err_param_redefinition : Error<"redefinition of parameter %0">; def warn_method_param_redefinition : Warning<"redefinition of method parameter %0">; def warn_method_param_declaration : Warning<"redeclaration of method parameter %0">, @@ -71,11 +72,12 @@ def err_module_not_found : Error<"module '%0' not found">, DefaultFatal; def err_module_not_built : Error<"could not build module '%0'">, DefaultFatal; def err_module_cycle : Error<"cyclic dependency in module '%0': %1">, DefaultFatal; -def warn_module_build : Warning<"building module '%0' from source">, - InGroup<ModuleBuild>, DefaultIgnore; def note_pragma_entered_here : Note<"#pragma entered here">; def note_decl_hiding_tag_type : Note< "%1 %0 is hidden by a non-type declaration of %0 here">; +def err_attribute_not_type_attr : Error< + "%0 attribute cannot be applied to types">; +def err_enum_template : Error<"enumeration cannot be a template">; // Sema && Lex def ext_c99_longlong : Extension< @@ -115,4 +117,8 @@ def err_unable_to_rename_temp : Error< "unable to rename temporary '%0' to output file '%1': '%2'">; def err_unable_to_make_temp : Error< "unable to make temporary file: %0">; + +// Modules +def err_module_file_conflict : Error<"module '%0' found in both '%1' and '%2'">; + } diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 4b43035..15b8948 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -35,6 +35,8 @@ def err_drv_use_of_Z_option : Error< "unsupported use of internal gcc -Z option '%0'">; def err_drv_output_argument_with_multiple_files : Error< "cannot specify -o when generating multiple output files">; +def err_no_external_windows_assembler : Error< + "there is no external assembler we can use on windows">; def err_drv_unable_to_remove_file : Error< "unable to remove file: %0">; def err_drv_command_failure : Error< @@ -57,6 +59,8 @@ def err_drv_no_linker_llvm_support : Error< "'%0': unable to pass LLVM bit-code files to linker">; def err_drv_no_ast_support : Error< "'%0': unable to use AST files with this tool">; +def err_drv_no_module_support : Error< + "'%0': unable to use module files with this tool">; def err_drv_clang_unsupported : Error< "the clang compiler does not support '%0'">; def err_drv_clang_unsupported_per_platform : Error< @@ -67,6 +71,8 @@ def err_drv_command_failed : Error< "%0 command failed with exit code %1 (use -v to see invocation)">; def err_drv_command_signalled : Error< "%0 command failed due to signal (use -v to see invocation)">; +def err_drv_force_crash : Error< + "failing because environment variable '%0' is set">; def err_drv_invalid_mfloat_abi : Error< "invalid float ABI '%0'">; def err_drv_invalid_libcxx_deployment : Error< @@ -108,19 +114,21 @@ def warn_c_kext : Warning< "ignoring -fapple-kext which is valid for C++ and Objective-C++ only">; def warn_drv_input_file_unused : Warning< "%0: '%1' input unused%select{ when '%3' is present|}2">, - InGroup<DiagGroup<"unused-command-line-argument">>; + InGroup<UnusedCommandLineArgument>; def warn_drv_input_file_unused_by_cpp : Warning< "%0: '%1' input unused in cpp mode">, - InGroup<DiagGroup<"unused-command-line-argument">>; + InGroup<UnusedCommandLineArgument>; def warn_drv_preprocessed_input_file_unused : Warning< "%0: previously preprocessed input%select{ unused when '%2' is present|}1">, - InGroup<DiagGroup<"unused-command-line-argument">>; + InGroup<UnusedCommandLineArgument>; def warn_drv_unused_argument : Warning< "argument unused during compilation: '%0'">, - InGroup<DiagGroup<"unused-command-line-argument">>; + InGroup<UnusedCommandLineArgument>; def warn_drv_empty_joined_argument : Warning< "joined argument expects additional value: '%0'">, - InGroup<DiagGroup<"unused-command-line-argument">>; + InGroup<UnusedCommandLineArgument>; +def warn_drv_unused_sanitizer : Warning<"'%0' is ignored in absence of '%1'">, + InGroup<UnusedSanitizeArgument>; def warn_drv_clang_unsupported : Warning< "the clang compiler does not support '%0'">; def warn_drv_deprecated_arg : Warning< @@ -136,6 +144,8 @@ def warn_drv_objc_gc_unsupported : Warning< "Objective-C garbage collection is not supported on this platform, ignoring '%0'">; def warn_drv_pch_not_first_include : Warning< "precompiled header '%0' was ignored because '%1' is not first '-include'">; +def warn_missing_sysroot : Warning<"no such sysroot directory: '%0'">, + InGroup<DiagGroup<"missing-sysroot">>; def note_drv_command_failed_diag_msg : Note< "diagnostic msg: %0">; diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index b7a8476..111622e 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -48,8 +48,6 @@ def err_fe_unable_to_interface_with_target : Error< "unable to interface with target machine">; def err_fe_unable_to_open_output : Error< "unable to open output file '%0': '%1'">; -def err_fe_unable_to_open_logfile : Error< - "unable to open logfile file '%0': '%1'">; def err_fe_pth_file_has_no_source_header : Error< "PTH file '%0' does not designate an original source header file for -include-pth">; def warn_fe_macro_contains_embedded_newline : Warning< @@ -60,6 +58,8 @@ def warn_fe_cc_log_diagnostics_failure : Warning< "unable to open CC_LOG_DIAGNOSTICS file: %0 (using stderr)">; def err_fe_no_pch_in_dir : Error< "no suitable precompiled header file found in directory '%0'">; +def err_fe_action_not_available : Error< + "action %0 not compiled in">; def warn_fe_serialized_diag_failure : Warning< "unable to open file %0 for serializing diagnostics (%1)">, @@ -100,19 +100,19 @@ def err_relocatable_without_isysroot : Error< def warn_unknown_warning_option : Warning< "unknown warning option '%0'">, - InGroup<DiagGroup<"unknown-warning-option"> >; + InGroup<UnknownWarningOption>; def warn_unknown_negative_warning_option : Warning< "unknown warning option '%0'">, - InGroup<DiagGroup<"unknown-warning-option"> >; + InGroup<UnknownWarningOption>; def warn_unknown_warning_option_suggest : Warning< "unknown warning option '%0'; did you mean '%1'?">, - InGroup<DiagGroup<"unknown-warning-option"> >; + InGroup<UnknownWarningOption>; def warn_unknown_negative_warning_option_suggest : Warning< "unknown warning option '%0'; did you mean '%1'?">, - InGroup<DiagGroup<"unknown-warning-option"> >; + InGroup<UnknownWarningOption>; def warn_unknown_warning_specifier : Warning< "unknown %0 warning specifier: '%1'">, - InGroup<DiagGroup<"unknown-warning-option"> >; + InGroup<UnknownWarningOption>; def err_unknown_analyzer_checker : Error< "no analyzer checkers are associated with '%0'">; @@ -129,8 +129,6 @@ def err_missing_module_name : Error< DefaultFatal; def err_missing_module : Error< "no module named '%0' declared in module map file '%1'">, DefaultFatal; -def err_missing_umbrella_header : Error< - "cannot open umbrella header '%0': %1">, DefaultFatal; def err_no_submodule : Error<"no submodule named %0 in module '%1'">; def err_no_submodule_suggest : Error< "no submodule named %0 in module '%1'; did you mean '%2'?">; @@ -139,5 +137,11 @@ def warn_missing_submodule : Warning<"missing submodule '%0'">, def err_module_map_temp_file : Error< "unable to write temporary module map file '%0'">, DefaultFatal; def err_module_unavailable : Error<"module '%0' requires feature '%1'">; - +def warn_module_config_macro_undef : Warning< + "%select{definition|#undef}0 of configuration macro '%1' has no effect on " + "the import of '%2'; pass '%select{-D%1=...|-U%1}0' on the command line " + "to configure the module">, + InGroup<ConfigMacros>; +def note_module_def_undef_here : Note< + "macro was %select{defined|#undef'd}0 here">; } diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index f9f9ec7..a12a4f9 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -22,6 +22,8 @@ def : DiagGroup<"address">; def AddressOfTemporary : DiagGroup<"address-of-temporary">; def : DiagGroup<"aggregate-return">; def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">; +def ArrayBounds : DiagGroup<"array-bounds">; +def ArrayBoundsPointerArithmetic : DiagGroup<"array-bounds-pointer-arithmetic">; def Availability : DiagGroup<"availability">; def Section : DiagGroup<"section">; def AutoImport : DiagGroup<"auto-import">; @@ -36,14 +38,17 @@ def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">; def NullConversion : DiagGroup<"null-conversion">; def ImplicitConversionFloatingPointToBool : DiagGroup<"implicit-conversion-floating-point-to-bool">; +def BadArrayNewLength : DiagGroup<"bad-array-new-length">; +def BuiltinMacroRedefined : DiagGroup<"builtin-macro-redefined">; def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">; +def C99Compat : DiagGroup<"c99-compat">; def CXXCompat: DiagGroup<"c++-compat">; def CastAlign : DiagGroup<"cast-align">; def : DiagGroup<"cast-qual">; def : DiagGroup<"char-align">; def Comment : DiagGroup<"comment">; +def ConfigMacros : DiagGroup<"config-macros">; def : DiagGroup<"ctor-dtor-privacy">; -def DefaultArgSpecialMember : DiagGroup<"default-arg-special-member">; def GNUDesignator : DiagGroup<"gnu-designator">; def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor">; @@ -118,10 +123,18 @@ def BitwiseOpParentheses: DiagGroup<"bitwise-op-parentheses">; def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">; def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">; def DanglingElse: DiagGroup<"dangling-else">; +def DanglingField : DiagGroup<"dangling-field">; +def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">; def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">; def : DiagGroup<"import">; -def IncompatiblePointerTypes : DiagGroup<"incompatible-pointer-types">; +def IncompatiblePointerTypesDiscardsQualifiers + : DiagGroup<"incompatible-pointer-types-discards-qualifiers">; +def IncompatiblePointerTypes + : DiagGroup<"incompatible-pointer-types", + [IncompatiblePointerTypesDiscardsQualifiers]>; def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">; +def InvalidNoreturn : DiagGroup<"invalid-noreturn">; +def InvalidSourceEncoding : DiagGroup<"invalid-source-encoding">; def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">; def : DiagGroup<"init-self">; def : DiagGroup<"inline">; @@ -136,19 +149,23 @@ def MissingBraces : DiagGroup<"missing-braces">; def MissingDeclarations: DiagGroup<"missing-declarations">; def : DiagGroup<"missing-format-attribute">; def : DiagGroup<"missing-include-dirs">; +def MissingNoreturn : DiagGroup<"missing-noreturn">; def MultiChar : DiagGroup<"multichar">; def : DiagGroup<"nested-externs">; def CXX11LongLong : DiagGroup<"c++11-long-long">; def LongLong : DiagGroup<"long-long", [CXX11LongLong]>; +def MethodSignatures : DiagGroup<"method-signatures">; def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">; def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">; def MismatchedTags : DiagGroup<"mismatched-tags">; def MissingFieldInitializers : DiagGroup<"missing-field-initializers">; -def ModuleBuild : DiagGroup<"module-build">; +def ModuleConflict : DiagGroup<"module-conflict">; +def NullArithmetic : DiagGroup<"null-arithmetic">; def NullCharacter : DiagGroup<"null-character">; def NullDereference : DiagGroup<"null-dereference">; def InitializerOverrides : DiagGroup<"initializer-overrides">; def NonNull : DiagGroup<"nonnull">; +def NonPODVarargs : DiagGroup<"non-pod-varargs">; def : DiagGroup<"nonportable-cfstrings">; def NonVirtualDtor : DiagGroup<"non-virtual-dtor">; def OveralignedType : DiagGroup<"over-aligned">; @@ -170,6 +187,7 @@ def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">; def ObjCRetainBlockProperty : DiagGroup<"objc-noncopy-retain-block-property">; def ObjCReadonlyPropertyHasSetter : DiagGroup<"objc-readonly-with-setter-property">; def ObjCRootClass : DiagGroup<"objc-root-class">; +def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">; def Packed : DiagGroup<"packed">; def Padded : DiagGroup<"padded">; def PointerArith : DiagGroup<"pointer-arith">; @@ -179,6 +197,7 @@ def PoundPragmaMessage : DiagGroup<"#pragma-messages">, DiagCategory<"#pragma message Directive">; def : DiagGroup<"pointer-to-int-cast">; def : DiagGroup<"redundant-decls">; +def ReturnStackAddress : DiagGroup<"return-stack-address">; def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">; def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>; def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy", @@ -188,7 +207,6 @@ def SelfAssignment : DiagGroup<"self-assign", [SelfAssignmentField]>; def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">; def Sentinel : DiagGroup<"sentinel">; def MissingMethodReturnType : DiagGroup<"missing-method-return-type">; -def : DiagGroup<"sequence-point">; def Shadow : DiagGroup<"shadow">; def Shorten64To32 : DiagGroup<"shorten-64-to-32">; def : DiagGroup<"sign-promo">; @@ -197,6 +215,12 @@ def : DiagGroup<"stack-protector">; def : DiagGroup<"switch-default">; def : DiagGroup<"synth">; def SizeofArrayArgument : DiagGroup<"sizeof-array-argument">; +def SizeofArrayDecay : DiagGroup<"sizeof-array-decay">; +def SizeofPointerMemaccess : DiagGroup<"sizeof-pointer-memaccess">; +def StaticInInline : DiagGroup<"static-in-inline">; +def StaticLocalInInline : DiagGroup<"static-local-in-inline">; +def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">; +def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>; def StringPlusInt : DiagGroup<"string-plus-int">; def StrncatSize : DiagGroup<"strncat-size">; def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">; @@ -206,6 +230,10 @@ def HeaderHygiene : DiagGroup<"header-hygiene">; def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">; def CompareDistinctPointerType : DiagGroup<"compare-distinct-pointer-types">; +def Unsequenced : DiagGroup<"unsequenced">; +// GCC name for -Wunsequenced +def : DiagGroup<"sequence-point", [Unsequenced]>; + // Preprocessor warnings. def AmbiguousMacro : DiagGroup<"ambiguous-macro">; @@ -240,17 +268,25 @@ def InvalidPPToken : DiagGroup<"invalid-pp-token">; def Trigraphs : DiagGroup<"trigraphs">; def : DiagGroup<"type-limits">; +def UndefinedReinterpretCast : DiagGroup<"undefined-reinterpret-cast">; +def ReinterpretBaseClass : DiagGroup<"reinterpret-base-class">; def Unicode : DiagGroup<"unicode">; def UninitializedMaybe : DiagGroup<"conditional-uninitialized">; def UninitializedSometimes : DiagGroup<"sometimes-uninitialized">; -def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes]>; +def UninitializedStaticSelfInit : DiagGroup<"static-self-init">; +def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes, + UninitializedStaticSelfInit]>; def UnknownPragmas : DiagGroup<"unknown-pragmas">; +def UnknownWarningOption : DiagGroup<"unknown-warning-option">; def NSobjectAttribute : DiagGroup<"NSObject-attribute">; def UnknownAttributes : DiagGroup<"attributes">; def IgnoredAttributes : DiagGroup<"ignored-attributes">; def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args", [CXX98CompatUnnamedTypeTemplateArgs]>; def UnusedArgument : DiagGroup<"unused-argument">; +def UnusedSanitizeArgument : DiagGroup<"unused-sanitize-argument">; +def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument", + [UnusedSanitizeArgument]>; def UnusedComparison : DiagGroup<"unused-comparison">; def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">; def UnneededInternalDecl : DiagGroup<"unneeded-internal-declaration">; @@ -293,6 +329,7 @@ def VariadicMacros : DiagGroup<"variadic-macros">; def VectorConversion : DiagGroup<"vector-conversion">; // clang specific def VexingParse : DiagGroup<"vexing-parse">; def VLA : DiagGroup<"vla">; +def VLAExtension : DiagGroup<"vla-extension">; def VolatileRegisterVar : DiagGroup<"volatile-register-var">; def Visibility : DiagGroup<"visibility">; def ZeroLengthArray : DiagGroup<"zero-length-array">; @@ -379,7 +416,6 @@ def Most : DiagGroup<"most", [ DeleteNonVirtualDtor, Format, Implicit, - IntToPointerCast, MismatchedTags, MissingBraces, MultiChar, @@ -387,6 +423,7 @@ def Most : DiagGroup<"most", [ ReturnType, SelfAssignment, SizeofArrayArgument, + SizeofArrayDecay, StringPlusInt, Trigraphs, Uninitialized, @@ -407,6 +444,7 @@ def ThreadSafety : DiagGroup<"thread-safety", [ThreadSafetyAttributes, ThreadSafetyAnalysis, ThreadSafetyPrecise]>; +def ThreadSafetyBeta : DiagGroup<"thread-safety-beta">; // Note that putting warnings in -Wall will not disable them by default. If a // warning should be active _only_ when -Wall is passed in, mark it as @@ -449,7 +487,8 @@ def C11 : DiagGroup<"c11-extensions">; def C99 : DiagGroup<"c99-extensions">; // A warning group for warnings about GCC extensions. -def GNU : DiagGroup<"gnu", [GNUDesignator, VLA, ZeroLengthArray]>; +def GNU : DiagGroup<"gnu", [GNUDesignator, VLAExtension, + ZeroLengthArray, GNUStaticFloatInit]>; // A warning group for warnings about code that clang accepts but gcc doesn't. def GccCompat : DiagGroup<"gcc-compat">; @@ -460,6 +499,8 @@ def ObjCNonUnifiedException : DiagGroup<"objc-nonunified-exceptions">; def ObjCProtocolMethodImpl : DiagGroup<"objc-protocol-method-implementation">; +def ObjCNoPropertyAutoSynthesis : DiagGroup<"objc-property-synthesis">; + // ObjC API warning groups. def ObjCRedundantLiteralUse : DiagGroup<"objc-redundant-literal-use">; def ObjCRedundantAPIUse : DiagGroup<"objc-redundant-api-use", [ @@ -480,3 +521,6 @@ def ASMOperandWidths : DiagGroup<"asm-operand-widths">; def ASM : DiagGroup<"asm", [ ASMOperandWidths ]>; + +// OpenMP warnings. +def SourceUsesOpenMP : DiagGroup<"source-uses-openmp">; diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h index 11552af..d35b907 100644 --- a/include/clang/Basic/DiagnosticIDs.h +++ b/include/clang/Basic/DiagnosticIDs.h @@ -15,13 +15,9 @@ #ifndef LLVM_CLANG_DIAGNOSTICIDS_H #define LLVM_CLANG_DIAGNOSTICIDS_H +#include "clang/Basic/LLVM.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" -#include "clang/Basic/LLVM.h" - -namespace llvm { - template<typename T, unsigned> class SmallVector; -} namespace clang { class DiagnosticsEngine; @@ -128,7 +124,7 @@ public: /// \brief Return an ID for a diagnostic with the specified message and level. /// - /// If this is the first request for this diagnosic, it is registered and + /// If this is the first request for this diagnostic, it is registered and /// created, otherwise the existing ID is returned. unsigned getCustomDiagID(Level L, StringRef Message); @@ -231,10 +227,10 @@ public: /// \param Diags [out] - On return, the diagnostics in the group. /// \returns True if the given group is unknown, false otherwise. bool getDiagnosticsInGroup(StringRef Group, - llvm::SmallVectorImpl<diag::kind> &Diags) const; + SmallVectorImpl<diag::kind> &Diags) const; /// \brief Get the set of all diagnostic IDs. - void getAllDiagnostics(llvm::SmallVectorImpl<diag::kind> &Diags) const; + void getAllDiagnostics(SmallVectorImpl<diag::kind> &Diags) const; /// \brief Get the warning option with the closest edit distance to the given /// group name. @@ -245,7 +241,7 @@ private: /// /// \param Diags [out] - On return, the diagnostics in the group. void getDiagnosticsInGroup(const WarningOption *Group, - llvm::SmallVectorImpl<diag::kind> &Diags) const; + SmallVectorImpl<diag::kind> &Diags) const; /// \brief Based on the way the client configured the DiagnosticsEngine /// object, classify the specified diagnostic ID into a Level, consumable by diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index c6c50ab..339788b 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -93,26 +93,63 @@ def ext_multichar_character_literal : ExtWarn< "multi-character character constant">, InGroup<MultiChar>; def ext_four_char_character_literal : Extension< "multi-character character constant">, InGroup<FourByteMultiChar>; - -// Literal -def ext_nonstandard_escape : Extension< - "use of non-standard escape character '\\%0'">; -def ext_unknown_escape : ExtWarn<"unknown escape sequence '\\%0'">; -def err_hex_escape_no_digits : Error<"\\x used with no following hex digits">; -def err_ucn_escape_no_digits : Error<"\\u used with no following hex digits">; -def err_ucn_escape_invalid : Error<"invalid universal character">; -def err_ucn_escape_incomplete : Error<"incomplete universal character name">; + +// Unicode and UCNs +def err_invalid_utf8 : Error< + "source file is not valid UTF-8">; +def err_non_ascii : Error< + "non-ASCII characters are not allowed outside of literals and identifiers">; +def ext_unicode_whitespace : ExtWarn< + "treating Unicode character as whitespace">, + InGroup<DiagGroup<"unicode-whitespace">>; + +def err_hex_escape_no_digits : Error< + "\\%0 used with no following hex digits">; +def warn_ucn_escape_no_digits : Warning< + "\\%0 used with no following hex digits; " + "treating as '\\' followed by identifier">, InGroup<Unicode>; +def err_ucn_escape_incomplete : Error< + "incomplete universal character name">; +def warn_ucn_escape_incomplete : Warning< + "incomplete universal character name; " + "treating as '\\' followed by identifier">, InGroup<Unicode>; +def note_ucn_four_not_eight : Note<"did you mean to use '\\u'?">; + def err_ucn_escape_basic_scs : Error< "character '%0' cannot be specified by a universal character name">; def err_ucn_control_character : Error< "universal character name refers to a control character">; +def err_ucn_escape_invalid : Error<"invalid universal character">; +def warn_ucn_escape_surrogate : Warning< + "universal character name refers to a surrogate character">, + InGroup<Unicode>; + +def warn_c99_compat_unicode_id : Warning< + "%select{using this character in an identifier|starting an identifier with " + "this character}0 is incompatible with C99">, + InGroup<C99Compat>, DefaultIgnore; +def warn_cxx98_compat_unicode_id : Warning< + "using this character in an identifier is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; + def warn_cxx98_compat_literal_ucn_escape_basic_scs : Warning< "specifying character '%0' with a universal character name " "is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def warn_cxx98_compat_literal_ucn_control_character : Warning< "universal character name referring to a control character " "is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; +def warn_ucn_not_valid_in_c89 : Warning< + "universal character names are only valid in C99 or C++; " + "treating as '\\' followed by identifier">, InGroup<Unicode>; +def warn_ucn_not_valid_in_c89_literal : ExtWarn< + "universal character names are only valid in C99 or C++">, InGroup<Unicode>; + + +// Literal +def ext_nonstandard_escape : Extension< + "use of non-standard escape character '\\%0'">; +def ext_unknown_escape : ExtWarn<"unknown escape sequence '\\%0'">; def err_invalid_decimal_digit : Error<"invalid digit '%0' in decimal constant">; def err_invalid_binary_digit : Error<"invalid digit '%0' in binary constant">; def err_invalid_octal_digit : Error<"invalid digit '%0' in octal constant">; @@ -145,8 +182,9 @@ def ext_string_too_long : Extension<"string literal of length %0 exceeds " "support">, InGroup<OverlengthStrings>; def err_character_too_large : Error< "character too large for enclosing character literal type">; -def warn_ucn_not_valid_in_c89 : ExtWarn< - "unicode escape sequences are only valid in C99 or C++">, InGroup<Unicode>; +def warn_c99_compat_unicode_literal : Warning< + "unicode literals are incompatible with C99">, + InGroup<C99Compat>, DefaultIgnore; def warn_cxx98_compat_unicode_literal : Warning< "unicode literals are incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; @@ -175,12 +213,12 @@ def err_bad_string_encoding : Error< "illegal character encoding in string literal">; def warn_bad_string_encoding : ExtWarn< "illegal character encoding in string literal">, - InGroup<DiagGroup<"invalid-source-encoding">>; + InGroup<InvalidSourceEncoding>; def err_bad_character_encoding : Error< "illegal character encoding in character literal">; def warn_bad_character_encoding : ExtWarn< "illegal character encoding in character literal">, - InGroup<DiagGroup<"invalid-source-encoding">>; + InGroup<InvalidSourceEncoding>; def err_lexing_string : Error<"failure when lexing a string">; @@ -218,9 +256,10 @@ def pp_pragma_sysheader_in_main_file : Warning< def pp_poisoning_existing_macro : Warning<"poisoning existing macro">; def pp_out_of_date_dependency : Warning< "current file is older than dependency %0">; -def pp_undef_builtin_macro : Warning<"undefining builtin macro">; -def pp_redef_builtin_macro : Warning<"redefining builtin macro">, - InGroup<DiagGroup<"builtin-macro-redefined">>; +def ext_pp_undef_builtin_macro : ExtWarn<"undefining builtin macro">, + InGroup<BuiltinMacroRedefined>; +def ext_pp_redef_builtin_macro : ExtWarn<"redefining builtin macro">, + InGroup<BuiltinMacroRedefined>; def pp_disabled_macro_expansion : Warning< "disabled expansion of recursive macro">, DefaultIgnore, InGroup<DiagGroup<"disabled-macro-expansion">>; @@ -284,7 +323,12 @@ def warn_cxx98_compat_empty_fnmacro_arg : Warning< InGroup<CXX98CompatPedantic>, DefaultIgnore; def note_macro_here : Note<"macro %0 defined here">; +def err_pp_opencl_variadic_macros : + Error<"variadic macros not supported in OpenCL">; + def err_pp_invalid_directive : Error<"invalid preprocessing directive">; +def err_pp_directive_required : Error< + "%0 must be used within a preprocessing directive">; def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal; def err_pp_file_not_found_not_fatal : Error< "'%0' file not found with <angled> include; use \"quotes\" instead">; @@ -486,6 +530,16 @@ def err_mmap_umbrella_clash : Error< "umbrella for module '%0' already covers this directory">; def err_mmap_export_module_id : Error< "expected an exported module name or '*'">; +def err_mmap_expected_library_name : Error< + "expected %select{library|framework}0 name as a string">; +def err_mmap_config_macro_submodule : Error< + "configuration macros are only allowed on top-level modules">; +def err_mmap_expected_config_macro : Error< + "expected configuration macro name after ','">; +def err_mmap_expected_conflicts_comma : Error< + "expected ',' after conflicting module name">; +def err_mmap_expected_conflicts_message : Error< + "expected a message describing the conflict with '%0'">; def err_mmap_missing_module_unqualified : Error< "no module named '%0' visible from '%1'">; def err_mmap_missing_module_qualified : Error< @@ -521,7 +575,8 @@ def warn_auto_module_import : Warning< "treating #%select{include|import|include_next|__include_macros}0 as an " "import of module '%1'">, InGroup<AutoImport>, DefaultIgnore; def warn_uncovered_module_header : Warning< - "umbrella header does not include header '%0'">, InGroup<IncompleteUmbrella>; + "umbrella header for module '%0' does not include header '%1'">, + InGroup<IncompleteUmbrella>; def err_expected_id_building_module : Error< "expected a module name in '__building_module' expression">; diff --git a/include/clang/Basic/DiagnosticOptions.def b/include/clang/Basic/DiagnosticOptions.def index 476ac1e..8e5562c 100644 --- a/include/clang/Basic/DiagnosticOptions.def +++ b/include/clang/Basic/DiagnosticOptions.def @@ -54,6 +54,7 @@ DIAGOPT(ShowCarets, 1, 1) /// Show carets in diagnostics. DIAGOPT(ShowFixits, 1, 1) /// Show fixit information. DIAGOPT(ShowSourceRanges, 1, 0) /// Show source ranges in numeric form. DIAGOPT(ShowParseableFixits, 1, 0) /// Show machine parseable fix-its. +DIAGOPT(ShowPresumedLoc, 1, 0) /// Show presumed location for diagnostics. DIAGOPT(ShowOptionNames, 1, 0) /// Show the option name for mappable /// diagnostics. DIAGOPT(ShowNoteIncludeStack, 1, 0) /// Show include stacks for notes. @@ -71,6 +72,7 @@ DIAGOPT(VerifyDiagnostics, 1, 0) /// Check that diagnostics match the expected DIAGOPT(ElideType, 1, 0) /// Elide identical types in template diffing DIAGOPT(ShowTemplateTree, 1, 0) /// Print a template tree when diffing +DIAGOPT(WarnOnSpellCheck, 1, 0) /// -fwarn-on-spellcheck VALUE_DIAGOPT(ErrorLimit, 32, 0) /// Limit # errors emitted. /// Limit depth of macro expansion backtrace. diff --git a/include/clang/Basic/DiagnosticOptions.h b/include/clang/Basic/DiagnosticOptions.h index b75cb0c..2fba384 100644 --- a/include/clang/Basic/DiagnosticOptions.h +++ b/include/clang/Basic/DiagnosticOptions.h @@ -10,8 +10,8 @@ #ifndef LLVM_CLANG_BASIC_DIAGNOSTICOPTIONS_H #define LLVM_CLANG_BASIC_DIAGNOSTICOPTIONS_H +#include "clang/Basic/LLVM.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" - #include <string> #include <vector> @@ -24,9 +24,8 @@ enum OverloadsShown { Ovl_Best ///< Show just the "best" overload candidates. }; -/// DiagnosticOptions - Options for controlling the compiler diagnostics -/// engine. -class DiagnosticOptions : public llvm::RefCountedBase<DiagnosticOptions>{ +/// \brief Options for controlling the compiler diagnostics engine. +class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{ public: enum TextDiagnosticFormat { Clang, Msvc, Vi }; @@ -49,14 +48,10 @@ protected: #include "clang/Basic/DiagnosticOptions.def" public: - /// If non-empty, a file to log extended build information to, for development - /// testing and analysis. - std::string DumpBuildInformation; - - /// The file to log diagnostic output to. + /// \brief The file to log diagnostic output to. std::string DiagnosticLogFile; - /// The file to serialize diagnostics to (non-appending). + /// \brief The file to serialize diagnostics to (non-appending). std::string DiagnosticSerializationFile; /// The list of -W... options used to alter the diagnostic mappings, with the diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 21eeccb..04a433c 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -18,9 +18,6 @@ def w_asm_qualifier_ignored : Warning<"ignored %0 qualifier on asm">, def warn_file_asm_volatile : Warning< "meaningless 'volatile' on asm outside function">, CatInlineAsm; -def warn_unsupported_msasm : Warning< - "MS-style inline assembly is not supported">, InGroup<Microsoft>; - let CategoryName = "Parse Issue" in { def ext_empty_translation_unit : Extension< @@ -98,6 +95,8 @@ def warn_cxx98_compat_enum_fixed_underlying_type : Warning< def warn_cxx98_compat_alignof : Warning< "alignof expressions are incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; +def ext_alignof_expr : ExtWarn< + "%0 applied to an expression is a GNU extension">, InGroup<GNU>; def warn_microsoft_dependent_exists : Warning< "dependent %select{__if_not_exists|__if_exists}0 declarations are ignored">, @@ -113,6 +112,9 @@ def note_previous_default_assoc : Note< def ext_c11_alignment : Extension< "%0 is a C11-specific feature">, InGroup<C11>; +def ext_c11_noreturn : Extension< + "_Noreturn functions are a C11-specific feature">, InGroup<C11>; + def ext_gnu_indirect_goto : Extension< "use of GNU indirect-goto extension">, InGroup<GNU>; def ext_gnu_address_of_label : Extension< @@ -225,13 +227,10 @@ def note_missing_selector_name : Note< def note_force_empty_selector_name : Note< "or insert whitespace before ':' to use %0 as parameter name " "and have an empty entry in the selector">; -def note_missing_argument_name : Note< - "did you mean to use %0 as the selector name instead of %1">; def err_label_end_of_compound_statement : Error< "label at end of compound statement: expected statement">; def err_address_of_label_outside_fn : Error< "use of address-of-label extension outside of a function body">; -def err_expected_string_literal : Error<"expected string literal">; def err_asm_operand_wide_string_literal : Error< "cannot use %select{unicode|wide}0 string literal in 'asm'">; def err_expected_selector_for_method : Error< @@ -364,7 +363,7 @@ def note_objc_container_start : Note< "%select{class|protocol|category|class extension|implementation" "|category implementation}0 started here">; def warn_objc_protocol_qualifier_missing_id : Warning< - "protocol qualifiers without 'id' is archaic">; + "protocol has no object type specified; defaults to qualified 'id'">; def err_objc_unknown_at : Error<"expected an Objective-C directive after '@'">; def err_illegal_super_cast : Error< "cannot cast 'super' (it isn't an expression)">; @@ -400,6 +399,11 @@ def err_objc_properties_require_objc2 : Error< "properties are an Objective-C 2 feature">; def err_objc_unexpected_attr : Error< "prefix attribute must be followed by an interface or protocol">; +def err_objc_postfix_attribute : Error < + "postfix attributes are not allowed on Objective-C directives">; +def err_objc_postfix_attribute_hint : Error < + "postfix attributes are not allowed on Objective-C directives, place" + " them in front of '%select{@interface|@protocol}0'">; def err_objc_directive_only_in_protocol : Error< "directive may only be specified in protocols only">; def err_missing_catch_finally : Error< @@ -407,6 +411,8 @@ def err_missing_catch_finally : Error< def err_objc_concat_string : Error<"unexpected token after Objective-C string">; def err_expected_objc_container : Error< "'@end' must appear in an Objective-C context">; +def err_objc_unexpected_atend : Error< + "'@end' appears where closing brace '}' is expected">; def error_property_ivar_decl : Error< "property synthesize requires specification of an ivar">; def err_synthesized_property_name : Error< @@ -425,6 +431,8 @@ def err_declaration_does_not_declare_param : Error< def err_no_matching_param : Error<"parameter named %0 is missing">; /// C++ parser diagnostics +def err_invalid_operator_on_type : Error< + "cannot use %select{dot|arrow}0 operator on a type">; def err_expected_unqualified_id : Error< "expected %select{identifier|unqualified-id}0">; def err_func_def_no_params : Error< @@ -464,11 +472,16 @@ def err_destructor_template_id : Error< "destructor name %0 does not refer to a template">; def err_default_arg_unparsed : Error< "unexpected end of default argument expression">; -def err_parser_impl_limit_overflow : Error< - "parser recursion limit reached, program too complex">, DefaultFatal; +def err_bracket_depth_exceeded : Error< + "bracket nesting level exceeded maximum of %0">, DefaultFatal; +def note_bracket_depth : Note< + "use -fbracket-depth=N to increase maximum nesting level">; def err_misplaced_ellipsis_in_declaration : Error< "'...' must %select{immediately precede declared identifier|" "be innermost component of anonymous pack declaration}0">; +def ext_abstract_pack_declarator_parens : ExtWarn< + "ISO C++11 requires a parenthesized pack declaration to have a name">, + InGroup<DiagGroup<"anonymous-pack-parens">>; // C++ derived classes def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">; @@ -504,12 +517,12 @@ def err_cxx11_attribute_forbids_arguments : Error< "attribute '%0' cannot have an argument list">; def err_cxx11_attribute_forbids_ellipsis : Error< "attribute '%0' cannot be used as an attribute pack">; +def err_cxx11_attribute_repeated : Error< + "attribute %0 cannot appear multiple times in an attribute specifier">; def err_attributes_not_allowed : Error<"an attribute list cannot appear here">; def err_l_square_l_square_not_attribute : Error< "C++11 only allows consecutive left square brackets when " "introducing an attribute">; -def err_alignas_pack_exp_unsupported : Error< - "pack expansions in alignment specifiers are not supported yet">; def err_ms_declspec_type : Error< "__declspec attributes must be an identifier or string literal">; def warn_ms_declspec_unknown : Warning< @@ -548,7 +561,6 @@ def err_explicit_instantiation_with_definition : Error< "explicit template instantiation cannot have a definition; if this " "definition is meant to be an explicit specialization, add '<>' after the " "'template' keyword">; -def err_enum_template : Error<"enumeration cannot be a template">; def err_explicit_instantiation_enum : Error< "enumerations cannot be explicitly instantiated">; def err_expected_template_parameter : Error<"expected template parameter">; @@ -764,14 +776,25 @@ def err_seh___except_filter : Error< def err_seh___finally_block : Error< "%0 only allowed in __finally block">; - + +// OpenMP support. +def warn_pragma_omp_ignored : Warning < + "unexpected '#pragma omp ...' in program">, InGroup<SourceUsesOpenMP>, DefaultIgnore; +def warn_omp_extra_tokens_at_eol : Warning < + "extra tokens at end of '#pragma omp %0' are ignored">, + InGroup<ExtraTokens>; +def err_omp_unknown_directive : Error < + "expected an OpenMP directive">; +def err_omp_unexpected_directive : Error < + "unexpected OpenMP directive '#pragma omp %0'">; + } // end of Parse Issue category. let CategoryName = "Modules Issue" in { def err_module_expected_ident : Error< "expected a module name after module import">; def err_module_expected_semi : Error< - "expected a semicolon name after module name">; + "expected ';' after module name">; } } // end of Parser diagnostics diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 0d64bf3..c4815cd 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -20,6 +20,11 @@ def warn_variables_not_in_loop_body : Warning< "used in loop condition not modified in loop body">, InGroup<DiagGroup<"loop-analysis">>, DefaultIgnore; +def warn_duplicate_enum_values : Warning< + "element %0 has been implicitly assigned %1 which another element has " + "been assigned">, InGroup<DiagGroup<"duplicate-enum">>, DefaultIgnore; +def note_duplicate_element : Note<"element %0 also has value %1">; + // Constant expressions def err_expr_not_ice : Error< "expression is not an %select{integer|integral}0 constant expression">; @@ -70,7 +75,9 @@ def warn_double_const_requires_fp64 : Warning< // C99 variable-length arrays def ext_vla : Extension<"variable length arrays are a C99 feature">, - InGroup<VLA>; + InGroup<VLAExtension>; +def warn_vla_used : Warning<"variable length array used">, + InGroup<VLA>, DefaultIgnore; def err_vla_non_pod : Error<"variable length array of non-POD element type %0">; def err_vla_in_sfinae : Error< "variable length array cannot be formed during template argument deduction">; @@ -209,6 +216,8 @@ def warn_use_out_of_scope_declaration : Warning< "use of out-of-scope declaration of %0">; def err_inline_non_function : Error< "'inline' can only appear on functions">; +def err_noreturn_non_function : Error< + "'_Noreturn' can only appear on functions">; def warn_qual_return_type : Warning< "'%0' type qualifier%s1 on return type %plural{1:has|:have}1 no effect">, InGroup<IgnoredQualifiers>, DefaultIgnore; @@ -245,19 +254,20 @@ def note_using_decl_constructor_conflict_previous_ctor : Note< "previous constructor">; def note_using_decl_constructor_conflict_previous_using : Note< "previously inherited here">; +def warn_using_decl_constructor_ellipsis : Warning< + "inheriting constructor does not inherit ellipsis">, + InGroup<DiagGroup<"inherited-variadic-ctor">>; +def note_using_decl_constructor_ellipsis : Note< + "constructor declared with ellipsis here">; def err_using_decl_can_not_refer_to_class_member : Error< "using declaration can not refer to class member">; def err_using_decl_can_not_refer_to_namespace : Error< "using declaration can not refer to namespace">; def err_using_decl_constructor : Error< "using declaration can not refer to a constructor">; -def err_using_decl_constructor_unsupported : Error< - "inheriting constructors are not supported">; -// FIXME: Replace the above error with this warning if support for -// inheriting constructors is implemented. -//def warn_cxx98_compat_using_decl_constructor : Warning< -// "inheriting constructors are incompatible with C++98">, -// InGroup<CXX98Compat>, DefaultIgnore; +def warn_cxx98_compat_using_decl_constructor : Warning< + "inheriting constructors are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_using_decl_destructor : Error< "using declaration can not refer to a destructor">; def err_using_decl_template_id : Error< @@ -304,10 +314,10 @@ def err_falloff_nonvoid_block : Error< "control reaches end of non-void block">; def warn_suggest_noreturn_function : Warning< "%select{function|method}0 %1 could be declared with attribute 'noreturn'">, - InGroup<DiagGroup<"missing-noreturn">>, DefaultIgnore; + InGroup<MissingNoreturn>, DefaultIgnore; def warn_suggest_noreturn_block : Warning< "block could be declared with attribute 'noreturn'">, - InGroup<DiagGroup<"missing-noreturn">>, DefaultIgnore; + InGroup<MissingNoreturn>, DefaultIgnore; def warn_unreachable : Warning<"will never be executed">, InGroup<DiagGroup<"unreachable-code">>, DefaultIgnore; @@ -331,7 +341,8 @@ def warn_implicit_decl_requires_ucontext : Warning< "<ucontext.h>">, InGroup<BuiltinRequiresHeader>; def warn_redecl_library_builtin : Warning< - "incompatible redeclaration of library function %0">; + "incompatible redeclaration of library function %0">, + InGroup<DiagGroup<"incompatible-library-redeclaration">>; def err_builtin_definition : Error<"definition of builtin function %0">; def err_types_compatible_p_in_cplusplus : Error< "__builtin_types_compatible_p is not valid in C++">; @@ -347,7 +358,7 @@ def note_bad_memaccess_silence : Note< def warn_sizeof_pointer_expr_memaccess : Warning< "'%0' call operates on objects of type %1 while the size is based on a " "different type %2">, - InGroup<DiagGroup<"sizeof-pointer-memaccess">>; + InGroup<SizeofPointerMemaccess>; def warn_sizeof_pointer_expr_memaccess_note : Note< "did you mean to %select{dereference the argument to 'sizeof' (and multiply " "it by the number of elements)|remove the addressof in the argument to " @@ -356,7 +367,7 @@ def warn_sizeof_pointer_expr_memaccess_note : Note< def warn_sizeof_pointer_type_memaccess : Warning< "argument to 'sizeof' in %0 call is the same pointer type %1 as the " "%select{destination|source}2; expected %3 or an explicit length">, - InGroup<DiagGroup<"sizeof-pointer-memaccess">>; + InGroup<SizeofPointerMemaccess>; def warn_strlcpycat_wrong_size : Warning< "size argument in %0 call appears to be size of the source; expected the size of " "the destination">, @@ -376,17 +387,21 @@ def note_strncat_wrong_size : Note< "the terminating null byte">; /// main() -// static/inline main() are not errors in C, just in C++. +// static main() is not an error in C, just in C++. def warn_static_main : Warning<"'main' should not be declared static">, InGroup<Main>; def err_static_main : Error<"'main' is not allowed to be declared static">; def err_inline_main : Error<"'main' is not allowed to be declared inline">; +def ext_noreturn_main : ExtWarn< + "'main' is not allowed to be declared _Noreturn">, InGroup<Main>; +def note_main_remove_noreturn : Note<"remove '_Noreturn'">; def err_constexpr_main : Error< "'main' is not allowed to be declared constexpr">; def err_main_template_decl : Error<"'main' cannot be a template">; def err_main_returns_nonint : Error<"'main' must return 'int'">; def ext_main_returns_nonint : ExtWarn<"return type of 'main' is not 'int'">, InGroup<MainReturnType>; +def note_main_change_return_type : Note<"change return type to 'int'">; def err_main_surplus_args : Error<"too many parameters (%0) for 'main': " "must be 0, 2, or 3">; def warn_main_one_arg : Warning<"only one parameter on 'main' declaration">, @@ -396,6 +411,8 @@ def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 " "platform-specific data}0) must be of type %1">; /// parser diagnostics +def ext_no_declarators : ExtWarn<"declaration does not declare anything">, + InGroup<MissingDeclarations>; def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">, InGroup<MissingDeclarations>; def err_typedef_not_identifier : Error<"typedef name must be an identifier">; @@ -406,6 +423,15 @@ def err_object_cannot_be_passed_returned_by_value : Error< "; did you forget * in %1?">; def err_parameters_retval_cannot_have_fp16_type : Error< "%select{parameters|function return value}0 cannot have __fp16 type; did you forget * ?">; +def err_opencl_half_load_store : Error< + "%select{loading directly from|assigning directly to}0 pointer to type %1 is not allowed">; +def err_opencl_cast_to_half : Error<"casting to type %0 is not allowed">; +def err_opencl_half_declaration : Error< + "declaring variable of type %0 is not allowed">; +def err_opencl_half_argument : Error< + "declaring function argument of type %0 is not allowed; did you forget * ?">; +def err_opencl_half_return : Error< + "declaring function return value of type %0 is not allowed; did you forget * ?">; def warn_enum_value_overflow : Warning<"overflow in enumeration value">; def warn_pragma_options_align_reset_failed : Warning< "#pragma options align=reset failed: %0">; @@ -456,7 +482,7 @@ def warn_readonly_property : Warning< "'readwrite' of property inherited from %1">; def warn_property_attribute : Warning< - "property %0 '%1' attribute does not match the property inherited from %2">; + "'%1' attribute on property %0 does not match the property inherited from %2">; def warn_property_types_are_incompatible : Warning< "property type %0 is incompatible with type %1 inherited from %2">; def err_undef_interface : Error<"cannot find interface declaration for %0">; @@ -499,9 +525,8 @@ def err_conflicting_ivar_name : Error< "conflicting instance variable names: %0 vs %1">; def err_inconsistant_ivar_count : Error< "inconsistent number of instance variables specified">; -def warn_incomplete_impl : Warning<"incomplete implementation">, +def warn_undef_method_impl : Warning<"method definition for %0 not found">, InGroup<DiagGroup<"incomplete-implementation">>; -def note_undef_method_impl : Note<"method definition for %0 not found">; def note_required_for_protocol_at : Note<"required for direct or indirect protocol %0">; @@ -523,7 +548,7 @@ def warn_conflicting_overriding_ret_type_modifiers : Warning< def warn_conflicting_ret_type_modifiers : Warning< "conflicting distributed object modifiers on return type " "in implementation of %0">, - InGroup<DiagGroup<"distributed-object-modifiers">>; + InGroup<DistributedObjectModifiers>; def warn_non_covariant_overriding_ret_types : Warning< "conflicting return type in " @@ -533,7 +558,7 @@ def warn_non_covariant_overriding_ret_types : Warning< def warn_non_covariant_ret_types : Warning< "conflicting return type in " "implementation of %0: %1 vs %2">, - InGroup<DiagGroup<"method-signatures">>, DefaultIgnore; + InGroup<MethodSignatures>, DefaultIgnore; def warn_conflicting_overriding_param_types : Warning< "conflicting parameter types in " @@ -548,7 +573,7 @@ def warn_conflicting_param_types : Warning< def warn_conflicting_param_modifiers : Warning< "conflicting distributed object modifiers on parameter type " "in implementation of %0">, - InGroup<DiagGroup<"distributed-object-modifiers">>; + InGroup<DistributedObjectModifiers>; def warn_conflicting_overriding_param_modifiers : Warning< "conflicting distributed object modifiers on parameter type " @@ -563,7 +588,7 @@ def warn_non_contravariant_overriding_param_types : Warning< def warn_non_contravariant_param_types : Warning< "conflicting parameter types in " "implementation of %0: %1 vs %2">, - InGroup<DiagGroup<"method-signatures">>, DefaultIgnore; + InGroup<MethodSignatures>, DefaultIgnore; def warn_conflicting_overriding_variadic :Warning< "conflicting variadic declaration of method and its " @@ -609,9 +634,11 @@ def warn_objc_property_no_assignment_attribute : Warning< "'assign' is assumed">, InGroup<ObjCPropertyNoAttribute>; def warn_objc_isa_use : Warning< - "direct access to objective-c's isa is deprecated " - "in favor of object_setClass() and object_getClass()">, - InGroup<DiagGroup<"deprecated-objc-isa-usage">>; + "direct access to Objective-C's isa is deprecated in favor of " + "object_getClass()">, InGroup<DeprecatedObjCIsaUsage>; +def warn_objc_isa_assign : Warning< + "assignment to Objective-C's isa is deprecated in favor of " + "object_setClass()">, InGroup<DeprecatedObjCIsaUsage>; def warn_objc_property_default_assign_on_object : Warning< "default property attribute 'assign' not appropriate for non-GC object">, InGroup<ObjCPropertyNoAttribute>; @@ -643,6 +670,15 @@ def warn_auto_synthesizing_protocol_property :Warning< "auto property synthesis will not synthesize property" " declared in a protocol">, InGroup<DiagGroup<"objc-protocol-property-synthesis">>; +def warn_no_autosynthesis_shared_ivar_property : Warning < + "auto property synthesis will not synthesize property " + "'%0' because it cannot share an ivar with another synthesized property">, + InGroup<ObjCNoPropertyAutoSynthesis>; +def warn_no_autosynthesis_property : Warning< + "auto property synthesis will not synthesize property " + "'%0' because it is 'readwrite' but it will be synthesized 'readonly' " + "via another property">, + InGroup<ObjCNoPropertyAutoSynthesis>; def warn_autosynthesis_property_ivar_match :Warning< "autosynthesized property %0 will use %select{|synthesized}1 instance variable " "%2, not existing instance variable %3">, @@ -684,6 +720,8 @@ def error_category_property : Error< "class implementation">; def note_property_declare : Note< "property declared here">; +def note_property_synthesize : Note< + "property synthesized here">; def error_synthesize_category_decl : Error< "@synthesize not allowed in a category's implementation">; def error_reference_property : Error< @@ -762,9 +800,9 @@ def warn_undeclared_selector : Warning< def warn_implicit_atomic_property : Warning< "property is assumed atomic by default">, InGroup<ImplicitAtomic>, DefaultIgnore; def note_auto_readonly_iboutlet_fixup_suggest : Note< - "readonly IBOutlet property should be changed to be readwrite">; + "property should be changed to be readwrite">; def warn_auto_readonly_iboutlet_property : Warning< - "readonly IBOutlet property when auto-synthesized may " + "readonly IBOutlet property '%0' when auto-synthesized may " "not work correctly with 'nib' loader">, InGroup<DiagGroup<"readonly-iboutlet-property">>; def warn_auto_implicit_atomic_property : Warning< @@ -829,6 +867,8 @@ def err_friend_def_in_local_class : Error< "friend function cannot be defined in a local class">; def err_friend_not_first_in_declaration : Error< "'friend' must appear first in a non-function declaration">; +def err_using_decl_friend : Error< + "cannot befriend target of using declaration">; def err_invalid_member_in_interface : Error< "%select{data member |non-public member function |static member function |" @@ -892,6 +932,8 @@ def err_distant_exception_spec : Error< def err_incomplete_in_exception_spec : Error< "%select{|pointer to |reference to }0incomplete type %1 is not allowed " "in exception specification">; +def err_rref_in_exception_spec : Error< + "rvalue reference type %0 is not allowed in exception specification">; def err_mismatched_exception_spec : Error< "exception specification in declaration does not match previous declaration">; def warn_mismatched_exception_spec : ExtWarn< @@ -1063,14 +1105,18 @@ def note_field_decl : Note<"member is declared here">; def note_ivar_decl : Note<"instance variable is declared here">; def note_bitfield_decl : Note<"bit-field is declared here">; def note_previous_decl : Note<"%0 declared here">; +def note_implicit_param_decl : Note<"%0 is an implicit parameter">; def note_member_synthesized_at : Note< "implicit default %select{constructor|copy constructor|move constructor|copy " "assignment operator|move assignment operator|destructor}0 for %1 first " "required here">; +def note_inhctor_synthesized_at : Note< + "inheriting constructor for %0 first required here">; def err_missing_default_ctor : Error< - "%select{|implicit default }0constructor for %1 must explicitly initialize " - "the %select{base class|member}2 %3 which does not have a default " + "%select{|implicit default |inheriting }0constructor for %1 must explicitly " + "initialize the %select{base class|member}2 %3 which does not have a default " "constructor">; + def err_illegal_union_or_anon_struct_member : Error< "%select{anonymous struct|union}0 member %1 has a non-trivial " "%select{constructor|copy constructor|move constructor|copy assignment " @@ -1080,16 +1126,38 @@ def warn_cxx98_compat_nontrivial_union_or_anon_struct_member : Warning< "%select{constructor|copy constructor|move constructor|copy assignment " "operator|move assignment operator|destructor}2 is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; + +def note_nontrivial_virtual_dtor : Note< + "destructor for %0 is not trivial because it is virtual">; def note_nontrivial_has_virtual : Note< "because type %0 has a virtual %select{member function|base class}1">; -def note_nontrivial_has_nontrivial : Note< - "because type %0 has a %select{member|base class}1 with a non-trivial " - "%select{constructor|copy constructor|move constructor|copy assignment " - "operator|move assignment operator|destructor}2">; -def note_nontrivial_user_defined : Note< - "because type %0 has a user-declared %select{constructor|copy constructor|" - "move constructor|copy assignment operator|move assignment operator|" - "destructor}1">; +def note_nontrivial_no_def_ctor : Note< + "because %select{base class of |field of |}0type %1 has no " + "default constructor">; +def note_user_declared_ctor : Note< + "implicit default constructor suppressed by user-declared constructor">; +def note_nontrivial_no_copy : Note< + "because no %select{<<ERROR>>|constructor|constructor|assignment operator|" + "assignment operator|<<ERROR>>}2 can be used to " + "%select{<<ERROR>>|copy|move|copy|move|<<ERROR>>}2 " + "%select{base class|field|an object}0 of type %3">; +def note_nontrivial_user_provided : Note< + "because %select{base class of |field of |}0type %1 has a user-provided " + "%select{default constructor|copy constructor|move constructor|" + "copy assignment operator|move assignment operator|destructor}2">; +def note_nontrivial_in_class_init : Note< + "because field %0 has an initializer">; +def note_nontrivial_param_type : Note< + "because its parameter is %diff{of type $, not $|of the wrong type}2,3">; +def note_nontrivial_default_arg : Note<"because it has a default argument">; +def note_nontrivial_variadic : Note<"because it is a variadic function">; +def note_nontrivial_subobject : Note< + "because the function selected to %select{construct|copy|move|copy|move|" + "destroy}2 %select{base class|field}0 of type %1 is not trivial">; +def note_nontrivial_objc_ownership : Note< + "because type %0 has a member with %select{no|no|__strong|__weak|" + "__autoreleasing}1 ownership">; + def err_static_data_member_not_allowed_in_anon_struct : Error< "static data member %0 not allowed in anonymous struct">; def ext_static_data_member_in_union : ExtWarn< @@ -1100,14 +1168,17 @@ def warn_cxx98_compat_static_data_member_in_union : Warning< def err_union_member_of_reference_type : Error< "union member %0 has reference type %1">; def ext_anonymous_struct_union_qualified : Extension< - "anonymous %select{struct|union}0 cannot be '%select{const|volatile|" - "restrict}1'">; + "anonymous %select{struct|union}0 cannot be '%1'">; def err_different_return_type_for_overriding_virtual_function : Error< "virtual function %0 has a different return type " "%diff{($) than the function it overrides (which has return type $)|" "than the function it overrides}1,2">; def note_overridden_virtual_function : Note< "overridden virtual function is here">; +def err_conflicting_overriding_cc_attributes : Error< + "virtual function %0 has different calling convention attributes " + "%diff{($) than the function it overrides (which has calling convention $)|" + "than the function it overrides}1,2">; def err_covariant_return_inaccessible_base : Error< "invalid covariant return for virtual function: %1 is a " @@ -1236,6 +1307,8 @@ def err_reference_var_requires_init : Error< "declaration of reference variable %0 requires an initializer">; def err_reference_without_init : Error< "reference to type %0 requires an initializer">; +def note_value_initialization_here : Note< + "in value-initialization of type %0 here">; def err_reference_has_multiple_inits : Error< "reference cannot be initialized with multiple values">; def err_init_non_aggr_init_list : Error< @@ -1249,6 +1322,9 @@ def warn_field_is_uninit : Warning<"field %0 is uninitialized when used here">, def warn_reference_field_is_uninit : Warning< "reference %0 is not yet bound to a value when used here">, InGroup<Uninitialized>; +def warn_static_self_reference_in_init : Warning< + "static variable %0 is suspiciously used within its own initialization">, + InGroup<UninitializedStaticSelfInit>; def warn_uninit_self_reference_in_init : Warning< "variable %0 is uninitialized when used within its own initialization">, InGroup<Uninitialized>; @@ -1284,6 +1360,11 @@ def note_uninit_fixit_remove_cond : Note< "is always %select{false|true}2">; def err_init_incomplete_type : Error<"initialization of incomplete type %0">; +def warn_unsequenced_mod_mod : Warning< + "multiple unsequenced modifications to %0">, InGroup<Unsequenced>; +def warn_unsequenced_mod_use : Warning< + "unsequenced modification and access to %0">, InGroup<Unsequenced>; + def err_temp_copy_no_viable : Error< "no viable constructor %select{copying variable|copying parameter|" "returning object|throwing object|copying member subobject|copying array " @@ -1469,6 +1550,8 @@ def warn_cxx98_compat_constexpr : Warning< def err_invalid_constexpr : Error< "%select{function parameter|typedef|non-static data member}0 " "cannot be constexpr">; +def err_invalid_constexpr_member : Error<"non-static data member cannot be " + "constexpr%select{; did you intend to make it %select{const|static}0?|}1">; def err_constexpr_tag : Error< "%select{class|struct|interface|union|enum}0 cannot be marked constexpr">; def err_constexpr_dtor : Error<"destructor cannot be marked constexpr">; @@ -1509,7 +1592,7 @@ def err_constexpr_vla : Error< "%select{function|constructor}1">; def err_constexpr_var_declaration : Error< "variables cannot be declared in a constexpr %select{function|constructor}0">; -def err_constexpr_function_never_constant_expr : ExtWarn< +def ext_constexpr_function_never_constant_expr : ExtWarn< "constexpr %select{function|constructor}0 never produces a " "constant expression">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError; def err_constexpr_body_no_return : Error< @@ -1584,8 +1667,19 @@ def err_attribute_argument_not_int : Error< "'%0' attribute requires integer constant">; def err_aligned_attribute_argument_not_int : Error< "'aligned' attribute requires integer constant">; -def err_attribute_argument_not_class : Error< - "%0 attribute requires arguments that are class type or point to class type">; +def err_alignas_attribute_wrong_decl_type : Error< + "'%select{alignas|_Alignas}0' attribute cannot be applied to a %select{" + "function parameter|variable with 'register' storage class|" + "'catch' variable|bit-field}1">; +def err_alignas_missing_on_definition : Error< + "'%select{alignas|_Alignas}0' must be specified on definition if it is " + "specified on any declaration">; +def note_alignas_on_declaration : Note< + "declared with '%select{alignas|_Alignas}0' attribute here">; +def err_alignas_mismatch : Error< + "redeclaration has different alignment requirement (%1 vs %0)">; +def err_alignas_underaligned : Error< + "requested alignment is less than minimum alignment of %1 for type %0">; def err_attribute_first_argument_not_int_or_bool : Error< "%0 attribute first argument must be of int or bool type">; def err_attribute_argument_outof_range : Error< @@ -1594,6 +1688,8 @@ def err_attribute_argument_outof_range : Error< def err_init_priority_object_attr : Error< "can only use 'init_priority' attribute on file-scope definitions " "of objects of class type">; +def err_attribute_argument_vec_type_hint : Error< + "invalid attribute argument %0 - expecting a vector or vectorizable scalar type">; def err_attribute_argument_n_not_int : Error< "'%0' attribute requires parameter %1 to be an integer constant">; def err_attribute_argument_n_not_string : Error< @@ -1651,6 +1747,8 @@ def err_as_qualified_auto_decl : Error< "automatic variable qualified with an address space">; def err_arg_with_address_space : Error< "parameter may not be qualified with an address space">; +def err_field_with_address_space : Error< + "field may not be qualified with an address space">; def err_attr_objc_ownership_redundant : Error< "the type %0 is already explicitly ownership-qualified">; def err_attribute_not_string : Error< @@ -1725,12 +1823,14 @@ def warn_attribute_after_definition_ignored : Warning< InGroup<IgnoredAttributes>; def warn_unknown_attribute_ignored : Warning< "unknown attribute %0 ignored">, InGroup<UnknownAttributes>; +def warn_cxx11_gnu_attribute_on_type : Warning< + "attribute %0 ignored, because it cannot be applied to a type">, + InGroup<IgnoredAttributes>; def warn_unhandled_ms_attribute_ignored : Warning< "__declspec attribute %0 is not supported">, InGroup<IgnoredAttributes>; -def warn_attribute_invalid_on_stmt : Warning< - "attribute %0 cannot be specified on a statement">, - InGroup<IgnoredAttributes>; +def err_attribute_invalid_on_stmt : Error< + "%0 attribute cannot be applied to a statement">; def warn_declspec_attribute_ignored : Warning< "attribute %0 is ignored, place it after " "\"%select{class|struct|union|interface|enum}1\" to apply attribute to " @@ -1773,17 +1873,22 @@ def err_alias_not_supported_on_darwin : Error < def warn_attribute_wrong_decl_type : Warning< "%0 attribute only applies to %select{functions|unions|" "variables and functions|functions and methods|parameters|" - "functions, methods and blocks|functions, methods, and parameters|" - "classes|variables|methods|variables, functions and labels|" - "fields and global variables|structs|" - "variables, functions and tag types|thread-local variables}1">, + "functions, methods and blocks|functions, methods, and classes|" + "functions, methods, and parameters|classes|variables|methods|" + "variables, functions and labels|fields and global variables|structs|" + "variables, functions and tag types|thread-local variables|" + "variables and fields|variables, data members and tag types|" + "types and namespaces}1">, InGroup<IgnoredAttributes>; def err_attribute_wrong_decl_type : Error< "%0 attribute only applies to %select{functions|unions|" "variables and functions|functions and methods|parameters|" - "functions, methods and blocks|functions, methods, and parameters|" - "classes|variables|methods|variables, functions and labels|" - "fields and global variables|structs|thread-local variables}1">; + "functions, methods and blocks|functions, methods, and classes|" + "functions, methods, and parameters|classes|variables|methods|" + "variables, functions and labels|fields and global variables|structs|" + "variables, functions and tag types|thread-local variables|" + "variables and fields|variables, data members and tag types|" + "types and namespaces}1">; def warn_function_attribute_wrong_type : Warning< "'%0' only applies to function types; type here is %1">, InGroup<IgnoredAttributes>; @@ -1813,7 +1918,7 @@ def err_cconv_knr : Error< "function with no prototype cannot use %0 calling convention">; def err_cconv_varargs : Error< "variadic function cannot use %0 calling convention">; -def err_regparm_mismatch : Error<"function declared with with regparm(%0) " +def err_regparm_mismatch : Error<"function declared with regparm(%0) " "attribute was previously declared " "%plural{0:without the regparm|:with the regparm(%1)}1 attribute">; def err_returns_retained_mismatch : Error< @@ -1824,11 +1929,13 @@ def err_objc_precise_lifetime_bad_type : Error< def warn_objc_precise_lifetime_meaningless : Error< "objc_precise_lifetime is not meaningful for " "%select{__unsafe_unretained|__autoreleasing}0 objects">; -def err_invalid_pcs : Error<"Invalid PCS type">; +def err_invalid_pcs : Error<"invalid PCS type">; def err_attribute_can_be_applied_only_to_value_decl : Error< "%0 attribute can only be applied to value declarations">; -def warn_attribute_not_on_decl : Error< - "%0 attribute ignored when parsing type">; +def warn_attribute_not_on_decl : Warning< + "%0 attribute ignored when parsing type">, InGroup<IgnoredAttributes>; +def err_base_specifier_attribute : Error< + "%0 attribute cannot be applied to a base specifier">; // Availability attribute def warn_availability_unknown_platform : Warning< @@ -1839,6 +1946,16 @@ def warn_availability_version_ordering : Warning< "attribute ignored">, InGroup<Availability>; def warn_mismatched_availability: Warning< "availability does not match previous declaration">, InGroup<Availability>; +def warn_mismatched_availability_override : Warning< + "overriding method %select{introduced after|" + "deprecated before|obsoleted before}0 overridden method on %1 (%2 vs. %3)">, + InGroup<Availability>; +def warn_mismatched_availability_override_unavail : Warning< + "overriding method cannot be unavailable on %0 when its overridden method is " + "available">, + InGroup<Availability>; +def note_overridden_method : Note< + "overridden method is here">; // Thread Safety Attributes def warn_thread_attribute_ignored : Warning< @@ -1938,18 +2055,22 @@ def warn_fun_requires_lock_precise : Warning< InGroup<ThreadSafetyPrecise>, DefaultIgnore; def note_found_mutex_near_match : Note<"found near match '%0'">; +// Dummy warning that will trigger "beta" warnings from the analysis if enabled. +def warn_thread_safety_beta : Warning< + "Thread safety beta warning.">, InGroup<ThreadSafetyBeta>, DefaultIgnore; + def warn_impcast_vector_scalar : Warning< "implicit conversion turns vector to scalar: %0 to %1">, - InGroup<DiagGroup<"conversion">>, DefaultIgnore; + InGroup<Conversion>, DefaultIgnore; def warn_impcast_complex_scalar : Warning< "implicit conversion discards imaginary component: %0 to %1">, - InGroup<DiagGroup<"conversion">>, DefaultIgnore; + InGroup<Conversion>, DefaultIgnore; def warn_impcast_float_precision : Warning< "implicit conversion loses floating-point precision: %0 to %1">, - InGroup<DiagGroup<"conversion">>, DefaultIgnore; + InGroup<Conversion>, DefaultIgnore; def warn_impcast_float_integer : Warning< "implicit conversion turns floating-point number into integer: %0 to %1">, - InGroup<DiagGroup<"conversion">>, DefaultIgnore; + InGroup<Conversion>, DefaultIgnore; def warn_impcast_integer_sign : Warning< "implicit conversion changes signedness: %0 to %1">, InGroup<SignConversion>, DefaultIgnore; @@ -1958,7 +2079,7 @@ def warn_impcast_integer_sign_conditional : Warning< InGroup<SignConversion>, DefaultIgnore; def warn_impcast_integer_precision : Warning< "implicit conversion loses integer precision: %0 to %1">, - InGroup<DiagGroup<"conversion">>, DefaultIgnore; + InGroup<Conversion>, DefaultIgnore; def warn_impcast_integer_64_32 : Warning< "implicit conversion loses integer precision: %0 to %1">, InGroup<Shorten64To32>, DefaultIgnore; @@ -2036,6 +2157,8 @@ def warn_attribute_protected_visibility : Warning<"target does not support 'protected' visibility; using 'default'">, InGroup<DiagGroup<"unsupported-visibility">>; def err_mismatched_visibility: Error<"visibility does not match previous declaration">; +def warn_attribute_unknown_endian : Warning<"unknown endian '%0'">, + InGroup<IgnoredAttributes>; def note_previous_attribute : Note<"previous attribute is here">; def err_unknown_machine_mode : Error<"unknown machine mode %0">; def err_unsupported_machine_mode : Error<"unsupported machine mode %0">; @@ -2158,15 +2281,11 @@ def err_uninitialized_member_for_assign : Error< "non-static %select{reference|const}1 member %2 can't use default " "assignment operator">; def err_uninitialized_member_in_ctor : Error< - "%select{|implicit default }0constructor for %1 must explicitly initialize " - "the %select{reference|const}2 member %3">; -def warn_default_arg_makes_ctor_special : Warning< + "%select{|implicit default |inheriting }0constructor for %1 must explicitly " + "initialize the %select{reference|const}2 member %3">; +def err_default_arg_makes_ctor_special : Error< "addition of default argument on redeclaration makes this constructor a " - "%select{default|copy|move}0 constructor">, InGroup<DefaultArgSpecialMember>; -def note_previous_declaration_special : Note< - // The ERRORs are in hopes that if they occur, they'll get reported. - "previous declaration was %select{*ERROR*|a copy constructor|a move " - "constructor|*ERROR*|*ERROR*|*ERROR*|not a special member function}0">; + "%select{default|copy|move}0 constructor">; def err_use_of_default_argument_to_function_declared_later : Error< "use of default argument to function %0 that is declared later in class %1">; @@ -2246,6 +2365,11 @@ def note_ovl_candidate_substitution_failure : Note< "candidate template ignored: substitution failure%0%1">; def note_ovl_candidate_disabled_by_enable_if : Note< "candidate template ignored: disabled by %0%1">; +def note_ovl_candidate_failed_overload_resolution : Note< + "candidate template ignored: couldn't resolve reference to overloaded " + "function %0">; +def note_ovl_candidate_non_deduced_mismatch : Note< + "candidate template ignored: could not match %diff{$ against $|types}0,1">; // Note that we don't treat templates differently for this diagnostic. def note_ovl_candidate_arity : Note<"candidate " @@ -2473,9 +2597,10 @@ def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">; def err_ovl_deleted_oper : Error< "overload resolution selected %select{unavailable|deleted}0 operator '%1'%2">; def err_ovl_deleted_special_oper : Error< - "overload resolution selected implicitly-deleted %select{default constructor|" - "copy constructor|move constructor|copy assignment operator|move assignment " - "operator|destructor|'%1'}0%2">; + "object of type %0 cannot be %select{constructed|copied|moved|assigned|" + "assigned|destroyed}1 because its %select{default constructor|" + "copy constructor|move constructor|copy assignment operator|" + "move assignment operator|destructor}1 is implicitly deleted">; def err_ovl_no_viable_subscript : Error<"no viable overloaded operator[] for type %0">; def err_ovl_no_oper : @@ -2597,7 +2722,7 @@ def err_template_arg_must_be_type_suggest : Error< def err_template_arg_must_be_expr : Error< "template argument for non-type template parameter must be an expression">; def err_template_arg_nontype_ambig : Error< - "template argument for non-type template parameter is treated as type %0">; + "template argument for non-type template parameter is treated as function type %0">; def err_template_arg_must_be_template : Error< "template argument for template template parameter must be a class template%select{| or type alias template}0">; def ext_template_arg_local_type : ExtWarn< @@ -3021,9 +3146,9 @@ def warn_cxx98_compat_template_outside_of_template : Warning< InGroup<CXX98Compat>, DefaultIgnore; def err_non_type_template_in_nested_name_specifier : Error< - "qualified name refers into a specialization of function template '%0'">; + "qualified name refers into a specialization of function template %0">; def err_template_id_not_a_type : Error< - "template name refers to non-type template '%0'">; + "template name refers to non-type template %0">; def note_template_declared_here : Note< "%select{function template|class template|type alias template|template template parameter}0 " "%1 declared here">; @@ -3142,6 +3267,8 @@ def note_sentinel_here : Note< def warn_missing_prototype : Warning< "no previous prototype for function %0">, InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore; +def note_declaration_not_a_prototype : Note< + "this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function">; def warn_missing_variable_declarations : Warning< "no previous extern declaration for non-static variable %0">, InGroup<DiagGroup<"missing-variable-declarations">>, DefaultIgnore; @@ -3189,18 +3316,23 @@ def note_deleted_assign_field : Note< "%select{copy|move}0 assignment operator of %1 is implicitly deleted " "because field %2 is of %select{reference|const-qualified}4 type %3">; -// This should eventually be an error. +// These should be errors. def warn_undefined_internal : Warning< "%select{function|variable}0 %q1 has internal linkage but is not defined">, - DiagGroup<"undefined-internal">; + InGroup<DiagGroup<"undefined-internal">>; +def warn_undefined_inline : Warning<"inline function %q0 is not defined">, + InGroup<DiagGroup<"undefined-inline">>; def note_used_here : Note<"used here">; def warn_internal_in_extern_inline : ExtWarn< "static %select{function|variable}0 %1 is used in an inline function with " - "external linkage">, InGroup<DiagGroup<"static-in-inline"> >; + "external linkage">, InGroup<StaticInInline>; def ext_internal_in_extern_inline : Extension< "static %select{function|variable}0 %1 is used in an inline function with " - "external linkage">, InGroup<DiagGroup<"static-in-inline"> >; + "external linkage">, InGroup<StaticInInline>; +def warn_static_local_in_extern_inline : Warning< + "non-constant static local variable in inline function may be different " + "in different files">, InGroup<StaticLocalInInline>; def note_convert_inline_to_static : Note< "use 'static' to give inline function %0 internal linkage">; def note_internal_decl_declared_here : Note< @@ -3216,6 +3348,8 @@ def err_inline_declaration_block_scope : Error< "inline declaration of %0 not allowed in block scope">; def err_static_non_static : Error< "static declaration of %0 follows non-static declaration">; +def err_different_language_linkage : Error< + "declaration of %0 has a different language linkage">; def warn_weak_import : Warning < "an already-declared variable is made a weak_import declaration %0">; def warn_static_non_static : ExtWarn< @@ -3304,7 +3438,7 @@ def err_array_too_large : Error< "array is too large (%0 elements)">; def warn_array_new_too_large : Warning<"array is too large (%0 elements)">, // FIXME PR11644: ", will throw std::bad_array_new_length at runtime" - InGroup<DiagGroup<"bad-array-new-length">>; + InGroup<BadArrayNewLength>; // -Wpadded, -Wpacked def warn_padded_struct_field : Warning< @@ -3324,7 +3458,7 @@ def warn_unnecessary_packed : Warning< def err_typecheck_negative_array_size : Error<"array size is negative">; def warn_typecheck_negative_array_new_size : Warning<"array size is negative">, // FIXME PR11644: ", will throw std::bad_array_new_length at runtime" - InGroup<DiagGroup<"bad-array-new-length">>; + InGroup<BadArrayNewLength>; def warn_typecheck_function_qualifiers : Warning< "qualifier on function type %0 has unspecified behavior">; def err_typecheck_invalid_restrict_not_pointer : Error< @@ -3339,7 +3473,7 @@ def err_typecheck_zero_array_size : Error< "zero-length arrays are not permitted in C++">; def warn_typecheck_zero_static_array_size : Warning< "'static' has no effect on zero-length arrays">, - InGroup<DiagGroup<"array-bounds">>; + InGroup<ArrayBounds>; def err_array_size_non_int : Error<"size of array has non-integer type %0">; def err_init_element_not_constant : Error< "initializer element is not a compile-time constant">; @@ -3610,8 +3744,9 @@ def err_arc_mismatched_cast : Error< " to %3 is disallowed with ARC">; def err_arc_nolifetime_behavior : Error< "explicit ownership qualifier on cast result has no effect">; -def err_arc_objc_object_in_struct : Error< - "ARC forbids %select{Objective-C objects|blocks}0 in structs or unions">; +def err_arc_objc_object_in_tag : Error< + "ARC forbids %select{Objective-C objects|blocks}0 in " + "%select{struct|interface|union|<<ERROR>>|enum}1">; def err_arc_objc_property_default_assign_on_object : Error< "ARC forbids synthesizing a property of an Objective-C object " "with unspecified ownership or storage attribute">; @@ -3653,6 +3788,11 @@ def warn_arc_retained_property_assign : Warning< "assigning retained object to unsafe property" "; object will be released after assignment">, InGroup<ARCUnsafeRetainedAssign>; +def warn_arc_literal_assign : Warning< + "assigning %select{array literal|dictionary literal|numeric literal|boxed expression|<should not happen>|block literal}0" + " to a weak %select{property|variable}1" + "; object will be released after assignment">, + InGroup<ARCUnsafeRetainedAssign>; def err_arc_new_array_without_ownership : Error< "'new' cannot allocate an array of %0 with no explicit ownership">; def err_arc_autoreleasing_var : Error< @@ -3691,6 +3831,10 @@ def err_arc_collection_forward : Error< def err_arc_multiple_method_decl : Error< "multiple methods named %0 found with mismatched result, " "parameter type or attributes">; +def warn_arc_lifetime_result_type : Warning< + "ARC %select{unused|__unsafe_unretained|__strong|__weak|__autoreleasing}0 " + "lifetime qualifier on return type is ignored">, + InGroup<IgnoredQualifiers>; let CategoryName = "ARC Retain Cycle" in { @@ -3703,9 +3847,6 @@ def note_arc_retain_cycle_owner : Note< } // end "ARC Retain Cycle" category -def note_nontrivial_objc_ownership : Note< - "because type %0 has %select{no|no|__strong|__weak|__autoreleasing}1 " - "ownership">; def warn_arc_object_memaccess : Warning< "%select{destination for|source of}0 this %1 call is a pointer to " "ownership-qualified type %2">, InGroup<ARCNonPodMemAccess>; @@ -3743,12 +3884,20 @@ def err_arc_cast_requires_bridge : Error< "requires a bridged cast">; def note_arc_bridge : Note< "use __bridge to convert directly (no change in ownership)">; +def note_arc_cstyle_bridge : Note< + "use __bridge with C-style cast to convert directly (no change in ownership)">; def note_arc_bridge_transfer : Note< "use %select{__bridge_transfer|CFBridgingRelease call}1 to transfer " "ownership of a +1 %0 into ARC">; +def note_arc_cstyle_bridge_transfer : Note< + "use __bridge_transfer with C-style cast to transfer " + "ownership of a +1 %0 into ARC">; def note_arc_bridge_retained : Note< "use %select{__bridge_retained|CFBridgingRetain call}1 to make an " "ARC object available as a +1 %0">; +def note_arc_cstyle_bridge_retained : Note< + "use __bridge_retained with C-style cast to make an " + "ARC object available as a +1 %0">; } // ARC Casting category @@ -3796,16 +3945,17 @@ def err_atomic_specifier_bad_type : Error< "%1 %select{||||||which is not trivially copyable}0">; // Expressions. -def ext_sizeof_function_type : Extension< - "invalid application of 'sizeof' to a function type">, InGroup<PointerArith>; -def ext_sizeof_void_type : Extension< - "invalid application of '%select{sizeof|__alignof|vec_step}0' to a void " +def ext_sizeof_alignof_function_type : Extension< + "invalid application of '%select{sizeof|alignof|vec_step}0' to a " + "function type">, InGroup<PointerArith>; +def ext_sizeof_alignof_void_type : Extension< + "invalid application of '%select{sizeof|alignof|vec_step}0' to a void " "type">, InGroup<PointerArith>; def err_sizeof_alignof_incomplete_type : Error< - "invalid application of '%select{sizeof|__alignof|vec_step}0' to an " + "invalid application of '%select{sizeof|alignof|vec_step}0' to an " "incomplete type %1">; def err_sizeof_alignof_bitfield : Error< - "invalid application of '%select{sizeof|__alignof}0' to bit-field">; + "invalid application of '%select{sizeof|alignof}0' to bit-field">; def err_vecstep_non_scalar_vector_type : Error< "'vec_step' requires built-in scalar or vector type, %0 invalid">; def err_offsetof_incomplete_type : Error< @@ -3888,6 +4038,10 @@ def warn_sizeof_array_param : Warning< "sizeof on array function parameter will return size of %0 instead of %1">, InGroup<SizeofArrayArgument>; +def warn_sizeof_array_decay : Warning< + "sizeof on pointer operation will return size of %0 instead of %1">, + InGroup<SizeofArrayDecay>; + def err_sizeof_nonfragile_interface : Error< "application of '%select{alignof|sizeof}1' to interface %0 is " "not supported on this architecture and platform">; @@ -3912,6 +4066,8 @@ def err_subscript_function_type : Error< "subscript of pointer to function type %0">; def err_subscript_incomplete_type : Error< "subscript of pointer to incomplete type %0">; +def err_dereference_incomplete_type : Error< + "dereference of pointer to incomplete type %0">; def ext_gnu_subscript_void_type : Extension< "subscript of a pointer to void is a GNU extension">, InGroup<PointerArith>; def err_typecheck_member_reference_struct_union : Error< @@ -4038,7 +4194,13 @@ def err_typecheck_sclass_fscope : Error< "illegal storage class on file-scoped variable">; def err_unsupported_global_register : Error< "global register variables are not supported">; -def warn_standalone_specifier : Warning<"'%0' ignored on this declaration">; +def warn_standalone_specifier : Warning<"'%0' ignored on this declaration">, + InGroup<MissingDeclarations>; +def ext_standalone_specifier : ExtWarn<"'%0' is not permitted on a declaration " + "of a type">, InGroup<MissingDeclarations>; +def err_standalone_class_nested_name_specifier : Error< + "forward declaration of %select{class|struct|interface|union|enum}0 cannot " + "have a nested name specifier">; def err_typecheck_sclass_func : Error<"illegal storage class on function">; def err_static_block_func : Error< "function declared in block scope cannot have 'static' storage class">; @@ -4052,12 +4214,14 @@ def err_invalid_form_pointer_member_function : Error< "cannot create a non-constant pointer to member function">; def err_parens_pointer_member_function : Error< "cannot parenthesize the name of a method when forming a member pointer">; +def err_typecheck_invalid_lvalue_addrof_addrof_function : Error< + "extra '&' taking address of overloaded function">; def err_typecheck_invalid_lvalue_addrof : Error< - "address expression must be an lvalue or a function designator">; -def ext_typecheck_addrof_class_temporary : ExtWarn< + "cannot take the address of an rvalue of type %0">; +def ext_typecheck_addrof_temporary : ExtWarn< "taking the address of a temporary object of type %0">, InGroup<DiagGroup<"address-of-temporary">>, DefaultError; -def err_typecheck_addrof_class_temporary : Error< +def err_typecheck_addrof_temporary : Error< "taking the address of a temporary object of type %0">; def err_typecheck_unary_expr : Error< "invalid argument type %0 to unary expression">; @@ -4070,7 +4234,7 @@ def note_indirection_through_null : Note< def warn_pointer_indirection_from_incompatible_type : Warning< "dereference of type %1 that was reinterpret_cast from type %0 has undefined " "behavior">, - InGroup<DiagGroup<"undefined-reinterpret-cast">>, DefaultIgnore; + InGroup<UndefinedReinterpretCast>, DefaultIgnore; def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; @@ -4127,11 +4291,11 @@ def warn_comparison_of_mixed_enum_types : Warning< InGroup<DiagGroup<"enum-compare">>; def warn_null_in_arithmetic_operation : Warning< "use of NULL in arithmetic operation">, - InGroup<DiagGroup<"null-arithmetic">>; + InGroup<NullArithmetic>; def warn_null_in_comparison_operation : Warning< "comparison between NULL and non-pointer " "%select{(%1 and NULL)|(NULL and %1)}0">, - InGroup<DiagGroup<"null-arithmetic">>; + InGroup<NullArithmetic>; def err_invalid_this_use : Error< "invalid use of 'this' outside of a non-static member function">; @@ -4178,6 +4342,9 @@ def err_unexpected_interface : Error< def err_ref_non_value : Error<"%0 does not refer to a value">; def err_ref_vm_type : Error< "cannot refer to declaration with a variably modified type inside block">; +def err_ref_flexarray_type : Error< + "cannot refer to declaration of structure variable with flexible array member " + "inside block">; def err_ref_array_type : Error< "cannot refer to declaration with an array type inside block">; def err_property_not_found : Error< @@ -4185,7 +4352,7 @@ def err_property_not_found : Error< def err_invalid_property_name : Error< "%0 is not a valid property name (accessing an object of type %1)">; def err_getter_not_found : Error< - "expected getter method not found on object of type %0">; + "no getter method for read from property">; def err_objc_subscript_method_not_found : Error< "expected method to %select{read|write}1 %select{dictionary|array}2 element not " "found on object of type %0">; @@ -4276,8 +4443,6 @@ def error_no_super_class_message : Error< "no @interface declaration found in class messaging of %0">; def error_root_class_cannot_use_super : Error< "%0 cannot use 'super' because it is a root class">; -def err_invalid_receiver_to_message : Error< - "invalid receiver to message expression">; def err_invalid_receiver_to_message_super : Error< "'super' is only valid in a method body">; def err_invalid_receiver_class_message : Error< @@ -4337,6 +4502,14 @@ def note_parameter_here : Note< def err_bad_reinterpret_cast_overload : Error< "reinterpret_cast cannot resolve overloaded function %0 to type %1">; +def warn_reinterpret_different_from_static : Warning< + "'reinterpret_cast' %select{from|to}3 class %0 %select{to|from}3 its " + "%select{virtual base|base at non-zero offset}2 %1 behaves differently from " + "'static_cast'">, InGroup<ReinterpretBaseClass>; +def note_reinterpret_updowncast_use_static: Note< + "use 'static_cast' to adjust the pointer correctly while " + "%select{upcasting|downcasting}0">; + def err_bad_static_cast_overload : Error< "address of overloaded function %0 cannot be static_cast to type %1">; @@ -4386,7 +4559,7 @@ def err_bad_reinterpret_cast_reference : Error< "reinterpret_cast of a %0 to %1 needs its address which is not allowed">; def warn_undefined_reinterpret_cast : Warning< "reinterpret_cast from %0 to %1 has undefined behavior">, - InGroup<DiagGroup<"undefined-reinterpret-cast">>, DefaultIgnore; + InGroup<UndefinedReinterpretCast>, DefaultIgnore; // These messages don't adhere to the pattern. // FIXME: Display the path somehow better. @@ -4464,7 +4637,7 @@ def ext_delete_void_ptr_operand : ExtWarn< def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete " "expression of type %0 to a pointer">; def warn_delete_incomplete : Warning< - "deleting pointer to incomplete type %0 may cause undefined behaviour">, + "deleting pointer to incomplete type %0 may cause undefined behavior">, InGroup<DiagGroup<"delete-incomplete">>; def err_delete_incomplete_class_type : Error< "deleting incomplete class type %0; no conversions to pointer type">; @@ -4563,6 +4736,9 @@ let CategoryName = "Lambda Issue" in { def err_lambda_capture_vm_type : Error< "variable %0 with variably modified type cannot be captured in " "a lambda expression">; + def err_lambda_capture_flexarray_type : Error< + "variable %0 with flexible array member cannot be captured in " + "a lambda expression">; def err_lambda_impcap : Error< "variable %0 cannot be implicitly captured in a lambda with no " "capture-default specified">; @@ -4573,8 +4749,6 @@ let CategoryName = "Lambda Issue" in { "cannot deduce lambda return type from initializer list">; def err_lambda_capture_default_arg : Error< "lambda expression in default argument cannot capture any entity">; - def err_lambda_unexpanded_pack : Error< - "unexpanded function parameter pack capture is unsupported">; def err_lambda_incomplete_result : Error< "incomplete result type %0 in lambda expression">; def err_lambda_objc_object_result : Error< @@ -4823,7 +4997,7 @@ def ext_typecheck_convert_discards_qualifiers : ExtWarn< "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2" " discards qualifiers">, - InGroup<IncompatiblePointerTypes>; + InGroup<IncompatiblePointerTypesDiscardsQualifiers>; def ext_nested_pointer_qualifier_mismatch : ExtWarn< "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" @@ -4837,7 +5011,7 @@ def ext_nested_pointer_qualifier_mismatch : ExtWarn< "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2" " discards qualifiers in nested pointer types">, - InGroup<IncompatiblePointerTypes>; + InGroup<IncompatiblePointerTypesDiscardsQualifiers>; def warn_incompatible_vectors : Warning< "incompatible vector types " "%select{%diff{assigning to $ from $|assigning to different types}0,1" @@ -5015,7 +5189,7 @@ def err_ref_bad_target : Error< def warn_non_pod_vararg_with_format_string : Warning< "cannot pass %select{non-POD|non-trivial}0 object of type %1 to variadic " "%select{function|block|method|constructor}2; expected type from format " - "string was %3">, InGroup<DiagGroup<"non-pod-varargs">>, DefaultError; + "string was %3">, InGroup<NonPODVarargs>, DefaultError; // The arguments to this diagnostic should match the warning above. def err_cannot_pass_objc_interface_to_vararg_format : Error< "cannot pass object with interface type %1 by value to variadic " @@ -5028,7 +5202,7 @@ def err_cannot_pass_objc_interface_to_vararg : Error< def warn_cannot_pass_non_pod_arg_to_vararg : Warning< "cannot pass object of %select{non-POD|non-trivial}0 type %1 through variadic" " %select{function|block|method|constructor}2; call will abort at runtime">, - InGroup<DiagGroup<"non-pod-varargs">>, DefaultError; + InGroup<NonPODVarargs>, DefaultError; def warn_cxx98_compat_pass_non_pod_arg_to_vararg : Warning< "passing object of trivial but non-POD type %0 through variadic" " %select{function|block|method|constructor}1 is incompatible with C++98">, @@ -5141,10 +5315,14 @@ let CategoryName = "Inline Assembly Issue" in { "%diff{$ matching output with type $|}0,1">; def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">; def err_asm_empty : Error<"__asm used with no assembly instructions">; + def err_asm_invalid_input_size : Error< + "invalid input size for constraint '%0'">; def err_invalid_asm_cast_lvalue : Error< "invalid use of a cast in a inline asm context requiring an l-value: " "remove the cast or build with -fheinous-gnu-extensions">; def err_inline_ms_asm_parsing : Error<"%0">; + def err_msasm_unsupported_arch : Error< + "Unsupported architecture '%0' for MS-style inline assembly">; def warn_asm_label_on_auto_decl : Warning< "ignored asm label '%0' on automatic variable">; @@ -5153,7 +5331,8 @@ let CategoryName = "Inline Assembly Issue" in { "accepted due to -fheinous-gnu-extensions, but clang may remove support " "for this in the future">; def warn_asm_mismatched_size_modifier : Warning< - "the size being stored is truncated, use a modifier to specify the size">, + "the value is truncated when put into register, " + "use a modifier to specify the size">, InGroup<ASMOperandWidths>; } @@ -5205,9 +5384,11 @@ def err_in_class_initializer_bad_type : Error< "static data member of type %0 must be initialized out of line">; def ext_in_class_initializer_float_type : ExtWarn< "in-class initializer for static data member of type %0 is a GNU extension">, - InGroup<GNU>; -def note_in_class_initializer_float_type_constexpr : Note< - "use 'constexpr' specifier to silence this warning">; + InGroup<GNUStaticFloatInit>; +def ext_in_class_initializer_float_type_cxx11 : ExtWarn< + "in-class initializer for static data member of type %0 requires " + "'constexpr' specifier">, InGroup<StaticFloatInit>, DefaultError; +def note_in_class_initializer_float_type_cxx11 : Note<"add 'constexpr'">; def err_in_class_initializer_literal_type : Error< "in-class initializer for static data member of type %0 requires " "'constexpr' specifier">; @@ -5244,6 +5425,9 @@ def err_anonymous_record_with_type : Error< def ext_anonymous_record_with_type : Extension< "types declared in an anonymous %select{struct|union}0 are a Microsoft " "extension">, InGroup<Microsoft>; +def ext_anonymous_record_with_anonymous_type : Extension< + "anonymous types declared in an anonymous %select{struct|union}0 " + "are an extension">, InGroup<DiagGroup<"nested-anon-types">>; def err_anonymous_record_with_function : Error< "functions cannot be declared in an anonymous %select{struct|union}0">; def err_anonymous_record_with_static : Error< @@ -5403,6 +5587,9 @@ def warn_cxx98_compat_explicit_conversion_functions : Warning< def err_defaulted_special_member_params : Error< "an explicitly-defaulted %select{|copy |move }0constructor cannot " "have default arguments">; +def err_defaulted_special_member_variadic : Error< + "an explicitly-defaulted %select{|copy |move }0constructor cannot " + "be variadic">; def err_defaulted_special_member_return_type : Error< "explicitly-defaulted %select{copy|move}0 assignment operator must " "return %1">; @@ -5420,10 +5607,6 @@ def err_defaulted_special_member_copy_const_param : Error< "the parameter for this explicitly-defaulted copy " "%select{constructor|assignment operator}0 is const, but a member or base " "requires it to be non-const">; -def err_defaulted_special_member_copy_non_const_param : Error< - "explicitly-defaulted copy %select{constructor|assignment operator}0 with " - "a non-const parameter must be defaulted outside the class, unless a base or " - "member requires the parameter to be non-const">; def err_defaulted_copy_assign_not_ref : Error< "the parameter for an explicitly-defaulted copy assignment operator must be an " "lvalue reference type">; @@ -5446,17 +5629,17 @@ def ext_implicit_exception_spec_mismatch : ExtWarn< def warn_ptr_arith_precedes_bounds : Warning< "the pointer decremented by %0 refers before the beginning of the array">, - InGroup<DiagGroup<"array-bounds-pointer-arithmetic">>, DefaultIgnore; + InGroup<ArrayBoundsPointerArithmetic>, DefaultIgnore; def warn_ptr_arith_exceeds_bounds : Warning< "the pointer incremented by %0 refers past the end of the array (that " "contains %1 element%s2)">, - InGroup<DiagGroup<"array-bounds-pointer-arithmetic">>, DefaultIgnore; + InGroup<ArrayBoundsPointerArithmetic>, DefaultIgnore; def warn_array_index_precedes_bounds : Warning< "array index %0 is before the beginning of the array">, - InGroup<DiagGroup<"array-bounds">>; + InGroup<ArrayBounds>; def warn_array_index_exceeds_bounds : Warning< "array index %0 is past the end of the array (which contains %1 " - "element%s2)">, InGroup<DiagGroup<"array-bounds">>; + "element%s2)">, InGroup<ArrayBounds>; def note_array_index_out_of_bounds : Note< "array %0 declared here">; @@ -5494,7 +5677,7 @@ def warn_format_mix_positional_nonpositional_args : Warning< InGroup<Format>; def warn_static_array_too_small : Warning< "array argument is too small; contains %0 elements, callee requires at least %1">, - InGroup<DiagGroup<"array-bounds">>; + InGroup<ArrayBounds>; def note_callee_static_array : Note< "callee declares array parameter as static here">; def warn_empty_format_string : Warning< @@ -5543,19 +5726,19 @@ def warn_null_arg : Warning< // CHECK: returning address/reference of stack memory def warn_ret_stack_addr : Warning< "address of stack memory associated with local variable %0 returned">, - InGroup<DiagGroup<"return-stack-address">>; + InGroup<ReturnStackAddress>; def warn_ret_stack_ref : Warning< "reference to stack memory associated with local variable %0 returned">, - InGroup<DiagGroup<"return-stack-address">>; + InGroup<ReturnStackAddress>; def warn_ret_local_temp_addr : Warning< "returning address of local temporary object">, - InGroup<DiagGroup<"return-stack-address">>; + InGroup<ReturnStackAddress>; def warn_ret_local_temp_ref : Warning< "returning reference to local temporary object">, - InGroup<DiagGroup<"return-stack-address">>; + InGroup<ReturnStackAddress>; def warn_ret_addr_label : Warning< "returning address of label, which is local">, - InGroup<DiagGroup<"return-stack-address">>; + InGroup<ReturnStackAddress>; def err_ret_local_block : Error< "returning block that lives on the local stack">; def note_ref_var_local_bind : Note< @@ -5565,13 +5748,13 @@ def note_ref_var_local_bind : Note< // a constructor parameter. def warn_bind_ref_member_to_parameter : Warning< "binding reference member %0 to stack allocated parameter %1">, - InGroup<DiagGroup<"dangling-field">>; + InGroup<DanglingField>; def warn_init_ptr_member_to_parameter_addr : Warning< "initializing pointer member %0 with the stack address of parameter %1">, - InGroup<DiagGroup<"dangling-field">>; + InGroup<DanglingField>; def warn_bind_ref_member_to_temporary : Warning< "binding reference member %0 to a temporary value">, - InGroup<DiagGroup<"dangling-field">>; + InGroup<DanglingField>; def note_ref_or_ptr_member_declared_here : Note< "%select{reference|pointer}0 member declared here">; @@ -5657,7 +5840,7 @@ def warn_bool_switch_condition : Warning< "switch condition has boolean value">; def warn_case_value_overflow : Warning< "overflow converting case value to switch condition type (%0 to %1)">, - InGroup<DiagGroup<"switch">>; + InGroup<Switch>; def err_duplicate_case : Error<"duplicate case value '%0'">; def err_duplicate_case_differing_expr : Error< "duplicate case value: '%0' and '%1' both equal '%2'">; @@ -5760,10 +5943,10 @@ def err_second_parameter_to_va_arg_abstract: Error< "second argument to 'va_arg' is of abstract type %0">; def warn_second_parameter_to_va_arg_not_pod : Warning< "second argument to 'va_arg' is of non-POD type %0">, - InGroup<DiagGroup<"non-pod-varargs">>, DefaultError; + InGroup<NonPODVarargs>, DefaultError; def warn_second_parameter_to_va_arg_ownership_qualified : Warning< "second argument to 'va_arg' is of ARC ownership-qualified type %0">, - InGroup<DiagGroup<"non-pod-varargs">>, DefaultError; + InGroup<NonPODVarargs>, DefaultError; def warn_second_parameter_to_va_arg_never_compatible : Warning< "second argument to 'va_arg' is of promotable type %0; this va_arg has " "undefined behavior because arguments will be promoted to %1">; @@ -5785,12 +5968,24 @@ def err_return_init_list : Error< "must not return a value">; def warn_noreturn_function_has_return_expr : Warning< "function %0 declared 'noreturn' should not return">, - InGroup<DiagGroup<"invalid-noreturn">>; + InGroup<InvalidNoreturn>; def warn_falloff_noreturn_function : Warning< "function declared 'noreturn' should not return">, - InGroup<DiagGroup<"invalid-noreturn">>; + InGroup<InvalidNoreturn>; def err_noreturn_block_has_return_expr : Error< "block declared 'noreturn' should not return">; +def err_noreturn_missing_on_first_decl : Error< + "function declared '[[noreturn]]' after its first declaration">; +def note_noreturn_missing_first_decl : Note< + "declaration missing '[[noreturn]]' attribute is here">; +def err_carries_dependency_missing_on_first_decl : Error< + "%select{function|parameter}0 declared '[[carries_dependency]]' " + "after its first declaration">; +def note_carries_dependency_missing_first_decl : Note< + "declaration missing '[[carries_dependency]]' attribute is here">; +def err_carries_dependency_param_not_function_decl : Error< + "'[[carries_dependency]]' attribute only allowed on parameter in a function " + "declaration or lambda">; def err_block_on_nonlocal : Error< "__block attribute not allowed, only allowed on local variables">; def err_block_on_vm : Error< @@ -5870,6 +6065,8 @@ def err_c99_array_usage_cxx : Error< "feature, not permitted in C++">; def err_double_requires_fp64 : Error< "use of type 'double' requires cl_khr_fp64 extension to be enabled">; +def err_int128_unsupported : Error< + "__int128 is not supported on this target">; def err_nsconsumed_attribute_mismatch : Error< "overriding method has mismatched ns_consumed attribute on its" " parameter">; @@ -5986,8 +6183,44 @@ def err_invalid_astype_of_different_size : Error< "invalid reinterpretation: sizes of %0 and %1 must match">; def err_static_kernel : Error< "kernel functions cannot be declared static">; +def err_opencl_ptrptr_kernel_arg : Error< + "kernel argument cannot be declared as a pointer to a pointer">; def err_static_function_scope : Error< "variables in function scope cannot be declared static">; +def err_opencl_bitfields : Error< + "bitfields are not supported in OpenCL">; +def err_opencl_vla : Error< + "variable length arrays are not supported in OpenCL">; +def err_event_t_kernel_arg : Error< + "the event_t type cannot be used to declare a kernel function argument">; +def err_event_t_global_var : Error< + "the event_t type cannot be used to declare a program scope variable">; +def err_event_t_struct_field : Error< + "the event_t type cannot be used to declare a structure or union field">; +def err_event_t_addr_space_qual : Error< + "the event_t type can only be used with __private address space qualifier">; +def err_expected_kernel_void_return_type : Error< + "kernel must have void return type">; +def err_sampler_argument_required : Error< + "sampler_t variable required - got %0">; +def err_wrong_sampler_addressspace: Error< + "sampler type cannot be used with the __local and __global address space qualifiers">; + +// OpenMP support. +def err_omp_expected_var_arg_suggest : Error< + "%0 is not a global variable, static local variable or static data member%select{|; did you mean %2?}1">; +def err_omp_global_var_arg : Error< + "arguments of '#pragma omp %0' must have %select{global storage|static storage duration}1">; +def err_omp_ref_type_arg : Error< + "arguments of '#pragma omp %0' cannot be of reference type %1">; +def err_omp_var_scope : Error< + "'#pragma omp %0' must appear in the scope of the %1 variable declaration">; +def err_omp_var_used : Error< + "'#pragma omp %0' must precede all references to variable %1">; +def err_omp_var_thread_local : Error< + "variable %0 cannot be threadprivate because it is thread-local">; +def err_omp_incomplete_type : Error< + "a threadprivate variable must not have incomplete type %0">; } // end of sema category @@ -6000,15 +6233,19 @@ def warn_related_result_type_compatibility_class : Warning< def warn_related_result_type_compatibility_protocol : Warning< "protocol method is expected to return an instance of the implementing " "class, but is declared to return %0">; -def note_related_result_type_overridden_family : Note< - "overridden method is part of the '%select{|alloc|copy|init|mutableCopy|" - "new|autorelease|dealloc|finalize|release|retain|retainCount|self}0' method " - "family">; +def note_related_result_type_family : Note< + "%select{overridden|current}0 method is part of the '%select{|alloc|copy|init|" + "mutableCopy|new|autorelease|dealloc|finalize|release|retain|retainCount|" + "self}1' method family%select{| and is expected to return an instance of its " + "class type}0">; def note_related_result_type_overridden : Note< "overridden method returns an instance of its class type">; def note_related_result_type_inferred : Note< "%select{class|instance}0 method %1 is assumed to return an instance of " "its receiver type (%2)">; +def note_related_result_type_explicit : Note< + "%select{overridden|current}0 method is explicitly declared 'instancetype'" + "%select{| and is expected to return an instance of its class type}0">; } @@ -6023,7 +6260,7 @@ def err_module_private_local_class : Error< "local %select{struct|interface|union|class|enum}0 cannot be declared " "__module_private__">; def err_module_private_definition : Error< - "definition of %0 must be imported before it is required">; + "definition of %0 must be imported from module '%1' before it is required">; } let CategoryName = "Documentation Issue" in { diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td index e9df09d..7137404 100644 --- a/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/include/clang/Basic/DiagnosticSerializationKinds.td @@ -17,10 +17,8 @@ def err_fe_pch_malformed : Error< "malformed or corrupted PCH file: '%0'">, DefaultFatal; def err_fe_pch_malformed_block : Error< "malformed block record in PCH file: '%0'">, DefaultFatal; -def err_fe_pch_error_at_end_block : Error< - "error at end of module block in PCH file: '%0'">, DefaultFatal; def err_fe_pch_file_modified : Error< - "file '%0' has been modified since the precompiled header was built">, + "file '%0' has been modified since the precompiled header '%1' was built">, DefaultFatal; def err_fe_pch_file_overridden : Error< "file '%0' from the precompiled header has been overridden">; @@ -46,19 +44,16 @@ def warn_pch_different_branch : Error< def err_pch_with_compiler_errors : Error< "PCH file contains compiler errors">; - +def warn_module_conflict : Warning< + "module '%0' conflicts with already-imported module '%1': %2">, + InGroup<ModuleConflict>; + def err_pch_macro_def_undef : Error< "macro '%0' was %select{defined|undef'd}1 in the precompiled header but " "%select{undef'd|defined}1 on the command line">; def err_pch_macro_def_conflict : Error< "definition of macro '%0' differs between the precompiled header ('%1') " "and the command line ('%2')">; -def err_pch_include_opt_missing : Error< - "precompiled header depends on '%select{-include|-imacros}0 %1' option " - "that is missing from the command line">; -def err_pch_include_opt_conflict : Error< - "precompiled header option '%select{-include|-imacros}0 %1' conflicts with " - "corresponding option '%select{-include|-imacros}0 %2' on command line">; def err_pch_undef : Error< "%select{command line contains|precompiled header was built with}0 " "'-undef' but %select{precompiled header was not built with it|" diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index b2f578d..6d9e53b 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -17,11 +17,12 @@ #include "clang/Basic/FileSystemOptions.h" #include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/Allocator.h" // FIXME: Enhance libsystem to support inode and other fields in stat. #include <sys/types.h> @@ -152,6 +153,12 @@ class FileManager : public RefCountedBase<FileManager> { /// \see SeenDirEntries llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> SeenFileEntries; + /// \brief The canonical names of directories. + llvm::DenseMap<const DirectoryEntry *, llvm::StringRef> CanonicalDirNames; + + /// \brief Storage for canonical names that we have computed. + llvm::BumpPtrAllocator CanonicalNameStorage; + /// \brief Each FileEntry we create is assigned a unique ID #. /// unsigned NextFileUID; @@ -164,7 +171,7 @@ class FileManager : public RefCountedBase<FileManager> { OwningPtr<FileSystemStatCache> StatCache; bool getStatValue(const char *Path, struct stat &StatBuf, - int *FileDescriptor); + bool isFile, int *FileDescriptor); /// Add all ancestors of the given path (pointing to either a file /// or a directory) as virtual directories. @@ -257,6 +264,13 @@ public: static void modifyFileEntry(FileEntry *File, off_t Size, time_t ModificationTime); + /// \brief Retrieve the canonical name for a given directory. + /// + /// This is a very expensive operation, despite its results being cached, + /// and should only be used when the physical layout of the file system is + /// required, which is (almost) never. + StringRef getCanonicalName(const DirectoryEntry *Dir); + void PrintStats() const; }; diff --git a/include/clang/Basic/FileSystemStatCache.h b/include/clang/Basic/FileSystemStatCache.h index a802c7c..ff70373 100644 --- a/include/clang/Basic/FileSystemStatCache.h +++ b/include/clang/Basic/FileSystemStatCache.h @@ -18,8 +18,8 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" -#include <sys/types.h> #include <sys/stat.h> +#include <sys/types.h> namespace clang { @@ -44,13 +44,13 @@ public: /// /// \returns \c true if the path does not exist or \c false if it exists. /// - /// If FileDescriptor is non-null, then this lookup should only return success - /// for files (not directories). If it is null this lookup should only return + /// If isFile is true, then this lookup should only return success for files + /// (not directories). If it is false this lookup should only return /// success for directories (not files). On a successful file lookup, the /// implementation can optionally fill in FileDescriptor with a valid /// descriptor and the client guarantees that it will close it. - static bool get(const char *Path, struct stat &StatBuf, int *FileDescriptor, - FileSystemStatCache *Cache); + static bool get(const char *Path, struct stat &StatBuf, + bool isFile, int *FileDescriptor, FileSystemStatCache *Cache); /// \brief Sets the next stat call cache in the chain of stat caches. @@ -69,16 +69,17 @@ public: protected: virtual LookupResult getStat(const char *Path, struct stat &StatBuf, - int *FileDescriptor) = 0; + bool isFile, int *FileDescriptor) = 0; LookupResult statChained(const char *Path, struct stat &StatBuf, - int *FileDescriptor) { + bool isFile, int *FileDescriptor) { if (FileSystemStatCache *Next = getNextStatCache()) - return Next->getStat(Path, StatBuf, FileDescriptor); + return Next->getStat(Path, StatBuf, isFile, FileDescriptor); // If we hit the end of the list of stat caches to try, just compute and // return it without a cache. - return get(Path, StatBuf, FileDescriptor, 0) ? CacheMissing : CacheExists; + return get(Path, StatBuf, + isFile, FileDescriptor, 0) ? CacheMissing : CacheExists; } }; @@ -97,7 +98,7 @@ public: iterator end() const { return StatCalls.end(); } virtual LookupResult getStat(const char *Path, struct stat &StatBuf, - int *FileDescriptor); + bool isFile, int *FileDescriptor); }; } // end namespace clang diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index 76242ec..c04a893 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -16,9 +16,9 @@ #ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H #define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H +#include "clang/Basic/LLVM.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/TokenKinds.h" -#include "clang/Basic/LLVM.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/PointerLikeTypeTraits.h" @@ -146,9 +146,6 @@ public: bool hadMacroDefinition() const { return HadMacro; } - void setHadMacroDefinition(bool Val) { - HadMacro = Val; - } /// getTokenID - If this is a source-language token (e.g. 'for'), this API /// can be used to cause the lexer to map identifiers to source-language @@ -297,11 +294,11 @@ public: } /// \brief Determine whether this is the contextual keyword - /// '__experimental_modules_import'. + /// 'import'. bool isModulesImport() const { return IsModulesImport; } /// \brief Set whether this identifier is the contextual keyword - /// '__experimental_modules_import'. + /// 'import'. void setModulesImport(bool I) { IsModulesImport = I; if (I) diff --git a/include/clang/Basic/LLVM.h b/include/clang/Basic/LLVM.h index 13c5b44..306c75e 100644 --- a/include/clang/Basic/LLVM.h +++ b/include/clang/Basic/LLVM.h @@ -16,19 +16,24 @@ #ifndef CLANG_BASIC_LLVM_H #define CLANG_BASIC_LLVM_H -// This should be the only #include, force #includes of all the others on -// clients. +// Do not proliferate #includes here, require clients to #include their +// dependencies. +// Casting.h has complex templates that cannot be easily forward declared. #include "llvm/Support/Casting.h" +// None.h includes an enumerator that is desired & cannot be forward declared +// without a definition of NoneType. +#include "llvm/ADT/None.h" namespace llvm { // ADT's. class StringRef; class Twine; template<typename T> class ArrayRef; - template<class T> class OwningPtr; + template<typename T> class OwningPtr; template<unsigned InternalLen> class SmallString; template<typename T, unsigned N> class SmallVector; template<typename T> class SmallVectorImpl; + template<typename T> class Optional; template<typename T> struct SaveAndRestore; @@ -53,6 +58,8 @@ namespace clang { using llvm::cast_or_null; // ADT's. + using llvm::None; + using llvm::Optional; using llvm::StringRef; using llvm::Twine; using llvm::ArrayRef; diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index dbc08c7..3de0107 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -45,9 +45,10 @@ LANGOPT(C99 , 1, 0, "C99") LANGOPT(C11 , 1, 0, "C11") LANGOPT(MicrosoftExt , 1, 0, "Microsoft extensions") LANGOPT(MicrosoftMode , 1, 0, "Microsoft compatibility mode") +LANGOPT(AsmBlocks , 1, 0, "Microsoft inline asm blocks") LANGOPT(Borland , 1, 0, "Borland extensions") LANGOPT(CPlusPlus , 1, 0, "C++") -LANGOPT(CPlusPlus0x , 1, 0, "C++0x") +LANGOPT(CPlusPlus11 , 1, 0, "C++0x") LANGOPT(CPlusPlus1y , 1, 0, "C++1y") LANGOPT(ObjC1 , 1, 0, "Objective-C 1") LANGOPT(ObjC2 , 1, 0, "Objective-C 2") @@ -115,7 +116,9 @@ LANGOPT(ShortEnums , 1, 0, "short enum types") LANGOPT(OpenCL , 1, 0, "OpenCL") LANGOPT(OpenCLVersion , 32, 0, "OpenCL version") +LANGOPT(NativeHalfType , 1, 0, "Native half type support") LANGOPT(CUDA , 1, 0, "CUDA") +LANGOPT(OpenMP , 1, 0, "OpenMP support") LANGOPT(AssumeSaneOperatorNew , 1, 1, "implicit __attribute__((malloc)) for C++'s new operators") BENIGN_LANGOPT(ElideConstructors , 1, 1, "C++ copy constructor elision") @@ -144,18 +147,21 @@ BENIGN_LANGOPT(DelayedTemplateParsing , 1, 0, "delayed template parsing") LANGOPT(BlocksRuntimeOptional , 1, 0, "optional blocks runtime") ENUM_LANGOPT(GC, GCMode, 2, NonGC, "Objective-C Garbage Collection mode") -ENUM_LANGOPT(VisibilityMode, Visibility, 3, DefaultVisibility, - "symbol visibility") +ENUM_LANGOPT(ValueVisibilityMode, Visibility, 3, DefaultVisibility, + "value symbol visibility") +ENUM_LANGOPT(TypeVisibilityMode, Visibility, 3, DefaultVisibility, + "type symbol visibility") ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff, "stack protector mode") ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined, "signed integer overflow handling") -ENUM_LANGOPT(FPContractMode, FPContractModeKind, 2, FPC_On, "FP_CONTRACT mode") BENIGN_LANGOPT(InstantiationDepth, 32, 512, "maximum template instantiation depth") BENIGN_LANGOPT(ConstexprCallDepth, 32, 512, "maximum constexpr call depth") +BENIGN_LANGOPT(BracketDepth, 32, 256, + "maximum bracket nesting depth") BENIGN_LANGOPT(NumLargeByValueCopy, 32, 0, "if non-zero, warn about parameter or return Warn if parameter/return value is larger in bytes than this setting. 0 is no check.") VALUE_LANGOPT(MSCVersion, 32, 0, @@ -163,17 +169,8 @@ VALUE_LANGOPT(MSCVersion, 32, 0, LANGOPT(ApplePragmaPack, 1, 0, "Apple gcc-compatible #pragma pack handling") -BENIGN_LANGOPT(EmitMicrosoftInlineAsm , 1, 0, - "Enable emission of MS-style inline assembly.") - - BENIGN_LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments from system headers in the AST") -/// Runtime sanitizers. -#define SANITIZER(NAME, ID) \ -BENIGN_LANGOPT(Sanitize##ID, 1, 0, NAME " sanitizer") -#include "clang/Basic/Sanitizers.def" - #undef LANGOPT #undef VALUE_LANGOPT #undef BENIGN_LANGOPT diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index fbb014e..21ca7eb 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -15,14 +15,23 @@ #ifndef LLVM_CLANG_LANGOPTIONS_H #define LLVM_CLANG_LANGOPTIONS_H -#include <string> +#include "clang/Basic/CommentOptions.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Visibility.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include <string> namespace clang { +struct SanitizerOptions { +#define SANITIZER(NAME, ID) unsigned ID : 1; +#include "clang/Basic/Sanitizers.def" + + /// \brief Cached set of sanitizer options with all sanitizers disabled. + static const SanitizerOptions Disabled; +}; + /// Bitfields of LangOptions, split out from LangOptions in order to ensure that /// this large collection of bitfields is a trivial class type. class LangOptionsBase { @@ -32,6 +41,7 @@ public: #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) #include "clang/Basic/LangOptions.def" + SanitizerOptions Sanitize; protected: // Define language options of enumeration type. These are private, and will // have accessors (below). @@ -56,12 +66,6 @@ public: SOB_Trapping // -ftrapv }; - enum FPContractModeKind { - FPC_Off, // Form fused FP ops only where result will not be affected. - FPC_On, // Form fused FP ops according to FP_CONTRACT rules. - FPC_Fast // Aggressively fuse FP ops (E.g. FMA). - }; - public: clang::ObjCRuntime ObjCRuntime; @@ -75,6 +79,9 @@ public: /// \brief The name of the current module. std::string CurrentModule; + + /// \brief Options for parsing comments. + CommentOptions CommentOpts; LangOptions(); diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h index 6bc1f5d..01b8db1 100644 --- a/include/clang/Basic/Linkage.h +++ b/include/clang/Basic/Linkage.h @@ -42,6 +42,14 @@ enum Linkage { ExternalLinkage }; +/// \brief Describes the different kinds of language linkage +/// (C++ [dcl.link]) that an entity may have. +enum LanguageLinkage { + CLanguageLinkage, + CXXLanguageLinkage, + NoLanguageLinkage +}; + /// \brief A more specific kind of linkage than enum Linkage. /// /// This is relevant to CodeGen and AST file reading. diff --git a/include/clang/Basic/MacroBuilder.h b/include/clang/Basic/MacroBuilder.h index 6df3a38..9a9eaa2 100644 --- a/include/clang/Basic/MacroBuilder.h +++ b/include/clang/Basic/MacroBuilder.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_BASIC_MACROBUILDER_H #define LLVM_CLANG_BASIC_MACROBUILDER_H +#include "clang/Basic/LLVM.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/raw_ostream.h" diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index b6b088c..d2a43f0 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -18,10 +18,10 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/SetVector.h" #include <string> #include <utility> #include <vector> @@ -34,12 +34,12 @@ namespace clang { class DirectoryEntry; class FileEntry; +class FileManager; class LangOptions; class TargetInfo; /// \brief Describes the name of a module. -typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2> - ModuleId; +typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId; /// \brief Describes a module or submodule. class Module { @@ -68,23 +68,26 @@ private: /// \brief The AST file if this is a top-level module which has a /// corresponding serialized AST file, or null otherwise. const FileEntry *ASTFile; - + + /// \brief The top-level headers associated with this module. + llvm::SmallSetVector<const FileEntry *, 2> TopHeaders; + + /// \brief top-level header filenames that aren't resolved to FileEntries yet. + std::vector<std::string> TopHeaderNames; + public: /// \brief The headers that are part of this module. - llvm::SmallVector<const FileEntry *, 2> Headers; + SmallVector<const FileEntry *, 2> Headers; /// \brief The headers that are explicitly excluded from this module. - llvm::SmallVector<const FileEntry *, 2> ExcludedHeaders; - - /// \brief The top-level headers associated with this module. - llvm::SmallSetVector<const FileEntry *, 2> TopHeaders; + SmallVector<const FileEntry *, 2> ExcludedHeaders; /// \brief The set of language features required to use this module. /// /// If any of these features is not present, the \c IsAvailable bit /// will be false to indicate that this (sub)module is not /// available. - llvm::SmallVector<std::string, 2> Requires; + SmallVector<std::string, 2> Requires; /// \brief Whether this module is available in the current /// translation unit. @@ -116,7 +119,14 @@ public: /// \brief Whether, when inferring submodules, the inferr submodules should /// export all modules they import (e.g., the equivalent of "export *"). unsigned InferExportWildcard : 1; - + + /// \brief Whether the set of configuration macros is exhaustive. + /// + /// When the set of configuration macros is exhaustive, meaning + /// that no identifier not in this list should affect how the module is + /// built. + unsigned ConfigMacrosExhaustive : 1; + /// \brief Describes the visibility of the various names within a /// particular module. enum NameVisibilityKind { @@ -137,7 +147,7 @@ public: /// \brief The set of modules imported by this module, and on which this /// module depends. - llvm::SmallVector<Module *, 2> Imports; + SmallVector<Module *, 2> Imports; /// \brief Describes an exported module. /// @@ -146,7 +156,7 @@ public: typedef llvm::PointerIntPair<Module *, 1, bool> ExportDecl; /// \brief The set of export declarations. - llvm::SmallVector<ExportDecl, 2> Exports; + SmallVector<ExportDecl, 2> Exports; /// \brief Describes an exported module that has not yet been resolved /// (perhaps because the module it refers to has not yet been loaded). @@ -164,8 +174,58 @@ public: }; /// \brief The set of export declarations that have yet to be resolved. - llvm::SmallVector<UnresolvedExportDecl, 2> UnresolvedExports; - + SmallVector<UnresolvedExportDecl, 2> UnresolvedExports; + + /// \brief A library or framework to link against when an entity from this + /// module is used. + struct LinkLibrary { + LinkLibrary() : IsFramework(false) { } + LinkLibrary(const std::string &Library, bool IsFramework) + : Library(Library), IsFramework(IsFramework) { } + + /// \brief The library to link against. + /// + /// This will typically be a library or framework name, but can also + /// be an absolute path to the library or framework. + std::string Library; + + /// \brief Whether this is a framework rather than a library. + bool IsFramework; + }; + + /// \brief The set of libraries or frameworks to link against when + /// an entity from this module is used. + llvm::SmallVector<LinkLibrary, 2> LinkLibraries; + + /// \brief The set of "configuration macros", which are macros that + /// (intentionally) change how this module is built. + std::vector<std::string> ConfigMacros; + + /// \brief An unresolved conflict with another module. + struct UnresolvedConflict { + /// \brief The (unresolved) module id. + ModuleId Id; + + /// \brief The message provided to the user when there is a conflict. + std::string Message; + }; + + /// \brief The list of conflicts for which the module-id has not yet been + /// resolved. + std::vector<UnresolvedConflict> UnresolvedConflicts; + + /// \brief A conflict between two modules. + struct Conflict { + /// \brief The module that this module conflicts with. + Module *Other; + + /// \brief The message provided to the user when there is a conflict. + std::string Message; + }; + + /// \brief The list of conflicts. + std::vector<Conflict> Conflicts; + /// \brief Construct a top-level module. explicit Module(StringRef Name, SourceLocation DefinitionLoc, bool IsFramework) @@ -173,7 +233,8 @@ public: IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(false), IsSystem(false), InferSubmodules(false), InferExplicitSubmodules(false), - InferExportWildcard(false), NameVisibility(Hidden) { } + InferExportWildcard(false), ConfigMacrosExhaustive(false), + NameVisibility(Hidden) { } /// \brief Construct a new module or submodule. Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, @@ -217,7 +278,13 @@ public: return false; } - + + /// \brief Determine whether this module is a subframework of another + /// framework. + bool isSubFramework() const { + return IsFramework && Parent && Parent->isPartOfFramework(); + } + /// \brief Retrieve the full name of this module, including the path from /// its top-level module. std::string getFullModuleName() const; @@ -266,6 +333,20 @@ public: return Umbrella && Umbrella.is<const DirectoryEntry *>(); } + /// \brief Add a top-level header associated with this module. + void addTopHeader(const FileEntry *File) { + assert(File); + TopHeaders.insert(File); + } + + /// \brief Add a top-level header filename associated with this module. + void addTopHeaderFilename(StringRef Filename) { + TopHeaderNames.push_back(Filename); + } + + /// \brief The top-level headers associated with this module. + ArrayRef<const FileEntry *> getTopHeaders(FileManager &FileMgr); + /// \brief Add the given feature requirement to the list of features /// required by this module. /// @@ -284,7 +365,7 @@ public: /// /// \returns The submodule if found, or NULL otherwise. Module *findSubmodule(StringRef Name) const; - + typedef std::vector<Module *>::iterator submodule_iterator; typedef std::vector<Module *>::const_iterator submodule_const_iterator; @@ -292,14 +373,17 @@ public: submodule_const_iterator submodule_begin() const {return SubModules.begin();} submodule_iterator submodule_end() { return SubModules.end(); } submodule_const_iterator submodule_end() const { return SubModules.end(); } - + + /// \brief Returns the exported modules based on the wildcard restrictions. + void getExportedModules(SmallVectorImpl<Module *> &Exported) const; + static StringRef getModuleInputBufferName() { return "<module-includes>"; } /// \brief Print the module map for this module to the given stream. /// - void print(llvm::raw_ostream &OS, unsigned Indent = 0) const; + void print(raw_ostream &OS, unsigned Indent = 0) const; /// \brief Dump the contents of this module to the given output stream. void dump() const; diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h index d543b76..18ef64a 100644 --- a/include/clang/Basic/ObjCRuntime.h +++ b/include/clang/Basic/ObjCRuntime.h @@ -104,7 +104,7 @@ public: return true; } - /// \brief Is this runtime basically of the GNUstep family of runtimes? + /// \brief Is this runtime basically of the GNU family of runtimes? bool isGNUFamily() const { switch (getKind()) { case FragileMacOSX: @@ -164,6 +164,8 @@ public: return getVersion() >= VersionTuple(10, 8); case iOS: return (getVersion() >= VersionTuple(6)); + case GNUstep: + return getVersion() >= VersionTuple(1, 7); default: return false; @@ -272,6 +274,18 @@ public: llvm_unreachable("bad kind"); } + bool hasAtomicCopyHelper() const { + switch (getKind()) { + case FragileMacOSX: + case MacOSX: + case iOS: + return true; + case GNUstep: + return getVersion() >= VersionTuple(1, 7); + default: return false; + } + } + /// \brief Try to parse an Objective-C runtime specification from the given /// string. /// diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h index cc9ca9f..06cb143 100644 --- a/include/clang/Basic/OnDiskHashTable.h +++ b/include/clang/Basic/OnDiskHashTable.h @@ -14,11 +14,12 @@ #ifndef LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H #define LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H +#include "clang/Basic/LLVM.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/Host.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Host.h" #include <cassert> #include <cstdlib> diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def new file mode 100644 index 0000000..f968977 --- /dev/null +++ b/include/clang/Basic/OpenMPKinds.def @@ -0,0 +1,23 @@ +//===--- OpenMPKinds.def - OpenMP directives and clauses list ---*- 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 the list of supported OpenMP directives and +/// clauses. +/// +//===----------------------------------------------------------------------===// + +#ifndef OPENMP_DIRECTIVE +# define OPENMP_DIRECTIVE(Name) +#endif + +// OpenMP directives. +OPENMP_DIRECTIVE(threadprivate) +OPENMP_DIRECTIVE(parallel) + +#undef OPENMP_DIRECTIVE diff --git a/include/clang/Basic/OpenMPKinds.h b/include/clang/Basic/OpenMPKinds.h new file mode 100644 index 0000000..c90e9a0 --- /dev/null +++ b/include/clang/Basic/OpenMPKinds.h @@ -0,0 +1,37 @@ +//===--- OpenMPKinds.h - OpenMP enums ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines some OpenMP-specific enums and functions. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_OPENMPKINDS_H +#define LLVM_CLANG_BASIC_OPENMPKINDS_H + +#include "llvm/ADT/StringRef.h" + +namespace clang { + +/// \brief OpenMP directives. +enum OpenMPDirectiveKind { + OMPD_unknown = 0, +#define OPENMP_DIRECTIVE(Name) \ + OMPD_##Name, +#include "clang/Basic/OpenMPKinds.def" + NUM_OPENMP_DIRECTIVES +}; + +OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str); +const char *getOpenMPDirectiveName(OpenMPDirectiveKind Kind); + +} + +#endif + diff --git a/include/clang/Basic/OperatorPrecedence.h b/include/clang/Basic/OperatorPrecedence.h new file mode 100644 index 0000000..b68d577 --- /dev/null +++ b/include/clang/Basic/OperatorPrecedence.h @@ -0,0 +1,52 @@ +//===--- OperatorPrecedence.h - Operator precedence levels ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines and computes precedence levels for binary/ternary operators. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_OPERATOR_PRECEDENCE_H +#define LLVM_CLANG_OPERATOR_PRECEDENCE_H + +#include "clang/Basic/TokenKinds.h" + +namespace clang { + +/// PrecedenceLevels - These are precedences for the binary/ternary +/// operators in the C99 grammar. These have been named to relate +/// with the C99 grammar productions. Low precedences numbers bind +/// more weakly than high numbers. +namespace prec { + enum Level { + Unknown = 0, // Not binary operator. + Comma = 1, // , + Assignment = 2, // =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |= + Conditional = 3, // ? + LogicalOr = 4, // || + LogicalAnd = 5, // && + InclusiveOr = 6, // | + ExclusiveOr = 7, // ^ + And = 8, // & + Equality = 9, // ==, != + Relational = 10, // >=, <=, >, < + Shift = 11, // <<, >> + Additive = 12, // -, + + Multiplicative = 13, // *, /, % + PointerToMember = 14 // .*, ->* + }; +} + +/// \brief Return the precedence of the specified binary operator token. +prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, + bool CPlusPlus11); + +} // end namespace clang + +#endif // LLVM_CLANG_OPERATOR_PRECEDENCE_H diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h index 3f4626e..3f68160 100644 --- a/include/clang/Basic/PartialDiagnostic.h +++ b/include/clang/Basic/PartialDiagnostic.h @@ -19,6 +19,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" #include <cassert> @@ -200,6 +201,14 @@ public: } } +#if LLVM_HAS_RVALUE_REFERENCES + PartialDiagnostic(PartialDiagnostic &&Other) + : DiagID(Other.DiagID), DiagStorage(Other.DiagStorage), + Allocator(Other.Allocator) { + Other.DiagStorage = 0; + } +#endif + PartialDiagnostic(const PartialDiagnostic &Other, Storage *DiagStorage) : DiagID(Other.DiagID), DiagStorage(DiagStorage), Allocator(reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) @@ -242,6 +251,19 @@ public: return *this; } +#if LLVM_HAS_RVALUE_REFERENCES + PartialDiagnostic &operator=(PartialDiagnostic &&Other) { + freeStorage(); + + DiagID = Other.DiagID; + DiagStorage = Other.DiagStorage; + Allocator = Other.Allocator; + + Other.DiagStorage = 0; + return *this; + } +#endif + ~PartialDiagnostic() { freeStorage(); } @@ -299,7 +321,7 @@ public: } void EmitToString(DiagnosticsEngine &Diags, - llvm::SmallVectorImpl<char> &Buf) const { + SmallVectorImpl<char> &Buf) const { // FIXME: It should be possible to render a diagnostic to a string without // messing with the state of the diagnostics engine. DiagnosticBuilder DB(Diags.Report(getDiagID())); diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def index 085ca16..709ec8d 100644 --- a/include/clang/Basic/Sanitizers.def +++ b/include/clang/Basic/Sanitizers.def @@ -40,30 +40,61 @@ // AddressSanitizer SANITIZER("address", Address) +// More features of AddressSanitizer that should be turned on explicitly. +SANITIZER("init-order", InitOrder) +SANITIZER("use-after-return", UseAfterReturn) +SANITIZER("use-after-scope", UseAfterScope) + +SANITIZER_GROUP("address-full", AddressFull, + Address | InitOrder | UseAfterReturn | UseAfterScope) + +// MemorySanitizer +SANITIZER("memory", Memory) // ThreadSanitizer SANITIZER("thread", Thread) // UndefinedBehaviorSanitizer -SANITIZER("signed-integer-overflow", SignedIntegerOverflow) -SANITIZER("divide-by-zero", DivideByZero) +SANITIZER("alignment", Alignment) +SANITIZER("bool", Bool) +SANITIZER("bounds", Bounds) +SANITIZER("enum", Enum) +SANITIZER("float-cast-overflow", FloatCastOverflow) +SANITIZER("float-divide-by-zero", FloatDivideByZero) +SANITIZER("integer-divide-by-zero", IntegerDivideByZero) +SANITIZER("null", Null) +SANITIZER("object-size", ObjectSize) +SANITIZER("return", Return) SANITIZER("shift", Shift) +SANITIZER("signed-integer-overflow", SignedIntegerOverflow) SANITIZER("unreachable", Unreachable) -SANITIZER("return", Return) SANITIZER("vla-bound", VLABound) -SANITIZER("alignment", Alignment) -SANITIZER("null", Null) SANITIZER("vptr", Vptr) -SANITIZER("object-size", ObjectSize) -SANITIZER("float-cast-overflow", FloatCastOverflow) -// -fsanitize=undefined (and its alias -fcatch-undefined-behavior). This should -// include all the sanitizers which have low overhead, no ABI or address space -// layout implications, and only catch undefined behavior. +// IntegerSanitizer +SANITIZER("unsigned-integer-overflow", UnsignedIntegerOverflow) + +// -fsanitize=undefined includes all the sanitizers which have low overhead, no +// ABI or address space layout implications, and only catch undefined behavior. SANITIZER_GROUP("undefined", Undefined, - SignedIntegerOverflow | DivideByZero | Shift | Unreachable | - Return | VLABound | Alignment | Null | Vptr | ObjectSize | - FloatCastOverflow) + Alignment | Bool | Bounds | Enum | FloatCastOverflow | + FloatDivideByZero | IntegerDivideByZero | Null | ObjectSize | + Return | Shift | SignedIntegerOverflow | Unreachable | + VLABound | Vptr) + +// -fsanitize=undefined-trap (and its alias -fcatch-undefined-behavior) includes +// all sanitizers included by -fsanitize=undefined, except those that require +// runtime support. This group is generally used in conjunction with the +// -fsanitize-undefined-trap-on-error flag. +SANITIZER_GROUP("undefined-trap", UndefinedTrap, + Alignment | Bool | Bounds | Enum | FloatCastOverflow | + FloatDivideByZero | IntegerDivideByZero | Null | ObjectSize | + Return | Shift | SignedIntegerOverflow | Unreachable | + VLABound) + +SANITIZER_GROUP("integer", Integer, + SignedIntegerOverflow | UnsignedIntegerOverflow | Shift | + IntegerDivideByZero) #undef SANITIZER #undef SANITIZER_GROUP diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h index cfcf468..143beb6 100644 --- a/include/clang/Basic/SourceLocation.h +++ b/include/clang/Basic/SourceLocation.h @@ -16,12 +16,12 @@ #define LLVM_CLANG_SOURCELOCATION_H #include "clang/Basic/LLVM.h" -#include "llvm/Support/PointerLikeTypeTraits.h" #include "llvm/Support/Compiler.h" -#include <utility> -#include <functional> +#include "llvm/Support/PointerLikeTypeTraits.h" #include <cassert> +#include <functional> #include <string> +#include <utility> namespace llvm { class MemoryBuffer; @@ -165,7 +165,7 @@ public: return (void*)(uintptr_t)getRawEncoding(); } - /// getFromPtrEncoding - Turn a pointer encoding of a SourceLocation object + /// \brief Turn a pointer encoding of a SourceLocation object back /// into a real SourceLocation. static SourceLocation getFromPtrEncoding(const void *Encoding) { return getFromRawEncoding((unsigned)(uintptr_t)Encoding); @@ -218,7 +218,7 @@ public: /// \brief Represents a character-granular source range. /// /// The underlying SourceRange can either specify the starting/ending character -/// of the range, or it can specify the start or the range and the start of the +/// of the range, or it can specify the start of the range and the start of the /// last token of the range (a "token range"). In the token range case, the /// size of the last token must be measured to determine the actual end of the /// range. @@ -227,20 +227,14 @@ class CharSourceRange { bool IsTokenRange; public: CharSourceRange() : IsTokenRange(false) {} - CharSourceRange(SourceRange R, bool ITR) : Range(R),IsTokenRange(ITR){} + CharSourceRange(SourceRange R, bool ITR) : Range(R), IsTokenRange(ITR) {} static CharSourceRange getTokenRange(SourceRange R) { - CharSourceRange Result; - Result.Range = R; - Result.IsTokenRange = true; - return Result; + return CharSourceRange(R, true); } static CharSourceRange getCharRange(SourceRange R) { - CharSourceRange Result; - Result.Range = R; - Result.IsTokenRange = false; - return Result; + return CharSourceRange(R, false); } static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) { diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index db6bfd2..00c96c3 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -10,7 +10,7 @@ /// \file /// \brief Defines the SourceManager interface. /// -/// There are three different types of locations in a file: a spelling +/// There are three different types of locations in a %file: a spelling /// location, an expansion location, and a presumed location. /// /// Given an example of: @@ -35,21 +35,22 @@ #ifndef LLVM_CLANG_SOURCEMANAGER_H #define LLVM_CLANG_SOURCEMANAGER_H -#include "clang/Basic/LLVM.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/MemoryBuffer.h" +#include <cassert> #include <map> #include <vector> -#include <cassert> namespace clang { @@ -78,7 +79,7 @@ namespace SrcMgr { }; /// \brief One instance of this struct is kept for every file loaded or used. - //// + /// /// This object owns the MemoryBuffer object. class ContentCache { enum CCFlags { @@ -270,7 +271,7 @@ namespace SrcMgr { return SourceLocation::getFromRawEncoding(IncludeLoc); } const ContentCache* getContentCache() const { - return reinterpret_cast<const ContentCache*>(Data & ~7UL); + return reinterpret_cast<const ContentCache*>(Data & ~uintptr_t(7)); } /// \brief Return whether this is a system header or not. @@ -328,6 +329,11 @@ namespace SrcMgr { SourceLocation::getFromRawEncoding(ExpansionLocEnd).isInvalid(); } + bool isMacroBodyExpansion() const { + return getExpansionLocStart().isValid() && + SourceLocation::getFromRawEncoding(ExpansionLocEnd).isValid(); + } + bool isFunctionMacroExpansion() const { return getExpansionLocStart().isValid() && getExpansionLocStart() != getExpansionLocEnd(); @@ -429,6 +435,11 @@ public: /// \returns true if an error occurred that prevented the source-location /// entry from being loaded. virtual bool ReadSLocEntry(int ID) = 0; + + /// \brief Retrieve the module import location and name for the given ID, if + /// in fact it was loaded from a module (rather than, say, a precompiled + /// header). + virtual std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) = 0; }; @@ -436,7 +447,7 @@ public: /// /// The cache structure is complex enough to be worth breaking out of /// SourceManager. -class IsBeforeInTranslationUnitCache { +class InBeforeInTUCacheEntry { /// \brief The FileID's of the cached query. /// /// If these match up with a subsequent query, the result can be reused. @@ -458,7 +469,6 @@ class IsBeforeInTranslationUnitCache { /// random token in the parent. unsigned LCommonOffset, RCommonOffset; public: - /// \brief Return true if the currently cached values match up with /// the specified LHS/RHS query. /// @@ -508,6 +518,11 @@ public: }; +/// \brief The stack used when building modules on demand, which is used +/// to provide a link between the source managers of the different compiler +/// instances. +typedef ArrayRef<std::pair<std::string, FullSourceLoc> > ModuleBuildStack; + /// \brief This class handles loading and caching of source files into memory. /// /// This object owns the MemoryBuffer objects for all of the loaded @@ -572,13 +587,13 @@ class SourceManager : public RefCountedBase<SourceManager> { /// /// Positive FileIDs are indexes into this table. Entry 0 indicates an invalid /// expansion. - std::vector<SrcMgr::SLocEntry> LocalSLocEntryTable; + SmallVector<SrcMgr::SLocEntry, 0> LocalSLocEntryTable; /// \brief The table of SLocEntries that are loaded from other modules. /// /// Negative FileIDs are indexes into this table. To get from ID to an index, /// use (-ID - 2). - mutable std::vector<SrcMgr::SLocEntry> LoadedSLocEntryTable; + mutable SmallVector<SrcMgr::SLocEntry, 0> LoadedSLocEntryTable; /// \brief The starting offset of the next local SLocEntry. /// @@ -631,8 +646,21 @@ class SourceManager : public RefCountedBase<SourceManager> { // Statistics for -print-stats. mutable unsigned NumLinearScans, NumBinaryProbes; - // Cache results for the isBeforeInTranslationUnit method. - mutable IsBeforeInTranslationUnitCache IsBeforeInTUCache; + /// The key value into the IsBeforeInTUCache table. + typedef std::pair<FileID, FileID> IsBeforeInTUCacheKey; + + /// The IsBeforeInTranslationUnitCache is a mapping from FileID pairs + /// to cache results. + typedef llvm::DenseMap<IsBeforeInTUCacheKey, InBeforeInTUCacheEntry> + InBeforeInTUCache; + + /// Cache results for the isBeforeInTranslationUnit method. + mutable InBeforeInTUCache IBTUCache; + mutable InBeforeInTUCacheEntry IBTUCacheOverflow; + + /// Return the cache entry for comparing the given file IDs + /// for isBeforeInTranslationUnit. + InBeforeInTUCacheEntry &getInBeforeInTUCache(FileID LFID, FileID RFID) const; // Cache for the "fake" buffer used for error-recovery purposes. mutable llvm::MemoryBuffer *FakeBufferForRecovery; @@ -645,6 +673,15 @@ class SourceManager : public RefCountedBase<SourceManager> { mutable llvm::DenseMap<FileID, MacroArgsMap *> MacroArgsCacheMap; + /// \brief The stack of modules being built, which is used to detect + /// cycles in the module dependency graph as modules are being built, as + /// well as to describe why we're rebuilding a particular module. + /// + /// There is no way to set this value from the command line. If we ever need + /// to do so (e.g., if on-demand module construction moves out-of-process), + /// we can add a cc1-level option to do so. + SmallVector<std::pair<std::string, FullSourceLoc>, 2> StoredModuleBuildStack; + // SourceManager doesn't support copy construction. explicit SourceManager(const SourceManager&) LLVM_DELETED_FUNCTION; void operator=(const SourceManager&) LLVM_DELETED_FUNCTION; @@ -669,6 +706,22 @@ public: /// (likely to change while trying to use them). bool userFilesAreVolatile() const { return UserFilesAreVolatile; } + /// \brief Retrieve the module build stack. + ModuleBuildStack getModuleBuildStack() const { + return StoredModuleBuildStack; + } + + /// \brief Set the module build stack. + void setModuleBuildStack(ModuleBuildStack stack) { + StoredModuleBuildStack.clear(); + StoredModuleBuildStack.append(stack.begin(), stack.end()); + } + + /// \brief Push an entry to the module build stack. + void pushModuleBuildStack(StringRef moduleName, FullSourceLoc importLoc) { + StoredModuleBuildStack.push_back(std::make_pair(moduleName.str(),importLoc)); + } + /// \brief Create the FileID for a memory buffer that will represent the /// FileID for the main source. /// @@ -959,6 +1012,21 @@ public: return Entry.getFile().getIncludeLoc(); } + // \brief Returns the import location if the given source location is + // located within a module, or an invalid location if the source location + // is within the current translation unit. + std::pair<SourceLocation, StringRef> + getModuleImportLoc(SourceLocation Loc) const { + FileID FID = getFileID(Loc); + + // Positive file IDs are in the current translation unit, and -1 is a + // placeholder. + if (FID.ID >= -1) + return std::make_pair(SourceLocation(), ""); + + return ExternalSLocEntries->getModuleImportLoc(FID.ID); + } + /// \brief Given a SourceLocation object \p Loc, return the expansion /// location referenced by the ID. SourceLocation getExpansionLoc(SourceLocation Loc) const { @@ -1075,6 +1143,13 @@ public: /// expanded. bool isMacroArgExpansion(SourceLocation Loc) const; + /// \brief Tests whether the given source location represents the expansion of + /// a macro body. + /// + /// This is equivalent to testing whether the location is part of a macro + /// expansion but not the expansion of an argument to a function-like macro. + bool isMacroBodyExpansion(SourceLocation Loc) const; + /// \brief Returns true if \p Loc is inside the [\p Start, +\p Length) /// chunk of the source location address space. /// @@ -1187,7 +1262,8 @@ public: /// presumed location cannot be calculate (e.g., because \p Loc is invalid /// or the file containing \p Loc has changed on disk), returns an invalid /// presumed location. - PresumedLoc getPresumedLoc(SourceLocation Loc) const; + PresumedLoc getPresumedLoc(SourceLocation Loc, + bool UseLineDirectives = true) const; /// \brief Returns true if both SourceLocations correspond to the same file. bool isFromSameFile(SourceLocation Loc1, SourceLocation Loc2) const { @@ -1421,40 +1497,13 @@ public: return !isLoadedFileID(FID); } - /// Get a presumed location suitable for displaying in a diagnostic message, - /// taking into account macro arguments and expansions. - PresumedLoc getPresumedLocForDisplay(SourceLocation Loc) const { - // This is a condensed form of the algorithm used by emitCaretDiagnostic to - // walk to the top of the macro call stack. - while (Loc.isMacroID()) { - Loc = skipToMacroArgExpansion(Loc); - Loc = getImmediateMacroCallerLoc(Loc); - } - - return getPresumedLoc(Loc); - } - - /// Look through spelling locations for a macro argument expansion, and if - /// found skip to it so that we can trace the argument rather than the macros - /// in which that argument is used. If no macro argument expansion is found, - /// don't skip anything and return the starting location. - SourceLocation skipToMacroArgExpansion(SourceLocation StartLoc) const { - for (SourceLocation L = StartLoc; L.isMacroID(); - L = getImmediateSpellingLoc(L)) { - if (isMacroArgExpansion(L)) - return L; - } - // Otherwise just return initial location, there's nothing to skip. - return StartLoc; - } - /// Gets the location of the immediate macro caller, one level up the stack /// toward the initial macro typed into the source. SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const { if (!Loc.isMacroID()) return Loc; // When we have the location of (part of) an expanded parameter, its - // spelling location points to the argument as typed into the macro call, + // spelling location points to the argument as expanded in the macro call, // and therefore is used to locate the macro caller. if (isMacroArgExpansion(Loc)) return getImmediateSpellingLoc(Loc); @@ -1464,22 +1513,6 @@ public: return getImmediateExpansionRange(Loc).first; } - /// Gets the location of the immediate macro callee, one level down the stack - /// toward the leaf macro. - SourceLocation getImmediateMacroCalleeLoc(SourceLocation Loc) const { - if (!Loc.isMacroID()) return Loc; - - // When we have the location of (part of) an expanded parameter, its - // expansion location points to the unexpanded parameter reference within - // the macro definition (or callee). - if (isMacroArgExpansion(Loc)) - return getImmediateExpansionRange(Loc).first; - - // Otherwise, the callee of the macro is located where this location was - // spelled inside the macro definition. - return getImmediateSpellingLoc(Loc); - } - private: const llvm::MemoryBuffer *getFakeBufferForRecovery() const; const SrcMgr::ContentCache *getFakeContentCacheForRecovery() const; @@ -1599,4 +1632,5 @@ public: } // end namespace clang + #endif diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index c82b8cb..8706179 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -62,13 +62,21 @@ namespace clang { TST_auto, // C++0x auto TST_unknown_anytype, // __unknown_anytype extension TST_atomic, // C11 _Atomic + TST_image1d_t, // OpenCL image1d_t + TST_image1d_array_t, // OpenCL image1d_array_t + TST_image1d_buffer_t, // OpenCL image1d_buffer_t + TST_image2d_t, // OpenCL image2d_t + TST_image2d_array_t, // OpenCL image2d_array_t + TST_image3d_t, // OpenCL image3d_t + TST_sampler_t, // OpenCL sampler_t + TST_event_t, // OpenCL event_t TST_error // erroneous type }; /// \brief Structure that packs information about the type specifiers that /// were written in a particular type specifier sequence. struct WrittenBuiltinSpecs { - /*DeclSpec::TST*/ unsigned Type : 5; + /*DeclSpec::TST*/ unsigned Type : 6; /*DeclSpec::TSS*/ unsigned Sign : 2; /*DeclSpec::TSW*/ unsigned Width : 2; bool ModeAttr : 1; @@ -186,7 +194,8 @@ namespace clang { CC_X86Pascal, // __attribute__((pascal)) CC_AAPCS, // __attribute__((pcs("aapcs"))) CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp"))) - CC_PnaclCall // __attribute__((pnaclcall)) + CC_PnaclCall, // __attribute__((pnaclcall)) + CC_IntelOclBicc // __attribute__((intel_ocl_bicc)) }; } // end namespace clang diff --git a/include/clang/Basic/TargetCXXABI.h b/include/clang/Basic/TargetCXXABI.h new file mode 100644 index 0000000..c9d28f8 --- /dev/null +++ b/include/clang/Basic/TargetCXXABI.h @@ -0,0 +1,261 @@ +//===--- TargetCXXABI.h - C++ ABI Target Configuration ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines the TargetCXXABI class, which abstracts details of the +/// C++ ABI that we're targeting. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TARGETCXXABI_H +#define LLVM_CLANG_TARGETCXXABI_H + +#include "llvm/ADT/Triple.h" +#include "llvm/Support/ErrorHandling.h" + +namespace clang { + +/// \brief The basic abstraction for the target C++ ABI. +class TargetCXXABI { +public: + /// \brief The basic C++ ABI kind. + enum Kind { + /// The generic Itanium ABI is the standard ABI of most open-source + /// and Unix-like platforms. It is the primary ABI targeted by + /// many compilers, including Clang and GCC. + /// + /// It is documented here: + /// http://www.codesourcery.com/public/cxx-abi/ + GenericItanium, + + /// The generic ARM ABI is a modified version of the Itanium ABI + /// proposed by ARM for use on ARM-based platforms. + /// + /// These changes include: + /// - the representation of member function pointers is adjusted + /// to not conflict with the 'thumb' bit of ARM function pointers; + /// - constructors and destructors return 'this'; + /// - guard variables are smaller; + /// - inline functions are never key functions; + /// - array cookies have a slightly different layout; + /// - additional convenience functions are specified; + /// - and more! + /// + /// It is documented here: + /// http://infocenter.arm.com + /// /help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf + GenericARM, + + /// The iOS ABI is a partial implementation of the ARM ABI. + /// Several of the features of the ARM ABI were not fully implemented + /// in the compilers that iOS was launched with. + /// + /// Essentially, the iOS ABI includes the ARM changes to: + /// - member function pointers, + /// - guard variables, + /// - array cookies, and + /// - constructor/destructor signatures. + iOS, + + /// The generic AArch64 ABI is also a modified version of the Itanium ABI, + /// but it has fewer divergences than the 32-bit ARM ABI. + /// + /// The relevant changes from the generic ABI in this case are: + /// - representation of member function pointers adjusted as in ARM. + /// - guard variables are smaller. + GenericAArch64, + + /// The Microsoft ABI is the ABI used by Microsoft Visual Studio (and + /// compatible compilers). + /// + /// FIXME: should this be split into Win32 and Win64 variants? + /// + /// Only scattered and incomplete official documentation exists. + Microsoft + }; + +private: + // Right now, this class is passed around as a cheap value type. + // If you add more members, especially non-POD members, please + // audit the users to pass it by reference instead. + Kind TheKind; + +public: + /// A bogus initialization of the platform ABI. + TargetCXXABI() : TheKind(GenericItanium) {} + + TargetCXXABI(Kind kind) : TheKind(kind) {} + + void set(Kind kind) { + TheKind = kind; + } + + Kind getKind() const { return TheKind; } + + /// \brief Does this ABI generally fall into the Itanium family of ABIs? + bool isItaniumFamily() const { + switch (getKind()) { + case GenericAArch64: + case GenericItanium: + case GenericARM: + case iOS: + return true; + + case Microsoft: + return false; + } + llvm_unreachable("bad ABI kind"); + } + + /// \brief Is this ABI an MSVC-compatible ABI? + bool isMicrosoft() const { + switch (getKind()) { + case GenericAArch64: + case GenericItanium: + case GenericARM: + case iOS: + return false; + + case Microsoft: + return true; + } + llvm_unreachable("bad ABI kind"); + } + + /// \brief Is the default C++ member function calling convention + /// the same as the default calling convention? + bool isMemberFunctionCCDefault() const { + // Right now, this is always true for Microsoft. + return !isMicrosoft(); + } + + /// \brief Does this ABI have different entrypoints for complete-object + /// and base-subobject constructors? + bool hasConstructorVariants() const { + return isItaniumFamily(); + } + + /// \brief Does this ABI have different entrypoints for complete-object + /// and base-subobject destructors? + bool hasDestructorVariants() const { + return isItaniumFamily(); + } + + /// \brief Does this ABI allow virtual bases to be primary base classes? + bool hasPrimaryVBases() const { + return isItaniumFamily(); + } + + /// \brief Can an out-of-line inline function serve as a key function? + /// + /// This flag is only useful in ABIs where type data (for example, + /// v-tables and type_info objects) are emitted only after processing + /// the definition of a special "key" virtual function. (This is safe + /// because the ODR requires that every virtual function be defined + /// somewhere in a program.) This usually permits such data to be + /// emitted in only a single object file, as opposed to redundantly + /// in every object file that requires it. + /// + /// One simple and common definition of "key function" is the first + /// virtual function in the class definition which is not defined there. + /// This rule works very well when that function has a non-inline + /// definition in some non-header file. Unfortunately, when that + /// function is defined inline, this rule requires the type data + /// to be emitted weakly, as if there were no key function. + /// + /// The ARM ABI observes that the ODR provides an additional guarantee: + /// a virtual function is always ODR-used, so if it is defined inline, + /// that definition must appear in every translation unit that defines + /// the class. Therefore, there is no reason to allow such functions + /// to serve as key functions. + /// + /// Because this changes the rules for emitting type data, + /// it can cause type data to be emitted with both weak and strong + /// linkage, which is not allowed on all platforms. Therefore, + /// exploiting this observation requires an ABI break and cannot be + /// done on a generic Itanium platform. + bool canKeyFunctionBeInline() const { + switch (getKind()) { + case GenericARM: + return false; + + case GenericAArch64: + case GenericItanium: + case iOS: // old iOS compilers did not follow this rule + case Microsoft: + return true; + } + llvm_unreachable("bad ABI kind"); + } + + /// When is record layout allowed to allocate objects in the tail + /// padding of a base class? + /// + /// This decision cannot be changed without breaking platform ABI + /// compatibility, and yet it is tied to language guarantees which + /// the committee has so far seen fit to strengthen no less than + /// three separate times: + /// - originally, there were no restrictions at all; + /// - C++98 declared that objects could not be allocated in the + /// tail padding of a POD type; + /// - C++03 extended the definition of POD to include classes + /// containing member pointers; and + /// - C++11 greatly broadened the definition of POD to include + /// all trivial standard-layout classes. + /// Each of these changes technically took several existing + /// platforms and made them permanently non-conformant. + enum TailPaddingUseRules { + /// The tail-padding of a base class is always theoretically + /// available, even if it's POD. This is not strictly conforming + /// in any language mode. + AlwaysUseTailPadding, + + /// Only allocate objects in the tail padding of a base class if + /// the base class is not POD according to the rules of C++ TR1. + /// This is non strictly conforming in C++11 mode. + UseTailPaddingUnlessPOD03, + + /// Only allocate objects in the tail padding of a base class if + /// the base class is not POD according to the rules of C++11. + UseTailPaddingUnlessPOD11 + }; + TailPaddingUseRules getTailPaddingUseRules() const { + switch (getKind()) { + // To preserve binary compatibility, the generic Itanium ABI has + // permanently locked the definition of POD to the rules of C++ TR1, + // and that trickles down to all the derived ABIs. + case GenericItanium: + case GenericAArch64: + case GenericARM: + case iOS: + return UseTailPaddingUnlessPOD03; + + // MSVC always allocates fields in the tail-padding of a base class + // subobject, even if they're POD. + case Microsoft: + return AlwaysUseTailPadding; + } + llvm_unreachable("bad ABI kind"); + } + + /// Try to parse an ABI name, returning false on error. + bool tryParse(llvm::StringRef name); + + friend bool operator==(const TargetCXXABI &left, const TargetCXXABI &right) { + return left.getKind() == right.getKind(); + } + + friend bool operator!=(const TargetCXXABI &left, const TargetCXXABI &right) { + return !(left == right); + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 2d26783..c05f062 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -15,20 +15,21 @@ #ifndef LLVM_CLANG_BASIC_TARGETINFO_H #define LLVM_CLANG_BASIC_TARGETINFO_H +#include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/Specifiers.h" +#include "clang/Basic/TargetOptions.h" +#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/DataTypes.h" -#include "clang/Basic/AddressSpaces.h" -#include "clang/Basic/TargetOptions.h" -#include "clang/Basic/VersionTuple.h" -#include "clang/Basic/Specifiers.h" #include <cassert> -#include <vector> #include <string> +#include <vector> namespace llvm { struct fltSemantics; @@ -43,26 +44,10 @@ class SourceManager; namespace Builtin { struct Info; } -/// \brief The types of C++ ABIs for which we can generate code. -enum TargetCXXABI { - /// The generic ("Itanium") C++ ABI, documented at: - /// http://www.codesourcery.com/public/cxx-abi/ - CXXABI_Itanium, - - /// The ARM C++ ABI, based largely on the Itanium ABI but with - /// significant differences. - /// http://infocenter.arm.com - /// /help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf - CXXABI_ARM, - - /// The Visual Studio ABI. Only scattered official documentation exists. - CXXABI_Microsoft -}; - /// \brief Exposes information about the current target. /// class TargetInfo : public RefCountedBase<TargetInfo> { - llvm::IntrusiveRefCntPtr<TargetOptions> TargetOpts; + IntrusiveRefCntPtr<TargetOptions> TargetOpts; llvm::Triple Triple; protected: // Target values set by the ctor of the actual target implementation. Default @@ -89,7 +74,7 @@ protected: const llvm::fltSemantics *HalfFormat, *FloatFormat, *DoubleFormat, *LongDoubleFormat; unsigned char RegParmMax, SSERegParmMax; - TargetCXXABI CXXABI; + TargetCXXABI TheCXXABI; const LangAS::Map *AddrSpaceMap; mutable StringRef PlatformName; @@ -109,7 +94,7 @@ public: /// modify the options to canonicalize the target feature information to match /// what the backend expects. static TargetInfo* CreateTargetInfo(DiagnosticsEngine &Diags, - TargetOptions &Opts); + TargetOptions *Opts); virtual ~TargetInfo(); @@ -119,8 +104,8 @@ public: return *TargetOpts; } - void setTargetOpts(TargetOptions &TargetOpts) { - this->TargetOpts = &TargetOpts; + void setTargetOpts(TargetOptions *TargetOpts) { + this->TargetOpts = TargetOpts; } ///===---- Target Data Type Query Methods -------------------------------===// @@ -151,6 +136,10 @@ public: /// typedef void* __builtin_va_list; VoidPtrBuiltinVaList, + /// __builtin_va_list as defind by the AArch64 ABI + /// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055a/IHI0055A_aapcs64.pdf + AArch64ABIBuiltinVaList, + /// __builtin_va_list as defined by the PNaCl ABI: /// http://www.chromium.org/nativeclient/pnacl/bitcode-abi#TOC-Machine-Types PNaClABIBuiltinVaList, @@ -270,6 +259,9 @@ public: unsigned getLongLongWidth() const { return LongLongWidth; } unsigned getLongLongAlign() const { return LongLongAlign; } + /// \brief Determine whether the __int128 type is supported on this target. + bool hasInt128Type() const { return getPointerWidth(0) >= 64; } // FIXME + /// \brief Return the alignment that is suitable for storing any /// object with a fundamental alignment requirement. unsigned getSuitableAlign() const { return SuitableAlign; } @@ -335,6 +327,9 @@ public: return getTypeWidth(IntMaxType); } + // Return the size of unwind_word for this target. + unsigned getUnwindWordWidth() const { return getPointerWidth(0); } + /// \brief Return the "preferred" register width on this target. uint64_t getRegisterWidth() const { // Currently we assume the register width on the target matches the pointer @@ -518,6 +513,10 @@ public: bool validateInputConstraint(ConstraintInfo *OutputConstraints, unsigned NumOutputs, ConstraintInfo &info) const; + virtual bool validateInputSize(StringRef /*Constraint*/, + unsigned /*Size*/) const { + return true; + } virtual bool validateConstraintModifier(StringRef /*Constraint*/, const char /*Modifier*/, unsigned /*Size*/) const { @@ -572,8 +571,6 @@ public: /// either; the entire thing is pretty badly mangled. virtual bool hasProtectedVisibility() const { return true; } - virtual bool useGlobalsForAutomaticVariables() const { return false; } - /// \brief Return the section to use for CFString literals, or 0 if no /// special section is used. virtual const char *getCFStringSection() const { @@ -624,8 +621,8 @@ public: } /// \brief Get the C++ ABI currently in use. - virtual TargetCXXABI getCXXABI() const { - return CXXABI; + TargetCXXABI getCXXABI() const { + return TheCXXABI; } /// \brief Target the specified CPU. @@ -645,14 +642,9 @@ public: /// \brief Use this specified C++ ABI. /// /// \return False on error (invalid C++ ABI name). - bool setCXXABI(const std::string &Name) { - static const TargetCXXABI Unknown = static_cast<TargetCXXABI>(-1); - TargetCXXABI ABI = llvm::StringSwitch<TargetCXXABI>(Name) - .Case("arm", CXXABI_ARM) - .Case("itanium", CXXABI_Itanium) - .Case("microsoft", CXXABI_Microsoft) - .Default(Unknown); - if (ABI == Unknown) return false; + bool setCXXABI(llvm::StringRef name) { + TargetCXXABI ABI; + if (!ABI.tryParse(name)) return false; return setCXXABI(ABI); } @@ -660,7 +652,7 @@ public: /// /// \return False on error (ABI not valid on this target) virtual bool setCXXABI(TargetCXXABI ABI) { - CXXABI = ABI; + TheCXXABI = ABI; return true; } @@ -735,13 +727,19 @@ public: bool isBigEndian() const { return BigEndian; } + enum CallingConvMethodType { + CCMT_Unknown, + CCMT_Member, + CCMT_NonMember + }; + /// \brief Gets the default calling convention for the given target and /// declaration context. - virtual CallingConv getDefaultCallingConv() const { + virtual CallingConv getDefaultCallingConv(CallingConvMethodType MT) const { // Not all targets will specify an explicit calling convention that we can // express. This will always do the right thing, even though it's not // an explicit calling convention. - return CC_Default; + return CC_C; } enum CallingConvCheckResult { diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h index d6deb02..c2183fd 100644 --- a/include/clang/Basic/TargetOptions.h +++ b/include/clang/Basic/TargetOptions.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H #define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H +#include "clang/Basic/LLVM.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include <string> #include <vector> diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 25e8d5a..a254fae 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -121,7 +121,7 @@ TOK(numeric_constant) // 0x123 TOK(char_constant) // 'a' TOK(wide_char_constant) // L'b' -// C++0x Character Constants +// C++11 Character Constants TOK(utf16_char_constant) // u'a' TOK(utf32_char_constant) // U'a' @@ -130,7 +130,7 @@ TOK(string_literal) // "foo" TOK(wide_string_literal) // L"foo" TOK(angle_string_literal)// <foo> -// C++0x String Literals. +// C++11 String Literals. TOK(utf8_string_literal) // u8"foo" TOK(utf16_string_literal)// u"foo" TOK(utf32_string_literal)// U"foo" @@ -208,7 +208,7 @@ PUNCTUATOR(greatergreatergreater, ">>>") // KEYCXX - This is a C++ keyword, or a C++-specific keyword in the // implementation namespace // KEYNOCXX - This is a keyword in every non-C++ dialect. -// KEYCXX0X - This is a C++ keyword introduced to C++ in C++0x +// KEYCXX11 - This is a C++ keyword introduced to C++ in C++11 // KEYGNU - This is a keyword if GNU extensions are enabled // KEYMS - This is a keyword if Microsoft extensions are enabled // KEYNOMS - This is a keyword that must never be enabled under @@ -260,6 +260,7 @@ KEYWORD(_Bool , KEYNOCXX) KEYWORD(_Complex , KEYALL) KEYWORD(_Generic , KEYALL) KEYWORD(_Imaginary , KEYALL) +KEYWORD(_Noreturn , KEYALL) KEYWORD(_Static_assert , KEYALL) KEYWORD(__func__ , KEYALL) KEYWORD(__objc_yes , KEYALL) @@ -311,17 +312,17 @@ CXX_KEYWORD_OPERATOR(or_eq , pipeequal) CXX_KEYWORD_OPERATOR(xor , caret) CXX_KEYWORD_OPERATOR(xor_eq , caretequal) -// C++0x keywords -KEYWORD(alignas , KEYCXX0X) -KEYWORD(alignof , KEYCXX0X) -KEYWORD(char16_t , KEYCXX0X|KEYNOMS) -KEYWORD(char32_t , KEYCXX0X|KEYNOMS) -KEYWORD(constexpr , KEYCXX0X) -KEYWORD(decltype , KEYCXX0X) -KEYWORD(noexcept , KEYCXX0X) -KEYWORD(nullptr , KEYCXX0X) -KEYWORD(static_assert , KEYCXX0X) -KEYWORD(thread_local , KEYCXX0X) +// C++11 keywords +KEYWORD(alignas , KEYCXX11) +KEYWORD(alignof , KEYCXX11) +KEYWORD(char16_t , KEYCXX11|KEYNOMS) +KEYWORD(char32_t , KEYCXX11|KEYNOMS) +KEYWORD(constexpr , KEYCXX11) +KEYWORD(decltype , KEYCXX11) +KEYWORD(noexcept , KEYCXX11) +KEYWORD(nullptr , KEYCXX11) +KEYWORD(static_assert , KEYCXX11) +KEYWORD(thread_local , KEYCXX11) // GNU Extensions (in impl-reserved namespace) KEYWORD(_Decimal32 , KEYALL) @@ -350,31 +351,34 @@ KEYWORD(typeof , KEYGNU) KEYWORD(L__FUNCTION__ , KEYMS) // GNU and MS Type Traits -KEYWORD(__has_nothrow_assign , KEYCXX) -KEYWORD(__has_nothrow_copy , KEYCXX) -KEYWORD(__has_nothrow_constructor , KEYCXX) -KEYWORD(__has_trivial_assign , KEYCXX) -KEYWORD(__has_trivial_copy , KEYCXX) -KEYWORD(__has_trivial_constructor , KEYCXX) -KEYWORD(__has_trivial_destructor , KEYCXX) -KEYWORD(__has_virtual_destructor , KEYCXX) -KEYWORD(__is_abstract , KEYCXX) -KEYWORD(__is_base_of , KEYCXX) -KEYWORD(__is_class , KEYCXX) -KEYWORD(__is_convertible_to , KEYCXX) -KEYWORD(__is_empty , KEYCXX) -KEYWORD(__is_enum , KEYCXX) -KEYWORD(__is_final , KEYCXX) -KEYWORD(__is_interface_class , KEYCXX) +KEYWORD(__has_nothrow_assign , KEYCXX) +KEYWORD(__has_nothrow_move_assign , KEYCXX) +KEYWORD(__has_nothrow_copy , KEYCXX) +KEYWORD(__has_nothrow_constructor , KEYCXX) +KEYWORD(__has_trivial_assign , KEYCXX) +KEYWORD(__has_trivial_move_assign , KEYCXX) +KEYWORD(__has_trivial_copy , KEYCXX) +KEYWORD(__has_trivial_constructor , KEYCXX) +KEYWORD(__has_trivial_move_constructor, KEYCXX) +KEYWORD(__has_trivial_destructor , KEYCXX) +KEYWORD(__has_virtual_destructor , KEYCXX) +KEYWORD(__is_abstract , KEYCXX) +KEYWORD(__is_base_of , KEYCXX) +KEYWORD(__is_class , KEYCXX) +KEYWORD(__is_convertible_to , KEYCXX) +KEYWORD(__is_empty , KEYCXX) +KEYWORD(__is_enum , KEYCXX) +KEYWORD(__is_final , KEYCXX) +KEYWORD(__is_interface_class , KEYCXX) // Tentative name - there's no implementation of std::is_literal_type yet. -KEYWORD(__is_literal , KEYCXX) +KEYWORD(__is_literal , KEYCXX) // Name for GCC 4.6 compatibility - people have already written libraries using // this name unfortunately. -KEYWORD(__is_literal_type , KEYCXX) -KEYWORD(__is_pod , KEYCXX) -KEYWORD(__is_polymorphic , KEYCXX) -KEYWORD(__is_trivial , KEYCXX) -KEYWORD(__is_union , KEYCXX) +KEYWORD(__is_literal_type , KEYCXX) +KEYWORD(__is_pod , KEYCXX) +KEYWORD(__is_polymorphic , KEYCXX) +KEYWORD(__is_trivial , KEYCXX) +KEYWORD(__is_union , KEYCXX) // Clang-only C++ Type Traits KEYWORD(__is_trivially_constructible, KEYCXX) @@ -448,6 +452,14 @@ ALIAS("read_only", __read_only , KEYOPENCL) ALIAS("write_only", __write_only , KEYOPENCL) ALIAS("read_write", __read_write , KEYOPENCL) KEYWORD(__builtin_astype , KEYOPENCL) +KEYWORD(image1d_t , KEYOPENCL) +KEYWORD(image1d_array_t , KEYOPENCL) +KEYWORD(image1d_buffer_t , KEYOPENCL) +KEYWORD(image2d_t , KEYOPENCL) +KEYWORD(image2d_array_t , KEYOPENCL) +KEYWORD(image3d_t , KEYOPENCL) +KEYWORD(sampler_t , KEYOPENCL) +KEYWORD(event_t , KEYOPENCL) // Borland Extensions. KEYWORD(__pascal , KEYALL) @@ -566,7 +578,7 @@ OBJC2_AT_KEYWORD(required) OBJC2_AT_KEYWORD(optional) OBJC2_AT_KEYWORD(synthesize) OBJC2_AT_KEYWORD(dynamic) -OBJC2_AT_KEYWORD(__experimental_modules_import) +OBJC2_AT_KEYWORD(import) // TODO: What to do about context-sensitive keywords like: // bycopy/byref/in/inout/oneway/out? @@ -637,6 +649,12 @@ ANNOTATION(pragma_fp_contract) // handles them. ANNOTATION(pragma_opencl_extension) +// Annotations for OpenMP pragma directives - #pragma omp ... +// The lexer produces these so that they only take effect when the parser +// handles #pragma omp ... directives. +ANNOTATION(pragma_openmp) +ANNOTATION(pragma_openmp_end) + #undef ANNOTATION #undef TESTING_KEYWORD #undef OBJC2_AT_KEYWORD diff --git a/include/clang/Basic/TokenKinds.h b/include/clang/Basic/TokenKinds.h index e850971..dcbe1da 100644 --- a/include/clang/Basic/TokenKinds.h +++ b/include/clang/Basic/TokenKinds.h @@ -68,15 +68,21 @@ inline bool isAnyIdentifier(TokenKind K) { return (K == tok::identifier) || (K == tok::raw_identifier); } +/// \brief Return true if this is a C or C++ string-literal (or +/// C++11 user-defined-string-literal) token. +inline bool isStringLiteral(TokenKind K) { + return K == tok::string_literal || K == tok::wide_string_literal || + K == tok::utf8_string_literal || K == tok::utf16_string_literal || + K == tok::utf32_string_literal; +} + /// \brief Return true if this is a "literal" kind, like a numeric /// constant, string, etc. inline bool isLiteral(TokenKind K) { - return (K == tok::numeric_constant) || (K == tok::char_constant) || - (K == tok::wide_char_constant) || (K == tok::utf16_char_constant) || - (K == tok::utf32_char_constant) || (K == tok::string_literal) || - (K == tok::wide_string_literal) || (K == tok::utf8_string_literal) || - (K == tok::utf16_string_literal) || (K == tok::utf32_string_literal) || - (K == tok::angle_string_literal); + return K == tok::numeric_constant || K == tok::char_constant || + K == tok::wide_char_constant || K == tok::utf16_char_constant || + K == tok::utf32_char_constant || isStringLiteral(K) || + K == tok::angle_string_literal; } /// \brief Return true if this is any of tok::annot_* kinds. diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h index 882b52d..1645796 100644 --- a/include/clang/Basic/TypeTraits.h +++ b/include/clang/Basic/TypeTraits.h @@ -20,11 +20,14 @@ namespace clang { /// \brief Names for the unary type traits. enum UnaryTypeTrait { UTT_HasNothrowAssign, + UTT_HasNothrowMoveAssign, UTT_HasNothrowCopy, UTT_HasNothrowConstructor, UTT_HasTrivialAssign, + UTT_HasTrivialMoveAssign, UTT_HasTrivialCopy, UTT_HasTrivialDefaultConstructor, + UTT_HasTrivialMoveConstructor, UTT_HasTrivialDestructor, UTT_HasVirtualDestructor, UTT_IsAbstract, diff --git a/include/clang/Basic/Version.h b/include/clang/Basic/Version.h index 3f1b4d8..7db8a2e 100644 --- a/include/clang/Basic/Version.h +++ b/include/clang/Basic/Version.h @@ -16,9 +16,8 @@ #ifndef LLVM_CLANG_BASIC_VERSION_H #define LLVM_CLANG_BASIC_VERSION_H -#include "llvm/ADT/StringRef.h" - #include "clang/Basic/Version.inc" +#include "llvm/ADT/StringRef.h" /// \brief Helper macro for CLANG_VERSION_STRING. #define CLANG_MAKE_VERSION_STRING2(X) #X diff --git a/include/clang/Basic/VersionTuple.h b/include/clang/Basic/VersionTuple.h index a94f76c..ff06a5c 100644 --- a/include/clang/Basic/VersionTuple.h +++ b/include/clang/Basic/VersionTuple.h @@ -55,16 +55,16 @@ public: unsigned getMajor() const { return Major; } /// \brief Retrieve the minor version number, if provided. - llvm::Optional<unsigned> getMinor() const { + Optional<unsigned> getMinor() const { if (!HasMinor) - return llvm::Optional<unsigned>(); + return None; return Minor; } /// \brief Retrieve the subminor version number, if provided. - llvm::Optional<unsigned> getSubminor() const { + Optional<unsigned> getSubminor() const { if (!HasSubminor) - return llvm::Optional<unsigned>(); + return None; return Subminor; } diff --git a/include/clang/Basic/Visibility.h b/include/clang/Basic/Visibility.h index e81ad91..b623b94 100644 --- a/include/clang/Basic/Visibility.h +++ b/include/clang/Basic/Visibility.h @@ -15,6 +15,8 @@ #ifndef LLVM_CLANG_BASIC_VISIBILITY_H #define LLVM_CLANG_BASIC_VISIBILITY_H +#include "clang/Basic/Linkage.h" + namespace clang { /// \brief Describes the different kinds of visibility that a declaration @@ -46,6 +48,80 @@ inline Visibility minVisibility(Visibility L, Visibility R) { return L < R ? L : R; } +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(getLinkage() == L && getVisibility() == V && + isVisibilityExplicit() == 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 getLinkage() const { return (Linkage)linkage_; } + Visibility getVisibility() const { return (Visibility)visibility_; } + bool isVisibilityExplicit() const { return explicit_; } + + void setLinkage(Linkage L) { linkage_ = L; } + + void mergeLinkage(Linkage L) { + setLinkage(minLinkage(getLinkage(), L)); + } + void mergeLinkage(LinkageInfo other) { + mergeLinkage(other.getLinkage()); + } + + /// Merge in the visibility 'newVis'. + void mergeVisibility(Visibility newVis, bool newExplicit) { + Visibility oldVis = getVisibility(); + + // Never increase visibility. + if (oldVis < newVis) + return; + + // If the new visibility is the same as the old and the new + // visibility isn't explicit, we have nothing to add. + if (oldVis == newVis && !newExplicit) + return; + + // Otherwise, we're either decreasing visibility or making our + // existing visibility explicit. + setVisibility(newVis, newExplicit); + } + void mergeVisibility(LinkageInfo other) { + mergeVisibility(other.getVisibility(), other.isVisibilityExplicit()); + } + + /// Merge both linkage and visibility. + void merge(LinkageInfo other) { + mergeLinkage(other); + mergeVisibility(other); + } + + /// Merge linkage and conditionally merge visibility. + void mergeMaybeWithVisibility(LinkageInfo other, bool withVis) { + mergeLinkage(other); + if (withVis) mergeVisibility(other); + } +}; } #endif // LLVM_CLANG_BASIC_VISIBILITY_H diff --git a/include/clang/CodeGen/ModuleBuilder.h b/include/clang/CodeGen/ModuleBuilder.h index ba9d1f9..cda7863 100644 --- a/include/clang/CodeGen/ModuleBuilder.h +++ b/include/clang/CodeGen/ModuleBuilder.h @@ -26,6 +26,7 @@ namespace clang { class DiagnosticsEngine; class LangOptions; class CodeGenOptions; + class TargetOptions; class CodeGenerator : public ASTConsumer { virtual void anchor(); @@ -40,6 +41,7 @@ namespace clang { CodeGenerator *CreateLLVMCodeGen(DiagnosticsEngine &Diags, const std::string &ModuleName, const CodeGenOptions &CGO, + const TargetOptions &TO, llvm::LLVMContext& C); } diff --git a/include/clang/Driver/Arg.h b/include/clang/Driver/Arg.h index 3b3829a..662a2e2 100644 --- a/include/clang/Driver/Arg.h +++ b/include/clang/Driver/Arg.h @@ -15,9 +15,8 @@ #ifndef CLANG_DRIVER_ARG_H_ #define CLANG_DRIVER_ARG_H_ -#include "clang/Driver/Option.h" - #include "Util.h" +#include "clang/Driver/Option.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include <string> @@ -52,7 +51,7 @@ namespace driver { /// ArgList. unsigned Index; - /// \brief Was this argument used to effect compilation? + /// \brief Was this argument used to affect compilation? /// /// This is used for generating "argument unused" diagnostics. mutable unsigned Claimed : 1; @@ -72,7 +71,7 @@ namespace driver { const char *Value0, const char *Value1, const Arg *BaseArg = 0); ~Arg(); - const Option getOption() const { return Opt; } + Option getOption() const { return Opt; } StringRef getSpelling() const { return Spelling; } unsigned getIndex() const { return Index; } diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h index 72ed7bf..3967dcc 100644 --- a/include/clang/Driver/ArgList.h +++ b/include/clang/Driver/ArgList.h @@ -11,12 +11,11 @@ #define CLANG_DRIVER_ARGLIST_H_ #include "clang/Basic/LLVM.h" -#include "clang/Driver/Option.h" #include "clang/Driver/OptSpecifier.h" +#include "clang/Driver/Option.h" #include "clang/Driver/Util.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" - #include <list> #include <string> #include <vector> @@ -291,6 +290,8 @@ namespace driver { StringRef RHS) const; /// @} + + void dump(); }; class InputArgList : public ArgList { diff --git a/include/clang/Driver/CC1AsOptions.td b/include/clang/Driver/CC1AsOptions.td index 9fd855a..2749bcd 100644 --- a/include/clang/Driver/CC1AsOptions.td +++ b/include/clang/Driver/CC1AsOptions.td @@ -37,6 +37,8 @@ def L : Flag<["-"], "L">, HelpText<"Save temporary labels in the symbol table. " "Note this may change .s semantics, it should almost never be used " "on compiler generated code!">; +def main_file_name : Separate<["-"], "main-file-name">, + HelpText<"Main file name to use for debug info">; //===----------------------------------------------------------------------===// // Frontend Options @@ -86,5 +88,11 @@ def fatal_warnings : Flag<["--"], "fatal-warnings">, def g : Flag<["-"], "g">, HelpText<"Generate source level debug information">; +def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">, + HelpText<"The compilation directory to embed in the debug info.">; + def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">, HelpText<"The string to embed in the Dwarf debug flags record.">; + +def dwarf_debug_producer : Separate<["-"], "dwarf-debug-producer">, + HelpText<"The string to embed in the Dwarf debug AT_producer record.">; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 3ff2549..e4dd345 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -81,15 +81,6 @@ def analyzer_inline_max_stack_depth : Separate<["-"], "analyzer-inline-max-stack def analyzer_inline_max_stack_depth_EQ : Joined<["-"], "analyzer-inline-max-stack-depth=">, Alias<analyzer_inline_max_stack_depth>; -def analyzer_inline_max_function_size : Separate<["-"], "analyzer-inline-max-function-size">, - HelpText<"Bound on the number of basic blocks in an inlined function (200 by default)">; -def analyzer_inline_max_function_size_EQ : Joined<["-"], "analyzer-inline-max-function-size=">, - Alias<analyzer_inline_max_function_size>; - -def analyzer_ipa : Separate<["-"], "analyzer-ipa">, - HelpText<"Specify the inter-procedural analysis mode">; -def analyzer_ipa_EQ : Joined<["-"], "analyzer-ipa=">, Alias<analyzer_ipa>; - def analyzer_inlining_mode : Separate<["-"], "analyzer-inlining-mode">, HelpText<"Specify the function selection heuristic used during inlining">; def analyzer_inlining_mode_EQ : Joined<["-"], "analyzer-inlining-mode=">, Alias<analyzer_inlining_mode>; @@ -97,8 +88,6 @@ def analyzer_inlining_mode_EQ : Joined<["-"], "analyzer-inlining-mode=">, Alias< def analyzer_disable_retry_exhausted : Flag<["-"], "analyzer-disable-retry-exhausted">, HelpText<"Do not re-analyze paths leading to exhausted nodes with a different strategy (may decrease code coverage)">; -def analyzer_max_nodes : Separate<["-"], "analyzer-max-nodes">, - HelpText<"The maximum number of nodes the analyzer can generate (150000 default, 0 = no limit)">; def analyzer_max_loop : Separate<["-"], "analyzer-max-loop">, HelpText<"The maximum number of times the analyzer will go through a loop">; def analyzer_stats : Flag<["-"], "analyzer-stats">, @@ -145,6 +134,8 @@ def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">, HelpText<"The string to embed in the Dwarf debug flags record.">; def dwarf_column_info : Flag<["-"], "dwarf-column-info">, HelpText<"Turn on column location information.">; +def split_dwarf : Flag<["-"], "split-dwarf">, + HelpText<"Split out the dwarf .dwo sections">; def fforbid_guard_variables : Flag<["-"], "fforbid-guard-variables">, HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; def no_implicit_float : Flag<["-"], "no-implicit-float">, @@ -158,10 +149,20 @@ def femit_coverage_data: Flag<["-"], "femit-coverage-data">, def coverage_file : Separate<["-"], "coverage-file">, HelpText<"Emit coverage data to this filename. The extension will be replaced.">; def coverage_file_EQ : Joined<["-"], "coverage-file=">, Alias<coverage_file>; +def coverage_cfg_checksum : Flag<["-"], "coverage-cfg-checksum">, + HelpText<"Emit CFG checksum for functions in .gcno files.">; +def coverage_no_function_names_in_data : Flag<["-"], "coverage-no-function-names-in-data">, + HelpText<"Emit function names in .gcda files.">; +def coverage_version_EQ : Joined<["-"], "coverage-version=">, + HelpText<"Four-byte version string for gcov files.">; +def test_coverage : Flag<["-"], "test-coverage">, + HelpText<"Do not generate coverage files or remove coverage changes from IR">; def fuse_register_sized_bitfield_access: Flag<["-"], "fuse-register-sized-bitfield-access">, HelpText<"Use register sized accesses to bit-fields, when possible.">; def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">, HelpText<"Turn off Type Based Alias Analysis">; +def struct_path_tbaa : Flag<["-"], "struct-path-tbaa">, + HelpText<"Turn on struct-path aware Type Based Alias Analysis">; def masm_verbose : Flag<["-"], "masm-verbose">, HelpText<"Generate verbose assembly output">; def mcode_model : Separate<["-"], "mcode-model">, @@ -185,6 +186,8 @@ def mlimit_float_precision : Separate<["-"], "mlimit-float-precision">, HelpText<"Limit float precision to the given value">; def mno_exec_stack : Flag<["-"], "mnoexecstack">, HelpText<"Mark the file as not needing an executable stack">; +def split_stacks : Flag<["-"], "split-stacks">, + HelpText<"Try to use a split stack if possible.">; def mno_zero_initialized_in_bss : Flag<["-"], "mno-zero-initialized-in-bss">, HelpText<"Do not put zero initialized data in the BSS">; def backend_option : Separate<["-"], "backend-option">, @@ -197,8 +200,6 @@ def mrelocation_model : Separate<["-"], "mrelocation-model">, HelpText<"The relocation model to use">; def munwind_tables : Flag<["-"], "munwind-tables">, HelpText<"Generate unwinding tables for all functions">; -def fuse_init_array : Flag<["-"], "fuse-init-array">, - HelpText<"Use .init_array instead of .ctors">; def mconstructor_aliases : Flag<["-"], "mconstructor-aliases">, HelpText<"Emit complete constructors and destructors as aliases when possible">; def mlink_bitcode_file : Separate<["-"], "mlink-bitcode-file">, @@ -217,9 +218,6 @@ def header_include_file : Separate<["-"], "header-include-file">, // Diagnostic Options //===----------------------------------------------------------------------===// -def dump_build_information : Separate<["-"], "dump-build-information">, - MetaVarName<"<filename>">, - HelpText<"output a dump of some build information to a file">; def diagnostic_log_file : Separate<["-"], "diagnostic-log-file">, HelpText<"Filename (or -) to log diagnostics to">; def diagnostic_serialized_file : Separate<["-"], "serialize-diagnostic-file">, @@ -230,6 +228,8 @@ def fdiagnostics_format : Separate<["-"], "fdiagnostics-format">, HelpText<"Change diagnostic formatting to match IDE and command line tools">; def fdiagnostics_show_category : Separate<["-"], "fdiagnostics-show-category">, HelpText<"Print diagnostic category">; +def fno_diagnostics_use_presumed_location : Flag<["-"], "fno-diagnostics-use-presumed-location">, + HelpText<"Ignore #line directives when displaying diagnostic locations">; def ftabstop : Separate<["-"], "ftabstop">, MetaVarName<"<N>">, HelpText<"Set the tab stop distance.">; def ferror_limit : Separate<["-"], "ferror-limit">, MetaVarName<"<N>">, @@ -245,6 +245,9 @@ def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"<N>">, def Wno_rewrite_macros : Flag<["-"], "Wno-rewrite-macros">, HelpText<"Silence ObjC rewriting warnings">; +def fwarn_on_spellcheck : Flag<["-"], "fwarn-on-spellcheck">, + HelpText<"Emit warning if spell-check is initiated, for testing">; + //===----------------------------------------------------------------------===// // Frontend Options //===----------------------------------------------------------------------===// @@ -283,8 +286,6 @@ def plugin_arg : JoinedAndSeparate<["-"], "plugin-arg-">, HelpText<"Pass <arg> to plugin <name>">; def add_plugin : Separate<["-"], "add-plugin">, MetaVarName<"<name>">, HelpText<"Use the named plugin action in addition to the default action">; -def resource_dir : Separate<["-"], "resource-dir">, - HelpText<"The directory which holds the compiler resource files">; def version : Flag<["-"], "version">, HelpText<"Print the compiler version">; def ast_dump_filter : Separate<["-"], "ast-dump-filter">, @@ -292,6 +293,8 @@ def ast_dump_filter : Separate<["-"], "ast-dump-filter">, HelpText<"Use with -ast-dump or -ast-print to dump/print only AST declaration" " nodes having a certain substring in a qualified name. Use" " -ast-list to list all filterable declaration node names.">; +def fno_modules_global_index : Flag<["-"], "fno-modules-global-index">, + HelpText<"Do not automatically generate or update the global module index">; let Group = Action_Group in { @@ -389,6 +392,8 @@ def fhidden_weak_vtables : Flag<["-"], "fhidden-weak-vtables">, HelpText<"Generate weak vtables and RTTI with hidden visibility">; def main_file_name : Separate<["-"], "main-file-name">, HelpText<"Main file name to use for debug info">; +def split_dwarf_file : Separate<["-"], "split-dwarf-file">, + HelpText<"File name to use for split dwarf debug info output">; def fno_signed_char : Flag<["-"], "fno-signed-char">, HelpText<"Char is unsigned">; def fno_wchar : Flag<["-"], "fno-wchar">, @@ -425,11 +430,15 @@ def stack_protector : Separate<["-"], "stack-protector">, def stack_protector_buffer_size : Separate<["-"], "stack-protector-buffer-size">, HelpText<"Lower bound for a buffer to be considered for stack protection">; def fvisibility : Separate<["-"], "fvisibility">, - HelpText<"Default symbol visibility">; + HelpText<"Default type and symbol visibility">; +def ftype_visibility : Separate<["-"], "ftype-visibility">, + HelpText<"Default type visibility">; def ftemplate_depth : Separate<["-"], "ftemplate-depth">, HelpText<"Maximum depth of recursive template instantiation">; def fconstexpr_depth : Separate<["-"], "fconstexpr-depth">, HelpText<"Maximum depth of recursive constexpr function calls">; +def fbracket_depth : Separate<["-"], "fbracket-depth">, + HelpText<"Maximum nesting level for parentheses, brackets, and braces">; def fconst_strings : Flag<["-"], "fconst-strings">, HelpText<"Use a const qualified type for string literals in C and ObjC">; def fno_const_strings : Flag<["-"], "fno-const-strings">, diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h index 5f63aa7..15c5e40 100644 --- a/include/clang/Driver/Compilation.h +++ b/include/clang/Driver/Compilation.h @@ -20,6 +20,7 @@ namespace driver { class DerivedArgList; class Driver; class InputArgList; + class JobAction; class JobList; class ToolChain; @@ -54,11 +55,11 @@ class Compilation { ArgStringList TempFiles; /// Result files which should be removed on failure. - ArgStringList ResultFiles; + ArgStringMap ResultFiles; /// Result files which are generated correctly on failure, and which should /// only be removed if we crash. - ArgStringList FailureResultFiles; + ArgStringMap FailureResultFiles; /// Redirection for stdout, stderr, etc. const llvm::sys::Path **Redirects; @@ -88,9 +89,9 @@ public: const ArgStringList &getTempFiles() const { return TempFiles; } - const ArgStringList &getResultFiles() const { return ResultFiles; } + const ArgStringMap &getResultFiles() const { return ResultFiles; } - const ArgStringList &getFailureResultFiles() const { + const ArgStringMap &getFailureResultFiles() const { return FailureResultFiles; } @@ -113,24 +114,40 @@ public: /// addResultFile - Add a file to remove on failure, and returns its /// argument. - const char *addResultFile(const char *Name) { - ResultFiles.push_back(Name); + const char *addResultFile(const char *Name, const JobAction *JA) { + ResultFiles[JA] = Name; return Name; } /// addFailureResultFile - Add a file to remove if we crash, and returns its /// argument. - const char *addFailureResultFile(const char *Name) { - FailureResultFiles.push_back(Name); + const char *addFailureResultFile(const char *Name, const JobAction *JA) { + FailureResultFiles[JA] = Name; return Name; } + /// CleanupFile - Delete a given file. + /// + /// \param IssueErrors - Report failures as errors. + /// \return Whether the file was removed successfully. + bool CleanupFile(const char *File, bool IssueErrors = false) const; + /// CleanupFileList - Remove the files in the given list. /// /// \param IssueErrors - Report failures as errors. /// \return Whether all files were removed successfully. bool CleanupFileList(const ArgStringList &Files, - bool IssueErrors=false) const; + bool IssueErrors = false) const; + + /// CleanupFileMap - Remove the files in the given map. + /// + /// \param JA - If specified, only delete the files associated with this + /// JobAction. Otherwise, delete all files in the map. + /// \param IssueErrors - Report failures as errors. + /// \return Whether all files were removed successfully. + bool CleanupFileMap(const ArgStringMap &Files, + const JobAction *JA, + bool IssueErrors = false) const; /// PrintJob - Print one job in -### format. /// @@ -158,10 +175,10 @@ public: /// ExecuteJob - Execute a single job. /// - /// \param FailingCommand - For non-zero results, this will be set to the - /// Command which failed. - /// \return The accumulated result code of the job. - int ExecuteJob(const Job &J, const Command *&FailingCommand) const; + /// \param FailingCommands - For non-zero results, this will be a vector of + /// failing commands and their associated result code. + void ExecuteJob(const Job &J, + SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands) const; /// initCompilationForDiagnostics - Remove stale state and suppress output /// so compilation can be reexecuted to generate additional diagnostic diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index b752ce6..1330e95 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -11,11 +11,10 @@ #define CLANG_DRIVER_DRIVER_H_ #include "clang/Basic/Diagnostic.h" - +#include "clang/Basic/LLVM.h" #include "clang/Driver/Phases.h" #include "clang/Driver/Types.h" #include "clang/Driver/Util.h" - #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" @@ -25,9 +24,6 @@ #include <set> #include <string> -namespace llvm { - template<typename T> class ArrayRef; -} namespace clang { namespace driver { class Action; @@ -178,7 +174,6 @@ public: Driver(StringRef _ClangExecutable, StringRef _DefaultTargetTriple, StringRef _DefaultImageName, - bool IsProduction, DiagnosticsEngine &_Diags); ~Driver(); @@ -277,7 +272,7 @@ public: /// to just running the subprocesses, for example reporting errors, removing /// temporary files, etc. int ExecuteCompilation(const Compilation &C, - const Command *&FailingCommand) const; + SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands) const; /// generateCompilationDiagnostics - Generate diagnostics information /// including preprocessed source file(s). @@ -363,10 +358,9 @@ public: /// GCC goes to extra lengths here to be a bit more robust. std::string GetTemporaryPath(StringRef Prefix, const char *Suffix) const; - /// ShouldUseClangCompilar - Should the clang compiler be used to + /// ShouldUseClangCompiler - Should the clang compiler be used to /// handle this action. - bool ShouldUseClangCompiler(const Compilation &C, const JobAction &JA, - const llvm::Triple &ArchName) const; + bool ShouldUseClangCompiler(const JobAction &JA) const; bool IsUsingLTO(const ArgList &Args) const; diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h index 84f5ee1..045b5d8 100644 --- a/include/clang/Driver/Job.h +++ b/include/clang/Driver/Job.h @@ -10,9 +10,9 @@ #ifndef CLANG_DRIVER_JOB_H_ #define CLANG_DRIVER_JOB_H_ +#include "clang/Basic/LLVM.h" #include "clang/Driver/Util.h" #include "llvm/ADT/SmallVector.h" -#include "clang/Basic/LLVM.h" namespace clang { namespace driver { diff --git a/include/clang/Driver/OptSpecifier.h b/include/clang/Driver/OptSpecifier.h index bb1cd17..e683ef3 100644 --- a/include/clang/Driver/OptSpecifier.h +++ b/include/clang/Driver/OptSpecifier.h @@ -10,6 +10,8 @@ #ifndef CLANG_DRIVER_OPTSPECIFIER_H #define CLANG_DRIVER_OPTSPECIFIER_H +#include "llvm/Support/Compiler.h" + namespace clang { namespace driver { class Option; @@ -19,7 +21,7 @@ namespace driver { unsigned ID; private: - explicit OptSpecifier(bool); // DO NOT IMPLEMENT + explicit OptSpecifier(bool) LLVM_DELETED_FUNCTION; public: OptSpecifier() : ID(0) {} diff --git a/include/clang/Driver/Option.h b/include/clang/Driver/Option.h index c3db773..764934f 100644 --- a/include/clang/Driver/Option.h +++ b/include/clang/Driver/Option.h @@ -10,10 +10,10 @@ #ifndef CLANG_DRIVER_OPTION_H_ #define CLANG_DRIVER_OPTION_H_ +#include "clang/Basic/LLVM.h" #include "clang/Driver/OptTable.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" -#include "clang/Basic/LLVM.h" namespace clang { namespace driver { diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 77ba17a..112feb7 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -152,7 +152,8 @@ def E : Flag<["-"], "E">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>, HelpText<"Only run the preprocessor">; def F : JoinedOrSeparate<["-"], "F">, Flags<[RenderJoined,CC1Option]>, HelpText<"Add directory to framework include search path">; -def G : Separate<["-"], "G">, Flags<[DriverOption]>; +def G : JoinedOrSeparate<["-"], "G">, Flags<[DriverOption]>; +def G_EQ : Joined<["-"], "G=">, Flags<[DriverOption]>; def H : Flag<["-"], "H">, Flags<[CC1Option]>, HelpText<"Show header includes and nesting depth">; def I_ : Flag<["-"], "I-">, Group<I_Group>; @@ -290,6 +291,7 @@ def faccess_control : Flag<["-"], "faccess-control">, Group<f_Group>; def fallow_unsupported : Flag<["-"], "fallow-unsupported">, Group<f_Group>; def faltivec : Flag<["-"], "faltivec">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Enable AltiVec vector initializer syntax">; +def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>, Flags<[CC1Option]>; def fapple_kext : Flag<["-"], "fapple-kext">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Use Apple's kernel extensions ABI">; def fapple_pragma_pack : Flag<["-"], "fapple-pragma-pack">, Group<f_Group>, Flags<[CC1Option]>, @@ -300,7 +302,7 @@ def fthread_sanitizer : Flag<["-"], "fthread-sanitizer">, Group<f_Group>; def fno_thread_sanitizer : Flag<["-"], "fno-thread-sanitizer">, Group<f_Group>; def fasm : Flag<["-"], "fasm">, Group<f_Group>; -def fasm_blocks : Flag<["-"], "fasm-blocks">, Group<f_Group>; +def fasm_blocks : Flag<["-"], "fasm-blocks">, Group<f_Group>, Flags<[CC1Option]>; def fno_asm_blocks : Flag<["-"], "fno-asm-blocks">, Group<f_Group>; def fassume_sane_operator_new : Flag<["-"], "fassume-sane-operator-new">, Group<f_Group>; @@ -325,6 +327,9 @@ def fcatch_undefined_behavior : Flag<["-"], "fcatch-undefined-behavior">, Group< def fclasspath_EQ : Joined<["-"], "fclasspath=">, Group<f_Group>; def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Use colors in diagnostics">; +def fcomment_block_commands : CommaJoined<["-"], "fcomment-block-commands=">, Group<f_clang_Group>, Flags<[CC1Option]>, + HelpText<"Treat each comma separated argument in <arg> as a documentation comment block command">, + MetaVarName<"<arg>">; def fcommon : Flag<["-"], "fcommon">, Group<f_Group>; def fcompile_resource_EQ : Joined<["-"], "fcompile-resource=">, Group<f_Group>; def fconstant_cfstrings : Flag<["-"], "fconstant-cfstrings">, Group<f_Group>; @@ -374,6 +379,10 @@ def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group<f_Group>; def fexceptions : Flag<["-"], "fexceptions">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Enable support for exception handling">; def fextdirs_EQ : Joined<["-"], "fextdirs=">, Group<f_Group>; +def fextended_identifiers : Flag<["-"], "fextended-identifiers">, + Group<clang_ignored_f_Group>; +def fno_extended_identifiers : Flag<["-"], "fno-extended-identifiers">, + Group<f_Group>, Flags<[Unsupported]>; def fhosted : Flag<["-"], "fhosted">, Group<f_Group>; def ffast_math : Flag<["-"], "ffast-math">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Enable the *frontend*'s 'fast-math' mode. This has no effect on " @@ -383,6 +392,7 @@ def fno_fast_math : Flag<["-"], "fno-fast-math">, Group<f_Group>; def fmath_errno : Flag<["-"], "fmath-errno">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Require math functions to indicate errors by setting errno">; def fno_math_errno : Flag<["-"], "fno-math-errno">, Group<f_Group>; +def fbracket_depth_EQ : Joined<["-"], "fbracket-depth=">, Group<f_Group>; def fsignaling_math : Flag<["-"], "fsignaling-math">, Group<f_Group>; def fno_signaling_math : Flag<["-"], "fno-signaling-math">, Group<f_Group>; def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>, @@ -391,6 +401,32 @@ def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>, "address (memory errors) | thread (race detection) | " "undefined (miscellaneous undefined behavior)">; def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>; +def fsanitize_address_zero_base_shadow : Flag<["-"], "fsanitize-address-zero-base-shadow">, + Group<f_clang_Group>, Flags<[CC1Option]>, + HelpText<"Make AddressSanitizer map shadow memory" + "at zero offset">; +def fno_sanitize_address_zero_base_shadow : Flag<["-"], "fno-sanitize-address-zero-base-shadow">, + Group<f_clang_Group>; +def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">, + Group<f_clang_Group>, Flags<[CC1Option]>, + HelpText<"Path to blacklist file for sanitizers">; +def fno_sanitize_blacklist : Flag<["-"], "fno-sanitize-blacklist">, + Group<f_clang_Group>, + HelpText<"Don't use blacklist file for sanitizers">; +def fsanitize_memory_track_origins : Flag<["-"], "fsanitize-memory-track-origins">, + Group<f_clang_Group>, Flags<[CC1Option]>, + HelpText<"Enable origins tracking in MemorySanitizer">; +def fno_sanitize_memory_track_origins : Flag<["-"], "fno-sanitize-memory-track-origins">, + Group<f_clang_Group>; +def fsanitize_recover : Flag<["-"], "fsanitize-recover">, + Group<f_clang_Group>; +def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">, + Group<f_clang_Group>, Flags<[CC1Option]>, + HelpText<"Disable sanitizer check recovery">; +def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on-error">, + Group<f_clang_Group>, Flags<[CC1Option]>; +def fno_sanitize_undefined_trap_on_error : Flag<["-"], "fno-sanitize-undefined-trap-on-error">, + Group<f_clang_Group>; def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">, Group<f_Group>; def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">, @@ -453,8 +489,6 @@ def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group<f_Group>; def fmessage_length_EQ : Joined<["-"], "fmessage-length=">, Group<f_Group>; def fms_extensions : Flag<["-"], "fms-extensions">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">; -def fenable_experimental_ms_inline_asm : Flag<["-"], "fenable-experimental-ms-inline-asm">, Group<f_Group>, Flags<[CC1Option]>, - HelpText<"Enable support for Microsoft style inine assembly">; def fms_compatibility : Flag<["-"], "fms-compatibility">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Enable Microsoft compatibility mode">; def fmsc_version : Joined<["-"], "fmsc-version=">, Group<f_Group>, Flags<[CC1Option]>, @@ -462,11 +496,23 @@ def fmsc_version : Joined<["-"], "fmsc-version=">, Group<f_Group>, Flags<[CC1Opt def fdelayed_template_parsing : Flag<["-"], "fdelayed-template-parsing">, Group<f_Group>, HelpText<"Parse templated function definitions at the end of the " "translation unit ">, Flags<[CC1Option]>; -def fmodule_cache_path : Separate<["-"], "fmodule-cache-path">, Group<i_Group>, +def fmodules_cache_path : Joined<["-"], "fmodules-cache-path=">, Group<i_Group>, Flags<[NoForward,CC1Option]>, MetaVarName<"<directory>">, HelpText<"Specify the module cache path">; +def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, Group<i_Group>, + Flags<[CC1Option]>, MetaVarName<"<seconds>">, + HelpText<"Specify the interval (in seconds) between attempts to prune the module cache">; +def fmodules_prune_after : Joined<["-"], "fmodules-prune-after=">, Group<i_Group>, + Flags<[CC1Option]>, MetaVarName<"<seconds>">, + HelpText<"Specify the interval (in seconds) after which a module file will be considered unused">; def fmodules : Flag <["-"], "fmodules">, Group<f_Group>, Flags<[NoForward,CC1Option]>, HelpText<"Enable the 'modules' language feature">; +def fmodules_autolink : Flag <["-"], "fmodules-autolink">, Group<f_Group>, Flags<[NoForward,CC1Option]>, + HelpText<"Enable autolinking of the libraries for imported modules">; +def fno_modules_autolink : Flag <["-"], "fno-modules-autolink">, Group<f_Group>, + HelpText<"Disable autolinking of the libraries for imported modules">; +def fmodules_ignore_macro : Joined<["-"], "fmodules-ignore-macro=">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Ignore the definition of the given macro when building and loading modules">; def fretain_comments_from_system_headers : Flag<["-"], "fretain-comments-from-system-headers">, Group<f_Group>, Flags<[CC1Option]>; def fmudflapth : Flag<["-"], "fmudflapth">, Group<f_Group>; @@ -541,12 +587,15 @@ def fno_spell_checking : Flag<["-"], "fno-spell-checking">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Disable spell-checking">; def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group<f_Group>; def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group<f_Group>; +def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group<f_Group>; def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group<f_Group>; def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group<f_Group>; def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Do not emit code to make initialization of local statics thread safe">; def fno_use_cxa_atexit : Flag<["-"], "fno-use-cxa-atexit">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Don't use __cxa_atexit for calling destructors">; +def fno_use_init_array : Flag<["-"], "fno-use-init-array">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Don't use .init_array instead of .ctors">; def fno_unit_at_a_time : Flag<["-"], "fno-unit-at-a-time">, Group<f_Group>; def fno_unwind_tables : Flag<["-"], "fno-unwind-tables">, Group<f_Group>; def fno_verbose_asm : Flag<["-"], "fno-verbose-asm">, Group<f_Group>; @@ -590,7 +639,7 @@ def fno_objc_nonfragile_abi : Flag<["-"], "fno-objc-nonfragile-abi">, Group<f_Gr def fobjc_sender_dependent_dispatch : Flag<["-"], "fobjc-sender-dependent-dispatch">, Group<f_Group>; def fobjc : Flag<["-"], "fobjc">, Group<f_Group>; def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>; -def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>; +def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option]>; def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>; def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>; def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">; @@ -627,6 +676,7 @@ def fshow_source_location : Flag<["-"], "fshow-source-location">, Group<f_Group> def fspell_checking : Flag<["-"], "fspell-checking">, Group<f_Group>; def fsigned_bitfields : Flag<["-"], "fsigned-bitfields">, Group<f_Group>; def fsigned_char : Flag<["-"], "fsigned-char">, Group<f_Group>; +def fsplit_stack : Flag<["-"], "fsplit-stack">, Group<f_Group>; def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group<f_Group>; def fstack_protector : Flag<["-"], "fstack-protector">, Group<f_Group>; def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group<f_Group>; @@ -641,6 +691,16 @@ def ftemplate_depth_ : Joined<["-"], "ftemplate-depth-">, Group<f_Group>; def ftemplate_backtrace_limit_EQ : Joined<["-"], "ftemplate-backtrace-limit=">, Group<f_Group>; def ftest_coverage : Flag<["-"], "ftest-coverage">, Group<f_Group>; +def fvectorize : Flag<["-"], "fvectorize">, Group<f_Group>, + HelpText<"Enable the loop vectorization passes">; +def fno_vectorize : Flag<["-"], "fno-vectorize">, Group<f_Group>; +def ftree_vectorize : Flag<["-"], "ftree-vectorize">, Alias<fvectorize>; +def fno_tree_vectorize : Flag<["-"], "fno-tree-vectorize">, Alias<fno_vectorize>; +def fslp_vectorize : Flag<["-"], "fslp-vectorize">, Group<f_Group>, + HelpText<"Enable the superword-level parallelism vectorization passes">; +def fno_slp_vectorize : Flag<["-"], "fno-slp-vectorize">, Group<f_Group>; +def ftree_slp_vectorize : Flag<["-"], "ftree-slp-vectorize">, Alias<fslp_vectorize>; +def fno_tree_slp_vectorize : Flag<["-"], "fno-tree-slp-vectorize">, Alias<fno_slp_vectorize>; def Wlarge_by_value_copy_def : Flag<["-"], "Wlarge-by-value-copy">, HelpText<"Warn if a function definition returns or accepts an object larger " "in bytes than a given value">, Flags<[HelpHidden]>; @@ -672,11 +732,17 @@ def funsigned_bitfields : Flag<["-"], "funsigned-bitfields">, Group<f_Group>; def funsigned_char : Flag<["-"], "funsigned-char">, Group<f_Group>; def funwind_tables : Flag<["-"], "funwind-tables">, Group<f_Group>; def fuse_cxa_atexit : Flag<["-"], "fuse-cxa-atexit">, Group<f_Group>; +def fuse_init_array : Flag<["-"], "fuse-init-array">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Use .init_array instead of .ctors">; def fverbose_asm : Flag<["-"], "fverbose-asm">, Group<f_Group>; -def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>; +def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>, + HelpText<"Set the default symbol visibility for all global declarations">; def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group<f_Group>, HelpText<"Give inline C++ member functions default visibility by default">, Flags<[CC1Option]>; +def fvisibility_ms_compat : Flag<["-"], "fvisibility-ms-compat">, Group<f_Group>, + HelpText<"Give global types 'default' visibility and global functions and " + "variables 'hidden' visibility by default">; def fwrapv : Flag<["-"], "fwrapv">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Treat signed integer overflow as two's complement">; def fwritable_strings : Flag<["-"], "fwritable-strings">, Group<f_Group>, Flags<[CC1Option]>, @@ -716,6 +782,7 @@ def gno_record_gcc_switches : Flag<["-"], "gno-record-gcc-switches">, def gstrict_dwarf : Flag<["-"], "gstrict-dwarf">, Group<g_flags_Group>; def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group<g_flags_Group>; def gcolumn_info : Flag<["-"], "gcolumn-info">, Group<g_flags_Group>; +def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>; def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">; def help : Flag<["-", "--"], "help">, Flags<[CC1Option]>, HelpText<"Display available options">; @@ -757,6 +824,8 @@ def keep__private__externs : Flag<["-"], "keep_private_externs">; def l : JoinedOrSeparate<["-"], "l">, Flags<[LinkerInput, RenderJoined]>; def lazy__framework : Separate<["-"], "lazy_framework">, Flags<[LinkerInput]>; def lazy__library : Separate<["-"], "lazy_library">, Flags<[LinkerInput]>; +def EL : Flag<["-"], "EL">, Flags<[DriverOption]>; +def EB : Flag<["-"], "EB">, Flags<[DriverOption]>; def m32 : Flag<["-"], "m32">, Group<m_Group>, Flags<[DriverOption]>; def mqdsp6_compat : Flag<["-"], "mqdsp6-compat">, Group<m_Group>, Flags<[DriverOption,CC1Option]>, HelpText<"Enable hexagon-qdsp6 backward compatibility">; @@ -766,6 +835,15 @@ def m64 : Flag<["-"], "m64">, Group<m_Group>, Flags<[DriverOption]>; def mabi_EQ : Joined<["-"], "mabi=">, Group<m_Group>; def march_EQ : Joined<["-"], "march=">, Group<m_Group>; def maltivec : Flag<["-"], "maltivec">, Alias<faltivec>; +def mno_altivec : Flag<["-"], "mno-altivec">, Alias<fno_altivec>; +def mfprnd : Flag<["-"], "mfprnd">, Group<m_Group>; +def mno_fprnd : Flag<["-"], "mno-fprnd">, Group<m_Group>; +def mmfcrf : Flag<["-"], "mmfcrf">, Group<m_Group>; +def mno_mfcrf : Flag<["-"], "mno-mfcrf">, Group<m_Group>; +def mpopcntd : Flag<["-"], "mpopcntd">, Group<m_Group>; +def mno_popcntd : Flag<["-"], "mno-popcntd">, Group<m_Group>; +def mqpx : Flag<["-"], "mqpx">, Group<m_Group>; +def mno_qpx : Flag<["-"], "mno-qpx">, Group<m_Group>; def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>; def mconstant_cfstrings : Flag<["-"], "mconstant-cfstrings">, Group<clang_ignored_m_Group>; def mcpu_EQ : Joined<["-"], "mcpu=">, Group<m_Group>; @@ -827,6 +905,8 @@ def mno_fma : Flag<["-"], "mno-fma">, Group<m_x86_Features_Group>; def mno_xop : Flag<["-"], "mno-xop">, Group<m_x86_Features_Group>; def mno_f16c : Flag<["-"], "mno-f16c">, Group<m_x86_Features_Group>; def mno_rtm : Flag<["-"], "mno-rtm">, Group<m_x86_Features_Group>; +def mno_prfchw : Flag<["-"], "mno-prfchw">, Group<m_x86_Features_Group>; +def mno_rdseed : Flag<["-"], "mno-rdseed">, Group<m_x86_Features_Group>; def mno_thumb : Flag<["-"], "mno-thumb">, Group<m_Group>; def marm : Flag<["-"], "marm">, Alias<mno_thumb>; @@ -835,6 +915,7 @@ def mno_warn_nonportable_cfstrings : Flag<["-"], "mno-warn-nonportable-cfstrings def mno_omit_leaf_frame_pointer : Flag<["-"], "mno-omit-leaf-frame-pointer">, Group<m_Group>; def momit_leaf_frame_pointer : Flag<["-"], "momit-leaf-frame-pointer">, Group<m_Group>, HelpText<"Omit frame pointer setup for leaf functions">, Flags<[CC1Option]>; +def moslib_EQ : Joined<["-"], "moslib=">, Group<m_Group>; def mpascal_strings : Flag<["-"], "mpascal-strings">, Group<m_Group>; def mred_zone : Flag<["-"], "mred-zone">, Group<m_Group>; def mregparm_EQ : Joined<["-"], "mregparm=">, Group<m_Group>; @@ -869,8 +950,12 @@ def mfma : Flag<["-"], "mfma">, Group<m_x86_Features_Group>; def mxop : Flag<["-"], "mxop">, Group<m_x86_Features_Group>; def mf16c : Flag<["-"], "mf16c">, Group<m_x86_Features_Group>; def mrtm : Flag<["-"], "mrtm">, Group<m_x86_Features_Group>; +def mprfchw : Flag<["-"], "mprfchw">, Group<m_x86_Features_Group>; +def mrdseed : Flag<["-"], "mrdseed">, Group<m_x86_Features_Group>; def mips16 : Flag<["-"], "mips16">, Group<m_Group>; def mno_mips16 : Flag<["-"], "mno-mips16">, Group<m_Group>; +def mxgot : Flag<["-"], "mxgot">, Group<m_Group>; +def mno_xgot : Flag<["-"], "mno-xgot">, Group<m_Group>; def mdsp : Flag<["-"], "mdsp">, Group<m_Group>; def mno_dsp : Flag<["-"], "mno-dsp">, Group<m_Group>; def mdspr2 : Flag<["-"], "mdspr2">, Group<m_Group>; @@ -883,6 +968,7 @@ def mips64 : Flag<["-"], "mips64">, Group<mips_CPUs_Group>, HelpText<"Equivalent to -march=mips64">, Flags<[HelpHidden]>; def mips64r2 : Flag<["-"], "mips64r2">, Group<mips_CPUs_Group>, HelpText<"Equivalent to -march=mips64r2">, Flags<[HelpHidden]>; +def module_file_info : Flag<["-"], "module-file-info">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>; def mthumb : Flag<["-"], "mthumb">, Group<m_Group>; def mtune_EQ : Joined<["-"], "mtune=">, Group<m_Group>; def multi__module : Flag<["-"], "multi_module">; @@ -951,6 +1037,11 @@ def rewrite_objc : Flag<["-"], "rewrite-objc">, Flags<[DriverOption,CC1Option]>, def rewrite_legacy_objc : Flag<["-"], "rewrite-legacy-objc">, Flags<[DriverOption]>, HelpText<"Rewrite Legacy Objective-C source to C++">; def rdynamic : Flag<["-"], "rdynamic">; +def resource_dir : Separate<["-"], "resource-dir">, + Flags<[DriverOption, CC1Option, HelpHidden]>, + HelpText<"The directory which holds the compiler resource files">; +def resource_dir_EQ : Joined<["-"], "resource-dir=">, Flags<[DriverOption]>, + Alias<resource_dir>; def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>; def rtlib_EQ : Joined<["-", "--"], "rtlib=">; def r : Flag<["-"], "r">; @@ -1100,7 +1191,7 @@ def _output_class_directory_EQ : Joined<["--"], "output-class-directory=">, Alia def _output_class_directory : Separate<["--"], "output-class-directory">, Alias<foutput_class_dir_EQ>; def _output_EQ : Joined<["--"], "output=">, Alias<o>; def _output : Separate<["--"], "output">, Alias<o>; -def _param : Separate<["--"], "param">; +def _param : Separate<["--"], "param">, Group<CompileOnly_Group>; def _param_EQ : Joined<["--"], "param=">, Alias<_param>; def _prefix_EQ : Joined<["--"], "prefix=">, Alias<B>; def _prefix : Separate<["--"], "prefix">, Alias<B>; diff --git a/include/clang/Driver/Phases.h b/include/clang/Driver/Phases.h index a0c42ea..4e0f40c 100644 --- a/include/clang/Driver/Phases.h +++ b/include/clang/Driver/Phases.h @@ -23,6 +23,10 @@ namespace phases { Link }; + enum { + MaxNumberOfPhases = Link + 1 + }; + const char *getPhaseName(ID Id); } // end namespace phases diff --git a/include/clang/Driver/Tool.h b/include/clang/Driver/Tool.h index c62e756..4c05d0a 100644 --- a/include/clang/Driver/Tool.h +++ b/include/clang/Driver/Tool.h @@ -50,6 +50,7 @@ public: virtual bool hasIntegratedAssembler() const { return false; } virtual bool hasIntegratedCPP() const = 0; virtual bool isLinkJob() const { return false; } + virtual bool isDsymutilJob() const { return false; } /// \brief Does this tool have "good" standardized diagnostics, or should the /// driver add an additional "command failed" diagnostic on failures. diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index 509e08d..ae9e397 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -10,8 +10,10 @@ #ifndef CLANG_DRIVER_TOOLCHAIN_H_ #define CLANG_DRIVER_TOOLCHAIN_H_ -#include "clang/Driver/Util.h" +#include "clang/Driver/Action.h" #include "clang/Driver/Types.h" +#include "clang/Driver/Util.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Path.h" @@ -47,6 +49,7 @@ public: private: const Driver &D; const llvm::Triple Triple; + const ArgList &Args; /// The list of toolchain specific path prefixes to search for /// files. @@ -56,8 +59,20 @@ private: /// programs. path_list ProgramPaths; + mutable OwningPtr<Tool> Clang; + mutable OwningPtr<Tool> Assemble; + mutable OwningPtr<Tool> Link; + Tool *getClang() const; + Tool *getAssemble() const; + Tool *getLink() const; + Tool *getClangAs() const; + protected: - ToolChain(const Driver &D, const llvm::Triple &T); + ToolChain(const Driver &D, const llvm::Triple &T, const ArgList &Args); + + virtual Tool *buildAssembler() const; + virtual Tool *buildLinker() const; + virtual Tool *getTool(Action::ActionClass AC) const; /// \name Utilities for implementing subclasses. ///@{ @@ -111,10 +126,8 @@ public: return 0; } - /// SelectTool - Choose a tool to use to handle the action \p JA with the - /// given \p Inputs. - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, - const ActionList &Inputs) const = 0; + /// Choose a tool to use to handle the action \p JA. + Tool *SelectTool(const JobAction &JA) const; // Helper methods @@ -138,6 +151,9 @@ public: /// by default. virtual bool IsIntegratedAssemblerDefault() const { return false; } + /// \brief Check if the toolchain should use the integrated assembler. + bool useIntegratedAs() const; + /// IsStrictAliasingDefault - Does this tool chain use -fstrict-aliasing by /// default. virtual bool IsStrictAliasingDefault() const { return true; } @@ -147,7 +163,7 @@ public: /// IsObjCDefaultSynthPropertiesDefault - Does this tool chain enable /// -fobjc-default-synthesize-properties by default. - virtual bool IsObjCDefaultSynthPropertiesDefault() const { return false; } + virtual bool IsObjCDefaultSynthPropertiesDefault() const { return true; } /// IsEncodeExtendedBlockSignatureDefault - Does this tool chain enable /// -fencode-extended-block-signature by default. @@ -233,9 +249,9 @@ public: virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const; - // addClangTargetOptions - Add options that need to be passed to cc1 for - // this target. - virtual void addClangTargetOptions(ArgStringList &CC1Args) const; + /// \brief Add options that need to be passed to cc1 for this target. + virtual void addClangTargetOptions(const ArgList &DriverArgs, + ArgStringList &CC1Args) const; // GetRuntimeLibType - Determine the runtime library type to use with the // given compilation arguments. diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def index 318c55a..42f0709 100644 --- a/include/clang/Driver/Types.def +++ b/include/clang/Driver/Types.def @@ -30,7 +30,7 @@ // The fourth value is the suffix to use when creating temporary files // of this type, or null if unspecified. -// The fifth value is a string containt option flags. Valid values: +// The fifth value is a string containing option flags. Valid values: // a - The type should only be assembled. // p - The type should only be precompiled. // u - The type can be user specified (with -x). @@ -80,6 +80,7 @@ TYPE("lto-bc", LTO_BC, INVALID, "o", "") // Misc. TYPE("ast", AST, INVALID, "ast", "u") +TYPE("pcm", ModuleFile, INVALID, "pcm", "u") TYPE("plist", Plist, INVALID, "plist", "") TYPE("rewritten-objc", RewrittenObjC,INVALID, "cpp", "") TYPE("rewritten-legacy-objc", RewrittenLegacyObjC,INVALID, "cpp", "") diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h index d28ca88..18cd2d5 100644 --- a/include/clang/Driver/Types.h +++ b/include/clang/Driver/Types.h @@ -11,6 +11,7 @@ #define CLANG_DRIVER_TYPES_H_ #include "clang/Driver/Phases.h" +#include "llvm/ADT/SmallVector.h" namespace clang { namespace driver { @@ -73,14 +74,12 @@ namespace types { /// specified type name. ID lookupTypeForTypeSpecifier(const char *Name); - /// getNumCompilationPhases - Return the complete number of phases - /// to be done for this type. - unsigned getNumCompilationPhases(ID Id); + /// getCompilationPhases - Get the list of compilation phases ('Phases') to be + /// done for type 'Id'. + void getCompilationPhases( + ID Id, + llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> &Phases); - /// getCompilationPhase - Return the \p N th compilation phase to - /// be done for this type. - phases::ID getCompilationPhase(ID Id, unsigned N); - /// lookupCXXTypeForCType - Lookup CXX input type that corresponds to given /// C type (used for clang++ emulation of g++ behaviour) ID lookupCXXTypeForCType(ID Id); diff --git a/include/clang/Driver/Util.h b/include/clang/Driver/Util.h index 65aef4b..06b82b9 100644 --- a/include/clang/Driver/Util.h +++ b/include/clang/Driver/Util.h @@ -11,14 +11,19 @@ #define CLANG_DRIVER_UTIL_H_ #include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMap.h" namespace clang { namespace driver { class Action; + class JobAction; /// ArgStringList - Type used for constructing argv lists for subprocesses. typedef SmallVector<const char*, 16> ArgStringList; + /// ArgStringMap - Type used to map a JobAction to its result file. + typedef llvm::DenseMap<const JobAction*, const char*> ArgStringMap; + /// ActionList - Type used for lists of actions. typedef SmallVector<Action*, 3> ActionList; diff --git a/include/clang/Edit/Commit.h b/include/clang/Edit/Commit.h index aaf6b18..48e3d59 100644 --- a/include/clang/Edit/Commit.h +++ b/include/clang/Edit/Commit.h @@ -11,12 +11,12 @@ #define LLVM_CLANG_EDIT_COMMIT_H #include "clang/Edit/FileOffset.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" namespace clang { class LangOptions; - class PreprocessingRecord; + class PPConditionalDirectiveRecord; namespace edit { class EditedSource; @@ -46,7 +46,7 @@ public: private: const SourceManager &SourceMgr; const LangOptions &LangOpts; - const PreprocessingRecord *PPRec; + const PPConditionalDirectiveRecord *PPRec; EditedSource *Editor; bool IsCommitable; @@ -55,7 +55,7 @@ private: public: explicit Commit(EditedSource &Editor); Commit(const SourceManager &SM, const LangOptions &LangOpts, - const PreprocessingRecord *PPRec = 0) + const PPConditionalDirectiveRecord *PPRec = 0) : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), Editor(0), IsCommitable(true) { } diff --git a/include/clang/Edit/EditedSource.h b/include/clang/Edit/EditedSource.h index c685753..733ad40 100644 --- a/include/clang/Edit/EditedSource.h +++ b/include/clang/Edit/EditedSource.h @@ -11,14 +11,14 @@ #define LLVM_CLANG_EDIT_EDITEDSOURCE_H #include "clang/Edit/FileOffset.h" -#include "llvm/Support/Allocator.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" #include <map> namespace clang { class LangOptions; - class PreprocessingRecord; + class PPConditionalDirectiveRecord; namespace edit { class Commit; @@ -27,7 +27,7 @@ namespace edit { class EditedSource { const SourceManager &SourceMgr; const LangOptions &LangOpts; - const PreprocessingRecord *PPRec; + const PPConditionalDirectiveRecord *PPRec; struct FileEdit { StringRef Text; @@ -45,13 +45,15 @@ class EditedSource { public: EditedSource(const SourceManager &SM, const LangOptions &LangOpts, - const PreprocessingRecord *PPRec = 0) + const PPConditionalDirectiveRecord *PPRec = 0) : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), StrAlloc(/*size=*/512) { } const SourceManager &getSourceManager() const { return SourceMgr; } const LangOptions &getLangOpts() const { return LangOpts; } - const PreprocessingRecord *getPreprocessingRecord() const { return PPRec; } + const PPConditionalDirectiveRecord *getPPCondDirectiveRecord() const { + return PPRec; + } bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs); diff --git a/include/clang/Edit/Rewriters.h b/include/clang/Edit/Rewriters.h index aa7a5b2..292878e 100644 --- a/include/clang/Edit/Rewriters.h +++ b/include/clang/Edit/Rewriters.h @@ -13,6 +13,7 @@ namespace clang { class ObjCMessageExpr; class NSAPI; + class ParentMap; namespace edit { class Commit; @@ -21,7 +22,8 @@ bool rewriteObjCRedundantCallWithLiteral(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit); bool rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit); + const NSAPI &NS, Commit &commit, + const ParentMap *PMap); bool rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit); diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h new file mode 100644 index 0000000..d6cc114e --- /dev/null +++ b/include/clang/Format/Format.h @@ -0,0 +1,131 @@ +//===--- Format.h - Format C++ code -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Various functions to configurably format source code. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FORMAT_FORMAT_H +#define LLVM_CLANG_FORMAT_FORMAT_H + +#include "clang/Frontend/FrontendAction.h" +#include "clang/Tooling/Refactoring.h" + +namespace clang { + +class Lexer; +class SourceManager; +class DiagnosticConsumer; + +namespace format { + +/// \brief The \c FormatStyle is used to configure the formatting to follow +/// specific guidelines. +struct FormatStyle { + /// \brief The column limit. + unsigned ColumnLimit; + + /// \brief The penalty for each character outside of the column limit. + unsigned PenaltyExcessCharacter; + + /// \brief The maximum number of consecutive empty lines to keep. + unsigned MaxEmptyLinesToKeep; + + /// \brief Set whether & and * bind to the type as opposed to the variable. + bool PointerBindsToType; + + /// \brief If \c true, analyze the formatted file for the most common binding. + bool DerivePointerBinding; + + /// \brief The extra indent or outdent of access modifiers (e.g.: public:). + int AccessModifierOffset; + + enum LanguageStandard { + LS_Cpp03, + LS_Cpp11, + LS_Auto + }; + + /// \brief Format compatible with this standard, e.g. use \c A<A<int> > + /// instead of \c A<A<int>> for LS_Cpp03. + LanguageStandard Standard; + + /// \brief If \c true, analyze the formatted file for C++03 compatibility. + bool DeriveBackwardsCompatibility; + + /// \brief Indent case labels one level from the switch statement. + /// + /// When false, use the same indentation level as for the switch statement. + /// Switch statement body is always indented one level more than case labels. + bool IndentCaseLabels; + + /// \brief The number of spaces to before trailing line comments. + unsigned SpacesBeforeTrailingComments; + + /// \brief If false, a function call's or function definition's parameters + /// will either all be on the same line or will have one line each. + bool BinPackParameters; + + /// \brief Allow putting all parameters of a function declaration onto + /// the next line even if \c BinPackParameters is \c false. + bool AllowAllParametersOfDeclarationOnNextLine; + + /// \brief Penalty for putting the return type of a function onto its own + /// line. + unsigned PenaltyReturnTypeOnItsOwnLine; + + /// \brief If the constructor initializers don't fit on a line, put each + /// initializer on its own line. + bool ConstructorInitializerAllOnOneLineOrOnePerLine; + + /// \brief If true, "if (a) return;" can be put on a single line. + bool AllowShortIfStatementsOnASingleLine; + + /// \brief Add a space in front of an Objective-C protocol list, i.e. use + /// Foo <Protocol> instead of Foo<Protocol>. + bool ObjCSpaceBeforeProtocolList; +}; + +/// \brief Returns a format style complying with the LLVM coding standards: +/// http://llvm.org/docs/CodingStandards.html. +FormatStyle getLLVMStyle(); + +/// \brief Returns a format style complying with Google's C++ style guide: +/// http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml. +FormatStyle getGoogleStyle(); + +/// \brief Returns a format style complying with Chromium's style guide: +/// http://www.chromium.org/developers/coding-style. +FormatStyle getChromiumStyle(); + +/// \brief Reformats the given \p Ranges in the token stream coming out of +/// \c Lex. +/// +/// Each range is extended on either end to its next bigger logic unit, i.e. +/// everything that might influence its formatting or might be influenced by its +/// formatting. +/// +/// \param DiagClient A custom DiagnosticConsumer. Can be 0, in this case +/// diagnostic is output to llvm::errs(). +/// +/// Returns the \c Replacements necessary to make all \p Ranges comply with +/// \p Style. +tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex, + SourceManager &SourceMgr, + std::vector<CharSourceRange> Ranges, + DiagnosticConsumer *DiagClient = 0); + +/// \brief Returns the \c LangOpts that the formatter expects you to set. +LangOptions getFormattingLangOpts(); + +} // end namespace format +} // end namespace clang + +#endif // LLVM_CLANG_FORMAT_FORMAT_H diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 5e409bd..02c57d7 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -14,30 +14,30 @@ #ifndef LLVM_CLANG_FRONTEND_ASTUNIT_H #define LLVM_CLANG_FRONTEND_ASTUNIT_H -#include "clang/Serialization/ASTBitCodes.h" -#include "clang/Sema/Sema.h" -#include "clang/Sema/CodeCompleteConsumer.h" -#include "clang/Lex/ModuleLoader.h" -#include "clang/Lex/PreprocessingRecord.h" -#include "clang/Lex/HeaderSearchOptions.h" +#include "clang-c/Index.h" #include "clang/AST/ASTContext.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/SourceManager.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemOptions.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetOptions.h" -#include "clang-c/Index.h" +#include "clang/Lex/HeaderSearchOptions.h" +#include "clang/Lex/ModuleLoader.h" +#include "clang/Lex/PreprocessingRecord.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/Sema/Sema.h" +#include "clang/Serialization/ASTBitCodes.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Path.h" +#include <cassert> #include <map> #include <string> -#include <vector> -#include <cassert> -#include <utility> #include <sys/types.h> +#include <utility> +#include <vector> namespace llvm { class MemoryBuffer; @@ -485,6 +485,9 @@ public: StringRef getMainFileName() const; + /// \brief If this ASTUnit came from an AST file, returns the filename for it. + StringRef getASTFileName() const; + typedef std::vector<Decl *>::iterator top_level_iterator; top_level_iterator top_level_begin() { @@ -830,12 +833,19 @@ public: /// \returns True if an error occurred, false otherwise. bool serialize(raw_ostream &OS); - virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, - Module::NameVisibilityKind Visibility, - bool IsInclusionDirective) { + virtual ModuleLoadResult loadModule(SourceLocation ImportLoc, + ModuleIdPath Path, + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective) { // ASTUnit doesn't know how to load modules (not that this matters). - return 0; + return ModuleLoadResult(); } + + virtual void makeModuleVisible(Module *Mod, + Module::NameVisibilityKind Visibility, + SourceLocation ImportLoc, + bool Complain) { } + }; } // namespace clang diff --git a/include/clang/Frontend/ChainedIncludesSource.h b/include/clang/Frontend/ChainedIncludesSource.h index d7119e9..e14580e 100644 --- a/include/clang/Frontend/ChainedIncludesSource.h +++ b/include/clang/Frontend/ChainedIncludesSource.h @@ -44,8 +44,8 @@ protected: virtual uint32_t GetNumExternalSelectors(); virtual Stmt *GetExternalDeclStmt(uint64_t Offset); virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); - virtual DeclContextLookupResult - FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); + virtual bool FindExternalVisibleDeclsByName(const DeclContext *DC, + DeclarationName Name); virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, bool (*isKindWeWant)(Decl::Kind), SmallVectorImpl<Decl*> &Result); diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 558e6f1..1c0b9fa 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -30,6 +30,8 @@ CODEGENOPT(Name, Bits, Default) CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm. CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe. +CODEGENOPT(CoverageExtraChecksum, 1, 0) ///< Whether we need a second checksum for functions in GCNO files. +CODEGENOPT(CoverageNoFunctionNamesInData, 1, 0) ///< Do not include function names in GCDA files. CODEGENOPT(CUDAIsDevice , 1, 0) ///< Set when compiling for CUDA device. CODEGENOPT(CXAAtExit , 1, 1) ///< Use __cxa_atexit for calling destructors. CODEGENOPT(CXXCtorDtorAliases, 1, 0) ///< Emit complete ctors/dtors as linker @@ -40,6 +42,7 @@ CODEGENOPT(DisableLLVMOpts , 1, 0) ///< Don't run any optimizations, for use i ///< getting .bc files that correspond to the ///< internal state before optimizations are ///< done. +CODEGENOPT(DisableGCov , 1, 0) ///< Don't run the GCov pass, for testing. CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled. CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls. CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what @@ -49,6 +52,8 @@ CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what CODEGENOPT(EmitGcovArcs , 1, 0) ///< Emit coverage data files, aka. GCDA. CODEGENOPT(EmitGcovNotes , 1, 0) ///< Emit coverage "notes" files, aka GCNO. CODEGENOPT(EmitOpenCLArgMetadata , 1, 0) ///< Emit OpenCL kernel arg metadata. +/// \brief FP_CONTRACT mode (on/off/fast). +ENUM_CODEGENOPT(FPContractMode, FPContractModeKind, 2, FPC_On) CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables ///< are required. CODEGENOPT(FunctionSections , 1, 0) ///< Set when -ffunction-sections is enabled. @@ -65,6 +70,7 @@ CODEGENOPT(NoDwarf2CFIAsm , 1, 0) ///< Set when -fno-dwarf2-cfi-asm is enable CODEGENOPT(NoDwarfDirectoryAsm , 1, 0) ///< Set when -fno-dwarf-directory-asm is ///< enabled. CODEGENOPT(NoExecStack , 1, 0) ///< Set when -Wa,--noexecstack is enabled. +CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled. CODEGENOPT(NoGlobalMerge , 1, 0) ///< Set when -mno-global-merge is enabled. CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled. CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf. @@ -80,7 +86,14 @@ VALUE_CODEGENOPT(OptimizationLevel, 3, 0) ///< The -O[0-4] option specified. VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified. CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. +CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA. CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels. +CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero + ///< offset in AddressSanitizer. +CODEGENOPT(SanitizeMemoryTrackOrigins, 1, 0) ///< Enable tracking origins in + ///< MemorySanitizer +CODEGENOPT(SanitizeUndefinedTrapOnError, 1, 0) ///< Set on + /// -fsanitize-undefined-trap-on-error CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float. CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition. @@ -107,13 +120,12 @@ VALUE_CODEGENOPT(StackAlignment , 32, 0) ///< Overrides default stack CODEGENOPT(DebugColumnInfo, 1, 0) ///< Whether or not to use column information ///< in debug info. +CODEGENOPT(ModulesAutolink, 1, 0) ///< Whether to auto-link imported modules + /// The user specified number of registers to be used for integral arguments, /// or 0 if unspecified. VALUE_CODEGENOPT(NumRegisterParameters, 32, 0) -/// The run-time penalty for bounds checking, or 0 to disable. -VALUE_CODEGENOPT(BoundsChecking, 8, 0) - /// The lower bound for a buffer to be considered for stack protection. VALUE_CODEGENOPT(SSPBufferSize, 32, 0) @@ -126,6 +138,9 @@ ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NoInlining) /// The default TLS model to use. ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel) +CODEGENOPT(SanitizeRecover, 1, 1) ///< Attempt to recover from sanitizer checks + ///< by continuing execution when possible + #undef CODEGENOPT #undef ENUM_CODEGENOPT #undef VALUE_CODEGENOPT diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index 3567187..d0bbf30 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -65,6 +65,12 @@ public: LocalExecTLSModel }; + enum FPContractModeKind { + FPC_Off, // Form fused FP ops only where result will not be affected. + FPC_On, // Form fused FP ops according to FP_CONTRACT rules. + FPC_Fast // Aggressively fuse FP ops (E.g. FMA). + }; + /// The code model to use (-mcmodel). std::string CodeModel; @@ -72,6 +78,9 @@ public: /// replaced. std::string CoverageFile; + /// The version string to put into coverage files. + char CoverageVersion[4]; + /// Enable additional debugging information. std::string DebugPass; @@ -96,9 +105,16 @@ public: /// file, for example with -save-temps. std::string MainFileName; + /// The name for the split debug info file that we'll break out. This is used + /// in the backend for setting the name in the skeleton cu. + std::string SplitDwarfFile; + /// The name of the relocation model to use. std::string RelocationModel; + /// Path to blacklist file for sanitizers. + std::string SanitizerBlacklistFile; + /// If not an empty string, trap intrinsics are lowered to calls to this /// function instead of to trap instructions. std::string TrapFuncName; @@ -121,6 +137,7 @@ public: #include "clang/Frontend/CodeGenOptions.def" RelocationModel = "pic"; + memcpy(CoverageVersion, "*204", 4); } }; diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 2f3dc3f..0d67462 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -10,15 +10,15 @@ #ifndef LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ #define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ -#include "clang/Frontend/CompilerInvocation.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" +#include "clang/Frontend/CompilerInvocation.h" #include "clang/Lex/ModuleLoader.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" #include <cassert> #include <list> #include <string> @@ -94,7 +94,7 @@ class CompilerInstance : public ModuleLoader { /// \brief The semantic analysis object. OwningPtr<Sema> TheSema; - + /// \brief The frontend timer OwningPtr<llvm::Timer> FrontendTimer; @@ -111,8 +111,15 @@ class CompilerInstance : public ModuleLoader { /// \brief The result of the last module import. /// - Module *LastModuleImportResult; - + ModuleLoadResult LastModuleImportResult; + + /// \brief Whether we should (re)build the global module index once we + /// have finished with this translation unit. + bool BuildGlobalModuleIndex; + + /// \brief One or more modules failed to build. + bool ModuleBuildFailed; + /// \brief Holds information about the output file. /// /// If TempFilename is not empty we must rename it to Filename at the end. @@ -186,6 +193,15 @@ public: /// setInvocation - Replace the current invocation. void setInvocation(CompilerInvocation *Value); + /// \brief Indicates whether we should (re)build the global module index. + bool shouldBuildGlobalModuleIndex() const; + + /// \brief Set the flag indicating whether we should (re)build the global + /// module index. + void setBuildGlobalModuleIndex(bool Build) { + BuildGlobalModuleIndex = Build; + } + /// } /// @name Forwarding Methods /// { @@ -479,17 +495,12 @@ public: /// /// \param ShouldCloneClient If Client is non-NULL, specifies whether that /// client should be cloned. - void createDiagnostics(int Argc, const char* const *Argv, - DiagnosticConsumer *Client = 0, + void createDiagnostics(DiagnosticConsumer *Client = 0, bool ShouldOwnClient = true, bool ShouldCloneClient = true); /// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter. /// - /// The \p Argc and \p Argv arguments are used only for logging purposes, - /// when the diagnostic options indicate that the compiler should output - /// logging information. - /// /// If no diagnostic client is provided, this creates a /// DiagnosticConsumer that is owned by the returned diagnostic /// object, if using directly the caller is responsible for @@ -507,8 +518,7 @@ public: /// /// \return The new object on success, or null on failure. static IntrusiveRefCntPtr<DiagnosticsEngine> - createDiagnostics(DiagnosticOptions *Opts, int Argc, - const char* const *Argv, + createDiagnostics(DiagnosticOptions *Opts, DiagnosticConsumer *Client = 0, bool ShouldOwnClient = true, bool ShouldCloneClient = true, @@ -542,7 +552,8 @@ public: bool DisablePCHValidation, bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context, - void *DeserializationListener, bool Preamble); + void *DeserializationListener, bool Preamble, + bool UseGlobalModuleIndex); /// Create a code completion consumer using the invocation; note that this /// will cause the source manager to truncate the input source file at the @@ -645,9 +656,16 @@ public: /// } - virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, - Module::NameVisibilityKind Visibility, - bool IsInclusionDirective); + virtual ModuleLoadResult loadModule(SourceLocation ImportLoc, + ModuleIdPath Path, + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective); + + virtual void makeModuleVisible(Module *Mod, + Module::NameVisibilityKind Visibility, + SourceLocation ImportLoc, + bool Complain); + }; } // end namespace clang diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h index 1314956..fac05c5 100644 --- a/include/clang/Frontend/CompilerInvocation.h +++ b/include/clang/Frontend/CompilerInvocation.h @@ -10,22 +10,22 @@ #ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_ #define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_ +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/FileSystemOptions.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/TargetOptions.h" -#include "clang/Basic/FileSystemOptions.h" -#include "clang/Basic/DiagnosticOptions.h" -#include "clang/Lex/HeaderSearchOptions.h" -#include "clang/Lex/PreprocessorOptions.h" -#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" -#include "clang/Frontend/MigratorOptions.h" #include "clang/Frontend/CodeGenOptions.h" #include "clang/Frontend/DependencyOutputOptions.h" #include "clang/Frontend/FrontendOptions.h" #include "clang/Frontend/LangStandard.h" +#include "clang/Frontend/MigratorOptions.h" #include "clang/Frontend/PreprocessorOutputOptions.h" +#include "clang/Lex/HeaderSearchOptions.h" +#include "clang/Lex/PreprocessorOptions.h" +#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include <string> #include <vector> diff --git a/include/clang/Frontend/DiagnosticRenderer.h b/include/clang/Frontend/DiagnosticRenderer.h index 086bb13..f3cd054 100644 --- a/include/clang/Frontend/DiagnosticRenderer.h +++ b/include/clang/Frontend/DiagnosticRenderer.h @@ -19,6 +19,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerUnion.h" namespace clang { @@ -31,7 +32,8 @@ typedef llvm::PointerUnion<const Diagnostic *, const StoredDiagnostic *> DiagOrStoredDiag; /// \brief Class to encapsulate the logic for formatting a diagnostic message. -/// Actual "printing" logic is implemented by subclasses. +/// +/// Actual "printing" logic is implemented by subclasses. /// /// This class provides an interface for building and emitting /// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt @@ -55,7 +57,7 @@ protected: /// \brief The location of the last include whose stack was printed if known. /// - /// Same restriction as \see LastLoc essentially, but tracking include stack + /// Same restriction as LastLoc essentially, but tracking include stack /// root locations rather than diagnostic locations. SourceLocation LastIncludeLoc; @@ -92,7 +94,13 @@ protected: virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, const SourceManager &SM) = 0; - + virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, + StringRef ModuleName, + const SourceManager &SM) = 0; + virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, + StringRef ModuleName, + const SourceManager &SM) = 0; + virtual void beginDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level) {} virtual void endDiagnostic(DiagOrStoredDiag D, @@ -100,16 +108,23 @@ protected: private: - void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level, - const SourceManager &SM); + void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, const SourceManager &SM); void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM); - void emitMacroExpansionsAndCarets(SourceLocation Loc, - DiagnosticsEngine::Level Level, - SmallVectorImpl<CharSourceRange>& Ranges, - ArrayRef<FixItHint> Hints, - const SourceManager &SM, - unsigned &MacroDepth, - unsigned OnMacroInst = 0); + void emitImportStack(SourceLocation Loc, const SourceManager &SM); + void emitImportStackRecursively(SourceLocation Loc, StringRef ModuleName, + const SourceManager &SM); + void emitModuleBuildStack(const SourceManager &SM); + void emitCaret(SourceLocation Loc, DiagnosticsEngine::Level Level, + ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints, + const SourceManager &SM); + void emitMacroExpansions(SourceLocation Loc, + DiagnosticsEngine::Level Level, + ArrayRef<CharSourceRange> Ranges, + ArrayRef<FixItHint> Hints, + const SourceManager &SM, + unsigned &MacroDepth, + unsigned OnMacroInst = 0); public: /// \brief Emit a diagnostic. /// @@ -149,7 +164,15 @@ public: virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, const SourceManager &SM); - + + virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, + StringRef ModuleName, + const SourceManager &SM); + + virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, + StringRef ModuleName, + const SourceManager &SM); + virtual void emitNote(SourceLocation Loc, StringRef Message, const SourceManager *SM) = 0; }; diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h index 3283444..c67be92 100644 --- a/include/clang/Frontend/FrontendAction.h +++ b/include/clang/Frontend/FrontendAction.h @@ -6,6 +6,14 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines the clang::FrontendAction interface and various convenience +/// abstract classes (clang::ASTFrontendAction, clang::PluginASTAction, +/// clang::PreprocessorFrontendAction, and clang::WrapperFrontendAction) +/// derived from it. +/// +//===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_FRONTEND_FRONTENDACTION_H #define LLVM_CLANG_FRONTEND_FRONTENDACTION_H @@ -13,8 +21,8 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" #include "clang/Frontend/FrontendOptions.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" #include <string> #include <vector> @@ -24,8 +32,7 @@ class ASTMergeAction; class ASTUnit; class CompilerInstance; -/// FrontendAction - Abstract base class for actions which can be performed by -/// the frontend. +/// Abstract base class for actions which can be performed by the frontend. class FrontendAction { FrontendInputFile CurrentInput; OwningPtr<ASTUnit> CurrentASTUnit; @@ -41,20 +48,19 @@ protected: /// @name Implementation Action Interface /// @{ - /// CreateASTConsumer - Create the AST consumer object for this action, if - /// supported. + /// \brief Create the AST consumer object for this action, if supported. /// - /// This routine is called as part of \see BeginSourceAction(), which will + /// This routine is called as part of BeginSourceFile(), which will /// fail if the AST consumer cannot be created. This will not be called if the /// action has indicated that it only uses the preprocessor. /// - /// \param CI - The current compiler instance, provided as a convenience, \see + /// \param CI - The current compiler instance, provided as a convenience, see /// getCompilerInstance(). /// - /// \param InFile - The current input file, provided as a convenience, \see + /// \param InFile - The current input file, provided as a convenience, see /// getCurrentFile(). /// - /// \return The new AST consumer, or 0 on failure. + /// \return The new AST consumer, or null on failure. virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef InFile) = 0; @@ -62,29 +68,29 @@ protected: /// opportunity to modify the CompilerInvocation or do some other action /// before BeginSourceFileAction is called. /// - /// \return True on success; on failure \see BeginSourceFileAction() and - /// ExecutionAction() and EndSourceFileAction() will not be called. + /// \return True on success; on failure BeginSourceFileAction(), + /// ExecuteAction() and EndSourceFileAction() will not be called. virtual bool BeginInvocation(CompilerInstance &CI) { return true; } - /// BeginSourceFileAction - Callback at the start of processing a single - /// input. + /// \brief Callback at the start of processing a single input. /// - /// \return True on success; on failure \see ExecutionAction() and + /// \return True on success; on failure ExecutionAction() and /// EndSourceFileAction() will not be called. virtual bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) { return true; } - /// ExecuteAction - Callback to run the program action, using the initialized + /// \brief Callback to run the program action, using the initialized /// compiler instance. /// - /// This routine is guaranteed to only be called between \see - /// BeginSourceFileAction() and \see EndSourceFileAction(). + /// This is guaranteed to only be called between BeginSourceFileAction() + /// and EndSourceFileAction(). virtual void ExecuteAction() = 0; - /// EndSourceFileAction - Callback at the end of processing a single input; - /// this is guaranteed to only be called following a successful call to + /// \brief Callback at the end of processing a single input. + /// + /// This is guaranteed to only be called following a successful call to /// BeginSourceFileAction (and BeginSourceFile). virtual void EndSourceFileAction() {} @@ -142,34 +148,35 @@ public: /// @name Supported Modes /// @{ - /// usesPreprocessorOnly - Does this action only use the preprocessor? If so - /// no AST context will be created and this action will be invalid with AST - /// file inputs. + /// \brief Does this action only use the preprocessor? + /// + /// If so no AST context will be created and this action will be invalid + /// with AST file inputs. virtual bool usesPreprocessorOnly() const = 0; /// \brief For AST-based actions, the kind of translation unit we're handling. virtual TranslationUnitKind getTranslationUnitKind() { return TU_Complete; } - /// hasPCHSupport - Does this action support use with PCH? + /// \brief Does this action support use with PCH? virtual bool hasPCHSupport() const { return !usesPreprocessorOnly(); } - /// hasASTFileSupport - Does this action support use with AST files? + /// \brief Does this action support use with AST files? virtual bool hasASTFileSupport() const { return !usesPreprocessorOnly(); } - /// hasIRSupport - Does this action support use with IR files? + /// \brief Does this action support use with IR files? virtual bool hasIRSupport() const { return false; } - /// hasCodeCompletionSupport - Does this action support use with code - /// completion? + /// \brief Does this action support use with code completion? virtual bool hasCodeCompletionSupport() const { return false; } /// @} /// @name Public Action Interface /// @{ - /// BeginSourceFile - Prepare the action for processing the input file - /// \p Input; this is run after the options and frontend have been - /// initialized, but prior to executing any per-file processing. + /// \brief Prepare the action for processing the input file \p Input. + /// + /// This is run after the options and frontend have been initialized, + /// but prior to executing any per-file processing. /// /// \param CI - The compiler instance this action is being run from. The /// action may store and use this object up until the matching EndSourceFile @@ -180,29 +187,28 @@ public: /// several objects which would normally be owned by the /// CompilerInstance. When processing AST input files, these objects should /// generally not be initialized in the CompilerInstance -- they will - /// automatically be shared with the AST file in between \see - /// BeginSourceFile() and \see EndSourceFile(). + /// automatically be shared with the AST file in between + /// BeginSourceFile() and EndSourceFile(). /// /// \return True on success; on failure the compilation of this file should - /// be aborted and neither Execute nor EndSourceFile should be called. + /// be aborted and neither Execute() nor EndSourceFile() should be called. bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input); - /// Execute - Set the source managers main input file, and run the action. + /// \brief Set the source manager's main input file, and run the action. bool Execute(); - /// EndSourceFile - Perform any per-file post processing, deallocate per-file + /// \brief Perform any per-file post processing, deallocate per-file /// objects, and run statistics and output file cleanup code. void EndSourceFile(); /// @} }; -/// ASTFrontendAction - Abstract base class to use for AST consumer based -/// frontend actions. +/// \brief Abstract base class to use for AST consumer-based frontend actions. class ASTFrontendAction : public FrontendAction { protected: - /// ExecuteAction - Implement the ExecuteAction interface by running Sema on - /// the already initialized AST consumer. + /// \brief Implement the ExecuteAction interface by running Sema on + /// the already-initialized AST consumer. /// /// This will also take care of instantiating a code completion consumer if /// the user requested it and the action supports it. @@ -219,7 +225,7 @@ protected: StringRef InFile) = 0; public: - /// ParseArgs - Parse the given plugin command line arguments. + /// \brief Parse the given plugin command line arguments. /// /// \param CI - The compiler instance, for use in reporting diagnostics. /// \return True if the parsing succeeded; otherwise the plugin will be @@ -229,11 +235,10 @@ public: const std::vector<std::string> &arg) = 0; }; -/// PreprocessorFrontendAction - Abstract base class to use for preprocessor -/// based frontend actions. +/// \brief Abstract base class to use for preprocessor-based frontend actions. class PreprocessorFrontendAction : public FrontendAction { protected: - /// CreateASTConsumer - Provide a default implementation which returns aborts, + /// \brief Provide a default implementation which returns aborts; /// this method should never be called by FrontendAction clients. virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef InFile); @@ -242,11 +247,12 @@ public: virtual bool usesPreprocessorOnly() const { return true; } }; -/// WrapperFrontendAction - A frontend action which simply wraps some other -/// runtime specified frontend action. Deriving from this class allows an -/// action to inject custom logic around some existing action's behavior. It -/// implements every virtual method in the FrontendAction interface by -/// forwarding to the wrapped action. +/// \brief A frontend action which simply wraps some other runtime-specified +/// frontend action. +/// +/// Deriving from this class allows an action to inject custom logic around +/// some existing action's behavior. It implements every virtual method in +/// the FrontendAction interface by forwarding to the wrapped action. class WrapperFrontendAction : public FrontendAction { OwningPtr<FrontendAction> WrappedAction; diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index 477ac45..1786190 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -123,7 +123,7 @@ public: std::string &OutputFile, raw_ostream *&OS); }; - + class SyntaxOnlyAction : public ASTFrontendAction { protected: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, @@ -133,6 +133,21 @@ public: virtual bool hasCodeCompletionSupport() const { return true; } }; +/// \brief Dump information about the given module file, to be used for +/// basic debugging and discovery. +class DumpModuleInfoAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile); + virtual void ExecuteAction(); + +public: + virtual bool hasPCHSupport() const { return false; } + virtual bool hasASTFileSupport() const { return true; } + virtual bool hasIRSupport() const { return false; } + virtual bool hasCodeCompletionSupport() const { return false; } +}; + /** * \brief Frontend action adaptor that merges ASTs together. * diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index db2f5a5..234e344 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -43,6 +43,7 @@ namespace frontend { GeneratePCH, ///< Generate pre-compiled header. GeneratePTH, ///< Generate pre-tokenized header. InitOnly, ///< Only execute frontend initialization. + ModuleFileInfo, ///< Dump information about a module file. ParseSyntaxOnly, ///< Parse and perform semantic analysis. PluginAction, ///< Run a plugin action, \see ActionName. PrintDeclContext, ///< Print DeclContext and their Decls. @@ -137,6 +138,10 @@ public: /// speed up parsing in cases you do /// not need them (e.g. with code /// completion). + unsigned UseGlobalModuleIndex : 1; ///< Whether we can use the + ///< global module index if available. + unsigned GenerateGlobalModuleIndex : 1; ///< Whether we can generate the + ///< global module index if needed. CodeCompleteOptions CodeCompleteOpts; @@ -204,20 +209,16 @@ public: std::string OverrideRecordLayoutsFile; public: - FrontendOptions() { - DisableFree = 0; - ProgramAction = frontend::ParseSyntaxOnly; - ActionName = ""; - RelocatablePCH = 0; - ShowHelp = 0; - ShowStats = 0; - ShowTimers = 0; - ShowVersion = 0; - ARCMTAction = ARCMT_None; - ARCMTMigrateEmitARCErrors = 0; - SkipFunctionBodies = 0; - ObjCMTAction = ObjCMT_None; - } + FrontendOptions() : + DisableFree(false), RelocatablePCH(false), ShowHelp(false), + ShowStats(false), ShowTimers(false), ShowVersion(false), + FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false), + FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false), + SkipFunctionBodies(false), UseGlobalModuleIndex(true), + GenerateGlobalModuleIndex(true), + ARCMTAction(ARCMT_None), ObjCMTAction(ObjCMT_None), + ProgramAction(frontend::ParseSyntaxOnly) + {} /// getInputKindForExtension - Return the appropriate input kind for a file /// extension. For example, "c" would return IK_C. diff --git a/include/clang/Frontend/LangStandard.h b/include/clang/Frontend/LangStandard.h index f07cb02..1124d53 100644 --- a/include/clang/Frontend/LangStandard.h +++ b/include/clang/Frontend/LangStandard.h @@ -23,7 +23,7 @@ enum LangFeatures { C99 = (1 << 2), C11 = (1 << 3), CPlusPlus = (1 << 4), - CPlusPlus0x = (1 << 5), + CPlusPlus11 = (1 << 5), CPlusPlus1y = (1 << 6), Digraphs = (1 << 7), GNUMode = (1 << 8), @@ -69,8 +69,8 @@ public: /// isCPlusPlus - Language is a C++ variant. bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; } - /// isCPlusPlus0x - Language is a C++0x variant. - bool isCPlusPlus0x() const { return Flags & frontend::CPlusPlus0x; } + /// isCPlusPlus11 - Language is a C++0x variant. + bool isCPlusPlus11() const { return Flags & frontend::CPlusPlus11; } /// isCPlusPlus1y - Language is a C++1y variant. bool isCPlusPlus1y() const { return Flags & frontend::CPlusPlus1y; } diff --git a/include/clang/Frontend/LangStandards.def b/include/clang/Frontend/LangStandards.def index 10807b7..7b2516b 100644 --- a/include/clang/Frontend/LangStandards.def +++ b/include/clang/Frontend/LangStandards.def @@ -96,23 +96,23 @@ LANGSTANDARD(gnucxx98, "gnu++98", LANGSTANDARD(cxx0x, "c++0x", "ISO C++ 2011 with amendments", - LineComment | CPlusPlus | CPlusPlus0x | Digraphs) + LineComment | CPlusPlus | CPlusPlus11 | Digraphs) LANGSTANDARD(cxx11, "c++11", "ISO C++ 2011 with amendments", - LineComment | CPlusPlus | CPlusPlus0x | Digraphs) + LineComment | CPlusPlus | CPlusPlus11 | Digraphs) LANGSTANDARD(gnucxx0x, "gnu++0x", "ISO C++ 2011 with amendments and GNU extensions", - LineComment | CPlusPlus | CPlusPlus0x | Digraphs | GNUMode) + LineComment | CPlusPlus | CPlusPlus11 | Digraphs | GNUMode) LANGSTANDARD(gnucxx11, "gnu++11", "ISO C++ 2011 with amendments and GNU extensions", - LineComment | CPlusPlus | CPlusPlus0x | Digraphs | GNUMode) + LineComment | CPlusPlus | CPlusPlus11 | Digraphs | GNUMode) LANGSTANDARD(cxx1y, "c++1y", "Working draft for ISO C++ 2014", - LineComment | CPlusPlus | CPlusPlus0x | CPlusPlus1y | Digraphs) + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | Digraphs) LANGSTANDARD(gnucxx1y, "gnu++1y", "Working draft for ISO C++ 2014 with GNU extensions", - LineComment | CPlusPlus | CPlusPlus0x | CPlusPlus1y | Digraphs | + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | Digraphs | GNUMode) // OpenCL diff --git a/include/clang/Frontend/LayoutOverrideSource.h b/include/clang/Frontend/LayoutOverrideSource.h index 225efe6..ec34e14 100644 --- a/include/clang/Frontend/LayoutOverrideSource.h +++ b/include/clang/Frontend/LayoutOverrideSource.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_FRONTEND_LAYOUTOVERRIDESOURCE_H #include "clang/AST/ExternalASTSource.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -31,7 +32,7 @@ namespace clang { uint64_t Align; /// \brief The offsets of the fields, in source order. - llvm::SmallVector<uint64_t, 8> FieldOffsets; + SmallVector<uint64_t, 8> FieldOffsets; }; /// \brief The set of layouts that will be overridden. @@ -42,7 +43,7 @@ namespace clang { /// set of record types. /// /// The file is the result of passing -fdump-record-layouts to a file. - explicit LayoutOverrideSource(llvm::StringRef Filename); + explicit LayoutOverrideSource(StringRef Filename); /// \brief If this particular record type has an overridden layout, /// return that layout. diff --git a/include/clang/Frontend/LogDiagnosticPrinter.h b/include/clang/Frontend/LogDiagnosticPrinter.h index f4fa876..0c700a7 100644 --- a/include/clang/Frontend/LogDiagnosticPrinter.h +++ b/include/clang/Frontend/LogDiagnosticPrinter.h @@ -12,8 +12,8 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" namespace clang { class DiagnosticOptions; @@ -42,7 +42,7 @@ class LogDiagnosticPrinter : public DiagnosticConsumer { raw_ostream &OS; const LangOptions *LangOpts; - llvm::IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; SourceLocation LastWarningLoc; FullSourceLoc LastLoc; diff --git a/include/clang/Frontend/MultiplexConsumer.h b/include/clang/Frontend/MultiplexConsumer.h index 539f2c5..6ea7547 100644 --- a/include/clang/Frontend/MultiplexConsumer.h +++ b/include/clang/Frontend/MultiplexConsumer.h @@ -17,7 +17,6 @@ #include "clang/Basic/LLVM.h" #include "clang/Sema/SemaConsumer.h" -#include "clang/Basic/LLVM.h" #include "llvm/ADT/OwningPtr.h" #include <vector> diff --git a/include/clang/Frontend/PreprocessorOutputOptions.h b/include/clang/Frontend/PreprocessorOutputOptions.h index 9793aa6..e273dd6 100644 --- a/include/clang/Frontend/PreprocessorOutputOptions.h +++ b/include/clang/Frontend/PreprocessorOutputOptions.h @@ -25,7 +25,7 @@ public: public: PreprocessorOutputOptions() { - ShowCPP = 1; + ShowCPP = 0; ShowComments = 0; ShowLineMarkers = 1; ShowMacroComments = 0; diff --git a/include/clang/Frontend/SerializedDiagnosticPrinter.h b/include/clang/Frontend/SerializedDiagnosticPrinter.h index ab70afd..117771d 100644 --- a/include/clang/Frontend/SerializedDiagnosticPrinter.h +++ b/include/clang/Frontend/SerializedDiagnosticPrinter.h @@ -10,6 +10,7 @@ #ifndef LLVM_CLANG_FRONTEND_SERIALIZE_DIAGNOSTIC_PRINTER_H_ #define LLVM_CLANG_FRONTEND_SERIALIZE_DIAGNOSTIC_PRINTER_H_ +#include "clang/Basic/LLVM.h" #include "llvm/Bitcode/BitstreamWriter.h" namespace llvm { @@ -53,7 +54,7 @@ enum RecordIDs { /// This allows wrapper tools for Clang to get diagnostics from Clang /// (via libclang) without needing to parse Clang's command line output. /// -DiagnosticConsumer *create(llvm::raw_ostream *OS, +DiagnosticConsumer *create(raw_ostream *OS, DiagnosticOptions *diags); } // end serialized_diags namespace diff --git a/include/clang/Frontend/TextDiagnostic.h b/include/clang/Frontend/TextDiagnostic.h index 51f841d..656aa57 100644 --- a/include/clang/Frontend/TextDiagnostic.h +++ b/include/clang/Frontend/TextDiagnostic.h @@ -18,8 +18,6 @@ #include "clang/Frontend/DiagnosticRenderer.h" -struct SourceColumnMap; - namespace clang { /// \brief Class to encapsulate the logic for formatting and printing a textual @@ -103,6 +101,14 @@ protected: virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, const SourceManager &SM); + virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, + StringRef ModuleName, + const SourceManager &SM); + + virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, + StringRef ModuleName, + const SourceManager &SM); + private: void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level, SmallVectorImpl<CharSourceRange>& Ranges, @@ -111,16 +117,6 @@ private: void emitSnippet(StringRef SourceLine); - void highlightRange(const CharSourceRange &R, - unsigned LineNo, FileID FID, - const SourceColumnMap &map, - std::string &CaretLine, - const SourceManager &SM); - - std::string buildFixItInsertionLine(unsigned LineNo, - const SourceColumnMap &map, - ArrayRef<FixItHint> Hints, - const SourceManager &SM); void emitParseableFixits(ArrayRef<FixItHint> Hints, const SourceManager &SM); }; diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h index 91ac3c8..470438e 100644 --- a/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/include/clang/Frontend/TextDiagnosticPrinter.h @@ -17,8 +17,8 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LLVM.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/OwningPtr.h" namespace clang { class DiagnosticOptions; @@ -27,7 +27,7 @@ class TextDiagnostic; class TextDiagnosticPrinter : public DiagnosticConsumer { raw_ostream &OS; - llvm::IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; /// \brief Handle to the currently active text diagnostic emitter. OwningPtr<TextDiagnostic> TextDiag; diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h index 6b1fc63..8830dce 100644 --- a/include/clang/Frontend/Utils.h +++ b/include/clang/Frontend/Utils.h @@ -60,7 +60,8 @@ void InitializePreprocessor(Preprocessor &PP, /// ProcessWarningOptions - Initialize the diagnostic client and process the /// warning options specified on the command line. void ProcessWarningOptions(DiagnosticsEngine &Diags, - const DiagnosticOptions &Opts); + const DiagnosticOptions &Opts, + bool ReportDiags = true); /// DoPrintPreprocessedInput - Implement -E mode. void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream* OS, diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h index d773fc6..261dfab 100644 --- a/include/clang/Lex/DirectoryLookup.h +++ b/include/clang/Lex/DirectoryLookup.h @@ -50,34 +50,34 @@ private: /// SrcMgr::CharacteristicKind. unsigned DirCharacteristic : 2; - /// UserSupplied - True if this is a user-supplied directory. - /// - bool UserSupplied : 1; - /// LookupType - This indicates whether this DirectoryLookup object is a /// normal directory, a framework, or a headermap. unsigned LookupType : 2; /// \brief Whether this is a header map used when building a framework. unsigned IsIndexHeaderMap : 1; + + /// \brief Whether we've performed an exhaustive search for module maps + /// within the subdirectories of this directory. + unsigned SearchedAllModuleMaps : 1; public: /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of /// 'dir'. DirectoryLookup(const DirectoryEntry *dir, SrcMgr::CharacteristicKind DT, - bool isUser, bool isFramework) - : DirCharacteristic(DT), UserSupplied(isUser), + bool isFramework) + : DirCharacteristic(DT), LookupType(isFramework ? LT_Framework : LT_NormalDir), - IsIndexHeaderMap(false) { + IsIndexHeaderMap(false), SearchedAllModuleMaps(false) { u.Dir = dir; } /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of /// 'map'. DirectoryLookup(const HeaderMap *map, SrcMgr::CharacteristicKind DT, - bool isUser, bool isIndexHeaderMap) - : DirCharacteristic(DT), UserSupplied(isUser), LookupType(LT_HeaderMap), - IsIndexHeaderMap(isIndexHeaderMap) { + bool isIndexHeaderMap) + : DirCharacteristic(DT), LookupType(LT_HeaderMap), + IsIndexHeaderMap(isIndexHeaderMap), SearchedAllModuleMaps(false) { u.Map = map; } @@ -113,16 +113,22 @@ public: /// isHeaderMap - Return true if this is a header map, not a normal directory. bool isHeaderMap() const { return getLookupType() == LT_HeaderMap; } + /// \brief Determine whether we have already searched this entire + /// directory for module maps. + bool haveSearchedAllModuleMaps() const { return SearchedAllModuleMaps; } + + /// \brief Specify whether we have already searched all of the subdirectories + /// for module maps. + void setSearchedAllModuleMaps(bool SAMM) { + SearchedAllModuleMaps = SAMM; + } + /// DirCharacteristic - The type of directory this is, one of the DirType enum /// values. SrcMgr::CharacteristicKind getDirCharacteristic() const { return (SrcMgr::CharacteristicKind)DirCharacteristic; } - /// isUserSupplied - True if this is a user-supplied directory. - /// - bool isUserSupplied() const { return UserSupplied; } - /// \brief Whether this header map is building a framework or not. bool isIndexHeaderMap() const { return isHeaderMap() && IsIndexHeaderMap; diff --git a/include/clang/Lex/ExternalPreprocessorSource.h b/include/clang/Lex/ExternalPreprocessorSource.h index d2e2412..d9a4de4 100644 --- a/include/clang/Lex/ExternalPreprocessorSource.h +++ b/include/clang/Lex/ExternalPreprocessorSource.h @@ -15,7 +15,9 @@ #define LLVM_CLANG_LEX_EXTERNAL_PREPROCESSOR_SOURCE_H namespace clang { - + +class IdentifierInfo; + /// \brief Abstract interface for external sources of preprocessor /// information. /// diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 4334db7..8a5a798 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -18,10 +18,10 @@ #include "clang/Lex/ModuleMap.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Allocator.h" -#include "llvm/ADT/OwningPtr.h" #include <vector> namespace clang { @@ -50,6 +50,9 @@ struct HeaderFileInfo { /// \brief Whether this header file info was supplied by an external source. unsigned External : 1; + + /// \brief Whether this header is part of a module. + unsigned isModuleHeader : 1; /// \brief Whether this structure is considered to already have been /// "resolved", meaning that it was loaded from the external source. @@ -90,7 +93,8 @@ struct HeaderFileInfo { HeaderFileInfo() : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User), - External(false), Resolved(false), IndexHeaderMapHeader(false), + External(false), isModuleHeader(false), Resolved(false), + IndexHeaderMapHeader(false), NumIncludes(0), ControllingMacroID(0), ControllingMacro(0) {} /// \brief Retrieve the controlling macro for this header file, if @@ -134,7 +138,7 @@ class HeaderSearch { }; /// \brief Header-search options used to initialize this header search. - llvm::IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts; + IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts; FileManager &FileMgr; /// \#include search path information. Requests for \#include "x" search the @@ -189,7 +193,7 @@ class HeaderSearch { std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps; /// \brief The mapping between modules and headers. - ModuleMap ModMap; + mutable ModuleMap ModMap; /// \brief Describes whether a given directory has a module map in it. llvm::DenseMap<const DirectoryEntry *, bool> DirectoryHasModuleMap; @@ -217,7 +221,7 @@ class HeaderSearch { friend class DirectoryLookup; public: - HeaderSearch(llvm::IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts, + HeaderSearch(IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts, FileManager &FM, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const TargetInfo *Target); ~HeaderSearch(); @@ -363,7 +367,8 @@ public: StringRef Filename, const FileEntry *RelativeFileEnt, SmallVectorImpl<char> *SearchPath, - SmallVectorImpl<char> *RelativePath); + SmallVectorImpl<char> *RelativePath, + Module **SuggestedModule); /// \brief Look up the specified framework name in our framework cache. /// \returns The DirectoryEntry it is in if we know, null otherwise. @@ -399,6 +404,9 @@ public: getFileInfo(File).DirInfo = SrcMgr::C_System; } + /// \brief Mark the specified file as part of a module. + void MarkFileModuleHeader(const FileEntry *File); + /// \brief Increment the count for the number of times the specified /// FileEntry has been entered. void IncrementIncludeCount(const FileEntry *File) { @@ -468,7 +476,7 @@ public: /// \brief Retrieve the module that corresponds to the given file, if any. /// /// \param File The header that we wish to map to a module. - Module *findModuleForHeader(const FileEntry *File); + Module *findModuleForHeader(const FileEntry *File) const; /// \brief Read the contents of the given module map file. /// @@ -480,7 +488,7 @@ public: /// \brief Collect the set of all known, top-level modules. /// /// \param Modules Will be filled with the set of known, top-level modules. - void collectAllModules(llvm::SmallVectorImpl<Module *> &Modules); + void collectAllModules(SmallVectorImpl<Module *> &Modules); private: /// \brief Retrieve a module with the given name, which may be part of the @@ -497,7 +505,11 @@ private: Module *loadFrameworkModule(StringRef Name, const DirectoryEntry *Dir, bool IsSystem); - + + /// \brief Load all of the module maps within the immediate subdirectories + /// of the given search directory. + void loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir); + public: /// \brief Retrieve the module map. ModuleMap &getModuleMap() { return ModMap; } diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h index 468fefa..afce5ba 100644 --- a/include/clang/Lex/HeaderSearchOptions.h +++ b/include/clang/Lex/HeaderSearchOptions.h @@ -10,8 +10,11 @@ #ifndef LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H #define LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H +#include "clang/Basic/LLVM.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringRef.h" +#include <string> #include <vector> namespace clang { @@ -27,6 +30,8 @@ namespace frontend { IndexHeaderMap, ///< Like Angled, but marks header maps used when /// building frameworks. System, ///< Like Angled, but marks system directories. + ExternCSystem, ///< Like System, but headers are implicitly wrapped in + /// extern "C". CSystem, ///< Like System, but only used for C. CXXSystem, ///< Like System, but only used for C++. ObjCSystem, ///< Like System, but only used for ObjC. @@ -37,12 +42,11 @@ namespace frontend { /// HeaderSearchOptions - Helper class for storing options related to the /// initialization of the HeaderSearch object. -class HeaderSearchOptions : public llvm::RefCountedBase<HeaderSearchOptions> { +class HeaderSearchOptions : public RefCountedBase<HeaderSearchOptions> { public: struct Entry { std::string Path; frontend::IncludeDirGroup Group; - unsigned IsUserSupplied : 1; unsigned IsFramework : 1; /// IgnoreSysRoot - This is false if an absolute path should be treated @@ -50,24 +54,10 @@ public: /// path. unsigned IgnoreSysRoot : 1; - /// \brief True if this entry is an internal search path. - /// - /// This typically indicates that users didn't directly provide it, but - /// instead it was provided by a compatibility layer for a particular - /// system. This isn't redundant with IsUserSupplied (even though perhaps - /// it should be) because that is false for user provided '-iwithprefix' - /// header search entries. - unsigned IsInternal : 1; - - /// \brief True if this entry's headers should be wrapped in extern "C". - unsigned ImplicitExternC : 1; - - Entry(StringRef path, frontend::IncludeDirGroup group, - bool isUserSupplied, bool isFramework, bool ignoreSysRoot, - bool isInternal, bool implicitExternC) - : Path(path), Group(group), IsUserSupplied(isUserSupplied), - IsFramework(isFramework), IgnoreSysRoot(ignoreSysRoot), - IsInternal(isInternal), ImplicitExternC(implicitExternC) {} + Entry(StringRef path, frontend::IncludeDirGroup group, bool isFramework, + bool ignoreSysRoot) + : Path(path), Group(group), IsFramework(isFramework), + IgnoreSysRoot(ignoreSysRoot) {} }; struct SystemHeaderPrefix { @@ -98,13 +88,35 @@ public: /// \brief The directory used for the module cache. std::string ModuleCachePath; - + /// \brief Whether we should disable the use of the hash string within the /// module cache. /// /// Note: Only used for testing! unsigned DisableModuleHash : 1; - + + /// \brief The interval (in seconds) between pruning operations. + /// + /// This operation is expensive, because it requires Clang to walk through + /// the directory structure of the module cache, stat()'ing and removing + /// files. + /// + /// The default value is large, e.g., the operation runs once a week. + unsigned ModuleCachePruneInterval; + + /// \brief The time (in seconds) after which an unused module file will be + /// considered unused and will, therefore, be pruned. + /// + /// When the module cache is pruned, any module file that has not been + /// accessed in this many seconds will be removed. The default value is + /// large, e.g., a month, to avoid forcing infrequently-used modules to be + /// regenerated often. + unsigned ModuleCachePruneAfter; + + /// \brief The set of macro names that should be ignored for the purposes + /// of computing the module hash. + llvm::SetVector<std::string> ModulesIgnoreMacros; + /// Include the compiler builtin includes. unsigned UseBuiltinIncludes : 1; @@ -122,16 +134,17 @@ public: public: HeaderSearchOptions(StringRef _Sysroot = "/") - : Sysroot(_Sysroot), DisableModuleHash(0), UseBuiltinIncludes(true), + : Sysroot(_Sysroot), DisableModuleHash(0), + ModuleCachePruneInterval(7*24*60*60), + ModuleCachePruneAfter(31*24*60*60), + UseBuiltinIncludes(true), UseStandardSystemIncludes(true), UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false) {} /// AddPath - Add the \p Path path to the specified \p Group list. void AddPath(StringRef Path, frontend::IncludeDirGroup Group, - bool IsUserSupplied, bool IsFramework, bool IgnoreSysRoot, - bool IsInternal = false, bool ImplicitExternC = false) { - UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework, - IgnoreSysRoot, IsInternal, ImplicitExternC)); + bool IsFramework, bool IgnoreSysRoot) { + UserEntries.push_back(Entry(Path, Group, IsFramework, IgnoreSysRoot)); } /// AddSystemHeaderPrefix - Override whether \#include directives naming a diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index 407b644..cb4f57f 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -14,11 +14,11 @@ #ifndef LLVM_CLANG_LEXER_H #define LLVM_CLANG_LEXER_H -#include "clang/Lex/PreprocessorLexer.h" #include "clang/Basic/LangOptions.h" +#include "clang/Lex/PreprocessorLexer.h" #include "llvm/ADT/SmallVector.h" -#include <string> #include <cassert> +#include <string> namespace clang { class DiagnosticsEngine; @@ -174,8 +174,8 @@ public: /// SetKeepWhitespaceMode - This method lets clients enable or disable /// whitespace retention mode. void SetKeepWhitespaceMode(bool Val) { - assert((!Val || LexingRawMode) && - "Can only enable whitespace retention in raw mode"); + assert((!Val || LexingRawMode || LangOpts.TraditionalCPP) && + "Can only retain whitespace in raw mode or -traditional-cpp"); ExtendedTokenMode = Val ? 2 : 0; } @@ -194,6 +194,14 @@ public: ExtendedTokenMode = Mode ? 1 : 0; } + /// Sets the extended token mode back to its initial value, according to the + /// language options and preprocessor. This controls whether the lexer + /// produces comment and whitespace tokens. + /// + /// This requires the lexer to have an associated preprocessor. A standalone + /// lexer has nothing to reset to. + void resetExtendedTokenMode(); + const char *getBufferStart() const { return BufferStart; } /// ReadToEndOfLine - Read the rest of the current preprocessor line as an @@ -260,10 +268,10 @@ public: /// location and does not jump to the expansion or spelling /// location. static StringRef getSpelling(SourceLocation loc, - SmallVectorImpl<char> &buffer, - const SourceManager &SourceMgr, - const LangOptions &LangOpts, - bool *invalid = 0); + SmallVectorImpl<char> &buffer, + const SourceManager &SourceMgr, + const LangOptions &LangOpts, + bool *invalid = 0); /// MeasureTokenLength - Relex the token at the specified location and return /// its length in bytes in the input file. If the token needs cleaning (e.g. @@ -273,6 +281,12 @@ public: const SourceManager &SM, const LangOptions &LangOpts); + /// \brief Relex the token at the specified location. + /// \returns true if there was a failure, false on success. + static bool getRawToken(SourceLocation Loc, Token &Result, + const SourceManager &SM, + const LangOptions &LangOpts); + /// \brief Given a location any where in a source buffer, find the location /// that corresponds to the beginning of the token in which the original /// source location lands. @@ -431,6 +445,11 @@ private: /// void LexTokenInternal(Token &Result); + /// Given that a token begins with the Unicode character \p C, figure out + /// what kind of token it is and dispatch to the appropriate lexing helper + /// function. + void LexUnicode(Token &Result, uint32_t C, const char *CurPtr); + /// FormTokenWithChars - When we lex a token, we have identified a span /// starting at BufferPtr, going to TokEnd that forms the token. This method /// takes that range and assigns it to the token as its location and size. In @@ -573,6 +592,21 @@ private: void cutOffLexing() { BufferPtr = BufferEnd; } bool isHexaLiteral(const char *Start, const LangOptions &LangOpts); + + + /// Read a universal character name. + /// + /// \param CurPtr The position in the source buffer after the initial '\'. + /// If the UCN is syntactically well-formed (but not necessarily + /// valid), this parameter will be updated to point to the + /// character after the UCN. + /// \param SlashLoc The position in the source buffer of the '\'. + /// \param Tok The token being formed. Pass \c NULL to suppress diagnostics + /// and handle token formation in the caller. + /// + /// \return The Unicode codepoint specified by the UCN, or 0 if the UCN is + /// invalid. + uint32_t tryReadUCN(const char *&CurPtr, const char *SlashLoc, Token *Tok); }; diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index 3b68d1b..b1430cc 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -15,13 +15,13 @@ #ifndef CLANG_LITERALSUPPORT_H #define CLANG_LITERALSUPPORT_H +#include "clang/Basic/CharInfo.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/TokenKinds.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" -#include "clang/Basic/TokenKinds.h" -#include <cctype> namespace clang { @@ -101,7 +101,7 @@ private: /// SkipHexDigits - Read and skip over any hex digits, up to End. /// Return a pointer to the first non-hex digit or End. const char *SkipHexDigits(const char *ptr) { - while (ptr != ThisTokEnd && isxdigit(*ptr)) + while (ptr != ThisTokEnd && isHexDigit(*ptr)) ptr++; return ptr; } @@ -117,7 +117,7 @@ private: /// SkipDigits - Read and skip over any digits, up to End. /// Return a pointer to the first non-hex digit or End. const char *SkipDigits(const char *ptr) { - while (ptr != ThisTokEnd && isdigit(*ptr)) + while (ptr != ThisTokEnd && isDigit(*ptr)) ptr++; return ptr; } diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index aba77d5..64323b7 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the MacroInfo interface. -// +/// +/// \file +/// \brief Defines the clang::MacroInfo and clang::MacroDirective classes. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_MACROINFO_H @@ -22,34 +23,28 @@ namespace clang { class Preprocessor; -/// MacroInfo - Each identifier that is \#define'd has an instance of this class -/// associated with it, used to implement macro expansion. +/// \brief Encapsulates the data about a macro definition (e.g. its tokens). +/// +/// There's an instance of this class for every #define. class MacroInfo { //===--------------------------------------------------------------------===// // State set when the macro is defined. - /// Location - This is the place the macro is defined. + /// \brief The location the macro is defined. SourceLocation Location; - /// EndLocation - The location of the last token in the macro. + /// \brief The location of the last token in the macro. SourceLocation EndLocation; - /// \brief The location where the macro was #undef'd, or an invalid location - /// for macros that haven't been undefined. - SourceLocation UndefLocation; - /// \brief Previous definition, the identifier of this macro was defined to, - /// or NULL. - MacroInfo *PreviousDefinition; - /// Arguments - The list of arguments for a function-like macro. This can be - /// empty, for, e.g. "#define X()". In a C99-style variadic macro, this + /// \brief The list of arguments for a function-like macro. + /// + /// ArgumentList points to the first of NumArguments pointers. + /// + /// This can be empty, for, e.g. "#define X()". In a C99-style variadic macro, this /// includes the \c __VA_ARGS__ identifier on the list. IdentifierInfo **ArgumentList; - unsigned NumArguments; - /// \brief The location at which this macro was either explicitly exported - /// from its module or marked as private. - /// - /// If invalid, this macro has not been explicitly given any visibility. - SourceLocation VisibilityLocation; + /// \see ArgumentList + unsigned NumArguments; /// \brief This is the list of tokens that the macro is defined to. SmallVector<Token, 8> ReplacementTokens; @@ -58,119 +53,88 @@ class MacroInfo { mutable unsigned DefinitionLength; mutable bool IsDefinitionLengthCached : 1; - /// \brief True if this macro is a function-like macro, false if it - /// is an object-like macro. + /// \brief True if this macro is function-like, false if it is object-like. bool IsFunctionLike : 1; - /// IsC99Varargs - True if this macro is of the form "#define X(...)" or - /// "#define X(Y,Z,...)". The __VA_ARGS__ token should be replaced with the - /// contents of "..." in an invocation. + /// \brief True if this macro is of the form "#define X(...)" or + /// "#define X(Y,Z,...)". + /// + /// The __VA_ARGS__ token should be replaced with the contents of "..." in an + /// invocation. bool IsC99Varargs : 1; - /// IsGNUVarargs - True if this macro is of the form "#define X(a...)". The - /// "a" identifier in the replacement list will be replaced with all arguments + /// \brief True if this macro is of the form "#define X(a...)". + /// + /// The "a" identifier in the replacement list will be replaced with all arguments /// of the macro starting with the specified one. bool IsGNUVarargs : 1; - /// IsBuiltinMacro - True if this is a builtin macro, such as __LINE__, and if - /// it has not yet been redefined or undefined. + /// \brief True if this macro requires processing before expansion. + /// + /// This is the case for builtin macros such as __LINE__, so long as they have + /// not been redefined, but not for regular predefined macros from the "<built-in>" + /// memory buffer (see Preprocessing::getPredefinesFileID). bool IsBuiltinMacro : 1; - /// \brief True if this macro was loaded from an AST file. - bool IsFromAST : 1; - - /// \brief Whether this macro changed after it was loaded from an AST file. - bool ChangedAfterLoad : 1; + /// \brief Whether this macro contains the sequence ", ## __VA_ARGS__" + bool HasCommaPasting : 1; private: //===--------------------------------------------------------------------===// // State that changes as the macro is used. - /// IsDisabled - True if we have started an expansion of this macro already. + /// \brief True if we have started an expansion of this macro already. + /// /// This disables recursive expansion, which would be quite bad for things /// like \#define A A. bool IsDisabled : 1; - /// IsUsed - True if this macro is either defined in the main file and has - /// been used, or if it is not defined in the main file. This is used to - /// emit -Wunused-macros diagnostics. + /// \brief True if this macro is either defined in the main file and has + /// been used, or if it is not defined in the main file. + /// + /// This is used to emit -Wunused-macros diagnostics. bool IsUsed : 1; - /// AllowRedefinitionsWithoutWarning - True if this macro can be redefined - /// without emitting a warning. + /// \brief True if this macro can be redefined without emitting a warning. bool IsAllowRedefinitionsWithoutWarning : 1; /// \brief Must warn if the macro is unused at the end of translation unit. bool IsWarnIfUnused : 1; - - /// \brief Whether the macro has public (when described in a module). - bool IsPublic : 1; - /// \brief Whether the macro definition is currently "hidden". - /// Note that this is transient state that is never serialized to the AST - /// file. - bool IsHidden : 1; + /// \brief Whether this macro info was loaded from an AST file. + unsigned FromASTFile : 1; - /// \brief Whether the definition of this macro is ambiguous, due to - /// multiple definitions coming in from multiple modules. - bool IsAmbiguous : 1; - - ~MacroInfo() { + ~MacroInfo() { assert(ArgumentList == 0 && "Didn't call destroy before dtor!"); } public: MacroInfo(SourceLocation DefLoc); - MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator); - /// FreeArgumentList - Free the argument list of the macro, restoring it to a - /// state where it can be reused for other devious purposes. + /// \brief Free the argument list of the macro. + /// + /// This restores this MacroInfo to a state where it can be reused for other + /// devious purposes. void FreeArgumentList() { ArgumentList = 0; NumArguments = 0; } - /// Destroy - destroy this MacroInfo object. + /// \brief Destroy this MacroInfo object. void Destroy() { FreeArgumentList(); this->~MacroInfo(); } - /// getDefinitionLoc - Return the location that the macro was defined at. - /// + /// \brief Return the location that the macro was defined at. SourceLocation getDefinitionLoc() const { return Location; } - /// setDefinitionEndLoc - Set the location of the last token in the macro. - /// + /// \brief Set the location of the last token in the macro. void setDefinitionEndLoc(SourceLocation EndLoc) { EndLocation = EndLoc; } - /// getDefinitionEndLoc - Return the location of the last token in the macro. - /// + /// \brief Return the location of the last token in the macro. SourceLocation getDefinitionEndLoc() const { return EndLocation; } - /// \brief Set the location where macro was undefined. Can only be set once. - void setUndefLoc(SourceLocation UndefLoc) { - assert(UndefLocation.isInvalid() && "UndefLocation is already set!"); - assert(UndefLoc.isValid() && "Invalid UndefLoc!"); - UndefLocation = UndefLoc; - } - - /// \brief Get the location where macro was undefined. - SourceLocation getUndefLoc() const { return UndefLocation; } - - /// \brief Set previous definition of the macro with the same name. - void setPreviousDefinition(MacroInfo *PreviousDef) { - PreviousDefinition = PreviousDef; - } - - /// \brief Get previous definition of the macro with the same name. - MacroInfo *getPreviousDefinition() { return PreviousDefinition; } - - /// \brief Find macro definition active in the specified source location. If - /// this macro was not defined there, return NULL. - const MacroInfo *findDefinitionAtLoc(SourceLocation L, - SourceManager &SM) const; - /// \brief Get length in characters of the macro definition. unsigned getDefinitionLength(SourceManager &SM) const { if (IsDefinitionLengthCached) @@ -178,25 +142,27 @@ public: return getDefinitionLengthSlow(SM); } - /// isIdenticalTo - Return true if the specified macro definition is equal to - /// this macro in spelling, arguments, and whitespace. This is used to emit - /// duplicate definition warnings. This implements the rules in C99 6.10.3. - bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const; - - /// setIsBuiltinMacro - Set or clear the isBuiltinMacro flag. + /// \brief Return true if the specified macro definition is equal to + /// this macro in spelling, arguments, and whitespace. /// + /// \param Syntactically if true, the macro definitions can be identical even + /// if they use different identifiers for the function macro parameters. + /// Otherwise the comparison is lexical and this implements the rules in + /// C99 6.10.3. + bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP, + bool Syntactically) const; + + /// \brief Set or clear the isBuiltinMacro flag. void setIsBuiltinMacro(bool Val = true) { IsBuiltinMacro = Val; } - /// setIsUsed - Set the value of the IsUsed flag. - /// + /// \brief Set the value of the IsUsed flag. void setIsUsed(bool Val) { IsUsed = Val; } - /// setIsAllowRedefinitionsWithoutWarning - Set the value of the - /// IsAllowRedefinitionsWithoutWarning flag. + /// \brief Set the value of the IsAllowRedefinitionsWithoutWarning flag. void setIsAllowRedefinitionsWithoutWarning(bool Val) { IsAllowRedefinitionsWithoutWarning = Val; } @@ -206,8 +172,8 @@ public: IsWarnIfUnused = val; } - /// setArgumentList - Set the specified list of identifiers as the argument - /// list for this macro. + /// \brief Set the specified list of identifiers as the argument list for + /// this macro. void setArgumentList(IdentifierInfo* const *List, unsigned NumArgs, llvm::BumpPtrAllocator &PPAllocator) { assert(ArgumentList == 0 && NumArguments == 0 && @@ -228,7 +194,7 @@ public: arg_iterator arg_end() const { return ArgumentList+NumArguments; } unsigned getNumArgs() const { return NumArguments; } - /// getArgumentNum - Return the argument number of the specified identifier, + /// \brief Return the argument number of the specified identifier, /// or -1 if the identifier is not a formal argument identifier. int getArgumentNum(IdentifierInfo *Arg) const { for (arg_iterator I = arg_begin(), E = arg_end(); I != E; ++I) @@ -249,30 +215,22 @@ public: bool isGNUVarargs() const { return IsGNUVarargs; } bool isVariadic() const { return IsC99Varargs | IsGNUVarargs; } - /// isBuiltinMacro - Return true if this macro is a builtin macro, such as - /// __LINE__, which requires processing before expansion. + /// \brief Return true if this macro requires processing before expansion. + /// + /// This is true only for builtin macro, such as \__LINE__, whose values + /// are not given by fixed textual expansions. Regular predefined macros + /// from the "<built-in>" buffer are not reported as builtins by this + /// function. bool isBuiltinMacro() const { return IsBuiltinMacro; } - /// isFromAST - Return true if this macro was loaded from an AST file. - bool isFromAST() const { return IsFromAST; } - - /// setIsFromAST - Set whether this macro was loaded from an AST file. - void setIsFromAST(bool FromAST = true) { IsFromAST = FromAST; } + bool hasCommaPasting() const { return HasCommaPasting; } + void setHasCommaPasting() { HasCommaPasting = true; } - /// \brief Determine whether this macro has changed since it was loaded from - /// an AST file. - bool hasChangedAfterLoad() const { return ChangedAfterLoad; } - - /// \brief Note whether this macro has changed after it was loaded from an - /// AST file. - void setChangedAfterLoad(bool CAL = true) { ChangedAfterLoad = CAL; } - - /// isUsed - Return false if this macro is defined in the main file and has + /// \brief Return false if this macro is defined in the main file and has /// not yet been used. bool isUsed() const { return IsUsed; } - /// isAllowRedefinitionsWithoutWarning - Return true if this macro can be - /// redefined without warning. + /// \brief Return true if this macro can be redefined without warning. bool isAllowRedefinitionsWithoutWarning() const { return IsAllowRedefinitionsWithoutWarning; } @@ -282,7 +240,7 @@ public: return IsWarnIfUnused; } - /// getNumTokens - Return the number of tokens that this macro expands to. + /// \brief Return the number of tokens that this macro expands to. /// unsigned getNumTokens() const { return ReplacementTokens.size(); @@ -298,16 +256,16 @@ public: tokens_iterator tokens_end() const { return ReplacementTokens.end(); } bool tokens_empty() const { return ReplacementTokens.empty(); } - /// AddTokenToBody - Add the specified token to the replacement text for the - /// macro. + /// \brief Add the specified token to the replacement text for the macro. void AddTokenToBody(const Token &Tok) { assert(!IsDefinitionLengthCached && "Changing replacement tokens after definition length got calculated"); ReplacementTokens.push_back(Tok); } - /// isEnabled - Return true if this macro is enabled: in other words, that we - /// are not currently in an expansion of this macro. + /// \brief Return true if this macro is enabled. + /// + /// In other words, that we are not currently in an expansion of this macro. bool isEnabled() const { return !IsDisabled; } void EnableMacro() { @@ -320,41 +278,272 @@ public: IsDisabled = true; } - /// \brief Set the export location for this macro. - void setVisibility(bool Public, SourceLocation Loc) { - VisibilityLocation = Loc; - IsPublic = Public; + /// \brief Determine whether this macro info came from an AST file (such as + /// a precompiled header or module) rather than having been parsed. + bool isFromASTFile() const { return FromASTFile; } + + /// \brief Retrieve the global ID of the module that owns this particular + /// macro info. + unsigned getOwningModuleID() const { + if (isFromASTFile()) + return *(const unsigned*)(this+1); + + return 0; } - /// \brief Determine whether this macro is part of the public API of its - /// module. - bool isPublic() const { return IsPublic; } - - /// \brief Determine the location where this macro was explicitly made - /// public or private within its module. - SourceLocation getVisibilityLocation() { return VisibilityLocation; } +private: + unsigned getDefinitionLengthSlow(SourceManager &SM) const; + + void setOwningModuleID(unsigned ID) { + assert(isFromASTFile()); + *(unsigned*)(this+1) = ID; + } + + friend class Preprocessor; +}; + +class DefMacroDirective; + +/// \brief Encapsulates changes to the "macros namespace" (the location where +/// the macro name became active, the location where it was undefined, etc.). +/// +/// MacroDirectives, associated with an identifier, are used to model the macro +/// history. Usually a macro definition (MacroInfo) is where a macro name +/// becomes active (MacroDirective) but modules can have their own macro +/// history, separate from the local (current translation unit) macro history. +/// +/// For example, if "@import A;" imports macro FOO, there will be a new local +/// MacroDirective created to indicate that "FOO" became active at the import +/// location. Module "A" itself will contain another MacroDirective in its macro +/// history (at the point of the definition of FOO) and both MacroDirectives +/// will point to the same MacroInfo object. +/// +class MacroDirective { +public: + enum Kind { + MD_Define, + MD_Undefine, + MD_Visibility + }; + +protected: + /// \brief Previous macro directive for the same identifier, or NULL. + MacroDirective *Previous; + + SourceLocation Loc; + + /// \brief MacroDirective kind. + unsigned MDKind : 2; + + /// \brief True if the macro directive was loaded from a PCH file. + bool IsFromPCH : 1; - /// \brief Determine whether this macro is currently defined (and has not - /// been #undef'd) or has been hidden. - bool isDefined() const { return UndefLocation.isInvalid() && !IsHidden; } + /// \brief Whether the macro directive is currently "hidden". + /// + /// Note that this is transient state that is never serialized to the AST + /// file. + bool IsHidden : 1; + + // Used by DefMacroDirective -----------------------------------------------// - /// \brief Determine whether this macro definition is hidden. + /// \brief True if this macro was imported from a module. + bool IsImported : 1; + + /// \brief Whether the definition of this macro is ambiguous, due to + /// multiple definitions coming in from multiple modules. + bool IsAmbiguous : 1; + + // Used by VisibilityMacroDirective ----------------------------------------// + + /// \brief Whether the macro has public visibility (when described in a + /// module). + bool IsPublic : 1; + + MacroDirective(Kind K, SourceLocation Loc) + : Previous(0), Loc(Loc), MDKind(K), IsFromPCH(false), IsHidden(false), + IsImported(false), IsAmbiguous(false), + IsPublic(true) { + } + +public: + Kind getKind() const { return Kind(MDKind); } + + SourceLocation getLocation() const { return Loc; } + + /// \brief Set previous definition of the macro with the same name. + void setPrevious(MacroDirective *Prev) { + Previous = Prev; + } + + /// \brief Get previous definition of the macro with the same name. + const MacroDirective *getPrevious() const { return Previous; } + + /// \brief Get previous definition of the macro with the same name. + MacroDirective *getPrevious() { return Previous; } + + /// \brief Return true if the macro directive was loaded from a PCH file. + bool isFromPCH() const { return IsFromPCH; } + + void setIsFromPCH() { IsFromPCH = true; } + + /// \brief Determine whether this macro directive is hidden. bool isHidden() const { return IsHidden; } - /// \brief Set whether this macro definition is hidden. + /// \brief Set whether this macro directive is hidden. void setHidden(bool Val) { IsHidden = Val; } + class DefInfo { + DefMacroDirective *DefDirective; + SourceLocation UndefLoc; + bool IsPublic; + + public: + DefInfo() : DefDirective(0) { } + + DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc, + bool isPublic) + : DefDirective(DefDirective), UndefLoc(UndefLoc), IsPublic(isPublic) { } + + const DefMacroDirective *getDirective() const { return DefDirective; } + DefMacroDirective *getDirective() { return DefDirective; } + + inline SourceLocation getLocation() const; + inline MacroInfo *getMacroInfo(); + const MacroInfo *getMacroInfo() const { + return const_cast<DefInfo*>(this)->getMacroInfo(); + } + + SourceLocation getUndefLocation() const { return UndefLoc; } + bool isUndefined() const { return UndefLoc.isValid(); } + + bool isPublic() const { return IsPublic; } + + bool isValid() const { return DefDirective != 0; } + bool isInvalid() const { return !isValid(); } + + operator bool() const { return isValid(); } + + inline DefInfo getPreviousDefinition(bool AllowHidden = false); + const DefInfo getPreviousDefinition(bool AllowHidden = false) const { + return const_cast<DefInfo*>(this)->getPreviousDefinition(AllowHidden); + } + }; + + /// \brief Traverses the macro directives history and returns the next + /// macro definition directive along with info about its undefined location + /// (if there is one) and if it is public or private. + DefInfo getDefinition(bool AllowHidden = false); + const DefInfo getDefinition(bool AllowHidden = false) const { + return const_cast<MacroDirective*>(this)->getDefinition(AllowHidden); + } + + bool isDefined(bool AllowHidden = false) const { + if (const DefInfo Def = getDefinition(AllowHidden)) + return !Def.isUndefined(); + return false; + } + + const MacroInfo *getMacroInfo(bool AllowHidden = false) const { + return getDefinition(AllowHidden).getMacroInfo(); + } + MacroInfo *getMacroInfo(bool AllowHidden = false) { + return getDefinition(AllowHidden).getMacroInfo(); + } + + /// \brief Find macro definition active in the specified source location. If + /// this macro was not defined there, return NULL. + const DefInfo findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const; + + static bool classof(const MacroDirective *) { return true; } +}; + +/// \brief A directive for a defined macro or a macro imported from a module. +class DefMacroDirective : public MacroDirective { + MacroInfo *Info; + +public: + explicit DefMacroDirective(MacroInfo *MI) + : MacroDirective(MD_Define, MI->getDefinitionLoc()), Info(MI) { + assert(MI && "MacroInfo is null"); + } + + DefMacroDirective(MacroInfo *MI, SourceLocation Loc, bool isImported) + : MacroDirective(MD_Define, Loc), Info(MI) { + assert(MI && "MacroInfo is null"); + IsImported = isImported; + } + + /// \brief The data for the macro definition. + const MacroInfo *getInfo() const { return Info; } + MacroInfo *getInfo() { return Info; } + + /// \brief True if this macro was imported from a module. + bool isImported() const { return IsImported; } + /// \brief Determine whether this macro definition is ambiguous with /// other macro definitions. bool isAmbiguous() const { return IsAmbiguous; } /// \brief Set whether this macro definition is ambiguous. void setAmbiguous(bool Val) { IsAmbiguous = Val; } - -private: - unsigned getDefinitionLengthSlow(SourceManager &SM) const; + + static bool classof(const MacroDirective *MD) { + return MD->getKind() == MD_Define; + } + static bool classof(const DefMacroDirective *) { return true; } +}; + +/// \brief A directive for an undefined macro. +class UndefMacroDirective : public MacroDirective { +public: + explicit UndefMacroDirective(SourceLocation UndefLoc) + : MacroDirective(MD_Undefine, UndefLoc) { + assert(UndefLoc.isValid() && "Invalid UndefLoc!"); + } + + static bool classof(const MacroDirective *MD) { + return MD->getKind() == MD_Undefine; + } + static bool classof(const UndefMacroDirective *) { return true; } +}; + +/// \brief A directive for setting the module visibility of a macro. +class VisibilityMacroDirective : public MacroDirective { +public: + explicit VisibilityMacroDirective(SourceLocation Loc, bool Public) + : MacroDirective(MD_Visibility, Loc) { + IsPublic = Public; + } + + /// \brief Determine whether this macro is part of the public API of its + /// module. + bool isPublic() const { return IsPublic; } + + static bool classof(const MacroDirective *MD) { + return MD->getKind() == MD_Visibility; + } + static bool classof(const VisibilityMacroDirective *) { return true; } }; +inline SourceLocation MacroDirective::DefInfo::getLocation() const { + if (isInvalid()) + return SourceLocation(); + return DefDirective->getLocation(); +} + +inline MacroInfo *MacroDirective::DefInfo::getMacroInfo() { + if (isInvalid()) + return 0; + return DefDirective->getInfo(); +} + +inline MacroDirective::DefInfo +MacroDirective::DefInfo::getPreviousDefinition(bool AllowHidden) { + if (isInvalid() || DefDirective->getPrevious() == 0) + return DefInfo(); + return DefDirective->getPrevious()->getDefinition(AllowHidden); +} + } // end namespace clang #endif diff --git a/include/clang/Lex/ModuleLoader.h b/include/clang/Lex/ModuleLoader.h index 36d03c0..3acf915 100644 --- a/include/clang/Lex/ModuleLoader.h +++ b/include/clang/Lex/ModuleLoader.h @@ -17,16 +17,36 @@ #include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/PointerIntPair.h" namespace clang { class IdentifierInfo; - +class Module; + /// \brief A sequence of identifier/location pairs used to describe a particular /// module or submodule, e.g., std.vector. -typedef llvm::ArrayRef<std::pair<IdentifierInfo*, SourceLocation> > - ModuleIdPath; - +typedef ArrayRef<std::pair<IdentifierInfo *, SourceLocation> > ModuleIdPath; + +/// \brief Describes the result of attempting to load a module. +class ModuleLoadResult { + llvm::PointerIntPair<Module *, 1, bool> Storage; + +public: + ModuleLoadResult() : Storage() { } + + ModuleLoadResult(Module *module, bool missingExpected) + : Storage(module, missingExpected) { } + + operator Module *() const { return Storage.getPointer(); } + + /// \brief Determines whether the module, which failed to load, was + /// actually a submodule that we expected to see (based on implying the + /// submodule from header structure), but didn't materialize in the actual + /// module. + bool isMissingExpected() const { return Storage.getInt(); } +}; + /// \brief Abstract interface for a module loader. /// /// This abstract interface describes a module loader, which is responsible @@ -55,9 +75,16 @@ public: /// /// \returns If successful, returns the loaded module. Otherwise, returns /// NULL to indicate that the module could not be loaded. - virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, - Module::NameVisibilityKind Visibility, - bool IsInclusionDirective) = 0; + virtual ModuleLoadResult loadModule(SourceLocation ImportLoc, + ModuleIdPath Path, + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective) = 0; + + /// \brief Make the given module visible. + virtual void makeModuleVisible(Module *Mod, + Module::NameVisibilityKind Visibility, + SourceLocation ImportLoc, + bool Complain) = 0; }; } diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index 082408d..1c9c673 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -22,8 +22,8 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include <string> namespace clang { @@ -33,6 +33,7 @@ class FileEntry; class FileManager; class DiagnosticConsumer; class DiagnosticsEngine; +class HeaderSearch; class ModuleMapParser; class ModuleMap { @@ -40,6 +41,7 @@ class ModuleMap { IntrusiveRefCntPtr<DiagnosticsEngine> Diags; const LangOptions &LangOpts; const TargetInfo *Target; + HeaderSearch &HeaderInfo; /// \brief The directory used for Clang-supplied, builtin include headers, /// such as "stdint.h". @@ -104,13 +106,17 @@ class ModuleMap { /// \brief The names of modules that cannot be inferred within this /// directory. - llvm::SmallVector<std::string, 2> ExcludedModules; + SmallVector<std::string, 2> ExcludedModules; }; /// \brief A mapping from directories to information about inferring /// framework modules from within those directories. llvm::DenseMap<const DirectoryEntry *, InferredDirectory> InferredDirectories; + /// \brief Describes whether we haved parsed a particular file as a module + /// map. + llvm::DenseMap<const FileEntry *, bool> ParsedModuleMap; + friend class ModuleMapParser; /// \brief Resolve the given export declaration into an actual export @@ -127,8 +133,21 @@ class ModuleMap { /// if the export could not be resolved. Module::ExportDecl resolveExport(Module *Mod, const Module::UnresolvedExportDecl &Unresolved, - bool Complain); - + bool Complain) const; + + /// \brief Resolve the given module id to an actual module. + /// + /// \param Id The module-id to resolve. + /// + /// \param Mod The module in which we're resolving the module-id. + /// + /// \param Complain Whether this routine should complain about unresolvable + /// module-ids. + /// + /// \returns The resolved module, or null if the module-id could not be + /// resolved. + Module *resolveModuleId(const ModuleId &Id, Module *Mod, bool Complain) const; + public: /// \brief Construct a new module map. /// @@ -143,7 +162,8 @@ public: /// /// \param Target The target for this translation unit. ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC, - const LangOptions &LangOpts, const TargetInfo *Target); + const LangOptions &LangOpts, const TargetInfo *Target, + HeaderSearch &HeaderInfo); /// \brief Destroy the module map. /// @@ -157,6 +177,7 @@ public: void setBuiltinIncludeDir(const DirectoryEntry *Dir) { BuiltinIncludeDir = Dir; } + const DirectoryEntry *getBuiltinIncludeDir() { return BuiltinIncludeDir; } /// \brief Retrieve the module that owns the given header file, if any. /// @@ -168,14 +189,14 @@ public: /// \brief Determine whether the given header is part of a module /// marked 'unavailable'. - bool isHeaderInUnavailableModule(const FileEntry *Header); + bool isHeaderInUnavailableModule(const FileEntry *Header) const; /// \brief Retrieve a module with the given name. /// /// \param Name The name of the module to look up. /// /// \returns The named module, if known; otherwise, returns null. - Module *findModule(StringRef Name); + Module *findModule(StringRef Name) const; /// \brief Retrieve a module with the given name using lexical name lookup, /// starting at the given context. @@ -186,7 +207,7 @@ public: /// name lookup. /// /// \returns The named module, if known; otherwise, returns null. - Module *lookupModuleUnqualified(StringRef Name, Module *Context); + Module *lookupModuleUnqualified(StringRef Name, Module *Context) const; /// \brief Retrieve a module with the given name within the given context, /// using direct (qualified) name lookup. @@ -197,7 +218,7 @@ public: /// null, we will look for a top-level module. /// /// \returns The named submodule, if known; otherwose, returns null. - Module *lookupModuleQualified(StringRef Name, Module *Context); + Module *lookupModuleQualified(StringRef Name, Module *Context) const; /// \brief Find a new module or submodule, or create it if it does not already /// exist. @@ -231,7 +252,7 @@ public: /// \returns true if we are allowed to infer a framework module, and false /// otherwise. bool canInferFrameworkModule(const DirectoryEntry *ParentDir, - StringRef Name, bool &IsSystem); + StringRef Name, bool &IsSystem) const; /// \brief Infer the contents of a framework module map from the given /// framework directory. @@ -246,7 +267,7 @@ public: /// /// \returns The file entry for the module map file containing the given /// module, or NULL if the module definition was inferred. - const FileEntry *getContainingModuleMapFile(Module *Module); + const FileEntry *getContainingModuleMapFile(Module *Module) const; /// \brief Resolve all of the unresolved exports in the given module. /// @@ -258,7 +279,17 @@ public: /// false otherwise. bool resolveExports(Module *Mod, bool Complain); - /// \brief Infers the (sub)module based on the given source location and + /// \brief Resolve all of the unresolved conflicts in the given module. + /// + /// \param Mod The module whose conflicts should be resolved. + /// + /// \param Complain Whether to emit diagnostics for failures. + /// + /// \returns true if any errors were encountered while resolving conflicts, + /// false otherwise. + bool resolveConflicts(Module *Mod, bool Complain); + + /// \brief Infers the (sub)module based on the given source location and /// source manager. /// /// \param Loc The location within the source that we are querying, along diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index 8ba02cc..96359a2 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -15,10 +15,10 @@ #ifndef LLVM_CLANG_LEX_PPCALLBACKS_H #define LLVM_CLANG_LEX_PPCALLBACKS_H +#include "clang/Basic/DiagnosticIDs.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Lex/DirectoryLookup.h" #include "clang/Lex/ModuleLoader.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Basic/DiagnosticIDs.h" #include "llvm/ADT/StringRef.h" #include <string> @@ -26,7 +26,7 @@ namespace clang { class SourceLocation; class Token; class IdentifierInfo; - class MacroInfo; + class MacroDirective; /// \brief This interface provides a way to observe the actions of the /// preprocessor as it does its thing. @@ -184,22 +184,25 @@ public: /// \brief Called by Preprocessor::HandleMacroExpandedIdentifier when a /// macro invocation is found. - virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI, + virtual void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD, SourceRange Range) { } /// \brief Hook called whenever a macro definition is seen. - virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) { + virtual void MacroDefined(const Token &MacroNameTok, + const MacroDirective *MD) { } /// \brief Hook called whenever a macro \#undef is seen. /// - /// MI is released immediately following this callback. - virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) { + /// MD is released immediately following this callback. + virtual void MacroUndefined(const Token &MacroNameTok, + const MacroDirective *MD) { } /// \brief Hook called whenever the 'defined' operator is seen. - virtual void Defined(const Token &MacroNameTok) { + /// \param MD The MacroDirective if the name was a macro, null otherwise. + virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD) { } /// \brief Hook called when a source range is skipped. @@ -228,13 +231,17 @@ public: /// \brief Hook called whenever an \#ifdef is seen. /// \param Loc the source location of the directive. /// \param MacroNameTok Information on the token being tested. - virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) { + /// \param MD The MacroDirective if the name was a macro, null otherwise. + virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD) { } /// \brief Hook called whenever an \#ifndef is seen. /// \param Loc the source location of the directive. /// \param MacroNameTok Information on the token being tested. - virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) { + /// \param MD The MacroDirective if the name was a macro, null otherwise. + virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD) { } /// \brief Hook called whenever an \#else is seen. @@ -346,25 +353,26 @@ public: Second->PragmaDiagnostic(Loc, Namespace, mapping, Str); } - virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI, + virtual void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD, SourceRange Range) { - First->MacroExpands(MacroNameTok, MI, Range); - Second->MacroExpands(MacroNameTok, MI, Range); + First->MacroExpands(MacroNameTok, MD, Range); + Second->MacroExpands(MacroNameTok, MD, Range); } - virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) { - First->MacroDefined(MacroNameTok, MI); - Second->MacroDefined(MacroNameTok, MI); + virtual void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) { + First->MacroDefined(MacroNameTok, MD); + Second->MacroDefined(MacroNameTok, MD); } - virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) { - First->MacroUndefined(MacroNameTok, MI); - Second->MacroUndefined(MacroNameTok, MI); + virtual void MacroUndefined(const Token &MacroNameTok, + const MacroDirective *MD) { + First->MacroUndefined(MacroNameTok, MD); + Second->MacroUndefined(MacroNameTok, MD); } - virtual void Defined(const Token &MacroNameTok) { - First->Defined(MacroNameTok); - Second->Defined(MacroNameTok); + virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD) { + First->Defined(MacroNameTok, MD); + Second->Defined(MacroNameTok, MD); } virtual void SourceRangeSkipped(SourceRange Range) { @@ -386,15 +394,17 @@ public: } /// \brief Hook called whenever an \#ifdef is seen. - virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) { - First->Ifdef(Loc, MacroNameTok); - Second->Ifdef(Loc, MacroNameTok); + virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD) { + First->Ifdef(Loc, MacroNameTok, MD); + Second->Ifdef(Loc, MacroNameTok, MD); } /// \brief Hook called whenever an \#ifndef is seen. - virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) { - First->Ifndef(Loc, MacroNameTok); - Second->Ifndef(Loc, MacroNameTok); + virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD) { + First->Ifndef(Loc, MacroNameTok, MD); + Second->Ifndef(Loc, MacroNameTok, MD); } /// \brief Hook called whenever an \#else is seen. diff --git a/include/clang/Lex/PPConditionalDirectiveRecord.h b/include/clang/Lex/PPConditionalDirectiveRecord.h new file mode 100644 index 0000000..b9a2252 --- /dev/null +++ b/include/clang/Lex/PPConditionalDirectiveRecord.h @@ -0,0 +1,102 @@ +//===--- PPConditionalDirectiveRecord.h - Preprocessing Directives-*- 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 PPConditionalDirectiveRecord class, which maintains +// a record of conditional directive regions. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H +#define LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H + +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/PPCallbacks.h" +#include "llvm/ADT/SmallVector.h" +#include <vector> + +namespace clang { + +/// \brief Records preprocessor conditional directive regions and allows +/// querying in which region source locations belong to. +class PPConditionalDirectiveRecord : public PPCallbacks { + SourceManager &SourceMgr; + + SmallVector<SourceLocation, 6> CondDirectiveStack; + + class CondDirectiveLoc { + SourceLocation Loc; + SourceLocation RegionLoc; + + public: + CondDirectiveLoc(SourceLocation Loc, SourceLocation RegionLoc) + : Loc(Loc), RegionLoc(RegionLoc) {} + + SourceLocation getLoc() const { return Loc; } + SourceLocation getRegionLoc() const { return RegionLoc; } + + class Comp { + SourceManager &SM; + public: + explicit Comp(SourceManager &SM) : SM(SM) {} + bool operator()(const CondDirectiveLoc &LHS, + const CondDirectiveLoc &RHS) { + return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS.getLoc()); + } + bool operator()(const CondDirectiveLoc &LHS, SourceLocation RHS) { + return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS); + } + bool operator()(SourceLocation LHS, const CondDirectiveLoc &RHS) { + return SM.isBeforeInTranslationUnit(LHS, RHS.getLoc()); + } + }; + }; + + typedef std::vector<CondDirectiveLoc> CondDirectiveLocsTy; + /// \brief The locations of conditional directives in source order. + CondDirectiveLocsTy CondDirectiveLocs; + + void addCondDirectiveLoc(CondDirectiveLoc DirLoc); + +public: + /// \brief Construct a new preprocessing record. + explicit PPConditionalDirectiveRecord(SourceManager &SM); + + size_t getTotalMemory() const; + + SourceManager &getSourceManager() const { return SourceMgr; } + + /// \brief Returns true if the given range intersects with a conditional + /// directive. if a \#if/\#endif block is fully contained within the range, + /// this function will return false. + bool rangeIntersectsConditionalDirective(SourceRange Range) const; + + /// \brief Returns true if the given locations are in different regions, + /// separated by conditional directive blocks. + bool areInDifferentConditionalDirectiveRegion(SourceLocation LHS, + SourceLocation RHS) const { + return findConditionalDirectiveRegionLoc(LHS) != + findConditionalDirectiveRegionLoc(RHS); + } + + SourceLocation findConditionalDirectiveRegionLoc(SourceLocation Loc) const; + +private: + virtual void If(SourceLocation Loc, SourceRange ConditionRange); + virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, + SourceLocation IfLoc); + virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD); + virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD); + virtual void Else(SourceLocation Loc, SourceLocation IfLoc); + virtual void Endif(SourceLocation Loc, SourceLocation IfLoc); +}; + +} // end namespace clang + +#endif // LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H diff --git a/include/clang/Lex/PPMutationListener.h b/include/clang/Lex/PPMutationListener.h deleted file mode 100644 index 5319c66..0000000 --- a/include/clang/Lex/PPMutationListener.h +++ /dev/null @@ -1,43 +0,0 @@ -//===--- PPMutationListener.h - Preprocessor Mutation Interface -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the PPMutationListener interface. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LEX_PPTMUTATIONLISTENER_H -#define LLVM_CLANG_LEX_PPTMUTATIONLISTENER_H - -#include "clang/Basic/SourceLocation.h" - -namespace clang { - -class MacroInfo; - -/// \brief A record that describes an update to a macro that was -/// originally loaded to an AST file and has been modified within the -/// current translation unit. -struct MacroUpdate { - /// \brief The source location at which this macro was #undef'd. - SourceLocation UndefLoc; -}; - -/// \brief An abstract interface that should be implemented by -/// listeners that want to be notified when a preprocessor entity gets -/// modified after its initial creation. -class PPMutationListener { -public: - virtual ~PPMutationListener(); - - /// \brief A macro has been #undef'd. - virtual void UndefinedMacro(MacroInfo *MI) { } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h index e64dbd8..fad0806 100644 --- a/include/clang/Lex/PTHManager.h +++ b/include/clang/Lex/PTHManager.h @@ -14,10 +14,10 @@ #ifndef LLVM_CLANG_PTHMANAGER_H #define LLVM_CLANG_PTHMANAGER_H -#include "clang/Lex/PTHLexer.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Lex/PTHLexer.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Allocator.h" #include <string> diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index 57e51b7..b13b2be 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -14,18 +14,19 @@ #ifndef LLVM_CLANG_LEX_PREPROCESSINGRECORD_H #define LLVM_CLANG_LEX_PREPROCESSINGRECORD_H -#include "clang/Lex/PPCallbacks.h" -#include "clang/Basic/SourceLocation.h" #include "clang/Basic/IdentifierTable.h" -#include "llvm/ADT/SmallVector.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/PPCallbacks.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" #include <vector> namespace clang { class IdentifierInfo; + class MacroInfo; class PreprocessingRecord; } @@ -277,9 +278,9 @@ namespace clang { /// \brief Optionally returns true or false if the preallocated preprocessed /// entity with index \p Index came from file \p FID. - virtual llvm::Optional<bool> isPreprocessedEntityInFileID(unsigned Index, - FileID FID) { - return llvm::Optional<bool>(); + virtual Optional<bool> isPreprocessedEntityInFileID(unsigned Index, + FileID FID) { + return None; } }; @@ -303,44 +304,6 @@ namespace clang { /// and are referenced by the iterator using negative indices. std::vector<PreprocessedEntity *> LoadedPreprocessedEntities; - bool RecordCondDirectives; - unsigned CondDirectiveNextIdx; - SmallVector<unsigned, 6> CondDirectiveStack; - - class CondDirectiveLoc { - SourceLocation Loc; - unsigned Idx; - - public: - CondDirectiveLoc(SourceLocation Loc, unsigned Idx) : Loc(Loc), Idx(Idx) {} - - SourceLocation getLoc() const { return Loc; } - unsigned getIdx() const { return Idx; } - - class Comp { - SourceManager &SM; - public: - explicit Comp(SourceManager &SM) : SM(SM) {} - bool operator()(const CondDirectiveLoc &LHS, - const CondDirectiveLoc &RHS) { - return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS.getLoc()); - } - bool operator()(const CondDirectiveLoc &LHS, SourceLocation RHS) { - return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS); - } - bool operator()(SourceLocation LHS, const CondDirectiveLoc &RHS) { - return SM.isBeforeInTranslationUnit(LHS, RHS.getLoc()); - } - }; - }; - - typedef std::vector<CondDirectiveLoc> CondDirectiveLocsTy; - /// \brief The locations of conditional directives in source order. - CondDirectiveLocsTy CondDirectiveLocs; - - void addCondDirectiveLoc(CondDirectiveLoc DirLoc); - unsigned findCondDirectiveIdx(SourceLocation Loc) const; - /// \brief Global (loaded or local) ID for a preprocessed entity. /// Negative values are used to indicate preprocessed entities /// loaded from the external source while non-negative values are used to @@ -363,7 +326,7 @@ namespace clang { } /// \brief Mapping from MacroInfo structures to their definitions. - llvm::DenseMap<const MacroInfo *, PPEntityID> MacroDefinitions; + llvm::DenseMap<const MacroInfo *, MacroDefinition *> MacroDefinitions; /// \brief External source of preprocessed entities. ExternalPreprocessingRecordSource *ExternalSource; @@ -394,11 +357,11 @@ namespace clang { unsigned allocateLoadedEntities(unsigned NumEntities); /// \brief Register a new macro definition. - void RegisterMacroDefinition(MacroInfo *Macro, PPEntityID PPID); + void RegisterMacroDefinition(MacroInfo *Macro, MacroDefinition *Def); public: /// \brief Construct a new preprocessing record. - PreprocessingRecord(SourceManager &SM, bool RecordConditionalDirectives); + explicit PreprocessingRecord(SourceManager &SM); /// \brief Allocate memory in the preprocessing record. void *Allocate(unsigned Size, unsigned Align = 8) { @@ -582,24 +545,6 @@ namespace clang { /// \brief Add a new preprocessed entity to this record. PPEntityID addPreprocessedEntity(PreprocessedEntity *Entity); - /// \brief Returns true if this PreprocessingRecord is keeping track of - /// conditional directives locations. - bool isRecordingConditionalDirectives() const { - return RecordCondDirectives; - } - - /// \brief Returns true if the given range intersects with a conditional - /// directive. if a \#if/\#endif block is fully contained within the range, - /// this function will return false. - bool rangeIntersectsConditionalDirective(SourceRange Range) const; - - /// \brief Returns true if the given locations are in different regions, - /// separated by conditional directive blocks. - bool areInDifferentConditionalDirectiveRegion(SourceLocation LHS, - SourceLocation RHS) const { - return findCondDirectiveIdx(LHS) != findCondDirectiveIdx(RHS); - } - /// \brief Set the external source for preprocessed entities. void SetExternalSource(ExternalPreprocessingRecordSource &Source); @@ -613,10 +558,10 @@ namespace clang { MacroDefinition *findMacroDefinition(const MacroInfo *MI); private: - virtual void MacroExpands(const Token &Id, const MacroInfo* MI, + virtual void MacroExpands(const Token &Id, const MacroDirective *MD, SourceRange Range); - virtual void MacroDefined(const Token &Id, const MacroInfo *MI); - virtual void MacroUndefined(const Token &Id, const MacroInfo *MI); + virtual void MacroDefined(const Token &Id, const MacroDirective *MD); + virtual void MacroUndefined(const Token &Id, const MacroDirective *MD); virtual void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, @@ -626,13 +571,15 @@ namespace clang { StringRef SearchPath, StringRef RelativePath, const Module *Imported); - virtual void If(SourceLocation Loc, SourceRange ConditionRange); - virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, - SourceLocation IfLoc); - virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok); - virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok); - virtual void Else(SourceLocation Loc, SourceLocation IfLoc); - virtual void Endif(SourceLocation Loc, SourceLocation IfLoc); + virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD); + virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD); + /// \brief Hook called whenever the 'defined' operator is seen. + virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD); + + void addMacroExpansion(const Token &Id, const MacroInfo *MI, + SourceRange Range); /// \brief Cached result of the last \see getPreprocessedEntitiesInRange /// query. diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index e9095fb..7a912ec 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -14,23 +14,22 @@ #ifndef LLVM_CLANG_LEX_PREPROCESSOR_H #define LLVM_CLANG_LEX_PREPROCESSOR_H -#include "clang/Lex/MacroInfo.h" -#include "clang/Lex/Lexer.h" -#include "clang/Lex/PTHLexer.h" -#include "clang/Lex/PPCallbacks.h" -#include "clang/Lex/PPMutationListener.h" -#include "clang/Lex/TokenLexer.h" -#include "clang/Lex/PTHManager.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/MacroInfo.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/PTHLexer.h" +#include "clang/Lex/PTHManager.h" +#include "clang/Lex/TokenLexer.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Allocator.h" #include <vector> @@ -84,7 +83,7 @@ public: /// like the \#include stack, token expansion, etc. /// class Preprocessor : public RefCountedBase<Preprocessor> { - llvm::IntrusiveRefCntPtr<PreprocessorOptions> PPOpts; + IntrusiveRefCntPtr<PreprocessorOptions> PPOpts; DiagnosticsEngine *Diags; LangOptions &LangOpts; const TargetInfo *Target; @@ -160,6 +159,12 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// \brief True if pragmas are enabled. bool PragmasEnabled : 1; + /// \brief True if the current build action is a preprocessing action. + bool PreprocessedOutput : 1; + + /// \brief True if we are currently preprocessing a #if or #elif directive + bool ParsingIfOrElifDirective; + /// \brief True if we are pre-expanding macro arguments. bool InMacroArgPreExpansion; @@ -215,8 +220,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> { SourceLocation ModuleImportLoc; /// \brief The module import path that we're currently processing. - llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> - ModuleImportPath; + SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> ModuleImportPath; /// \brief Whether the module import expectes an identifier next. Otherwise, /// it expects a '.' or ';'. @@ -291,24 +295,19 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// encountered (e.g. a file is \#included, etc). PPCallbacks *Callbacks; - /// \brief Listener whose actions are invoked when an entity in the - /// preprocessor (e.g., a macro) that was loaded from an AST file is - /// later mutated. - PPMutationListener *Listener; - struct MacroExpandsInfo { Token Tok; - MacroInfo *MI; + MacroDirective *MD; SourceRange Range; - MacroExpandsInfo(Token Tok, MacroInfo *MI, SourceRange Range) - : Tok(Tok), MI(MI), Range(Range) { } + MacroExpandsInfo(Token Tok, MacroDirective *MD, SourceRange Range) + : Tok(Tok), MD(MD), Range(Range) { } }; SmallVector<MacroExpandsInfo, 2> DelayedMacroExpandsCallbacks; /// Macros - For each IdentifierInfo that was associated with a macro, we /// keep a mapping to the history of all macro definitions and #undefs in /// the reverse order (the latest one is in the head of the list). - llvm::DenseMap<IdentifierInfo*, MacroInfo*> Macros; + llvm::DenseMap<const IdentifierInfo*, MacroDirective*> Macros; friend class ASTReader; /// \brief Macros that we want to warn because they are not used at the end @@ -343,6 +342,9 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// should use from the command line etc. std::string Predefines; + /// \brief The file ID for the preprocessor predefines. + FileID PredefinesFileID; + /// TokenLexerCache - Cache macro expanders to reduce malloc traffic. enum { TokenLexerCacheSize = 8 }; unsigned NumCachedTokenLexers; @@ -396,7 +398,7 @@ private: // Cached tokens state. MacroInfoChain *MICache; public: - Preprocessor(llvm::IntrusiveRefCntPtr<PreprocessorOptions> PPOpts, + Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts, DiagnosticsEngine &diags, LangOptions &opts, const TargetInfo *target, SourceManager &SM, HeaderSearch &Headers, @@ -447,6 +449,11 @@ public: /// \brief Retrieve the module loader associated with this preprocessor. ModuleLoader &getModuleLoader() const { return TheModuleLoader; } + /// \brief True if we are currently preprocessing a #if or #elif directive + bool isParsingIfOrElifDirective() const { + return ParsingIfOrElifDirective; + } + /// SetCommentRetentionState - Control whether or not the preprocessor retains /// comments in output. void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) { @@ -467,6 +474,16 @@ public: return SuppressIncludeNotFoundError; } + /// Sets whether the preprocessor is responsible for producing output or if + /// it is producing tokens to be consumed by Parse and Sema. + void setPreprocessedOutput(bool IsPreprocessedOutput) { + PreprocessedOutput = IsPreprocessedOutput; + } + + /// Returns true if the preprocessor is responsible for generating output, + /// false if it is producing tokens to be consumed by Parse and Sema. + bool isPreprocessedOutput() const { return PreprocessedOutput; } + /// isCurrentLexer - Return true if we are lexing directly from the specified /// lexer. bool isCurrentLexer(const PreprocessorLexer *L) const { @@ -483,6 +500,9 @@ public: /// expansions going on at the time. PreprocessorLexer *getCurrentFileLexer() const; + /// \brief Returns the file ID for the preprocessor predefines. + FileID getPredefinesFileID() const { return PredefinesFileID; } + /// getPPCallbacks/addPPCallbacks - Accessors for preprocessor callbacks. /// Note that this class takes ownership of any PPCallbacks object given to /// it. @@ -493,53 +513,54 @@ public: Callbacks = C; } - /// \brief Attach an preprocessor mutation listener to the preprocessor. - /// - /// The preprocessor mutation listener provides the ability to track - /// modifications to the preprocessor entities committed after they were - /// initially created. - void setPPMutationListener(PPMutationListener *Listener) { - this->Listener = Listener; - } - - /// \brief Retrieve a pointer to the preprocessor mutation listener - /// associated with this preprocessor, if any. - PPMutationListener *getPPMutationListener() const { return Listener; } - - /// \brief Given an identifier, return the MacroInfo it is \#defined to - /// or null if it isn't \#define'd. - MacroInfo *getMacroInfo(IdentifierInfo *II) const { + /// \brief Given an identifier, return its latest MacroDirective if it is + // \#defined or null if it isn't \#define'd. + MacroDirective *getMacroDirective(IdentifierInfo *II) const { if (!II->hasMacroDefinition()) return 0; - MacroInfo *MI = getMacroInfoHistory(II); - assert(MI->getUndefLoc().isInvalid() && "Macro is undefined!"); - return MI; + MacroDirective *MD = getMacroDirectiveHistory(II); + assert(MD->isDefined() && "Macro is undefined!"); + return MD; + } + + const MacroInfo *getMacroInfo(IdentifierInfo *II) const { + return const_cast<Preprocessor*>(this)->getMacroInfo(II); + } + + MacroInfo *getMacroInfo(IdentifierInfo *II) { + if (MacroDirective *MD = getMacroDirective(II)) + return MD->getMacroInfo(); + return 0; } /// \brief Given an identifier, return the (probably #undef'd) MacroInfo /// representing the most recent macro definition. One can iterate over all /// previous macro definitions from it. This method should only be called for /// identifiers that hadMacroDefinition(). - MacroInfo *getMacroInfoHistory(IdentifierInfo *II) const; - - /// \brief Specify a macro for this identifier. - void setMacroInfo(IdentifierInfo *II, MacroInfo *MI); - /// \brief Add a MacroInfo that was loaded from an AST file. - void addLoadedMacroInfo(IdentifierInfo *II, MacroInfo *MI, - MacroInfo *Hint = 0); - /// \brief Make the given MacroInfo, that was loaded from an AST file and - /// previously hidden, visible. - void makeLoadedMacroInfoVisible(IdentifierInfo *II, MacroInfo *MI); - /// \brief Undefine a macro for this identifier. - void clearMacroInfo(IdentifierInfo *II); + MacroDirective *getMacroDirectiveHistory(const IdentifierInfo *II) const; + + /// \brief Add a directive to the macro directive history for this identifier. + void appendMacroDirective(IdentifierInfo *II, MacroDirective *MD); + DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI, + SourceLocation Loc, + bool isImported) { + DefMacroDirective *MD = AllocateDefMacroDirective(MI, Loc, isImported); + appendMacroDirective(II, MD); + return MD; + } + DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI){ + return appendDefMacroDirective(II, MI, MI->getDefinitionLoc(), false); + } + /// \brief Set a MacroDirective that was loaded from a PCH file. + void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *MD); /// macro_iterator/macro_begin/macro_end - This allows you to walk the macro /// history table. Currently defined macros have /// IdentifierInfo::hasMacroDefinition() set and an empty /// MacroInfo::getUndefLoc() at the head of the list. - typedef llvm::DenseMap<IdentifierInfo*, - MacroInfo*>::const_iterator macro_iterator; + typedef llvm::DenseMap<const IdentifierInfo *, + MacroDirective*>::const_iterator macro_iterator; macro_iterator macro_begin(bool IncludeExternalMacros = true) const; macro_iterator macro_end(bool IncludeExternalMacros = true) const; @@ -611,7 +632,7 @@ public: /// \brief Create a new preprocessing record, which will keep track of /// all macro expansions, macro definitions, etc. - void createPreprocessingRecord(bool RecordConditionalDirectives); + void createPreprocessingRecord(); /// EnterMainSourceFile - Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. @@ -696,6 +717,25 @@ public: void LexAfterModuleImport(Token &Result); + /// \brief Lex a string literal, which may be the concatenation of multiple + /// string literals and may even come from macro expansion. + /// \returns true on success, false if a error diagnostic has been generated. + bool LexStringLiteral(Token &Result, std::string &String, + const char *DiagnosticTag, bool AllowMacroExpansion) { + if (AllowMacroExpansion) + Lex(Result); + else + LexUnexpandedToken(Result); + return FinishLexStringLiteral(Result, String, DiagnosticTag, + AllowMacroExpansion); + } + + /// \brief Complete the lexing of a string literal where the first token has + /// already been lexed (see LexStringLiteral). + bool FinishLexStringLiteral(Token &Result, std::string &String, + const char *DiagnosticTag, + bool AllowMacroExpansion); + /// LexNonComment - Lex a token. If it's a comment, keep lexing until we get /// something not a comment. This is useful in -E -C mode where comments /// would foul up preprocessor directive handling. @@ -901,8 +941,8 @@ public: /// "cleaning", e.g. if it contains trigraphs or escaped newlines /// \param invalid If non-null, will be set \c true if an error occurs. StringRef getSpelling(SourceLocation loc, - SmallVectorImpl<char> &buffer, - bool *invalid = 0) const { + SmallVectorImpl<char> &buffer, + bool *invalid = 0) const { return Lexer::getSpelling(loc, buffer, SourceMgr, LangOpts, invalid); } @@ -939,6 +979,12 @@ public: SmallVectorImpl<char> &Buffer, bool *Invalid = 0) const; + /// \brief Relex the token at the specified location. + /// \returns true if there was a failure, false on success. + bool getRawToken(SourceLocation Loc, Token &Result) { + return Lexer::getRawToken(Loc, Result, SourceMgr, LangOpts); + } + /// getSpellingOfSingleCharacterNumericConstant - Tok is a numeric constant /// with length 1, return the character. char getSpellingOfSingleCharacterNumericConstant(const Token &Tok, @@ -1143,8 +1189,9 @@ public: /// \brief Allocate a new MacroInfo object with the provided SourceLocation. MacroInfo *AllocateMacroInfo(SourceLocation L); - /// \brief Allocate a new MacroInfo object which is clone of \p MI. - MacroInfo *CloneMacroInfo(const MacroInfo &MI); + /// \brief Allocate a new MacroInfo object loaded from an AST file. + MacroInfo *AllocateDeserializedMacroInfo(SourceLocation L, + unsigned SubModuleID); /// \brief Turn the specified lexer token into a fully checked and spelled /// filename, e.g. as an operand of \#include. @@ -1221,6 +1268,13 @@ private: /// \brief Allocate a new MacroInfo object. MacroInfo *AllocateMacroInfo(); + DefMacroDirective *AllocateDefMacroDirective(MacroInfo *MI, + SourceLocation Loc, + bool isImported); + UndefMacroDirective *AllocateUndefMacroDirective(SourceLocation UndefLoc); + VisibilityMacroDirective *AllocateVisibilityMacroDirective(SourceLocation Loc, + bool isPublic); + /// \brief Release the specified MacroInfo for re-use. /// /// This memory will be reused for allocating new MacroInfo objects. @@ -1268,7 +1322,7 @@ private: /// HandleMacroExpandedIdentifier - If an identifier token is read that is to /// be expanded as a macro, handle it and return the next token as 'Tok'. If /// the macro should not be expanded return true, otherwise return false. - bool HandleMacroExpandedIdentifier(Token &Tok, MacroInfo *MI); + bool HandleMacroExpandedIdentifier(Token &Tok, MacroDirective *MD); /// \brief Cache macro expanded tokens for TokenLexers. // @@ -1312,6 +1366,12 @@ private: /// start getting tokens from it using the PTH cache. void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir); + /// \brief Set the file ID for the preprocessor predefines. + void setPredefinesFileID(FileID FID) { + assert(PredefinesFileID.isInvalid() && "PredefinesFileID already set!"); + PredefinesFileID = FID; + } + /// IsFileLexer - Returns true if we are lexing from a file and not a /// pragma or a macro. static bool IsFileLexer(const Lexer* L, const PreprocessorLexer* P) { @@ -1367,8 +1427,6 @@ private: // Macro handling. void HandleDefineDirective(Token &Tok); void HandleUndefDirective(Token &Tok); - void UndefineMacro(IdentifierInfo *II, MacroInfo *MI, - SourceLocation UndefLoc); // Conditional Inclusion. void HandleIfdefDirective(Token &Tok, bool isIfndef, diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h index e5fe373..eba2a13 100644 --- a/include/clang/Lex/PreprocessorOptions.h +++ b/include/clang/Lex/PreprocessorOptions.h @@ -10,14 +10,16 @@ #ifndef LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_ #define LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_ +#include "clang/Basic/SourceLocation.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" #include <cassert> +#include <set> #include <string> #include <utility> #include <vector> -#include <set> namespace llvm { class MemoryBuffer; @@ -39,23 +41,20 @@ enum ObjCXXARCStandardLibraryKind { /// PreprocessorOptions - This class is used for passing the various options /// used in preprocessor initialization to InitializePreprocessor(). -class PreprocessorOptions : public llvm::RefCountedBase<PreprocessorOptions> { +class PreprocessorOptions : public RefCountedBase<PreprocessorOptions> { public: std::vector<std::pair<std::string, bool/*isUndef*/> > Macros; std::vector<std::string> Includes; std::vector<std::string> MacroIncludes; - unsigned UsePredefines : 1; /// Initialize the preprocessor with the compiler - /// and target specific predefines. + /// \brief Initialize the preprocessor with the compiler and target specific + /// predefines. + unsigned UsePredefines : 1; + + /// \brief Whether we should maintain a detailed record of all macro + /// definitions and expansions. + unsigned DetailedRecord : 1; - unsigned DetailedRecord : 1; /// Whether we should maintain a detailed - /// record of all macro definitions and - /// expansions. - unsigned DetailedRecordConditionalDirectives : 1; /// Whether in the - /// preprocessing record we should also keep - /// track of locations of conditional directives - /// in non-system files. - /// The implicit PCH included at the start of the translation unit, or empty. std::string ImplicitPCHInclude; @@ -119,14 +118,28 @@ public: /// with support for lifetime-qualified pointers. ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary; - /// \brief The path of modules being build, which is used to detect - /// cycles in the module dependency graph as modules are being built. - /// - /// There is no way to set this value from the command line. If we ever need - /// to do so (e.g., if on-demand module construction moves out-of-process), - /// we can add a cc1-level option to do so. - SmallVector<std::string, 2> ModuleBuildPath; + /// \brief Records the set of modules + class FailedModulesSet : public RefCountedBase<FailedModulesSet> { + llvm::StringSet<> Failed; + + public: + bool hasAlreadyFailed(StringRef module) { + return Failed.count(module) > 0; + } + + void addFailed(StringRef module) { + Failed.insert(module); + } + }; + /// \brief The set of modules that failed to build. + /// + /// This pointer will be shared among all of the compiler instances created + /// to (re)build modules, so that once a module fails to build anywhere, + /// other instances will see that the module has failed and won't try to + /// build it again. + IntrusiveRefCntPtr<FailedModulesSet> FailedModules; + typedef std::vector<std::pair<std::string, std::string> >::iterator remapped_file_iterator; typedef std::vector<std::pair<std::string, std::string> >::const_iterator @@ -163,7 +176,6 @@ public: public: PreprocessorOptions() : UsePredefines(true), DetailedRecord(false), - DetailedRecordConditionalDirectives(false), DisablePCHValidation(false), AllowPCHWithCompilerErrors(false), DumpDeserializedPCHDecls(false), diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index 50b86c8..bcbe9c9 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -14,10 +14,10 @@ #ifndef LLVM_CLANG_TOKEN_H #define LLVM_CLANG_TOKEN_H +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TokenKinds.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Basic/OperatorKinds.h" #include <cstdlib> namespace clang { @@ -74,9 +74,10 @@ public: StartOfLine = 0x01, // At start of line or only after whitespace. LeadingSpace = 0x02, // Whitespace exists before this token. DisableExpand = 0x04, // This identifier may never be macro expanded. - NeedsCleaning = 0x08, // Contained an escaped newline or trigraph. + NeedsCleaning = 0x08, // Contained an escaped newline or trigraph. LeadingEmptyMacro = 0x10, // Empty macro exists before this token. - HasUDSuffix = 0x20 // This string or character literal has a ud-suffix. + HasUDSuffix = 0x20, // This string or character literal has a ud-suffix. + HasUCN = 0x40 // This identifier contains a UCN. }; tok::TokenKind getKind() const { return (tok::TokenKind)Kind; } @@ -257,6 +258,9 @@ public: /// \brief Return true if this token is a string or character literal which /// has a ud-suffix. bool hasUDSuffix() const { return (Flags & HasUDSuffix) ? true : false; } + + /// Returns true if this token contains a universal character name. + bool hasUCN() const { return (Flags & HasUCN) ? true : false; } }; /// \brief Information about the conditional stack (\#if directives) diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index c433344..8cc60a2 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -14,11 +14,13 @@ #ifndef LLVM_CLANG_PARSE_PARSER_H #define LLVM_CLANG_PARSE_PARSER_H +#include "clang/Basic/OpenMPKinds.h" +#include "clang/Basic/OperatorPrecedence.h" #include "clang/Basic/Specifiers.h" -#include "clang/Lex/Preprocessor.h" #include "clang/Lex/CodeCompletionHandler.h" -#include "clang/Sema/Sema.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Sema.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" @@ -44,39 +46,6 @@ namespace clang { class PoisonSEHIdentifiersRAIIObject; class VersionTuple; -/// PrettyStackTraceParserEntry - If a crash happens while the parser is active, -/// an entry is printed for it. -class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry { - const Parser &P; -public: - PrettyStackTraceParserEntry(const Parser &p) : P(p) {} - virtual void print(raw_ostream &OS) const; -}; - -/// PrecedenceLevels - These are precedences for the binary/ternary -/// operators in the C99 grammar. These have been named to relate -/// with the C99 grammar productions. Low precedences numbers bind -/// more weakly than high numbers. -namespace prec { - enum Level { - Unknown = 0, // Not binary operator. - Comma = 1, // , - Assignment = 2, // =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |= - Conditional = 3, // ? - LogicalOr = 4, // || - LogicalAnd = 5, // && - InclusiveOr = 6, // | - ExclusiveOr = 7, // ^ - And = 8, // & - Equality = 9, // ==, != - Relational = 10, // >=, <=, >, < - Shift = 11, // <<, >> - Additive = 12, // -, + - Multiplicative = 13, // *, /, % - PointerToMember = 14 // .*, ->* - }; -} - /// Parser - This implements a parser for the C family of languages. After /// parsing units of the grammar, productions are invoked to handle whatever has /// been read. @@ -179,6 +148,7 @@ class Parser : public CodeCompletionHandler { OwningPtr<PragmaHandler> FPContractHandler; OwningPtr<PragmaHandler> OpenCLExtensionHandler; OwningPtr<CommentHandler> CommentSemaHandler; + OwningPtr<PragmaHandler> OpenMPHandler; /// Whether the '>' token acts as an operator or not. This will be /// true except when we are parsing an expression within a C++ @@ -255,15 +225,6 @@ public: typedef llvm::MutableArrayRef<Stmt*> MultiStmtArg; typedef Sema::FullExprArg FullExprArg; - /// Adorns a ExprResult with Actions to make it an ExprResult - ExprResult Owned(ExprResult res) { - return ExprResult(res); - } - /// Adorns a StmtResult with Actions to make it an StmtResult - StmtResult Owned(StmtResult res) { - return StmtResult(res); - } - ExprResult ExprError() { return ExprResult(true); } StmtResult StmtError() { return StmtResult(true); } @@ -274,10 +235,6 @@ public: // Parsing methods. - /// ParseTranslationUnit - All in one method that initializes parses, and - /// shuts down the parser. - void ParseTranslationUnit(); - /// Initialize - Warm up the parser. /// void Initialize(); @@ -290,12 +247,12 @@ public: /// This does not work with all kinds of tokens: strings and specific other /// tokens must be consumed with custom methods below. This returns the /// location of the consumed token. - SourceLocation ConsumeToken() { + SourceLocation ConsumeToken(bool ConsumeCodeCompletionTok = false) { assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() && !isTokenBrace() && "Should consume special tokens with Consume*Token"); - if (Tok.is(tok::code_completion)) + if (!ConsumeCodeCompletionTok && Tok.is(tok::code_completion)) return handleUnexpectedCodeCompletionToken(); PrevTokLocation = Tok.getLocation(); @@ -324,11 +281,7 @@ private: /// isTokenStringLiteral - True if this token is a string-literal. /// bool isTokenStringLiteral() const { - return Tok.getKind() == tok::string_literal || - Tok.getKind() == tok::wide_string_literal || - Tok.getKind() == tok::utf8_string_literal || - Tok.getKind() == tok::utf16_string_literal || - Tok.getKind() == tok::utf32_string_literal; + return tok::isStringLiteral(Tok.getKind()); } /// \brief Returns true if the current token is '=' or is a type of '='. @@ -338,7 +291,7 @@ private: /// ConsumeAnyToken - Dispatch to the right Consume* method based on the /// current token type. This should only be used in cases where the type of /// the token really isn't known, e.g. in error recovery. - SourceLocation ConsumeAnyToken() { + SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok = false) { if (isTokenParen()) return ConsumeParen(); else if (isTokenBracket()) @@ -348,7 +301,7 @@ private: else if (isTokenStringLiteral()) return ConsumeStringToken(); else - return ConsumeToken(); + return ConsumeToken(ConsumeCodeCompletionTok); } /// ConsumeParen - This consume method keeps the paren count up-to-date. @@ -849,7 +802,7 @@ private: }; // A list of late-parsed attributes. Used by ParseGNUAttributes. - class LateParsedAttrList: public llvm::SmallVector<LateParsedAttribute*, 2> { + class LateParsedAttrList: public SmallVector<LateParsedAttribute *, 2> { public: LateParsedAttrList(bool PSoon = false) : ParseSoon(PSoon) { } @@ -869,7 +822,7 @@ private: /// \brief Whether this member function had an associated template /// scope. When true, D is a template declaration. - /// othewise, it is a member function declaration. + /// otherwise, it is a member function declaration. bool TemplateScope; explicit LexedMethod(Parser* P, Decl *MD) @@ -1097,7 +1050,8 @@ private: void DeallocateParsedClasses(ParsingClass *Class); void PopParsingClass(Sema::ParsingClassState); - Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, AttributeList *AccessAttrs, + NamedDecl *ParseCXXInlineMethodDef(AccessSpecifier AS, + AttributeList *AccessAttrs, ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo, const VirtSpecifiers& VS, @@ -1159,10 +1113,15 @@ private: ExprResult ParseAsmStringLiteral(); // Objective-C External Declarations + void MaybeSkipAttributes(tok::ObjCKeywordKind Kind); DeclGroupPtrTy ParseObjCAtDirectives(); DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc); Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, ParsedAttributes &prefixAttrs); + void HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc, + BalancedDelimiterTracker &T, + SmallVectorImpl<Decl *> &AllIvarDecls, + bool RBraceMissing); void ParseObjCClassInstanceVariables(Decl *interfaceDecl, tok::ObjCKeywordKind visibility, SourceLocation atLoc); @@ -1289,7 +1248,7 @@ private: SmallVectorImpl<SourceLocation> &CommaLocs, void (Sema::*Completer)(Scope *S, Expr *Data, - llvm::ArrayRef<Expr *> Args) = 0, + ArrayRef<Expr *> Args) = 0, Expr *Data = 0); /// ParenParseOption - Control what ParseParenExpression will parse. @@ -1332,7 +1291,8 @@ private: ParsedType ObjectType, bool EnteringContext, bool *MayBePseudoDestructor = 0, - bool IsTypename = false); + bool IsTypename = false, + IdentifierInfo **LastII = 0); void CheckForLParenAfterColonColon(); @@ -1342,7 +1302,7 @@ private: // [...] () -> type {...} ExprResult ParseLambdaExpression(); ExprResult TryParseLambdaExpression(); - llvm::Optional<unsigned> ParseLambdaIntroducer(LambdaIntroducer &Intro); + Optional<unsigned> ParseLambdaIntroducer(LambdaIntroducer &Intro); bool TryParseLambdaIntroducer(LambdaIntroducer &Intro); ExprResult ParseLambdaExpressionAfterIntroducer( LambdaIntroducer &Intro); @@ -1637,7 +1597,8 @@ private: bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, const ParsedTemplateInfo &TemplateInfo, - AccessSpecifier AS, DeclSpecContext DSC); + AccessSpecifier AS, DeclSpecContext DSC, + ParsedAttributesWithRange &Attrs); DeclSpecContext getDeclSpecContextFromDeclaratorContext(unsigned Context); void ParseDeclarationSpecifiers(DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), @@ -1843,7 +1804,8 @@ public: Declarator::TheContext Context = Declarator::TypeNameContext, AccessSpecifier AS = AS_none, - Decl **OwnedType = 0); + Decl **OwnedType = 0, + ParsedAttributes *Attrs = 0); private: void ParseBlockId(SourceLocation CaretLoc); @@ -1852,11 +1814,22 @@ private: // an attribute is not allowed. bool CheckProhibitedCXX11Attribute() { assert(Tok.is(tok::l_square)); - if (!getLangOpts().CPlusPlus0x || NextToken().isNot(tok::l_square)) + if (!getLangOpts().CPlusPlus11 || NextToken().isNot(tok::l_square)) return false; return DiagnoseProhibitedCXX11Attribute(); } bool DiagnoseProhibitedCXX11Attribute(); + void CheckMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs, + SourceLocation CorrectLocation) { + if (!getLangOpts().CPlusPlus11) + return; + if ((Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) && + Tok.isNot(tok::kw_alignas)) + return; + DiagnoseMisplacedCXX11Attribute(Attrs, CorrectLocation); + } + void DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs, + SourceLocation CorrectLocation); void ProhibitAttributes(ParsedAttributesWithRange &attrs) { if (!attrs.Range.isValid()) return; @@ -1896,26 +1869,26 @@ private: SourceLocation ScopeLoc, AttributeList::Syntax Syntax); - void MaybeParseCXX0XAttributes(Declarator &D) { - if (getLangOpts().CPlusPlus0x && isCXX11AttributeSpecifier()) { + void MaybeParseCXX11Attributes(Declarator &D) { + if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrs(AttrFactory); SourceLocation endLoc; ParseCXX11Attributes(attrs, &endLoc); D.takeAttributes(attrs, endLoc); } } - void MaybeParseCXX0XAttributes(ParsedAttributes &attrs, + void MaybeParseCXX11Attributes(ParsedAttributes &attrs, SourceLocation *endLoc = 0) { - if (getLangOpts().CPlusPlus0x && isCXX11AttributeSpecifier()) { + if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrsWithRange(AttrFactory); ParseCXX11Attributes(attrsWithRange, endLoc); attrs.takeAllFrom(attrsWithRange); } } - void MaybeParseCXX0XAttributes(ParsedAttributesWithRange &attrs, + void MaybeParseCXX11Attributes(ParsedAttributesWithRange &attrs, SourceLocation *endLoc = 0, bool OuterMightBeMessageSend = false) { - if (getLangOpts().CPlusPlus0x && + if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier(false, OuterMightBeMessageSend)) ParseCXX11Attributes(attrs, endLoc); } @@ -1954,7 +1927,7 @@ private: ParsedAttributes &attrs, SourceLocation *endLoc); - bool IsThreadSafetyAttribute(llvm::StringRef AttrName); + bool IsThreadSafetyAttribute(StringRef AttrName); void ParseThreadSafetyAttribute(IdentifierInfo &AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, @@ -1978,13 +1951,13 @@ private: void ParseAlignmentSpecifier(ParsedAttributes &Attrs, SourceLocation *endLoc = 0); - VirtSpecifiers::Specifier isCXX0XVirtSpecifier(const Token &Tok) const; - VirtSpecifiers::Specifier isCXX0XVirtSpecifier() const { - return isCXX0XVirtSpecifier(Tok); + VirtSpecifiers::Specifier isCXX11VirtSpecifier(const Token &Tok) const; + VirtSpecifiers::Specifier isCXX11VirtSpecifier() const { + return isCXX11VirtSpecifier(Tok); } - void ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS, bool IsInterface); + void ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS, bool IsInterface); - bool isCXX0XFinalKeyword() const; + bool isCXX11FinalKeyword() const; /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to /// enter a new C++ declarator scope and exit it when the function is @@ -2027,7 +2000,8 @@ private: DirectDeclParseFunction DirectDeclParser); void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true, - bool CXX0XAttributesAllowed = true); + bool CXX11AttributesAllowed = true, + bool AtomicAllowed = true); void ParseDirectDeclarator(Declarator &D); void ParseParenDeclarator(Declarator &D); void ParseFunctionDeclarator(Declarator &D, @@ -2098,8 +2072,12 @@ private: void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc, DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, bool EnteringContext, - DeclSpecContext DSC); - void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType, + DeclSpecContext DSC, + ParsedAttributesWithRange &Attributes); + void ParseCXXMemberSpecification(SourceLocation StartLoc, + SourceLocation AttrFixitLoc, + ParsedAttributesWithRange &Attrs, + unsigned TagType, Decl *TagDecl); ExprResult ParseCXXMemberInitializer(Decl *D, bool IsFunction, SourceLocation &EqualLoc); @@ -2131,6 +2109,11 @@ private: ParsedType ObjectType, UnqualifiedId &Result); + //===--------------------------------------------------------------------===// + // OpenMP: Directives and clauses. + DeclGroupPtrTy ParseOpenMPDeclarativeDirective(); + bool ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, + SmallVectorImpl<DeclarationNameInfo> &IdList); public: bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowDestructorName, @@ -2173,6 +2156,8 @@ private: // C++ 14.3: Template arguments [temp.arg] typedef SmallVector<ParsedTemplateArgument, 16> TemplateArgList; + bool ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, + bool ConsumeLastToken); bool ParseTemplateIdAfterTemplateName(TemplateTy Template, SourceLocation TemplateNameLoc, const CXXScopeSpec &SS, diff --git a/include/clang/Rewrite/Core/RewriteRope.h b/include/clang/Rewrite/Core/RewriteRope.h index 9f1bbe5..a5192ef 100644 --- a/include/clang/Rewrite/Core/RewriteRope.h +++ b/include/clang/Rewrite/Core/RewriteRope.h @@ -15,10 +15,9 @@ #define LLVM_CLANG_REWRITEROPE_H #include "llvm/Support/Compiler.h" - -#include <cstring> #include <cassert> #include <cstddef> +#include <cstring> #include <iterator> namespace clang { diff --git a/include/clang/Rewrite/Core/Rewriter.h b/include/clang/Rewrite/Core/Rewriter.h index a33ea13..cb044ae 100644 --- a/include/clang/Rewrite/Core/Rewriter.h +++ b/include/clang/Rewrite/Core/Rewriter.h @@ -52,7 +52,11 @@ public: iterator end() const { return Buffer.end(); } unsigned size() const { return Buffer.size(); } - raw_ostream &write(raw_ostream &) const; + /// \brief Write to \p Stream the result of applying all changes to the + /// original buffer. + /// + /// The original buffer is not actually changed. + raw_ostream &write(raw_ostream &Stream) const; /// RemoveText - Remove the specified text. void RemoveText(unsigned OrigOffset, unsigned Size, @@ -279,7 +283,7 @@ public: buffer_iterator buffer_begin() { return RewriteBuffers.begin(); } buffer_iterator buffer_end() { return RewriteBuffers.end(); } - /// SaveFiles - Save all changed files to disk. + /// overwriteChangedFiles - Save all changed files to disk. /// /// Returns whether not all changes were saved successfully. /// Outputs diagnostics via the source manager's diagnostic engine diff --git a/include/clang/Rewrite/Frontend/ASTConsumers.h b/include/clang/Rewrite/Frontend/ASTConsumers.h index c9c92e3..584af3f 100644 --- a/include/clang/Rewrite/Frontend/ASTConsumers.h +++ b/include/clang/Rewrite/Frontend/ASTConsumers.h @@ -35,7 +35,8 @@ ASTConsumer *CreateModernObjCRewriter(const std::string &InFile, raw_ostream *OS, DiagnosticsEngine &Diags, const LangOptions &LOpts, - bool SilenceRewriteMacroWarning); + bool SilenceRewriteMacroWarning, + bool LineInfo); /// CreateHTMLPrinter - Create an AST consumer which rewrites source code to /// HTML with syntax highlighting suitable for viewing in a web-browser. diff --git a/include/clang/Rewrite/Frontend/FixItRewriter.h b/include/clang/Rewrite/Frontend/FixItRewriter.h index f12a034..04c04a2 100644 --- a/include/clang/Rewrite/Frontend/FixItRewriter.h +++ b/include/clang/Rewrite/Frontend/FixItRewriter.h @@ -17,8 +17,8 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Rewrite/Core/Rewriter.h" #include "clang/Edit/EditedSource.h" +#include "clang/Rewrite/Core/Rewriter.h" namespace clang { diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index 2e8b0c0..0f0d218 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -15,11 +15,11 @@ #ifndef LLVM_CLANG_SEMA_ATTRLIST_H #define LLVM_CLANG_SEMA_ATTRLIST_H -#include "llvm/Support/Allocator.h" -#include "llvm/ADT/SmallVector.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/VersionTuple.h" #include "clang/Sema/Ownership.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" #include <cassert> namespace clang { @@ -44,8 +44,9 @@ struct AvailabilityChange { bool isValid() const { return !Version.empty(); } }; -/// AttributeList - Represents GCC's __attribute__ declaration. There are -/// 4 forms of this construct...they are: +/// AttributeList - Represents a syntactic attribute. +/// +/// For a GNU attribute, there are four forms of this construct: /// /// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused. /// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused. @@ -56,12 +57,14 @@ class AttributeList { // TODO: This should really be called ParsedAttribute public: /// The style used to specify an attribute. enum Syntax { + /// __attribute__((...)) AS_GNU, + /// [[...]] AS_CXX11, + /// __declspec(...) AS_Declspec, - // eg) __w64, __ptr32, etc. It is implied that an MSTypespec is also - // a declspec. - AS_MSTypespec + /// __ptr16, alignas(...), etc. + AS_Keyword }; private: IdentifierInfo *AttrName; @@ -70,6 +73,7 @@ private: SourceRange AttrRange; SourceLocation ScopeLoc; SourceLocation ParmLoc; + SourceLocation EllipsisLoc; /// The number of expression arguments this attribute has. /// The expressions themselves are stored after the object. @@ -140,6 +144,14 @@ private: return *reinterpret_cast<const TypeTagForDatatypeData *>(this + 1); } + ParsedType &getTypeBuffer() { + return *reinterpret_cast<ParsedType *>(this + 1); + } + + const ParsedType &getTypeBuffer() const { + return *reinterpret_cast<const ParsedType *>(this + 1); + } + AttributeList(const AttributeList &) LLVM_DELETED_FUNCTION; void operator=(const AttributeList &) LLVM_DELETED_FUNCTION; void operator delete(void *) LLVM_DELETED_FUNCTION; @@ -152,11 +164,11 @@ private: IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierInfo *parmName, SourceLocation parmLoc, Expr **args, unsigned numArgs, - Syntax syntaxUsed) + Syntax syntaxUsed, SourceLocation ellipsisLoc) : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), - NumArgs(numArgs), SyntaxUsed(syntaxUsed), Invalid(false), - UsedAsTypeAttr(false), IsAvailability(false), + EllipsisLoc(ellipsisLoc), NumArgs(numArgs), SyntaxUsed(syntaxUsed), + Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), NextInPosition(0), NextInPool(0) { if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*)); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); @@ -173,7 +185,7 @@ private: const Expr *messageExpr, Syntax syntaxUsed) : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), - AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), + AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), IsTypeTagForDatatype(false), @@ -194,7 +206,7 @@ private: bool mustBeNull, Syntax syntaxUsed) : AttrName(attrName), ScopeName(scopeName), ParmName(argumentKindName), AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(argumentKindLoc), - NumArgs(0), SyntaxUsed(syntaxUsed), + EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(true), NextInPosition(NULL), NextInPool(NULL) { TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot(); @@ -204,6 +216,20 @@ private: AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } + /// Constructor for attributes with a single type argument. + AttributeList(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + ParsedType typeArg, Syntax syntaxUsed) + : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), + AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), + EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false), + UsedAsTypeAttr(false), IsAvailability(false), + IsTypeTagForDatatype(false), NextInPosition(0), NextInPool(0) { + new (&getTypeBuffer()) ParsedType(typeArg); + AttrKind = getKind(getName(), getScopeName(), syntaxUsed); + } + friend class AttributePool; friend class AttributeFactory; @@ -227,12 +253,16 @@ public: IdentifierInfo *getParameterName() const { return ParmName; } SourceLocation getParameterLoc() const { return ParmLoc; } - /// Returns true if the attribute is a pure __declspec or a synthesized - /// declspec representing a type specification (like __w64 or __ptr32). - bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec || - SyntaxUsed == AS_MSTypespec; } - bool isCXX0XAttribute() const { return SyntaxUsed == AS_CXX11; } - bool isMSTypespecAttribute() const { return SyntaxUsed == AS_MSTypespec; } + bool isAlignasAttribute() const { + // FIXME: Use a better mechanism to determine this. + return getKind() == AT_Aligned && SyntaxUsed == AS_Keyword; + } + + bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; } + bool isCXX11Attribute() const { + return SyntaxUsed == AS_CXX11 || isAlignasAttribute(); + } + bool isKeywordAttribute() const { return SyntaxUsed == AS_Keyword; } bool isInvalid() const { return Invalid; } void setInvalid(bool b = true) const { Invalid = b; } @@ -240,6 +270,9 @@ public: bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; } void setUsedAsTypeAttr() { UsedAsTypeAttr = true; } + bool isPackExpansion() const { return EllipsisLoc.isValid(); } + SourceLocation getEllipsisLoc() const { return EllipsisLoc; } + Kind getKind() const { return Kind(AttrKind); } static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope, Syntax SyntaxUsed); @@ -340,6 +373,16 @@ public: "Not a type_tag_for_datatype attribute"); return getTypeTagForDatatypeDataSlot().MustBeNull; } + + const ParsedType &getTypeArg() const { + assert(getKind() == AT_VecTypeHint && "Not a type attribute"); + return getTypeBuffer(); + } + + /// \brief Get an index into the attribute spelling list + /// defined in Attr.td. This index is used by an attribute + /// to pretty print itself. + unsigned getAttributeSpellingListIndex() const; }; /// A factory, from which one makes pools, from which one creates @@ -448,13 +491,15 @@ public: IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierInfo *parmName, SourceLocation parmLoc, Expr **args, unsigned numArgs, - AttributeList::Syntax syntax) { + AttributeList::Syntax syntax, + SourceLocation ellipsisLoc = SourceLocation()) { void *memory = allocate(sizeof(AttributeList) + numArgs * sizeof(Expr*)); return add(new (memory) AttributeList(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, - args, numArgs, syntax)); + args, numArgs, syntax, + ellipsisLoc)); } AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, @@ -491,6 +536,18 @@ public: matchingCType, layoutCompatible, mustBeNull, syntax)); } + + AttributeList *createTypeAttribute( + IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + ParsedType typeArg, AttributeList::Syntax syntaxUsed) { + void *memory = allocate(sizeof(AttributeList) + sizeof(void *)); + return add(new (memory) AttributeList(attrName, attrRange, + scopeName, scopeLoc, + parmName, parmLoc, + typeArg, syntaxUsed)); + } }; /// addAttributeLists - Add two AttributeLists together @@ -511,18 +568,18 @@ inline AttributeList *addAttributeLists(AttributeList *Left, return Left; } -/// CXX0XAttributeList - A wrapper around a C++0x attribute list. +/// CXX11AttributeList - A wrapper around a C++11 attribute list. /// Stores, in addition to the list proper, whether or not an actual list was /// (as opposed to an empty list, which may be ill-formed in some places) and /// the source range of the list. -struct CXX0XAttributeList { +struct CXX11AttributeList { AttributeList *AttrList; SourceRange Range; bool HasAttr; - CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr) + CXX11AttributeList (AttributeList *attrList, SourceRange range, bool hasAttr) : AttrList(attrList), Range(range), HasAttr (hasAttr) { } - CXX0XAttributeList () + CXX11AttributeList () : AttrList(0), Range(), HasAttr(false) { } }; @@ -588,10 +645,11 @@ public: IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierInfo *parmName, SourceLocation parmLoc, Expr **args, unsigned numArgs, - AttributeList::Syntax syntax) { + AttributeList::Syntax syntax, + SourceLocation ellipsisLoc = SourceLocation()) { AttributeList *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, - args, numArgs, syntax); + args, numArgs, syntax, ellipsisLoc); add(attr); return attr; } @@ -632,6 +690,19 @@ public: return attr; } + /// Add an attribute with a single type argument. + AttributeList * + addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + ParsedType typeArg, AttributeList::Syntax syntaxUsed) { + AttributeList *attr = + pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc, + parmName, parmLoc, typeArg, syntaxUsed); + add(attr); + return attr; + } + AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name, SourceLocation loc, int arg) { AttributeList *attr = diff --git a/include/clang/Sema/CMakeLists.txt b/include/clang/Sema/CMakeLists.txt index 03f99a3..6b5d222 100644 --- a/include/clang/Sema/CMakeLists.txt +++ b/include/clang/Sema/CMakeLists.txt @@ -11,4 +11,9 @@ clang_tablegen(AttrParsedAttrList.inc -gen-clang-attr-parsed-attr-list clang_tablegen(AttrParsedAttrKinds.inc -gen-clang-attr-parsed-attr-kinds -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ SOURCE ../Basic/Attr.td - TARGET ClangAttrParsedAttrKinds)
\ No newline at end of file + TARGET ClangAttrParsedAttrKinds) + +clang_tablegen(AttrSpellingListIndex.inc -gen-clang-attr-spelling-index + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ + SOURCE ../Basic/Attr.td + TARGET ClangAttrSpellingListIndex) diff --git a/include/clang/Sema/CXXFieldCollector.h b/include/clang/Sema/CXXFieldCollector.h index 6f3c0b4..6685751 100644 --- a/include/clang/Sema/CXXFieldCollector.h +++ b/include/clang/Sema/CXXFieldCollector.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_SEMA_CXXFIELDCOLLECTOR_H #define LLVM_CLANG_SEMA_CXXFIELDCOLLECTOR_H +#include "clang/Basic/LLVM.h" #include "llvm/ADT/SmallVector.h" namespace clang { diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index b128bd8..a1ddec7 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -13,13 +13,13 @@ #ifndef LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H #define LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H -#include "clang/AST/Type.h" +#include "clang-c/Index.h" #include "clang/AST/CanonicalType.h" +#include "clang/AST/Type.h" #include "clang/Sema/CodeCompleteOptions.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" -#include "clang-c/Index.h" #include <string> namespace clang { @@ -121,7 +121,7 @@ SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T); /// \brief Determine the type that this declaration will have if it is used /// as a type or in an expression. -QualType getDeclUsageType(ASTContext &C, NamedDecl *ND); +QualType getDeclUsageType(ASTContext &C, const NamedDecl *ND); /// \brief Determine the priority to be given to a macro code completion result /// with the given name. @@ -138,7 +138,7 @@ unsigned getMacroUsagePriority(StringRef MacroName, /// \brief Determine the libclang cursor kind associated with the given /// declaration. -CXCursorKind getCursorKindForDecl(Decl *D); +CXCursorKind getCursorKindForDecl(const Decl *D); class FunctionDecl; class FunctionType; @@ -245,7 +245,8 @@ public: /// \brief Code completion in a parenthesized expression, which means that /// we may also have types here in C and Objective-C (as well as in C++). CCC_ParenthesizedExpression, - /// \brief Code completion where an Objective-C instance message is expcted. + /// \brief Code completion where an Objective-C instance message is + /// expected. CCC_ObjCInstanceMessage, /// \brief Code completion where an Objective-C class message is expected. CCC_ObjCClassMessage, @@ -530,7 +531,7 @@ class GlobalCodeCompletionAllocator }; class CodeCompletionTUInfo { - llvm::DenseMap<DeclContext *, StringRef> ParentNames; + llvm::DenseMap<const DeclContext *, StringRef> ParentNames; IntrusiveRefCntPtr<GlobalCodeCompletionAllocator> AllocatorRef; public: @@ -546,7 +547,7 @@ public: return *AllocatorRef; } - StringRef getParentName(DeclContext *DC); + StringRef getParentName(const DeclContext *DC); }; } // end namespace clang @@ -629,8 +630,9 @@ public: void AddAnnotation(const char *A) { Annotations.push_back(A); } /// \brief Add the parent context information to this code completion. - void addParentContext(DeclContext *DC); + void addParentContext(const DeclContext *DC); + const char *getBriefComment() const { return BriefComment; } void addBriefComment(StringRef Comment); StringRef getParentName() const { return ParentName; } @@ -649,7 +651,7 @@ public: /// \brief When Kind == RK_Declaration or RK_Pattern, the declaration we are /// referring to. In the latter case, the declaration might be NULL. - NamedDecl *Declaration; + const NamedDecl *Declaration; union { /// \brief When Kind == RK_Keyword, the string representing the keyword @@ -661,7 +663,7 @@ public: CodeCompletionString *Pattern; /// \brief When Kind == RK_Macro, the identifier that refers to a macro. - IdentifierInfo *Macro; + const IdentifierInfo *Macro; }; /// \brief The priority of this particular code-completion result. @@ -704,11 +706,12 @@ public: NestedNameSpecifier *Qualifier; /// \brief Build a result that refers to a declaration. - CodeCompletionResult(NamedDecl *Declaration, + CodeCompletionResult(const NamedDecl *Declaration, + unsigned Priority, NestedNameSpecifier *Qualifier = 0, bool QualifierIsInformative = false, bool Accessible = true) - : Declaration(Declaration), Priority(getPriorityFromDecl(Declaration)), + : Declaration(Declaration), Priority(Priority), StartParameter(0), Kind(RK_Declaration), Availability(CXAvailability_Available), Hidden(false), QualifierIsInformative(QualifierIsInformative), @@ -728,7 +731,8 @@ public: } /// \brief Build a result that refers to a macro. - CodeCompletionResult(IdentifierInfo *Macro, unsigned Priority = CCP_Macro) + CodeCompletionResult(const IdentifierInfo *Macro, + unsigned Priority = CCP_Macro) : Declaration(0), Macro(Macro), Priority(Priority), StartParameter(0), Kind(RK_Macro), CursorKind(CXCursor_MacroDefinition), Availability(CXAvailability_Available), Hidden(false), @@ -742,7 +746,7 @@ public: unsigned Priority = CCP_CodePattern, CXCursorKind CursorKind = CXCursor_NotImplemented, CXAvailabilityKind Availability = CXAvailability_Available, - NamedDecl *D = 0) + const NamedDecl *D = 0) : Declaration(D), Pattern(Pattern), Priority(Priority), StartParameter(0), Kind(RK_Pattern), CursorKind(CursorKind), Availability(Availability), Hidden(false), QualifierIsInformative(0), @@ -763,7 +767,7 @@ public: } /// \brief Retrieve the declaration stored in this result. - NamedDecl *getDeclaration() const { + const NamedDecl *getDeclaration() const { assert(Kind == RK_Declaration && "Not a declaration result"); return Declaration; } @@ -791,9 +795,6 @@ public: CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments); - /// \brief Determine a base priority for the given declaration. - static unsigned getPriorityFromDecl(NamedDecl *ND); - private: void computeCursorKindAndAvailability(bool Accessible = true); }; diff --git a/include/clang/Sema/CodeCompleteOptions.h b/include/clang/Sema/CodeCompleteOptions.h index 30712db..e43496f 100644 --- a/include/clang/Sema/CodeCompleteOptions.h +++ b/include/clang/Sema/CodeCompleteOptions.h @@ -13,16 +13,16 @@ /// Options controlling the behavior of code completion. class CodeCompleteOptions { public: - ///< Show macros in code completion results. + /// Show macros in code completion results. unsigned IncludeMacros : 1; - ///< Show code patterns in code completion results. + /// Show code patterns in code completion results. unsigned IncludeCodePatterns : 1; - ///< Show top-level decls in code completion results. + /// Show top-level decls in code completion results. unsigned IncludeGlobals : 1; - ///< Show brief documentation comments in code completion results. + /// Show brief documentation comments in code completion results. unsigned IncludeBriefComments : 1; CodeCompleteOptions() : diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 0728e87..5b90784 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -23,14 +23,14 @@ #ifndef LLVM_CLANG_SEMA_DECLSPEC_H #define LLVM_CLANG_SEMA_DECLSPEC_H -#include "clang/Sema/AttributeList.h" -#include "clang/Sema/Ownership.h" #include "clang/AST/NestedNameSpecifier.h" -#include "clang/Lex/Token.h" #include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/Lambda.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/Specifiers.h" +#include "clang/Lex/Token.h" +#include "clang/Sema/AttributeList.h" +#include "clang/Sema/Ownership.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" @@ -276,6 +276,14 @@ public: static const TST TST_auto = clang::TST_auto; static const TST TST_unknown_anytype = clang::TST_unknown_anytype; static const TST TST_atomic = clang::TST_atomic; + static const TST TST_image1d_t = clang::TST_image1d_t; + static const TST TST_image1d_array_t = clang::TST_image1d_array_t; + static const TST TST_image1d_buffer_t = clang::TST_image1d_buffer_t; + static const TST TST_image2d_t = clang::TST_image2d_t; + static const TST TST_image2d_array_t = clang::TST_image2d_array_t; + static const TST TST_image3d_t = clang::TST_image3d_t; + static const TST TST_sampler_t = clang::TST_sampler_t; + static const TST TST_event_t = clang::TST_event_t; static const TST TST_error = clang::TST_error; // type-qualifiers @@ -283,7 +291,10 @@ public: TQ_unspecified = 0, TQ_const = 1, TQ_restrict = 2, - TQ_volatile = 4 + TQ_volatile = 4, + // This has no corresponding Qualifiers::TQ value, because it's not treated + // as a qualifier in our type system. + TQ_atomic = 8 }; /// ParsedSpecifiers - Flags to query which specifiers were applied. This is @@ -306,19 +317,20 @@ private: /*TSW*/unsigned TypeSpecWidth : 2; /*TSC*/unsigned TypeSpecComplex : 2; /*TSS*/unsigned TypeSpecSign : 2; - /*TST*/unsigned TypeSpecType : 5; + /*TST*/unsigned TypeSpecType : 6; unsigned TypeAltiVecVector : 1; unsigned TypeAltiVecPixel : 1; unsigned TypeAltiVecBool : 1; unsigned TypeSpecOwned : 1; // type-qualifiers - unsigned TypeQualifiers : 3; // Bitwise OR of TQ. + unsigned TypeQualifiers : 4; // Bitwise OR of TQ. // function-specifier unsigned FS_inline_specified : 1; unsigned FS_virtual_specified : 1; unsigned FS_explicit_specified : 1; + unsigned FS_noreturn_specified : 1; // friend-specifier unsigned Friend_specified : 1; @@ -326,8 +338,6 @@ private: // constexpr-specifier unsigned Constexpr_specified : 1; - /*SCS*/unsigned StorageClassSpecAsWritten : 3; - union { UnionParsedType TypeRep; Decl *DeclRep; @@ -360,13 +370,12 @@ private: /// TSTNameLoc provides source range info for tag types. SourceLocation TSTNameLoc; SourceRange TypeofParensRange; - SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc; - SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc; + SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc; + SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc; SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc; WrittenBuiltinSpecs writtenBS; void SaveWrittenBuiltinSpecs(); - void SaveStorageSpecifierAsWritten(); ObjCDeclSpec *ObjCQualifiers; @@ -377,16 +386,16 @@ private: static bool isExprRep(TST T) { return (T == TST_typeofExpr || T == TST_decltype); } + + DeclSpec(const DeclSpec &) LLVM_DELETED_FUNCTION; + void operator=(const DeclSpec &) LLVM_DELETED_FUNCTION; +public: static bool isDeclRep(TST T) { return (T == TST_enum || T == TST_struct || T == TST_interface || T == TST_union || T == TST_class); } - DeclSpec(const DeclSpec &) LLVM_DELETED_FUNCTION; - void operator=(const DeclSpec &) LLVM_DELETED_FUNCTION; -public: - DeclSpec(AttributeFactory &attrFactory) : StorageClassSpec(SCS_unspecified), SCS_thread_specified(false), @@ -403,9 +412,9 @@ public: FS_inline_specified(false), FS_virtual_specified(false), FS_explicit_specified(false), + FS_noreturn_specified(false), Friend_specified(false), Constexpr_specified(false), - StorageClassSpecAsWritten(SCS_unspecified), Attrs(attrFactory), ProtocolQualifiers(0), NumProtocolQualifiers(0), @@ -493,6 +502,7 @@ public: SourceLocation getConstSpecLoc() const { return TQ_constLoc; } SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; } SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; } + SourceLocation getAtomicSpecLoc() const { return TQ_atomicLoc; } /// \brief Clear out all of the type qualifiers. void ClearTypeQualifiers() { @@ -500,6 +510,7 @@ public: TQ_constLoc = SourceLocation(); TQ_restrictLoc = SourceLocation(); TQ_volatileLoc = SourceLocation(); + TQ_atomicLoc = SourceLocation(); } // function-specifier @@ -512,6 +523,9 @@ public: bool isExplicitSpecified() const { return FS_explicit_specified; } SourceLocation getExplicitSpecLoc() const { return FS_explicitLoc; } + bool isNoreturnSpecified() const { return FS_noreturn_specified; } + SourceLocation getNoreturnSpecLoc() const { return FS_noreturnLoc; } + void ClearFunctionSpecs() { FS_inline_specified = false; FS_inlineLoc = SourceLocation(); @@ -519,6 +533,8 @@ public: FS_virtualLoc = SourceLocation(); FS_explicit_specified = false; FS_explicitLoc = SourceLocation(); + FS_noreturn_specified = false; + FS_noreturnLoc = SourceLocation(); } /// \brief Return true if any type-specifier has been found. @@ -533,10 +549,6 @@ public: /// DeclSpec includes. unsigned getParsedSpecifiers() const; - SCS getStorageClassSpecAsWritten() const { - return (SCS)StorageClassSpecAsWritten; - } - /// isEmpty - Return true if this declaration specifier is completely empty: /// no tokens were parsed in the production of it. bool isEmpty() const { @@ -602,12 +614,10 @@ public: bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const LangOptions &Lang); - bool SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID); - bool SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID); - bool SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID); + bool setFunctionSpecInline(SourceLocation Loc); + bool setFunctionSpecVirtual(SourceLocation Loc); + bool setFunctionSpecExplicit(SourceLocation Loc); + bool setFunctionSpecNoreturn(SourceLocation Loc); bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); @@ -808,6 +818,20 @@ public: IK_ImplicitSelfParam } Kind; + struct OFI { + /// \brief The kind of overloaded operator. + OverloadedOperatorKind Operator; + + /// \brief The source locations of the individual tokens that name + /// the operator, e.g., the "new", "[", and "]" tokens in + /// operator new []. + /// + /// Different operators have different numbers of tokens in their name, + /// up to three. Any remaining source locations in this array will be + /// set to an invalid value for operators with fewer than three tokens. + unsigned SymbolLocations[3]; + }; + /// \brief Anonymous union that holds extra data associated with the /// parsed unqualified-id. union { @@ -817,19 +841,7 @@ public: /// \brief When Kind == IK_OperatorFunctionId, the overloaded operator /// that we parsed. - struct { - /// \brief The kind of overloaded operator. - OverloadedOperatorKind Operator; - - /// \brief The source locations of the individual tokens that name - /// the operator, e.g., the "new", "[", and "]" tokens in - /// operator new []. - /// - /// Different operators have different numbers of tokens in their name, - /// up to three. Any remaining source locations in this array will be - /// set to an invalid value for operators with fewer than three tokens. - unsigned SymbolLocations[3]; - } OperatorFunctionId; + struct OFI OperatorFunctionId; /// \brief When Kind == IK_ConversionFunctionId, the type that the /// conversion function names. @@ -1010,8 +1022,8 @@ struct DeclaratorChunk { }; struct PointerTypeInfo : TypeInfoCommon { - /// The type qualifiers: const/volatile/restrict. - unsigned TypeQuals : 3; + /// The type qualifiers: const/volatile/restrict/atomic. + unsigned TypeQuals : 4; /// The location of the const-qualifier, if any. unsigned ConstQualLoc; @@ -1022,6 +1034,9 @@ struct DeclaratorChunk { /// The location of the restrict-qualifier, if any. unsigned RestrictQualLoc; + /// The location of the _Atomic-qualifier, if any. + unsigned AtomicQualLoc; + void destroy() { } }; @@ -1036,8 +1051,8 @@ struct DeclaratorChunk { }; struct ArrayTypeInfo : TypeInfoCommon { - /// The type qualifiers for the array: const/volatile/restrict. - unsigned TypeQuals : 3; + /// The type qualifiers for the array: const/volatile/restrict/_Atomic. + unsigned TypeQuals : 4; /// True if this dimension included the 'static' keyword. bool hasStatic : 1; @@ -1259,16 +1274,16 @@ struct DeclaratorChunk { struct BlockPointerTypeInfo : TypeInfoCommon { /// For now, sema will catch these as invalid. - /// The type qualifiers: const/volatile/restrict. - unsigned TypeQuals : 3; + /// The type qualifiers: const/volatile/restrict/_Atomic. + unsigned TypeQuals : 4; void destroy() { } }; struct MemberPointerTypeInfo : TypeInfoCommon { - /// The type qualifiers: const/volatile/restrict. - unsigned TypeQuals : 3; + /// The type qualifiers: const/volatile/restrict/_Atomic. + unsigned TypeQuals : 4; // CXXScopeSpec has a constructor, so it can't be a direct member. // So we need some pointer-aligned storage and a bit of trickery. union { @@ -1422,6 +1437,9 @@ struct DeclaratorChunk { return I; } + bool isParen() const { + return Kind == Paren; + } }; /// \brief Described the kind of function definition (if any) provided for @@ -1783,33 +1801,41 @@ public: return DeclTypeInfo[i]; } - void DropFirstTypeObject() - { + void DropFirstTypeObject() { assert(!DeclTypeInfo.empty() && "No type chunks to drop."); DeclTypeInfo.front().destroy(); DeclTypeInfo.erase(DeclTypeInfo.begin()); } + /// Return the innermost (closest to the declarator) chunk of this + /// declarator that is not a parens chunk, or null if there are no + /// non-parens chunks. + const DeclaratorChunk *getInnermostNonParenChunk() const { + for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) { + if (!DeclTypeInfo[i].isParen()) + return &DeclTypeInfo[i]; + } + return 0; + } + + /// Return the outermost (furthest from the declarator) chunk of + /// this declarator that is not a parens chunk, or null if there are + /// no non-parens chunks. + const DeclaratorChunk *getOutermostNonParenChunk() const { + for (unsigned i = DeclTypeInfo.size(), i_end = 0; i != i_end; --i) { + if (!DeclTypeInfo[i-1].isParen()) + return &DeclTypeInfo[i-1]; + } + return 0; + } + /// isArrayOfUnknownBound - This method returns true if the declarator /// is a declarator for an array of unknown bound (looking through /// parentheses). bool isArrayOfUnknownBound() const { - for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) { - switch (DeclTypeInfo[i].Kind) { - case DeclaratorChunk::Paren: - continue; - case DeclaratorChunk::Function: - case DeclaratorChunk::Pointer: - case DeclaratorChunk::Reference: - case DeclaratorChunk::BlockPointer: - case DeclaratorChunk::MemberPointer: - return false; - case DeclaratorChunk::Array: - return !DeclTypeInfo[i].Arr.NumElts; - } - llvm_unreachable("Invalid type chunk"); - } - return false; + const DeclaratorChunk *chunk = getInnermostNonParenChunk(); + return (chunk && chunk->Kind == DeclaratorChunk::Array && + !chunk->Arr.NumElts); } /// isFunctionDeclarator - This method returns true if the declarator @@ -1866,7 +1892,54 @@ public: /// isn't a function declarator, if the type specifier refers to a function /// type. This routine checks for both cases. bool isDeclarationOfFunction() const; + + /// \brief Return true if this declaration appears in a context where a + /// function declarator would be a function declaration. + bool isFunctionDeclarationContext() const { + if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) + return false; + + switch (Context) { + case FileContext: + case MemberContext: + case BlockContext: + return true; + + case ForContext: + case ConditionContext: + case KNRTypeListContext: + case TypeNameContext: + case AliasDeclContext: + case AliasTemplateContext: + case PrototypeContext: + case ObjCParameterContext: + case ObjCResultContext: + case TemplateParamContext: + case CXXNewContext: + case CXXCatchContext: + case ObjCCatchContext: + case BlockLiteralContext: + case LambdaExprContext: + case TemplateTypeArgContext: + case TrailingReturnContext: + return false; + } + llvm_unreachable("unknown context kind!"); + } + /// \brief Return true if a function declarator at this position would be a + /// function declaration. + bool isFunctionDeclaratorAFunctionDeclaration() const { + if (!isFunctionDeclarationContext()) + return false; + + for (unsigned I = 0, N = getNumTypeObjects(); I != N; ++I) + if (getTypeObject(I).Kind != DeclaratorChunk::Paren) + return false; + + return true; + } + /// takeAttributes - Takes attributes from the given parsed-attributes /// set and add them to this declarator. /// @@ -1897,6 +1970,17 @@ public: return false; } + /// \brief Return a source range list of C++11 attributes associated + /// with the declarator. + void getCXX11AttributeRanges(SmallVector<SourceRange, 4> &Ranges) { + AttributeList *AttrList = Attrs.getList(); + while (AttrList) { + if (AttrList->isCXX11Attribute()) + Ranges.push_back(AttrList->getRange()); + AttrList = AttrList->getNext(); + } + } + void setAsmLabel(Expr *E) { AsmLabel = E; } Expr *getAsmLabel() const { return AsmLabel; } @@ -1996,7 +2080,7 @@ struct LambdaIntroducer { SourceRange Range; SourceLocation DefaultLoc; LambdaCaptureDefault Default; - llvm::SmallVector<LambdaCapture, 4> Captures; + SmallVector<LambdaCapture, 4> Captures; LambdaIntroducer() : Default(LCD_None) {} diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h index a20480c..3704e09 100644 --- a/include/clang/Sema/DelayedDiagnostic.h +++ b/include/clang/Sema/DelayedDiagnostic.h @@ -199,21 +199,25 @@ public: } private: + + struct DD { + const NamedDecl *Decl; + const ObjCInterfaceDecl *UnknownObjCClass; + const ObjCPropertyDecl *ObjCProperty; + const char *Message; + size_t MessageLen; + }; + + struct FTD { + unsigned Diagnostic; + unsigned Argument; + void *OperandType; + }; + union { - /// Deprecation. - struct { - const NamedDecl *Decl; - const ObjCInterfaceDecl *UnknownObjCClass; - const ObjCPropertyDecl *ObjCProperty; - const char *Message; - size_t MessageLen; - } DeprecationData; - - struct { - unsigned Diagnostic; - unsigned Argument; - void *OperandType; - } ForbiddenTypeData; + /// Deprecation + struct DD DeprecationData; + struct FTD ForbiddenTypeData; /// Access control. char AccessData[sizeof(AccessedEntity)]; @@ -224,14 +228,14 @@ private: /// delayed. class DelayedDiagnosticPool { const DelayedDiagnosticPool *Parent; - llvm::SmallVector<DelayedDiagnostic, 4> Diagnostics; + SmallVector<DelayedDiagnostic, 4> Diagnostics; DelayedDiagnosticPool(const DelayedDiagnosticPool &) LLVM_DELETED_FUNCTION; void operator=(const DelayedDiagnosticPool &) LLVM_DELETED_FUNCTION; public: DelayedDiagnosticPool(const DelayedDiagnosticPool *parent) : Parent(parent) {} ~DelayedDiagnosticPool() { - for (llvm::SmallVectorImpl<DelayedDiagnostic>::iterator + for (SmallVectorImpl<DelayedDiagnostic>::iterator i = Diagnostics.begin(), e = Diagnostics.end(); i != e; ++i) i->Destroy(); } @@ -260,8 +264,7 @@ public: pool.Diagnostics.clear(); } - typedef llvm::SmallVectorImpl<DelayedDiagnostic>::const_iterator - pool_iterator; + typedef SmallVectorImpl<DelayedDiagnostic>::const_iterator pool_iterator; pool_iterator pool_begin() const { return Diagnostics.begin(); } pool_iterator pool_end() const { return Diagnostics.end(); } bool pool_empty() const { return Diagnostics.empty(); } diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h index 7a59849..cbce757 100644 --- a/include/clang/Sema/ExternalSemaSource.h +++ b/include/clang/Sema/ExternalSemaSource.h @@ -15,6 +15,7 @@ #include "clang/AST/ExternalASTSource.h" #include "clang/Sema/Weak.h" +#include "llvm/ADT/MapVector.h" #include <utility> namespace clang { @@ -65,7 +66,12 @@ public: /// which will be used during typo correction. virtual void ReadKnownNamespaces( SmallVectorImpl<NamespaceDecl *> &Namespaces); - + + /// \brief Load the set of used but not defined functions or variables with + /// internal linkage, or used but not defined internal functions. + virtual void ReadUndefinedButUsed( + llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined); + /// \brief Do last resort, unqualified lookup on a LookupResult that /// Sema cannot find. /// @@ -130,7 +136,7 @@ public: /// declarations to the given vector of declarations. Note that this routine /// may be invoked multiple times; the external source should take care not /// to introduce the same declarations repeatedly. - virtual void ReadLocallyScopedExternalDecls( + virtual void ReadLocallyScopedExternCDecls( SmallVectorImpl<NamedDecl *> &Decls) {} /// \brief Read the set of referenced selectors known to the diff --git a/include/clang/Sema/IdentifierResolver.h b/include/clang/Sema/IdentifierResolver.h index dff0134..0b1b74a 100644 --- a/include/clang/Sema/IdentifierResolver.h +++ b/include/clang/Sema/IdentifierResolver.h @@ -158,8 +158,7 @@ public: /// \param ExplicitInstantiationOrSpecialization When true, we are checking /// whether the declaration is in scope for the purposes of explicit template /// instantiation or specialization. The default is false. - bool isDeclInScope(Decl *D, DeclContext *Ctx, ASTContext &Context, - Scope *S = 0, + bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0, bool ExplicitInstantiationOrSpecialization = false) const; /// AddDecl - Link the decl to its shadowed decl chain. diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index 0b0af0c..8459be1 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -13,12 +13,13 @@ #ifndef LLVM_CLANG_SEMA_INITIALIZATION_H #define LLVM_CLANG_SEMA_INITIALIZATION_H -#include "clang/Sema/Ownership.h" -#include "clang/Sema/Overload.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/Type.h" #include "clang/AST/UnresolvedSet.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Sema/Overload.h" +#include "clang/Sema/Ownership.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" #include <cassert> @@ -87,7 +88,27 @@ private: /// \brief The type of the object or reference being initialized. QualType Type; - + + struct LN { + /// \brief When Kind == EK_Result, EK_Exception, EK_New, the + /// location of the 'return', 'throw', or 'new' keyword, + /// respectively. When Kind == EK_Temporary, the location where + /// the temporary is being created. + unsigned Location; + + /// \brief Whether the entity being initialized may end up using the + /// named return value optimization (NRVO). + bool NRVO; + }; + + struct C { + /// \brief The variable being captured by an EK_LambdaCapture. + VarDecl *Var; + + /// \brief The source location at which the capture occurs. + unsigned Location; + }; + union { /// \brief When Kind == EK_Variable, or EK_Member, the VarDecl or /// FieldDecl, respectively. @@ -100,18 +121,8 @@ private: /// \brief When Kind == EK_Temporary, the type source information for /// the temporary. TypeSourceInfo *TypeInfo; - - struct { - /// \brief When Kind == EK_Result, EK_Exception, EK_New, the - /// location of the 'return', 'throw', or 'new' keyword, - /// respectively. When Kind == EK_Temporary, the location where - /// the temporary is being created. - unsigned Location; - - /// \brief Whether the entity being initialized may end up using the - /// named return value optimization (NRVO). - bool NRVO; - } LocAndNRVO; + + struct LN LocAndNRVO; /// \brief When Kind == EK_Base, the base specifier that provides the /// base class. The lower bit specifies whether the base is an inherited @@ -122,14 +133,8 @@ private: /// EK_ComplexElement, the index of the array or vector element being /// initialized. unsigned Index; - - struct { - /// \brief The variable being captured by an EK_LambdaCapture. - VarDecl *Var; - - /// \brief The source location at which the capture occurs. - unsigned Location; - } Capture; + + struct C Capture; }; InitializedEntity() { } @@ -172,17 +177,25 @@ public: static InitializedEntity InitializeVariable(VarDecl *Var) { return InitializedEntity(Var); } - + /// \brief Create the initialization entity for a parameter. static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm) { + return InitializeParameter(Context, Parm, Parm->getType()); + } + + /// \brief Create the initialization entity for a parameter, but use + /// another type. + static InitializedEntity InitializeParameter(ASTContext &Context, + ParmVarDecl *Parm, + QualType Type) { bool Consumed = (Context.getLangOpts().ObjCAutoRefCount && Parm->hasAttr<NSConsumedAttr>()); InitializedEntity Entity; Entity.Kind = EK_Parameter; - Entity.Type = Context.getVariableArrayDecayedType( - Parm->getType().getUnqualifiedType()); + Entity.Type = + Context.getVariableArrayDecayedType(Type.getUnqualifiedType()); Entity.Parent = 0; Entity.Parameter = (static_cast<uintptr_t>(Consumed) | reinterpret_cast<uintptr_t>(Parm)); @@ -615,7 +628,11 @@ public: /// \brief Produce an Objective-C object pointer. SK_ProduceObjCObject, /// \brief Construct a std::initializer_list from an initializer list. - SK_StdInitializerList + SK_StdInitializerList, + /// \brief Initialize an OpenCL sampler from an integer. + SK_OCLSamplerInit, + /// \brief Passing zero to a function where OpenCL event_t is expected. + SK_OCLZeroEvent }; /// \brief A single step in the initialization sequence. @@ -626,7 +643,13 @@ public: // \brief The type that results from this initialization. QualType Type; - + + struct F { + bool HadMultipleCandidates; + FunctionDecl *Function; + DeclAccessPair FoundDecl; + }; + union { /// \brief When Kind == SK_ResolvedOverloadedFunction or Kind == /// SK_UserConversion, the function that the expression should be @@ -638,11 +661,7 @@ public: /// selected from an overloaded set having size greater than 1. /// For conversion decls, the naming class is the source type. /// For construct decls, the naming class is the target type. - struct { - bool HadMultipleCandidates; - FunctionDecl *Function; - DeclAccessPair FoundDecl; - } Function; + struct F Function; /// \brief When Kind = SK_ConversionSequence, the implicit conversion /// sequence. @@ -944,6 +963,14 @@ public: /// initializer list. void AddStdInitializerListConstructionStep(QualType T); + /// \brief Add a step to initialize an OpenCL sampler from an integer + /// constant. + void AddOCLSamplerInitStep(QualType T); + + /// \brief Add a step to initialize an OpenCL event_t from a NULL + /// constant. + void AddOCLZeroEventStep(QualType T); + /// \brief Add steps to unwrap a initializer list for a reference around a /// single element and rewrap it at the end. void RewrapReferenceInitList(QualType T, InitListExpr *Syntactic); diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h index fe5d262..3e7e3a1 100644 --- a/include/clang/Sema/Lookup.h +++ b/include/clang/Sema/Lookup.h @@ -15,8 +15,8 @@ #ifndef LLVM_CLANG_SEMA_LOOKUP_H #define LLVM_CLANG_SEMA_LOOKUP_H -#include "clang/Sema/Sema.h" #include "clang/AST/DeclCXX.h" +#include "clang/Sema/Sema.h" namespace clang { @@ -138,7 +138,8 @@ public: IDNS(0), Redecl(Redecl != Sema::NotForRedeclaration), HideTags(true), - Diagnose(Redecl == Sema::NotForRedeclaration) + Diagnose(Redecl == Sema::NotForRedeclaration), + AllowHidden(Redecl == Sema::ForRedeclaration) { configure(); } @@ -158,7 +159,8 @@ public: IDNS(0), Redecl(Redecl != Sema::NotForRedeclaration), HideTags(true), - Diagnose(Redecl == Sema::NotForRedeclaration) + Diagnose(Redecl == Sema::NotForRedeclaration), + AllowHidden(Redecl == Sema::ForRedeclaration) { configure(); } @@ -176,7 +178,8 @@ public: IDNS(Other.IDNS), Redecl(Other.Redecl), HideTags(Other.HideTags), - Diagnose(false) + Diagnose(false), + AllowHidden(Other.AllowHidden) {} ~LookupResult() { @@ -214,10 +217,16 @@ public: return Redecl; } + /// \brief Specify whether hidden declarations are visible, e.g., + /// for recovery reasons. + void setAllowHidden(bool AH) { + AllowHidden = AH; + } + /// \brief Determine whether this lookup is permitted to see hidden /// declarations, such as those in modules that have not yet been imported. bool isHiddenDeclarationVisible() const { - return Redecl || LookupKind == Sema::LookupTagName; + return AllowHidden || LookupKind == Sema::LookupTagName; } /// Sets whether tag declarations should be hidden by non-tag @@ -483,6 +492,7 @@ public: /// \brief Change this lookup's redeclaration kind. void setRedeclarationKind(Sema::RedeclarationKind RK) { Redecl = RK; + AllowHidden = (RK == Sema::ForRedeclaration); configure(); } @@ -615,7 +625,7 @@ private: bool sanityCheckUnresolved() const { for (iterator I = begin(), E = end(); I != E; ++I) - if (isa<UnresolvedUsingValueDecl>(*I)) + if (isa<UnresolvedUsingValueDecl>((*I)->getUnderlyingDecl())) return true; return false; } @@ -644,6 +654,9 @@ private: bool HideTags; bool Diagnose; + + /// \brief True if we should allow hidden declarations to be 'visible'. + bool AllowHidden; }; /// \brief Consumes visible declarations found when searching for diff --git a/include/clang/Sema/Makefile b/include/clang/Sema/Makefile index f6662d6..7d658a7 100644 --- a/include/clang/Sema/Makefile +++ b/include/clang/Sema/Makefile @@ -1,6 +1,7 @@ CLANG_LEVEL := ../../.. TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic -BUILT_SOURCES = AttrTemplateInstantiate.inc AttrParsedAttrList.inc AttrParsedAttrKinds.inc +BUILT_SOURCES = AttrTemplateInstantiate.inc AttrParsedAttrList.inc AttrParsedAttrKinds.inc \ + AttrSpellingListIndex.inc TABLEGEN_INC_FILES_COMMON = 1 @@ -24,4 +25,10 @@ $(ObjDir)/AttrParsedAttrKinds.inc.tmp : $(TD_SRC_DIR)/Attr.td \ $(Verb) $(ClangTableGen) -gen-clang-attr-parsed-attr-kinds -o \ $(call SYSPATH, $@) -I $(PROJ_SRC_DIR)/../../ $< +$(ObjDir)/AttrSpellingListIndex.inc.tmp : $(TD_SRC_DIR)/Attr.td \ + $(CLANG_TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang attribute spelling list index with tablegen" + $(Verb) $(ClangTableGen) -gen-clang-attr-spelling-index -o \ + $(call SYSPATH, $@) -I $(PROJ_SRC_DIR)/../../ $< + diff --git a/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h index 1513aeb..ff87d05 100644 --- a/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/include/clang/Sema/MultiplexExternalSemaSource.h @@ -15,9 +15,7 @@ #include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/Weak.h" - #include "llvm/ADT/SmallVector.h" - #include <utility> namespace clang { @@ -41,7 +39,7 @@ namespace clang { class MultiplexExternalSemaSource : public ExternalSemaSource { private: - llvm::SmallVector<ExternalSemaSource*, 2> Sources; // doesn't own them. + SmallVector<ExternalSemaSource *, 2> Sources; // doesn't own them. public: @@ -67,58 +65,30 @@ public: /// \brief Resolve a declaration ID into a declaration, potentially /// building a new declaration. - /// - /// This method only needs to be implemented if the AST source ever - /// passes back decl sets as VisibleDeclaration objects. - /// - /// The default implementation of this method is a no-op. virtual Decl *GetExternalDecl(uint32_t ID); /// \brief Resolve a selector ID into a selector. - /// - /// This operation only needs to be implemented if the AST source - /// returns non-zero for GetNumKnownSelectors(). - /// - /// The default implementation of this method is a no-op. virtual Selector GetExternalSelector(uint32_t ID); /// \brief Returns the number of selectors known to the external AST /// source. - /// - /// The default implementation of this method is a no-op. virtual uint32_t GetNumExternalSelectors(); /// \brief Resolve the offset of a statement in the decl stream into /// a statement. - /// - /// This operation is meant to be used via a LazyOffsetPtr. It only - /// needs to be implemented if the AST source uses methods like - /// FunctionDecl::setLazyBody when building decls. - /// - /// The default implementation of this method is a no-op. virtual Stmt *GetExternalDeclStmt(uint64_t Offset); /// \brief Resolve the offset of a set of C++ base specifiers in the decl /// stream into an array of specifiers. - /// - /// The default implementation of this method is a no-op. virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); - /// \brief Finds all declarations with the given name in the + /// \brief Find all declarations with the given name in the /// given context. - /// - /// Generally the final step of this method is either to call - /// SetExternalVisibleDeclsForName or to recursively call lookup on - /// the DeclContext after calling SetExternalVisibleDecls. - /// - /// The default implementation of this method is a no-op. - virtual DeclContextLookupResult + virtual bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); /// \brief Ensures that the table of all visible declarations inside this /// context is up to date. - /// - /// The default implementation of this functino is a no-op. virtual void completeVisibleDeclsMap(const DeclContext *DC); /// \brief Finds all declarations lexically contained within the given @@ -129,8 +99,6 @@ public: /// are returned. /// /// \return an indication of whether the load succeeded or failed. - /// - /// The default implementation of this method is a no-op. virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, bool (*isKindWeWant)(Decl::Kind), SmallVectorImpl<Decl*> &Result); @@ -174,26 +142,18 @@ public: /// \brief Notify ExternalASTSource that we started deserialization of /// a decl or type so until FinishedDeserializing is called there may be /// decls that are initializing. Must be paired with FinishedDeserializing. - /// - /// The default implementation of this method is a no-op. virtual void StartedDeserializing(); /// \brief Notify ExternalASTSource that we finished the deserialization of /// a decl or type. Must be paired with StartedDeserializing. - /// - /// The default implementation of this method is a no-op. virtual void FinishedDeserializing(); /// \brief Function that will be invoked when we begin parsing a new /// translation unit involving this external AST source. - /// - /// The default implementation of this method is a no-op. virtual void StartTranslationUnit(ASTConsumer *Consumer); /// \brief Print any statistics that have been gathered regarding /// the external AST source. - /// - /// The default implementation of this method is a no-op. virtual void PrintStats(); @@ -254,6 +214,11 @@ public: /// \brief Load the set of namespaces that are known to the external source, /// which will be used during typo correction. virtual void ReadKnownNamespaces(SmallVectorImpl<NamespaceDecl*> &Namespaces); + + /// \brief Load the set of used but not defined functions or variables with + /// internal linkage, or used but not defined inline functions. + virtual void ReadUndefinedButUsed( + llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined); /// \brief Do last resort, unqualified lookup on a LookupResult that /// Sema cannot find. @@ -311,14 +276,14 @@ public: /// introduce the same declarations repeatedly. virtual void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl*> &Decls); - /// \brief Read the set of locally-scoped external declarations known to the + /// \brief Read the set of locally-scoped extern "C" declarations known to the /// external Sema source. /// /// The external source should append its own locally-scoped external - /// declarations to the given vector of declarations. Note that this routine - /// may be invoked multiple times; the external source should take care not + /// declarations to the given vector of declarations. Note that this routine + /// may be invoked multiple times; the external source should take care not /// to introduce the same declarations repeatedly. - virtual void ReadLocallyScopedExternalDecls(SmallVectorImpl<NamedDecl*>&Decls); + virtual void ReadLocallyScopedExternCDecls(SmallVectorImpl<NamedDecl*>&Decls); /// \brief Read the set of referenced selectors known to the /// external Sema source. diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index 65ed781..c685843 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -78,8 +78,9 @@ namespace clang { ICK_Vector_Splat, ///< A vector splat from an arithmetic type ICK_Complex_Real, ///< Complex-real conversions (C99 6.3.1.7) ICK_Block_Pointer_Conversion, ///< Block Pointer conversions - ICK_TransparentUnionConversion, /// Transparent Union Conversions + ICK_TransparentUnionConversion, ///< Transparent Union Conversions ICK_Writeback_Conversion, ///< Objective-C ARC writeback conversion + ICK_Zero_Event_Conversion, ///< Zero constant to event (OpenCL1.2 6.12.10) ICK_Num_Conversion_Kinds ///< The number of conversion kinds }; @@ -694,6 +695,10 @@ namespace clang { /// \brief Return the second template argument this deduction failure /// refers to, if any. const TemplateArgument *getSecondArg(); + + /// \brief Return the expression this deduction failure refers to, + /// if any. + Expr *getExpr(); /// \brief Free any memory associated with this deduction failure. void Destroy(); @@ -809,7 +814,7 @@ namespace clang { void NoteCandidates(Sema &S, OverloadCandidateDisplayKind OCD, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, StringRef Opc = "", SourceLocation Loc = SourceLocation()); }; diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h index e59fb3f..e064b91 100644 --- a/include/clang/Sema/Ownership.h +++ b/include/clang/Sema/Ownership.h @@ -23,13 +23,10 @@ //===----------------------------------------------------------------------===// namespace clang { - class Attr; class CXXCtorInitializer; class CXXBaseSpecifier; class Decl; - class DeclGroupRef; class Expr; - class NestedNameSpecifier; class ParsedTemplateArgument; class QualType; class Stmt; diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h index 1329f97..d016b9b 100644 --- a/include/clang/Sema/Scope.h +++ b/include/clang/Sema/Scope.h @@ -32,70 +32,66 @@ public: /// ScopeFlags - These are bitfields that are or'd together when creating a /// scope, which defines the sorts of things the scope contains. enum ScopeFlags { - /// FnScope - This indicates that the scope corresponds to a function, which + /// \brief This indicates that the scope corresponds to a function, which /// means that labels are set here. FnScope = 0x01, - /// BreakScope - This is a while,do,switch,for, etc that can have break - /// stmts embedded into it. + /// \brief This is a while, do, switch, for, etc that can have break + /// statements embedded into it. BreakScope = 0x02, - /// ContinueScope - This is a while,do,for, which can have continue - /// stmt embedded into it. + /// \brief This is a while, do, for, which can have continue statements + /// embedded into it. ContinueScope = 0x04, - /// DeclScope - This is a scope that can contain a declaration. Some scopes + /// \brief This is a scope that can contain a declaration. Some scopes /// just contain loop constructs but don't contain decls. DeclScope = 0x08, - /// ControlScope - The controlling scope in a if/switch/while/for statement. + /// \brief The controlling scope in a if/switch/while/for statement. ControlScope = 0x10, - /// ClassScope - The scope of a struct/union/class definition. + /// \brief The scope of a struct/union/class definition. ClassScope = 0x20, - /// BlockScope - This is a scope that corresponds to a block/closure object. + /// \brief This is a scope that corresponds to a block/closure object. /// Blocks serve as top-level scopes for some objects like labels, they /// also prevent things like break and continue. BlockScopes always have /// the FnScope and DeclScope flags set as well. BlockScope = 0x40, - /// TemplateParamScope - This is a scope that corresponds to the + /// \brief This is a scope that corresponds to the /// template parameters of a C++ template. Template parameter /// scope starts at the 'template' keyword and ends when the /// template declaration ends. TemplateParamScope = 0x80, - /// FunctionPrototypeScope - This is a scope that corresponds to the + /// \brief This is a scope that corresponds to the /// parameters within a function prototype. FunctionPrototypeScope = 0x100, - /// AtCatchScope - This is a scope that corresponds to the Objective-C + /// \brief This is a scope that corresponds to the parameters within + /// a function prototype for a function declaration (as opposed to any + /// other kind of function declarator). Always has FunctionPrototypeScope + /// set as well. + FunctionDeclarationScope = 0x200, + + /// \brief This is a scope that corresponds to the Objective-C /// \@catch statement. - AtCatchScope = 0x200, + AtCatchScope = 0x400, - /// ObjCMethodScope - This scope corresponds to an Objective-C method body. + /// \brief This scope corresponds to an Objective-C method body. /// It always has FnScope and DeclScope set as well. - ObjCMethodScope = 0x400, - - /// SwitchScope - This is a scope that corresponds to a switch statement. - SwitchScope = 0x800, - - /// TryScope - This is the scope of a C++ try statement. - TryScope = 0x1000, - - /// CatchScope - This is the scope of a C++ catch statement. - CatchScope = 0x2000, + ObjCMethodScope = 0x800, - /// FnTryCatchScope - This is the scope for a function-level C++ try or - /// catch scope. - FnTryCatchScope = 0x4000, + /// \brief This is a scope that corresponds to a switch statement. + SwitchScope = 0x1000, - /// FnTryScope - This is the scope of a function-level C++ try scope. - FnTryScope = TryScope | FnTryCatchScope, + /// \brief This is the scope of a C++ try statement. + TryScope = 0x2000, - /// FnCatchScope - This is the scope of a function-level C++ catch scope. - FnCatchScope = CatchScope | FnTryCatchScope + /// \brief This is the scope for a function-level C++ try or catch scope. + FnTryCatchScope = 0x4000 }; private: /// The parent scope for this scope. This is null for the translation-unit @@ -244,7 +240,11 @@ public: void setEntity(void *E) { Entity = E; } bool hasErrorOccurred() const { return ErrorTrap.hasErrorOccurred(); } - + + bool hasUnrecoverableErrorOccurred() const { + return ErrorTrap.hasUnrecoverableErrorOccurred(); + } + /// isClassScope - Return true if this scope is a class/struct/union scope. bool isClassScope() const { return (getFlags() & Scope::ClassScope); diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index feda9c9..2295bf4 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -91,6 +91,9 @@ public: /// \brief Whether this function contains any indirect gotos. bool HasIndirectGoto; + /// \brief Whether a statement was dropped because it was invalid. + bool HasDroppedStmt; + /// A flag that is set when parsing a method that must call super's /// implementation, such as \c -dealloc, \c -finalize, or any method marked /// with \c __attribute__((objc_requires_super)). @@ -287,9 +290,14 @@ public: HasIndirectGoto = true; } + void setHasDroppedStmt() { + HasDroppedStmt = true; + } + bool NeedsScopeChecking() const { - return HasIndirectGoto || - (HasBranchProtectedScope && HasBranchIntoScope); + return !HasDroppedStmt && + (HasIndirectGoto || + (HasBranchProtectedScope && HasBranchIntoScope)); } FunctionScopeInfo(DiagnosticsEngine &Diag) @@ -297,6 +305,7 @@ public: HasBranchProtectedScope(false), HasBranchIntoScope(false), HasIndirectGoto(false), + HasDroppedStmt(false), ObjCShouldCallSuper(false), ErrorTrap(Diag) { } @@ -511,11 +520,11 @@ public: bool ContainsUnexpandedParameterPack; /// \brief Variables used to index into by-copy array captures. - llvm::SmallVector<VarDecl *, 4> ArrayIndexVars; + SmallVector<VarDecl *, 4> ArrayIndexVars; /// \brief Offsets into the ArrayIndexVars array at which each capture starts /// its list of array index variables. - llvm::SmallVector<unsigned, 4> ArrayIndexStarts; + SmallVector<unsigned, 4> ArrayIndexStarts; LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda, CXXMethodDecl *CallOperator) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 9b572d8..5b93e51 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -15,27 +15,30 @@ #ifndef LLVM_CLANG_SEMA_SEMA_H #define LLVM_CLANG_SEMA_SEMA_H -#include "clang/Sema/Ownership.h" -#include "clang/Sema/AnalysisBasedWarnings.h" -#include "clang/Sema/IdentifierResolver.h" -#include "clang/Sema/ObjCMethodList.h" -#include "clang/Sema/DeclSpec.h" -#include "clang/Sema/ExternalSemaSource.h" -#include "clang/Sema/LocInfoType.h" -#include "clang/Sema/TypoCorrection.h" -#include "clang/Sema/Weak.h" +#include "clang/AST/Attr.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" -#include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/LambdaMangleContext.h" -#include "clang/AST/TypeLoc.h" #include "clang/AST/NSAPI.h" -#include "clang/Lex/ModuleLoader.h" +#include "clang/AST/PrettyPrinter.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Basic/ExpressionTraits.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TypeTraits.h" -#include "clang/Basic/ExpressionTraits.h" +#include "clang/Lex/ModuleLoader.h" +#include "clang/Sema/AnalysisBasedWarnings.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ExternalSemaSource.h" +#include "clang/Sema/IdentifierResolver.h" +#include "clang/Sema/LocInfoType.h" +#include "clang/Sema/ObjCMethodList.h" +#include "clang/Sema/Ownership.h" +#include "clang/Sema/TypoCorrection.h" +#include "clang/Sema/Weak.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/OwningPtr.h" @@ -129,6 +132,7 @@ namespace clang { class ObjCMethodDecl; class ObjCPropertyDecl; class ObjCProtocolDecl; + class OMPThreadPrivateDecl; class OverloadCandidateSet; class OverloadExpr; class ParenListExpr; @@ -197,6 +201,8 @@ class Sema { ///\brief Whether Sema has generated a multiplexer and has to delete it. bool isMultiplexExternalSource; + static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD); + public: typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy; typedef OpaquePtr<TemplateName> TemplateTy; @@ -253,7 +259,7 @@ public: /// element type here is ExprWithCleanups::Object. SmallVector<BlockDecl*, 8> ExprCleanupObjects; - llvm::SmallPtrSet<Expr*, 8> MaybeODRUseExprs; + llvm::SmallPtrSet<Expr*, 2> MaybeODRUseExprs; /// \brief Stack containing information about each of the nested /// function, block, and method scopes that are currently active. @@ -272,12 +278,6 @@ public: /// This is only necessary for issuing pretty diagnostics. ExtVectorDeclsType ExtVectorDecls; - /// \brief The set of types for which we have already complained about the - /// definitions being hidden. - /// - /// This set is used to suppress redundant diagnostics. - llvm::SmallPtrSet<NamedDecl *, 4> HiddenDefinitions; - /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes. OwningPtr<CXXFieldCollector> FieldCollector; @@ -298,35 +298,35 @@ public: llvm::SmallPtrSet<const Decl*, 4> ParsingInitForAutoVars; /// \brief A mapping from external names to the most recent - /// locally-scoped external declaration with that name. + /// locally-scoped extern "C" declaration with that name. /// /// This map contains external declarations introduced in local - /// scoped, e.g., + /// scopes, e.g., /// /// \code - /// void f() { + /// extern "C" void f() { /// void foo(int, int); /// } /// \endcode /// - /// Here, the name "foo" will be associated with the declaration on + /// Here, the name "foo" will be associated with the declaration of /// "foo" within f. This name is not visible outside of /// "f". However, we still find it in two cases: /// - /// - If we are declaring another external with the name "foo", we - /// can find "foo" as a previous declaration, so that the types - /// of this external declaration can be checked for - /// compatibility. + /// - If we are declaring another global or extern "C" entity with + /// the name "foo", we can find "foo" as a previous declaration, + /// so that the types of this external declaration can be checked + /// for compatibility. /// /// - If we would implicitly declare "foo" (e.g., due to a call to /// "foo" in C when no prototype or definition is visible), then /// we find this declaration of "foo" and complain that it is /// not visible. - llvm::DenseMap<DeclarationName, NamedDecl *> LocallyScopedExternalDecls; + llvm::DenseMap<DeclarationName, NamedDecl *> LocallyScopedExternCDecls; - /// \brief Look for a locally scoped external declaration by the given name. + /// \brief Look for a locally scoped extern "C" declaration by the given name. llvm::DenseMap<DeclarationName, NamedDecl *>::iterator - findLocallyScopedExternalDecl(DeclarationName Name); + findLocallyScopedExternCDecl(DeclarationName Name); typedef LazyVector<VarDecl *, ExternalSemaSource, &ExternalSemaSource::ReadTentativeDefinitions, 2, 2> @@ -363,6 +363,16 @@ public: const CXXDestructorDecl*>, 2> DelayedDestructorExceptionSpecChecks; + /// \brief All the members seen during a class definition which were both + /// explicitly defaulted and had explicitly-specified exception + /// specifications, along with the function type containing their + /// user-specified exception specification. Those exception specifications + /// were overridden with the default specifications, but we still need to + /// check whether they are compatible with the default specification, and + /// we can't do that until the nesting set of class definitions is complete. + SmallVector<std::pair<CXXMethodDecl*, const FunctionProtoType*>, 2> + DelayedDefaultedMemberExceptionSpecs; + /// \brief Callback to the parser to parse templated functions when needed. typedef void LateTemplateParserCB(void *P, const FunctionDecl *FD); LateTemplateParserCB *LateTemplateParser; @@ -533,7 +543,7 @@ public: RecordDecl *MSVCGuidDecl; /// \brief Caches identifiers/selectors for NSFoundation APIs. - llvm::OwningPtr<NSAPI> NSAPIObj; + OwningPtr<NSAPI> NSAPIObj; /// \brief The declaration of the Objective-C NSNumber class. ObjCInterfaceDecl *NSNumberDecl; @@ -568,6 +578,9 @@ public: /// \brief id<NSCopying> type. QualType QIDNSCopying; + /// \brief will hold 'respondsToSelector:' + Selector RespondsToSelectorSel; + /// A flag to remember whether the implicit forms of operator new and delete /// have been declared. bool GlobalNewDeleteDeclared; @@ -619,11 +632,11 @@ public: /// this expression evaluation context. unsigned NumCleanupObjects; - llvm::SmallPtrSet<Expr*, 8> SavedMaybeODRUseExprs; + llvm::SmallPtrSet<Expr*, 2> SavedMaybeODRUseExprs; /// \brief The lambdas that are present within this context, if it /// is indeed an unevaluated context. - llvm::SmallVector<LambdaExpr *, 2> Lambdas; + SmallVector<LambdaExpr *, 2> Lambdas; /// \brief The declaration that provides context for the lambda expression /// if the normal declaration context does not suffice, e.g., in a @@ -635,15 +648,15 @@ public: /// /// This mangling information is allocated lazily, since most contexts /// do not have lambda expressions. - LambdaMangleContext *LambdaMangle; + IntrusiveRefCntPtr<LambdaMangleContext> LambdaMangle; /// \brief If we are processing a decltype type, a set of call expressions /// for which we have deferred checking the completeness of the return type. - llvm::SmallVector<CallExpr*, 8> DelayedDecltypeCalls; + SmallVector<CallExpr *, 8> DelayedDecltypeCalls; /// \brief If we are processing a decltype type, a set of temporary binding /// expressions for which we have deferred checking the destructor. - llvm::SmallVector<CXXBindTemporaryExpr*, 8> DelayedDecltypeBinds; + SmallVector<CXXBindTemporaryExpr *, 8> DelayedDecltypeBinds; ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, unsigned NumCleanupObjects, @@ -654,10 +667,6 @@ public: IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects), LambdaContextDecl(LambdaContextDecl), LambdaMangle() { } - ~ExpressionEvaluationContextRecord() { - delete LambdaMangle; - } - /// \brief Retrieve the mangling context for lambdas. LambdaMangleContext &getLambdaMangleContext() { assert(LambdaContextDecl && "Need to have a lambda context declaration"); @@ -730,11 +739,15 @@ public: // Contains the locations of the beginning of unparsed default // argument locations. - llvm::DenseMap<ParmVarDecl *,SourceLocation> UnparsedDefaultArgLocs; + llvm::DenseMap<ParmVarDecl *, SourceLocation> UnparsedDefaultArgLocs; + + /// UndefinedInternals - all the used, undefined objects which require a + /// definition in this translation unit. + llvm::DenseMap<NamedDecl *, SourceLocation> UndefinedButUsed; - /// UndefinedInternals - all the used, undefined objects with - /// internal linkage in this translation unit. - llvm::DenseMap<NamedDecl*, SourceLocation> UndefinedInternals; + /// Obtain a sorted list of functions that are undefined but ODR-used. + void getUndefinedButUsed( + llvm::SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined); typedef std::pair<ObjCMethodList, ObjCMethodList> GlobalMethods; typedef llvm::DenseMap<Selector, GlobalMethods> GlobalMethodPool; @@ -749,6 +762,24 @@ public: /// of -Wselector. llvm::DenseMap<Selector, SourceLocation> ReferencedSelectors; + /// Kinds of C++ special members. + enum CXXSpecialMember { + CXXDefaultConstructor, + CXXCopyConstructor, + CXXMoveConstructor, + CXXCopyAssignment, + CXXMoveAssignment, + CXXDestructor, + CXXInvalid + }; + + typedef std::pair<CXXRecordDecl*, CXXSpecialMember> SpecialMemberDecl; + + /// The C++ special members which we are currently in the process of + /// declaring. If this process recursively triggers the declaration of the + /// same special member, we should act as if it is not yet declared. + llvm::SmallSet<SpecialMemberDecl, 4> SpecialMembersBeingDeclared; + void ReadMethodPool(Selector Sel); /// Private Helper predicate to check for 'self'. @@ -903,10 +934,10 @@ public: // Type Analysis / Processing: SemaType.cpp. // - QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs); - QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVR) { - return BuildQualifiedType(T, Loc, Qualifiers::fromCVRMask(CVR)); - } + QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs, + const DeclSpec *DS = 0); + QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVRA, + const DeclSpec *DS = 0); QualType BuildPointerType(QualType T, SourceLocation Loc, DeclarationName Entity); QualType BuildReferenceType(QualType T, bool LValueRef, @@ -916,12 +947,39 @@ public: SourceRange Brackets, DeclarationName Entity); QualType BuildExtVectorType(QualType T, Expr *ArraySize, SourceLocation AttrLoc); + + /// \brief Build a function type. + /// + /// This routine checks the function type according to C++ rules and + /// under the assumption that the result type and parameter types have + /// just been instantiated from a template. It therefore duplicates + /// some of the behavior of GetTypeForDeclarator, but in a much + /// simpler form that is only suitable for this narrow use case. + /// + /// \param T The return type of the function. + /// + /// \param ParamTypes The parameter types of the function. This array + /// will be modified to account for adjustments to the types of the + /// function parameters. + /// + /// \param Loc The location of the entity whose type involves this + /// function type or, if there is no such entity, the location of the + /// type that will have function type. + /// + /// \param Entity The name of the entity that involves the function + /// type, if known. + /// + /// \param EPI Extra information about the function type. Usually this will + /// be taken from an existing function with the same prototype. + /// + /// \returns A suitable function type, if there are no errors. The + /// unqualified type will always be a FunctionProtoType. + /// Otherwise, returns a NULL type. QualType BuildFunctionType(QualType T, - QualType *ParamTypes, unsigned NumParamTypes, - bool Variadic, bool HasTrailingReturn, - unsigned Quals, RefQualifierKind RefQualifier, + llvm::MutableArrayRef<QualType> ParamTypes, SourceLocation Loc, DeclarationName Entity, - FunctionType::ExtInfo Info); + const FunctionProtoType::ExtProtoInfo &EPI); + QualType BuildMemberPointerType(QualType T, QualType Class, SourceLocation Loc, DeclarationName Entity); @@ -943,7 +1001,7 @@ public: CanThrowResult canThrow(const Expr *E); const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT); - bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range); + bool CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range); bool CheckDistantExceptionSpec(QualType T); bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New); bool CheckEquivalentExceptionSpec( @@ -1291,8 +1349,8 @@ public: Decl *ActOnDeclarator(Scope *S, Declarator &D); - Decl *HandleDeclarator(Scope *S, Declarator &D, - MultiTemplateParamsArg TemplateParameterLists); + NamedDecl *HandleDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParameterLists); void RegisterLocallyScopedExternCDecl(NamedDecl *ND, const LookupResult &Previous, Scope *S); @@ -1300,7 +1358,7 @@ public: bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, DeclarationName Name, SourceLocation Loc); - void DiagnoseFunctionSpecifiers(Declarator& D); + void DiagnoseFunctionSpecifiers(const DeclSpec &DS); void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R); void CheckShadow(Scope *S, VarDecl *D); void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange); @@ -1317,6 +1375,7 @@ public: // Returns true if the variable declaration is a redeclaration bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous); void CheckCompleteVariableDeclaration(VarDecl *var); + void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D); void ActOnStartFunctionDeclarator(); void ActOnEndFunctionDeclarator(); NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, @@ -1343,7 +1402,7 @@ public: ParmVarDecl *CheckParameter(DeclContext *DC, SourceLocation StartLoc, SourceLocation NameLoc, IdentifierInfo *Name, QualType T, TypeSourceInfo *TSInfo, - StorageClass SC, StorageClass SCAsWritten); + StorageClass SC); void ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, Expr *defarg); @@ -1383,9 +1442,19 @@ public: return D && isa<ObjCMethodDecl>(D); } + /// \brief Determine whether we can skip parsing the body of a function + /// definition, assuming we don't care about analyzing its body or emitting + /// code for that function. + /// + /// This will be \c false only if we may need the body of the function in + /// order to parse the rest of the program (for instance, if it is + /// \c constexpr in C++11 or has an 'auto' return type in C++14). + bool canSkipFunctionBody(Decl *D); + void computeNRVO(Stmt *Body, sema::FunctionScopeInfo *Scope); Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body); Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation); + Decl *ActOnSkippedFunctionBody(Decl *Decl); /// ActOnFinishDelayedAttribute - Invoked when we have finished parsing an /// attribute for which parsing is delayed. @@ -1409,6 +1478,11 @@ public: SourceLocation AsmLoc, SourceLocation RParenLoc); + /// \brief Handle a C++11 empty-declaration and attribute-declaration. + Decl *ActOnEmptyDeclaration(Scope *S, + AttributeList *AttrList, + SourceLocation SemiLoc); + /// \brief The parser has processed a module import declaration. /// /// \param AtLoc The location of the '@' symbol, if any. @@ -1419,6 +1493,14 @@ public: DeclResult ActOnModuleImport(SourceLocation AtLoc, SourceLocation ImportLoc, ModuleIdPath Path); + /// \brief Create an implicit import of the given module at the given + /// source location. + /// + /// This routine is typically used for error recovery, when the entity found + /// by name lookup is actually hidden within a module that we know about but + /// the user has forgotten to import. + void createImplicitModuleImport(SourceLocation Loc, Module *Mod); + /// \brief Retrieve a suitable printing policy. PrintingPolicy getPrintingPolicy() const { return getPrintingPolicy(Context, PP); @@ -1436,7 +1518,8 @@ public: DeclSpec &DS); Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, - MultiTemplateParamsArg TemplateParams); + MultiTemplateParamsArg TemplateParams, + bool IsExplicitInstantiation = false); Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, AccessSpecifier AS, @@ -1502,17 +1585,10 @@ public: AccessSpecifier AS, NamedDecl *PrevDecl, Declarator *D = 0); - enum CXXSpecialMember { - CXXDefaultConstructor, - CXXCopyConstructor, - CXXMoveConstructor, - CXXCopyAssignment, - CXXMoveAssignment, - CXXDestructor, - CXXInvalid - }; bool CheckNontrivialField(FieldDecl *FD); - void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem); + void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMember CSM); + bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, + bool Diagnose = false); CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD); void ActOnLastBitfield(SourceLocation DeclStart, SmallVectorImpl<Decl *> &AllIvarDecls); @@ -1522,7 +1598,7 @@ public: // This is used for both record definitions and ObjC interface declarations. void ActOnFields(Scope* S, SourceLocation RecLoc, Decl *TagDecl, - llvm::ArrayRef<Decl *> Fields, + ArrayRef<Decl *> Fields, SourceLocation LBrac, SourceLocation RBrac, AttributeList *AttrList); @@ -1639,30 +1715,54 @@ public: bool isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New); /// Attribute merging methods. Return true if a new attribute was added. - AvailabilityAttr *mergeAvailabilityAttr(Decl *D, SourceRange Range, + AvailabilityAttr *mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, IdentifierInfo *Platform, VersionTuple Introduced, VersionTuple Deprecated, VersionTuple Obsoleted, bool IsUnavailable, - StringRef Message); + StringRef Message, + bool Override, + unsigned AttrSpellingListIndex); + TypeVisibilityAttr *mergeTypeVisibilityAttr(Decl *D, SourceRange Range, + TypeVisibilityAttr::VisibilityType Vis, + unsigned AttrSpellingListIndex); VisibilityAttr *mergeVisibilityAttr(Decl *D, SourceRange Range, - VisibilityAttr::VisibilityType Vis); - DLLImportAttr *mergeDLLImportAttr(Decl *D, SourceRange Range); - DLLExportAttr *mergeDLLExportAttr(Decl *D, SourceRange Range); + VisibilityAttr::VisibilityType Vis, + unsigned AttrSpellingListIndex); + DLLImportAttr *mergeDLLImportAttr(Decl *D, SourceRange Range, + unsigned AttrSpellingListIndex); + DLLExportAttr *mergeDLLExportAttr(Decl *D, SourceRange Range, + unsigned AttrSpellingListIndex); FormatAttr *mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format, - int FormatIdx, int FirstArg); - SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name); - bool mergeDeclAttribute(Decl *New, InheritableAttr *Attr); + int FormatIdx, int FirstArg, + unsigned AttrSpellingListIndex); + SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name, + unsigned AttrSpellingListIndex); + + /// \brief Describes the kind of merge to perform for availability + /// attributes (including "deprecated", "unavailable", and "availability"). + enum AvailabilityMergeKind { + /// \brief Don't merge availability attributes at all. + AMK_None, + /// \brief Merge availability attributes for a redeclaration, which requires + /// an exact match. + AMK_Redeclaration, + /// \brief Merge availability attributes for an override, which requires + /// an exact match or a weakening of constraints. + AMK_Override + }; - void mergeDeclAttributes(Decl *New, Decl *Old, bool MergeDeprecation = true); + void mergeDeclAttributes(NamedDecl *New, Decl *Old, + AvailabilityMergeKind AMK = AMK_Redeclaration); void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls); bool MergeFunctionDecl(FunctionDecl *New, Decl *Old, Scope *S); bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, Scope *S); void mergeObjCMethodDecls(ObjCMethodDecl *New, ObjCMethodDecl *Old); - void MergeVarDecl(VarDecl *New, LookupResult &OldDecls); - void MergeVarDeclTypes(VarDecl *New, VarDecl *Old); + void MergeVarDecl(VarDecl *New, LookupResult &OldDecls, + bool OldDeclsWereHidden); + void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldIsHidden); void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old); bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S); @@ -1841,6 +1941,19 @@ public: }; ObjCSubscriptKind CheckSubscriptingKind(Expr *FromE); + // Note that LK_String is intentionally after the other literals, as + // this is used for diagnostics logic. + enum ObjCLiteralKind { + LK_Array, + LK_Dictionary, + LK_Numeric, + LK_Boxed, + LK_String, + LK_Block, + LK_None + }; + ObjCLiteralKind CheckLiteralKind(Expr *FromE); + ExprResult PerformObjectMemberConversion(Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, @@ -1853,13 +1966,13 @@ public: void AddOverloadCandidate(FunctionDecl *Function, DeclAccessPair FoundDecl, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, bool PartialOverloading = false, bool AllowExplicit = false); void AddFunctionCandidates(const UnresolvedSetImpl &Functions, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, TemplateArgumentListInfo *ExplicitTemplateArgs = 0); @@ -1873,7 +1986,7 @@ public: DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, QualType ObjectType, Expr::Classification ObjectClassification, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false); void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, @@ -1882,13 +1995,13 @@ public: TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, Expr::Classification ObjectClassification, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false); void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false); void AddConversionCandidate(CXXConversionDecl *Conversion, @@ -1905,7 +2018,7 @@ public: DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, const FunctionProtoType *Proto, - Expr *Object, llvm::ArrayRef<Expr*> Args, + Expr *Object, ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet); void AddMemberOperatorCandidates(OverloadedOperatorKind Op, SourceLocation OpLoc, @@ -1923,7 +2036,7 @@ public: OverloadCandidateSet& CandidateSet); void AddArgumentDependentLookupCandidates(DeclarationName Name, bool Operator, SourceLocation Loc, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, bool PartialOverloading = false); @@ -1971,7 +2084,7 @@ public: FunctionDecl *Fn); void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool PartialOverloading = false); @@ -2164,7 +2277,7 @@ private: // // The boolean value will be true to indicate that the namespace was loaded // from an AST/PCH file, or false otherwise. - llvm::DenseMap<NamespaceDecl*, bool> KnownNamespaces; + llvm::MapVector<NamespaceDecl*, bool> KnownNamespaces; /// \brief Whether we have already loaded known namespaces from an extenal /// source. @@ -2218,7 +2331,7 @@ public: void ArgumentDependentLookup(DeclarationName Name, bool Operator, SourceLocation Loc, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, ADLResult &Functions); void LookupVisibleDecls(Scope *S, LookupNameKind Kind, @@ -2237,7 +2350,7 @@ public: const ObjCObjectPointerType *OPT = 0); void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses); @@ -2260,19 +2373,25 @@ public: // More parsing and symbol table subroutines. + void ProcessPragmaWeak(Scope *S, Decl *D); // Decl attributes - this routine is the top level dispatcher. void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD, - bool NonInheritable = true, bool Inheritable = true); + bool NonInheritable = true, + bool Inheritable = true); void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL, - bool NonInheritable = true, bool Inheritable = true); + bool NonInheritable = true, + bool Inheritable = true, + bool IncludeCXX11Attributes = true); bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, const AttributeList *AttrList); void checkUnusedDeclAttributes(Declarator &D); bool CheckRegparmAttr(const AttributeList &attr, unsigned &value); - bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC); + bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, + const FunctionDecl *FD = 0); bool CheckNoReturnAttr(const AttributeList &attr); + void CheckAlignasUnderalignment(Decl *D); /// \brief Stmt attributes - this routine is the top level dispatcher. StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs, @@ -2339,21 +2458,27 @@ public: llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap, llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap); + /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is + /// an ivar synthesized for 'Method' and 'Method' is a property accessor + /// declared in class 'IFace'. + bool IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, + ObjCMethodDecl *Method, ObjCIvarDecl *IV); + /// Called by ActOnProperty to handle \@property declarations in /// class extensions. - Decl *HandlePropertyInClassExtension(Scope *S, - SourceLocation AtLoc, - SourceLocation LParenLoc, - FieldDeclarator &FD, - Selector GetterSel, - Selector SetterSel, - const bool isAssign, - const bool isReadWrite, - const unsigned Attributes, - const unsigned AttributesAsWritten, - bool *isOverridingProperty, - TypeSourceInfo *T, - tok::ObjCKeywordKind MethodImplKind); + ObjCPropertyDecl *HandlePropertyInClassExtension(Scope *S, + SourceLocation AtLoc, + SourceLocation LParenLoc, + FieldDeclarator &FD, + Selector GetterSel, + Selector SetterSel, + const bool isAssign, + const bool isReadWrite, + const unsigned Attributes, + const unsigned AttributesAsWritten, + bool *isOverridingProperty, + TypeSourceInfo *T, + tok::ObjCKeywordKind MethodImplKind); /// Called by ActOnProperty and HandlePropertyInClassExtension to /// handle creating the ObjcPropertyDecl for a category or \@interface. @@ -2507,8 +2632,15 @@ public: FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) { return FullExprArg(ActOnFinishFullExpr(Arg, CC).release()); } + FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) { + ExprResult FE = + ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(), + /*DiscardedValue*/ true); + return FullExprArg(FE.release()); + } - StmtResult ActOnExprStmt(FullExprArg Expr); + StmtResult ActOnExprStmt(ExprResult Arg); + StmtResult ActOnExprStmtError(); StmtResult ActOnNullStmt(SourceLocation SemiLoc, bool HasLeadingEmptyMacro = false); @@ -2616,7 +2748,7 @@ public: SourceLocation StarLoc, Expr *DestExp); StmtResult ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope); - StmtResult ActOnBreakStmt(SourceLocation GotoLoc, Scope *CurScope); + StmtResult ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope); const VarDecl *getCopyElisionCandidate(QualType ReturnType, Expr *E, bool AllowFunctionParameters); @@ -2632,7 +2764,8 @@ public: SourceLocation RParenLoc); NamedDecl *LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc, - unsigned &Size); + unsigned &Length, unsigned &Size, + unsigned &Type, bool &IsVarDecl); bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset, SourceLocation AsmLoc); StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, @@ -2766,7 +2899,7 @@ public: void DiscardCleanupsInEvaluationContext(); - ExprResult TranformToPotentiallyEvaluated(Expr *E); + ExprResult TransformToPotentiallyEvaluated(Expr *E); ExprResult HandleExprEvaluationContextForTypeof(Expr *E); ExprResult ActOnConstantExpression(ExprResult Res); @@ -2777,7 +2910,7 @@ public: // for expressions referring to a decl; these exist because odr-use marking // needs to be delayed for some constant variables when we build one of the // named expressions. - void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D); + void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool OdrUse); void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func); void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var); void MarkDeclRefReferenced(DeclRefExpr *E); @@ -2873,7 +3006,7 @@ public: bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs = 0, - llvm::ArrayRef<Expr *> Args = llvm::ArrayRef<Expr *>()); + ArrayRef<Expr *> Args = ArrayRef<Expr *>()); ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S, IdentifierInfo *II, @@ -2892,7 +3025,8 @@ public: ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, const DeclarationNameInfo &NameInfo, - const CXXScopeSpec *SS = 0); + const CXXScopeSpec *SS = 0, + NamedDecl *FoundD = 0); ExprResult BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, SourceLocation nameLoc, @@ -2925,7 +3059,7 @@ public: bool NeedsADL); ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, - NamedDecl *D); + NamedDecl *D, NamedDecl *FoundD = 0); ExprResult BuildLiteralOperatorCall(LookupResult &R, DeclarationNameInfo &SuffixInfo, @@ -3334,15 +3468,9 @@ public: MultiTemplateParamsArg TemplateParams, SourceLocation UsingLoc, UnqualifiedId &Name, + AttributeList *AttrList, TypeResult Type); - /// InitializeVarWithConstructor - Creates an CXXConstructExpr - /// and sets it as the initializer for the passed in VarDecl. - bool InitializeVarWithConstructor(VarDecl *VD, - CXXConstructorDecl *Constructor, - MultiExprArg Exprs, - bool HadMultipleCandidates); - /// BuildCXXConstructExpr - Creates a complete call to a constructor, /// including handling of its default argument expressions. /// @@ -3350,8 +3478,9 @@ public: ExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, MultiExprArg Exprs, - bool HadMultipleCandidates, bool RequiresZeroInit, - unsigned ConstructKind, SourceRange ParenRange); + bool HadMultipleCandidates, bool IsListInitialization, + bool RequiresZeroInit, unsigned ConstructKind, + SourceRange ParenRange); // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if // the constructor can be elidable? @@ -3359,8 +3488,8 @@ public: BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs, bool HadMultipleCandidates, - bool RequiresZeroInit, unsigned ConstructKind, - SourceRange ParenRange); + bool IsListInitialization, bool RequiresZeroInit, + unsigned ConstructKind, SourceRange ParenRange); /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating /// the default expr if needed. @@ -3395,7 +3524,7 @@ public: public: explicit ImplicitExceptionSpecification(Sema &Self) : Self(&Self), ComputedEST(EST_BasicNoexcept) { - if (!Self.getLangOpts().CPlusPlus0x) + if (!Self.getLangOpts().CPlusPlus11) ComputedEST = EST_DynamicNone; } @@ -3474,6 +3603,11 @@ public: ImplicitExceptionSpecification ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD); + /// \brief Determine what sort of exception specification an inheriting + /// constructor of a class will have. + ImplicitExceptionSpecification + ComputeInheritingCtorExceptionSpec(CXXMethodDecl *MD); + /// \brief Evaluate the implicit exception specification for a defaulted /// special member function. void EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD); @@ -3484,7 +3618,7 @@ public: ArrayRef<ParsedType> DynamicExceptions, ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr, - llvm::SmallVectorImpl<QualType> &Exceptions, + SmallVectorImpl<QualType> &Exceptions, FunctionProtoType::ExtProtoInfo &EPI); /// \brief Determine if a special member function should have a deleted @@ -3526,11 +3660,15 @@ public: void AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, CXXDestructorDecl *Destructor); - /// \brief Declare all inherited constructors for the given class. + /// \brief Declare all inheriting constructors for the given class. /// - /// \param ClassDecl The class declaration into which the inherited + /// \param ClassDecl The class declaration into which the inheriting /// constructors will be added. - void DeclareInheritedConstructors(CXXRecordDecl *ClassDecl); + void DeclareInheritingConstructors(CXXRecordDecl *ClassDecl); + + /// \brief Define the specified inheriting constructor. + void DefineInheritingConstructor(SourceLocation UseLoc, + CXXConstructorDecl *Constructor); /// \brief Declare the implicit copy constructor for the given class. /// @@ -3617,7 +3755,12 @@ public: MultiExprArg ArgsPtr, SourceLocation Loc, SmallVectorImpl<Expr*> &ConvertedArgs, - bool AllowExplicit = false); + bool AllowExplicit = false, + bool IsListInitialization = false); + + ParsedType getInheritingConstructorName(CXXScopeSpec &SS, + SourceLocation NameLoc, + IdentifierInfo &Name); ParsedType getDestructorName(SourceLocation TildeLoc, IdentifierInfo &II, SourceLocation NameLoc, @@ -3917,7 +4060,9 @@ public: return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc() : SourceLocation()); } - ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC); + ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC, + bool DiscardedValue = false, + bool IsConstexpr = false); StmtResult ActOnFinishFullStmt(Stmt *Stmt); // Marks SS invalid if it represents an incomplete type. @@ -3943,7 +4088,7 @@ public: bool ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc, CXXScopeSpec &SS); - bool isAcceptableNestedNameSpecifier(NamedDecl *SD); + bool isAcceptableNestedNameSpecifier(const NamedDecl *SD); NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS); bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, @@ -4100,7 +4245,7 @@ public: SourceRange IntroducerRange, TypeSourceInfo *MethodType, SourceLocation EndLoc, - llvm::ArrayRef<ParmVarDecl *> Params); + ArrayRef<ParmVarDecl *> Params); /// \brief Introduce the scope for a lambda expression. sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator, @@ -4247,7 +4392,7 @@ public: SourceLocation ColonLoc, AttributeList *Attrs = 0); - Decl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, + NamedDecl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, Expr *BitfieldWidth, const VirtSpecifiers &VS, @@ -4304,9 +4449,9 @@ public: bool SetDelegatingInitializer(CXXConstructorDecl *Constructor, CXXCtorInitializer *Initializer); - bool SetCtorInitializers(CXXConstructorDecl *Constructor, - CXXCtorInitializer **Initializers, - unsigned NumInitializers, bool AnyErrors); + bool SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors, + ArrayRef<CXXCtorInitializer *> Initializers = + ArrayRef<CXXCtorInitializer *>()); void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation); @@ -4369,8 +4514,7 @@ public: void ActOnMemInitializers(Decl *ConstructorDecl, SourceLocation ColonLoc, - CXXCtorInitializer **MemInits, - unsigned NumMemInits, + ArrayRef<CXXCtorInitializer*> MemInits, bool AnyErrors); void CheckCompletedCXXClass(CXXRecordDecl *Record); @@ -4407,8 +4551,8 @@ public: TypeSourceInfo *TSInfo); Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, MultiTemplateParamsArg TemplateParams); - Decl *ActOnFriendFunctionDecl(Scope *S, Declarator &D, - MultiTemplateParamsArg TemplateParams); + NamedDecl *ActOnFriendFunctionDecl(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParams); QualType CheckConstructorDeclarator(Declarator &D, QualType R, StorageClass& SC); @@ -4420,8 +4564,10 @@ public: StorageClass& SC); Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion); - void CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record); void CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD); + void CheckExplicitlyDefaultedMemberExceptionSpec(CXXMethodDecl *MD, + const FunctionProtoType *T); + void CheckDelayedExplicitlyDefaultedMemberExceptionSpecs(); //===--------------------------------------------------------------------===// // C++ Derived Classes @@ -4436,6 +4582,7 @@ public: BaseResult ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, + ParsedAttributes &Attrs, bool Virtual, AccessSpecifier Access, ParsedType basetype, SourceLocation BaseLoc, @@ -4467,6 +4614,9 @@ public: std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths); + bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New, + const CXXMethodDecl *Old); + /// CheckOverridingFunctionReturnType - Checks whether the return types are /// covariant, according to C++ [class.virtual]p5. bool CheckOverridingFunctionReturnType(const CXXMethodDecl *New, @@ -5234,14 +5384,14 @@ public: /// expansion. TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc, - llvm::Optional<unsigned> NumExpansions); + Optional<unsigned> NumExpansions); /// \brief Construct a pack expansion type from the pattern of the pack /// expansion. QualType CheckPackExpansion(QualType Pattern, SourceRange PatternRange, SourceLocation EllipsisLoc, - llvm::Optional<unsigned> NumExpansions); + Optional<unsigned> NumExpansions); /// \brief Invoked when parsing an expression followed by an ellipsis, which /// creates a pack expansion. @@ -5260,7 +5410,7 @@ public: /// /// \param EllipsisLoc The location of the ellipsis. ExprResult CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc, - llvm::Optional<unsigned> NumExpansions); + Optional<unsigned> NumExpansions); /// \brief Determine whether we could expand a pack expansion with the /// given set of parameter packs into separate arguments by repeatedly @@ -5298,11 +5448,11 @@ public: /// must be set. bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, SourceRange PatternRange, - llvm::ArrayRef<UnexpandedParameterPack> Unexpanded, + ArrayRef<UnexpandedParameterPack> Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand, bool &RetainExpansion, - llvm::Optional<unsigned> &NumExpansions); + Optional<unsigned> &NumExpansions); /// \brief Determine the number of arguments in the given pack expansion /// type. @@ -5311,8 +5461,8 @@ public: /// consistent across all of the unexpanded parameter packs in its pattern. /// /// Returns an empty Optional if the type can't be expanded. - llvm::Optional<unsigned> getNumArgumentsInExpansion(QualType T, - const MultiLevelTemplateArgumentList &TemplateArgs); + Optional<unsigned> getNumArgumentsInExpansion(QualType T, + const MultiLevelTemplateArgumentList &TemplateArgs); /// \brief Determine whether the given declarator contains any unexpanded /// parameter packs. @@ -5366,10 +5516,8 @@ public: /// \brief Substitution of the deduced template argument values /// resulted in an error. TDK_SubstitutionFailure, - /// \brief Substitution of the deduced template argument values - /// into a non-deduced context produced a type or value that - /// produces a type that does not match the original template - /// arguments provided. + /// \brief A non-depnedent component of the parameter did not match the + /// corresponding component of the argument. TDK_NonDeducedMismatch, /// \brief When performing template argument deduction for a function /// template, there were too many call arguments. @@ -5382,7 +5530,9 @@ public: TDK_InvalidExplicitArguments, /// \brief The arguments included an overloaded function name that could /// not be resolved to a suitable function. - TDK_FailedOverloadResolution + TDK_FailedOverloadResolution, + /// \brief Deduction failed; that's all we know. + TDK_MiscellaneousDeductionFailure }; TemplateDeductionResult @@ -5423,7 +5573,7 @@ public: TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info); @@ -5483,13 +5633,14 @@ public: bool OnlyDeduced, unsigned Depth, llvm::SmallBitVector &Used); - void MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate, - llvm::SmallBitVector &Deduced) { + void MarkDeducedTemplateParameters( + const FunctionTemplateDecl *FunctionTemplate, + llvm::SmallBitVector &Deduced) { return MarkDeducedTemplateParameters(Context, FunctionTemplate, Deduced); } static void MarkDeducedTemplateParameters(ASTContext &Ctx, - FunctionTemplateDecl *FunctionTemplate, - llvm::SmallBitVector &Deduced); + const FunctionTemplateDecl *FunctionTemplate, + llvm::SmallBitVector &Deduced); //===--------------------------------------------------------------------===// // C++ Template Instantiation @@ -5554,7 +5705,7 @@ public: NamedDecl *Template; /// \brief The entity that is being instantiated. - uintptr_t Entity; + Decl *Entity; /// \brief The list of template arguments we are substituting, if they /// are not part of the entity. @@ -5796,11 +5947,11 @@ public: /// template argument substitution failures are not considered /// errors. /// - /// \returns An empty \c llvm::Optional if we're not in a SFINAE context. + /// \returns An empty \c Optional if we're not in a SFINAE context. /// Otherwise, contains a pointer that, if non-NULL, contains the nearest /// template-deduction context object, which can be used to capture /// diagnostics that will be suppressed. - llvm::Optional<sema::TemplateDeductionInfo *> isSFINAEContext() const; + Optional<sema::TemplateDeductionInfo *> isSFINAEContext() const; /// \brief Determines whether we are currently in a context that /// is not evaluated as per C++ [expr] p5. @@ -5911,7 +6062,7 @@ public: ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs, int indexAdjustment, - llvm::Optional<unsigned> NumExpansions, + Optional<unsigned> NumExpansions, bool ExpectParameterPack); bool SubstParmTypes(SourceLocation Loc, ParmVarDecl **Params, unsigned NumParams, @@ -6141,10 +6292,6 @@ public: void DiagnosePropertyMismatch(ObjCPropertyDecl *Property, ObjCPropertyDecl *SuperProperty, const IdentifierInfo *Name); - void ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl); - - - void CompareProperties(Decl *CDecl, Decl *MergeProtocols); void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, ObjCInterfaceDecl *ID); @@ -6214,6 +6361,7 @@ public: ObjCMethodDecl *LookupMethodInObjectType(Selector Sel, QualType Ty, bool IsInstance); + bool CheckARCMethodDecl(ObjCMethodDecl *method); bool inferObjCARCLifetime(ValueDecl *decl); ExprResult @@ -6324,14 +6472,13 @@ public: ParsedType Type, SourceLocation RParenLoc, Expr *SubExpr); - + bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall); /// \brief Check whether the given new method is a valid override of the /// given overridden method, and set any properties that should be inherited. void CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, - const ObjCMethodDecl *Overridden, - bool IsImplementation); + const ObjCMethodDecl *Overridden); /// \brief Describes the compatibility of a result type with its method. enum ResultTypeCompatibilityKind { @@ -6450,9 +6597,21 @@ public: /// AddAlignedAttr - Adds an aligned attribute to a particular declaration. void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, - bool isDeclSpec); + unsigned SpellingListIndex, bool IsPackExpansion); void AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *T, - bool isDeclSpec); + unsigned SpellingListIndex, bool IsPackExpansion); + + // OpenMP directives and clauses. + + /// \brief Called on well-formed '#pragma omp threadprivate'. + DeclGroupPtrTy ActOnOpenMPThreadprivateDirective( + SourceLocation Loc, + Scope *CurScope, + ArrayRef<DeclarationNameInfo> IdList); + /// \brief Build a new OpenMPThreadPrivateDecl and check its correctness. + OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl( + SourceLocation Loc, + ArrayRef<DeclRefExpr *> VarList); /// \brief The kind of conversion being performed. enum CheckedConversionKind { @@ -6541,7 +6700,8 @@ public: Expr **Args, unsigned NumArgs, SmallVector<Expr *, 8> &AllArgs, VariadicCallType CallType = VariadicDoesNotApply, - bool AllowExplicit = false); + bool AllowExplicit = false, + bool IsListInitialization = false); // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but // will create a runtime trap if the resulting type is not a POD type. @@ -6812,6 +6972,11 @@ public: /// given type. ExprResult forceUnknownAnyToType(Expr *E, QualType ToType); + /// \brief Type-check an expression that's being passed to an + /// __unknown_anytype parameter. + ExprResult checkUnknownAnyArg(SourceLocation callLoc, + Expr *result, QualType ¶mType); + // CheckVectorCast - check type constraints for vectors. // Since vectors are an extension, there are no C standard reference for this. // We allow casting between vectors and integer datatypes of the same size. @@ -6883,6 +7048,11 @@ public: /// with a related result type, emit a note describing what happened. void EmitRelatedResultTypeNote(const Expr *E); + /// \brief Given that we had incompatible pointer types in a return + /// statement, check whether we're in a method with a related result + /// type, and if so, emit a note describing what happened. + void EmitRelatedResultTypeNoteForReturn(QualType destType); + /// CheckBooleanCondition - Diagnose problems involving the use of /// the given expression as a boolean condition (e.g. in an if /// statement). Also performs the standard function and array @@ -7033,7 +7203,7 @@ public: void CodeCompleteTag(Scope *S, unsigned TagSpec); void CodeCompleteTypeQualifiers(DeclSpec &DS); void CodeCompleteCase(Scope *S); - void CodeCompleteCall(Scope *S, Expr *Fn, llvm::ArrayRef<Expr *> Args); + void CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args); void CodeCompleteInitializer(Scope *S, Decl *D); void CodeCompleteReturn(Scope *S); void CodeCompleteAfterIf(Scope *S); @@ -7150,12 +7320,11 @@ private: bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall, const FunctionProtoType *Proto); void CheckConstructorCall(FunctionDecl *FDecl, - Expr **Args, - unsigned NumArgs, + ArrayRef<const Expr *> Args, const FunctionProtoType *Proto, SourceLocation Loc); - void checkCall(NamedDecl *FDecl, Expr **Args, unsigned NumArgs, + void checkCall(NamedDecl *FDecl, ArrayRef<const Expr *> Args, unsigned NumProtoArgs, bool IsMemberFunction, SourceLocation Loc, SourceRange Range, VariadicCallType CallType); @@ -7203,7 +7372,7 @@ private: }; StringLiteralCheckType checkFormatStringExpr(const Expr *E, - Expr **Args, unsigned NumArgs, + ArrayRef<const Expr *> Args, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, @@ -7212,16 +7381,17 @@ private: bool inFunctionCall = true); void CheckFormatString(const StringLiteral *FExpr, const Expr *OrigFormatExpr, - Expr **Args, unsigned NumArgs, bool HasVAListArg, + ArrayRef<const Expr *> Args, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, FormatStringType Type, bool inFunctionCall, VariadicCallType CallType); - bool CheckFormatArguments(const FormatAttr *Format, Expr **Args, - unsigned NumArgs, bool IsCXXMember, + bool CheckFormatArguments(const FormatAttr *Format, + ArrayRef<const Expr *> Args, + bool IsCXXMember, VariadicCallType CallType, SourceLocation Loc, SourceRange Range); - bool CheckFormatArguments(Expr **Args, unsigned NumArgs, + bool CheckFormatArguments(ArrayRef<const Expr *> Args, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, FormatStringType Type, VariadicCallType CallType, @@ -7245,6 +7415,13 @@ private: SourceLocation ReturnLoc); void CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr* RHS); void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation()); + void CheckForIntOverflow(Expr *E); + void CheckUnsequencedOperations(Expr *E); + + /// \brief Perform semantic checks on a completed expression. This will either + /// be a full-expression or a default argument expression. + void CheckCompletedExpr(Expr *E, SourceLocation CheckLoc = SourceLocation(), + bool IsConstexpr = false); void CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *Field, Expr *Init); @@ -7290,6 +7467,8 @@ private: /// The parser maintains this state here. Scope *CurScope; + mutable IdentifierInfo *Ident_super; + protected: friend class Parser; friend class InitializationSequence; @@ -7307,6 +7486,8 @@ public: /// template substitution or instantiation. Scope *getCurScope() const { return CurScope; } + IdentifierInfo *getSuperIdentifier() const; + Decl *getObjCDeclContext() const; DeclContext *getCurLexicalContext() const { diff --git a/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h index 64b83e3..bbf4272 100644 --- a/include/clang/Sema/SemaInternal.h +++ b/include/clang/Sema/SemaInternal.h @@ -15,9 +15,9 @@ #ifndef LLVM_CLANG_SEMA_SEMA_INTERNAL_H #define LLVM_CLANG_SEMA_SEMA_INTERNAL_H +#include "clang/AST/ASTContext.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaDiagnostic.h" -#include "clang/AST/ASTContext.h" namespace clang { diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h index bbccd25..492e580 100644 --- a/include/clang/Sema/Template.h +++ b/include/clang/Sema/Template.h @@ -14,6 +14,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclVisitor.h" +#include "clang/Sema/Sema.h" #include "llvm/ADT/SmallVector.h" #include <cassert> #include <utility> @@ -344,7 +345,16 @@ namespace clang { void SetPartiallySubstitutedPack(NamedDecl *Pack, const TemplateArgument *ExplicitArgs, unsigned NumExplicitArgs); - + + /// \brief Reset the partially-substituted pack when it is no longer of + /// interest. + void ResetPartiallySubstitutedPack() { + assert(PartiallySubstitutedPack && "No partially-substituted pack"); + PartiallySubstitutedPack = 0; + ArgsInPartiallySubstitutedPack = 0; + NumArgsInPartiallySubstitutedPack = 0; + } + /// \brief Retrieve the partially-substitued template parameter pack. /// /// If there is no partially-substituted parameter pack, returns NULL. @@ -420,6 +430,7 @@ namespace clang { Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); Decl *VisitClassScopeFunctionSpecializationDecl( ClassScopeFunctionSpecializationDecl *D); + Decl *VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); // Base case. FIXME: Remove once we can instantiate everything. Decl *VisitDecl(Decl *D) { diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h index 251a659..3abb8f1 100644 --- a/include/clang/Sema/TemplateDeduction.h +++ b/include/clang/Sema/TemplateDeduction.h @@ -13,8 +13,8 @@ #ifndef LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H #define LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H -#include "clang/Basic/PartialDiagnostic.h" #include "clang/AST/DeclTemplate.h" +#include "clang/Basic/PartialDiagnostic.h" #include "llvm/ADT/SmallVector.h" namespace clang { @@ -47,7 +47,7 @@ class TemplateDeductionInfo { public: TemplateDeductionInfo(SourceLocation Loc) - : Deduced(0), Loc(Loc), HasSFINAEDiagnostic(false) { } + : Deduced(0), Loc(Loc), HasSFINAEDiagnostic(false), Expression(0) { } /// \brief Returns the location at which template argument is /// occurring. @@ -141,15 +141,25 @@ public: /// TDK_SubstitutionFailure: this argument is the template /// argument we were instantiating when we encountered an error. /// - /// TDK_NonDeducedMismatch: this is the template argument - /// provided in the source code. + /// TDK_NonDeducedMismatch: this is the component of the 'parameter' + /// of the deduction, directly provided in the source code. TemplateArgument FirstArg; /// \brief The second template argument to which the template /// argument deduction failure refers. /// + /// TDK_NonDeducedMismatch: this is the mismatching component of the + /// 'argument' of the deduction, from which we are deducing arguments. + /// /// FIXME: Finish documenting this. TemplateArgument SecondArg; + + /// \brief The expression which caused a deduction failure. + /// + /// TDK_FailedOverloadResolution: this argument is the reference to + // an overloaded function which could not be resolved to a specific + // function. + Expr *Expression; }; } diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h index 2b4a9e6..cdd71c8 100644 --- a/include/clang/Sema/TypoCorrection.h +++ b/include/clang/Sema/TypoCorrection.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_SEMA_TYPOCORRECTION_H #include "clang/AST/DeclCXX.h" +#include "clang/Sema/DeclSpec.h" #include "llvm/ADT/SmallVector.h" namespace clang { @@ -181,12 +182,12 @@ public: return CorrectionRange; } - typedef llvm::SmallVector<NamedDecl*, 1>::iterator decl_iterator; + typedef SmallVector<NamedDecl *, 1>::iterator decl_iterator; decl_iterator begin() { return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin(); } decl_iterator end() { return CorrectionDecls.end(); } - typedef llvm::SmallVector<NamedDecl*, 1>::const_iterator const_decl_iterator; + typedef SmallVector<NamedDecl *, 1>::const_iterator const_decl_iterator; const_decl_iterator begin() const { return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin(); } @@ -200,7 +201,7 @@ private: // Results. DeclarationName CorrectionName; NestedNameSpecifier *CorrectionNameSpec; - llvm::SmallVector<NamedDecl*, 1> CorrectionDecls; + SmallVector<NamedDecl *, 1> CorrectionDecls; unsigned CharDistance; unsigned QualifierDistance; unsigned CallbackDistance; @@ -227,9 +228,11 @@ class CorrectionCandidateCallback { /// candidate is viable, without ranking potentially viable candidates. /// Only ValidateCandidate or RankCandidate need to be overriden by a /// callback wishing to check the viability of correction candidates. - virtual bool ValidateCandidate(const TypoCorrection &candidate) { - return true; - } + /// The default predicate always returns true if the candidate is not a type + /// name or keyword, true for types if WantTypeSpecifiers is true, and true + /// for keywords if WantTypeSpecifiers, WantExpressionKeywords, + /// WantCXXNamedCasts, WantRemainingKeywords, or WantObjCSuper is true. + virtual bool ValidateCandidate(const TypoCorrection &candidate); /// \brief Method used by Sema::CorrectTypo to assign an "edit distance" rank /// to a candidate (where a lower value represents a better candidate), or diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 8c58fb2..9b685ba 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -18,9 +18,9 @@ #define LLVM_CLANG_FRONTEND_PCHBITCODES_H #include "clang/AST/Type.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/Bitcode/BitCodes.h" #include "llvm/Support/DataTypes.h" -#include "llvm/ADT/DenseMap.h" namespace clang { namespace serialization { @@ -35,7 +35,7 @@ namespace clang { /// Version 4 of AST files also requires that the version control branch and /// revision match exactly, since there is no backward compatibility of /// AST files at this time. - const unsigned VERSION_MAJOR = 4; + const unsigned VERSION_MAJOR = 5; /// \brief AST file minor version number supported by this version of /// Clang. @@ -129,7 +129,14 @@ namespace clang { /// \brief An ID number that refers to a macro in an AST file. typedef uint32_t MacroID; - + + /// \brief A global ID number that refers to a macro in an AST file. + typedef uint32_t GlobalMacroID; + + /// \brief A local to a module ID number that refers to a macro in an + /// AST file. + typedef uint32_t LocalMacroID; + /// \brief The number of predefined macro IDs. const unsigned int NUM_PREDEF_MACRO_IDS = 1; @@ -259,21 +266,25 @@ namespace clang { /// \brief The directory that the PCH was originally created in. ORIGINAL_PCH_DIR = 6, + /// \brief Record code for file ID of the file or buffer that was used to + /// generate the AST file. + ORIGINAL_FILE_ID = 7, + /// \brief Offsets into the input-files block where input files /// reside. - INPUT_FILE_OFFSETS = 7, + INPUT_FILE_OFFSETS = 8, /// \brief Record code for the diagnostic options table. - DIAGNOSTIC_OPTIONS = 8, + DIAGNOSTIC_OPTIONS = 9, /// \brief Record code for the filesystem options table. - FILE_SYSTEM_OPTIONS = 9, + FILE_SYSTEM_OPTIONS = 10, /// \brief Record code for the headers search options table. - HEADER_SEARCH_OPTIONS = 10, + HEADER_SEARCH_OPTIONS = 11, /// \brief Record code for the preprocessor options table. - PREPROCESSOR_OPTIONS = 11 + PREPROCESSOR_OPTIONS = 12 }; /// \brief Record types that occur within the input-files block @@ -319,6 +330,11 @@ namespace clang { /// NULL-terminated string that corresponds to that identifier. IDENTIFIER_OFFSET = 3, + /// \brief This is so that older clang versions, before the introduction + /// of the control block, can read and reject the newer PCH format. + /// *DON"T CHANGE THIS NUMBER*. + METADATA_OLD_FORMAT = 4, + /// \brief Record code for the identifier table. /// /// The identifier table is a simple blob that contains @@ -331,7 +347,7 @@ namespace clang { /// between offsets (for unresolved identifier IDs) and /// IdentifierInfo pointers (for already-resolved identifier /// IDs). - IDENTIFIER_TABLE = 4, + IDENTIFIER_TABLE = 5, /// \brief Record code for the array of external definitions. /// @@ -341,7 +357,7 @@ namespace clang { /// reported to the AST consumer after the AST file has been /// read, since their presence can affect the semantics of the /// program (e.g., for code generation). - EXTERNAL_DEFINITIONS = 5, + EXTERNAL_DEFINITIONS = 6, /// \brief Record code for the set of non-builtin, special /// types. @@ -350,33 +366,33 @@ namespace clang { /// that are constructed during semantic analysis (e.g., /// __builtin_va_list). The SPECIAL_TYPE_* constants provide /// offsets into this record. - SPECIAL_TYPES = 6, + SPECIAL_TYPES = 7, /// \brief Record code for the extra statistics we gather while /// generating an AST file. - STATISTICS = 7, + STATISTICS = 8, /// \brief Record code for the array of tentative definitions. - TENTATIVE_DEFINITIONS = 8, + TENTATIVE_DEFINITIONS = 9, - /// \brief Record code for the array of locally-scoped external + /// \brief Record code for the array of locally-scoped extern "C" /// declarations. - LOCALLY_SCOPED_EXTERNAL_DECLS = 9, + LOCALLY_SCOPED_EXTERN_C_DECLS = 10, /// \brief Record code for the table of offsets into the /// Objective-C method pool. - SELECTOR_OFFSETS = 10, + SELECTOR_OFFSETS = 11, /// \brief Record code for the Objective-C method pool, - METHOD_POOL = 11, + METHOD_POOL = 12, /// \brief The value of the next __COUNTER__ to dispense. /// [PP_COUNTER_VALUE, Val] - PP_COUNTER_VALUE = 12, + PP_COUNTER_VALUE = 13, /// \brief Record code for the table of offsets into the block /// of source-location information. - SOURCE_LOCATION_OFFSETS = 13, + SOURCE_LOCATION_OFFSETS = 14, /// \brief Record code for the set of source location entries /// that need to be preloaded by the AST reader. @@ -384,7 +400,7 @@ namespace clang { /// This set contains the source location entry for the /// predefines buffer and for any file entries that need to be /// preloaded. - SOURCE_LOCATION_PRELOADS = 14, + SOURCE_LOCATION_PRELOADS = 15, /// \brief Record code for the set of ext_vector type names. EXT_VECTOR_DECLS = 16, @@ -513,9 +529,13 @@ namespace clang { /// macro definition. MACRO_OFFSET = 47, - /// \brief Record of updates for a macro that was modified after - /// being deserialized. - MACRO_UPDATES = 48 + /// \brief Mapping table from the identifier ID to the offset of the + /// macro directive history for the identifier. + MACRO_TABLE = 48, + + /// \brief Record code for undefined but used functions and variables that + /// need a definition in this TU. + UNDEFINED_BUT_USED = 49 }; /// \brief Record types used within a source manager block. @@ -552,7 +572,10 @@ namespace clang { /// \brief Describes one token. /// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags] - PP_TOKEN = 3 + PP_TOKEN = 3, + + /// \brief The macro directives history for a particular identifier. + PP_MACRO_DIRECTIVE_HISTORY = 4 }; /// \brief Record types used within a preprocessor detail block. @@ -594,7 +617,13 @@ namespace clang { SUBMODULE_REQUIRES = 8, /// \brief Specifies a header that has been explicitly excluded /// from this submodule. - SUBMODULE_EXCLUDED_HEADER = 9 + SUBMODULE_EXCLUDED_HEADER = 9, + /// \brief Specifies a library or framework to link against. + SUBMODULE_LINK_LIBRARY = 10, + /// \brief Specifies a configuration macro for this module. + SUBMODULE_CONFIG_MACRO = 11, + /// \brief Specifies a conflict with another module. + SUBMODULE_CONFLICT = 12 }; /// \brief Record types used within a comments block. @@ -692,7 +721,23 @@ namespace clang { /// \brief The __va_list_tag placeholder type. PREDEF_TYPE_VA_LIST_TAG = 36, /// \brief The placeholder type for builtin functions. - PREDEF_TYPE_BUILTIN_FN = 37 + PREDEF_TYPE_BUILTIN_FN = 37, + /// \brief OpenCL 1d image type. + PREDEF_TYPE_IMAGE1D_ID = 38, + /// \brief OpenCL 1d image array type. + PREDEF_TYPE_IMAGE1D_ARR_ID = 39, + /// \brief OpenCL 1d image buffer type. + PREDEF_TYPE_IMAGE1D_BUFF_ID = 40, + /// \brief OpenCL 2d image type. + PREDEF_TYPE_IMAGE2D_ID = 41, + /// \brief OpenCL 2d image array type. + PREDEF_TYPE_IMAGE2D_ARR_ID = 42, + /// \brief OpenCL 3d image type. + PREDEF_TYPE_IMAGE3D_ID = 43, + /// \brief OpenCL event type. + PREDEF_TYPE_EVENT_ID = 44, + /// \brief OpenCL sampler type. + PREDEF_TYPE_SAMPLER_ID = 45 }; /// \brief The number of predefined type IDs that are reserved for @@ -1000,7 +1045,11 @@ namespace clang { /// function specialization. (Microsoft extension). DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION, /// \brief An ImportDecl recording a module import. - DECL_IMPORT + DECL_IMPORT, + /// \brief A OMPThreadPrivateDecl record. + DECL_OMP_THREADPRIVATE, + /// \brief An EmptyDecl record. + DECL_EMPTY }; /// \brief Record codes for each kind of statement or expression. diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index e23ea5c..9255336 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -14,33 +14,33 @@ #ifndef LLVM_CLANG_FRONTEND_AST_READER_H #define LLVM_CLANG_FRONTEND_AST_READER_H -#include "clang/Serialization/ASTBitCodes.h" -#include "clang/Serialization/ContinuousRangeMap.h" -#include "clang/Serialization/Module.h" -#include "clang/Serialization/ModuleManager.h" -#include "clang/Sema/ExternalSemaSource.h" -#include "clang/AST/DeclarationName.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/TemplateBase.h" -#include "clang/Lex/ExternalPreprocessorSource.h" -#include "clang/Lex/HeaderSearch.h" -#include "clang/Lex/PPMutationListener.h" -#include "clang/Lex/PreprocessingRecord.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemOptions.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Version.h" +#include "clang/Lex/ExternalPreprocessorSource.h" +#include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/PreprocessingRecord.h" +#include "clang/Sema/ExternalSemaSource.h" +#include "clang/Serialization/ASTBitCodes.h" +#include "clang/Serialization/ContinuousRangeMap.h" +#include "clang/Serialization/Module.h" +#include "clang/Serialization/ModuleManager.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Support/DataTypes.h" #include <deque> @@ -48,6 +48,7 @@ #include <string> #include <utility> #include <vector> +#include <sys/stat.h> namespace llvm { class MemoryBuffer; @@ -68,8 +69,10 @@ class NestedNameSpecifier; class CXXBaseSpecifier; class CXXConstructorDecl; class CXXCtorInitializer; +class GlobalModuleIndex; class GotoStmt; class MacroDefinition; +class MacroDirective; class NamedDecl; class OpaqueValueExpr; class Preprocessor; @@ -85,6 +88,7 @@ class TypeLocReader; struct HeaderFileInfo; class VersionTuple; class TargetOptions; +class ASTUnresolvedSet; /// \brief Abstract interface for callback invocations by the ASTReader. /// @@ -96,6 +100,14 @@ class ASTReaderListener { public: virtual ~ASTReaderListener(); + /// \brief Receives the full Clang version information. + /// + /// \returns true to indicate that the version is invalid. Subclasses should + /// generally defer to this implementation. + virtual bool ReadFullVersionInformation(StringRef FullVersion) { + return FullVersion != getClangFullRepositoryVersion(); + } + /// \brief Receives the language options. /// /// \returns true to indicate the options are invalid or false otherwise. @@ -233,6 +245,8 @@ public: Success, /// \brief The AST file itself appears corrupted. Failure, + /// \brief The AST file was missing. + Missing, /// \brief The AST file is out-of-date relative to its input files, /// and needs to be regenerated. OutOfDate, @@ -291,6 +305,9 @@ private: /// \brief The module manager which manages modules and their dependencies ModuleManager ModuleMgr; + /// \brief The global module index, if loaded. + llvm::OwningPtr<GlobalModuleIndex> GlobalIndex; + /// \brief A map of global bit offsets to the module that stores entities /// at those bit offsets. ContinuousRangeMap<uint64_t, ModuleFile*, 4> GlobalBitOffsetsMap; @@ -387,7 +404,7 @@ private: typedef llvm::MapVector<Decl *, uint64_t, llvm::SmallDenseMap<Decl *, unsigned, 4>, - llvm::SmallVector<std::pair<Decl *, uint64_t>, 4> > + SmallVector<std::pair<Decl *, uint64_t>, 4> > PendingBodiesMap; /// \brief Functions or methods that have bodies that will be attached. @@ -431,15 +448,6 @@ private: /// global macro ID to produce a local ID. GlobalMacroMapType GlobalMacroMap; - typedef llvm::DenseMap<serialization::MacroID, - llvm::SmallVector<std::pair<serialization::SubmoduleID, - MacroUpdate>, 1> > - MacroUpdatesMap; - - /// \brief Mapping from (global) macro IDs to the set of updates to be - /// performed to the corresponding macro. - MacroUpdatesMap MacroUpdates; - /// \brief A vector containing submodules that have already been loaded. /// /// This vector is indexed by the Submodule ID (-1). NULL submodule entries @@ -459,28 +467,22 @@ private: public: enum NameKind { Declaration, - MacroVisibility, - MacroUndef + MacroVisibility } Kind; private: - unsigned Loc; - union { Decl *D; - MacroInfo *MI; + MacroDirective *MD; }; IdentifierInfo *Id; public: - HiddenName(Decl *D) : Kind(Declaration), Loc(), D(D), Id() { } + HiddenName(Decl *D) : Kind(Declaration), D(D), Id() { } - HiddenName(IdentifierInfo *II, MacroInfo *MI) - : Kind(MacroVisibility), Loc(), MI(MI), Id(II) { } - - HiddenName(IdentifierInfo *II, MacroInfo *MI, SourceLocation Loc) - : Kind(MacroUndef), Loc(Loc.getRawEncoding()), MI(MI), Id(II) { } + HiddenName(IdentifierInfo *II, MacroDirective *MD) + : Kind(MacroVisibility), MD(MD), Id(II) { } NameKind getKind() const { return Kind; } @@ -489,21 +491,14 @@ private: return D; } - std::pair<IdentifierInfo *, MacroInfo *> getMacro() const { - assert((getKind() == MacroUndef || getKind() == MacroVisibility) - && "Hidden name is not a macro!"); - return std::make_pair(Id, MI); - } - - SourceLocation getMacroUndefLoc() const { - assert(getKind() == MacroUndef && "Hidden name is not an undef!"); - return SourceLocation::getFromRawEncoding(Loc); + std::pair<IdentifierInfo *, MacroDirective *> getMacro() const { + assert(getKind() == MacroVisibility && "Hidden name is not a macro!"); + return std::make_pair(Id, MD); } }; /// \brief A set of hidden declarations. - typedef llvm::SmallVector<HiddenName, 2> - HiddenNames; + typedef SmallVector<HiddenName, 2> HiddenNames; typedef llvm::DenseMap<Module *, HiddenNames> HiddenNamesMapType; @@ -512,28 +507,30 @@ private: HiddenNamesMapType HiddenNamesMap; - /// \brief A module import or export that hasn't yet been resolved. - struct UnresolvedModuleImportExport { + /// \brief A module import, export, or conflict that hasn't yet been resolved. + struct UnresolvedModuleRef { /// \brief The file in which this module resides. ModuleFile *File; /// \brief The module that is importing or exporting. Module *Mod; - + + /// \brief The kind of module reference. + enum { Import, Export, Conflict } Kind; + /// \brief The local ID of the module that is being exported. unsigned ID; - - /// \brief Whether this is an import (vs. an export). - unsigned IsImport : 1; - + /// \brief Whether this is a wildcard export. unsigned IsWildcard : 1; + + /// \brief String data. + StringRef String; }; /// \brief The set of module imports and exports that still need to be /// resolved. - llvm::SmallVector<UnresolvedModuleImportExport, 2> - UnresolvedModuleImportExports; + SmallVector<UnresolvedModuleRef, 2> UnresolvedModuleRefs; /// \brief A vector containing selectors that have already been loaded. /// @@ -546,7 +543,7 @@ private: GlobalSelectorMapType; /// \brief Mapping from global selector IDs to the module in which the - /// selector resides along with the offset that should be added to the + /// global selector ID to produce a local ID. GlobalSelectorMapType GlobalSelectorMap; @@ -554,8 +551,35 @@ private: /// global method pool for this selector. llvm::DenseMap<Selector, unsigned> SelectorGeneration; - typedef llvm::MapVector<IdentifierInfo *, - llvm::SmallVector<serialization::MacroID, 2> > + struct PendingMacroInfo { + ModuleFile *M; + + struct ModuleMacroDataTy { + serialization::GlobalMacroID GMacID; + unsigned ImportLoc; + }; + struct PCHMacroDataTy { + uint64_t MacroDirectivesOffset; + }; + + union { + ModuleMacroDataTy ModuleMacroData; + PCHMacroDataTy PCHMacroData; + }; + + PendingMacroInfo(ModuleFile *M, + serialization::GlobalMacroID GMacID, + SourceLocation ImportLoc) : M(M) { + ModuleMacroData.GMacID = GMacID; + ModuleMacroData.ImportLoc = ImportLoc.getRawEncoding(); + } + + PendingMacroInfo(ModuleFile *M, uint64_t MacroDirectivesOffset) : M(M) { + PCHMacroData.MacroDirectivesOffset = MacroDirectivesOffset; + } + }; + + typedef llvm::MapVector<IdentifierInfo *, SmallVector<PendingMacroInfo, 2> > PendingMacroIDsMap; /// \brief Mapping from identifiers that have a macro history to the global @@ -637,11 +661,11 @@ private: /// \brief Fields containing data that is used for semantic analysis //@{ - /// \brief The IDs of all locally scoped external decls in the chain. + /// \brief The IDs of all locally scoped extern "C" decls in the chain. /// /// Sema tracks these to validate that the types are consistent across all - /// local external declarations. - SmallVector<uint64_t, 16> LocallyScopedExternalDecls; + /// local extern "C" declarations. + SmallVector<uint64_t, 16> LocallyScopedExternCDecls; /// \brief The IDs of all dynamic class declarations in the chain. /// @@ -674,6 +698,10 @@ private: /// \brief A list of the namespaces we've seen. SmallVector<uint64_t, 4> KnownNamespaces; + /// \brief A list of undefined decls with internal linkage followed by the + /// SourceLocation of a matching ODR-use. + SmallVector<uint64_t, 8> UndefinedButUsed; + /// \brief A list of modules that were imported by precompiled headers or /// any other non-module AST file. SmallVector<serialization::SubmoduleID, 2> ImportedModules; @@ -693,6 +721,12 @@ private: /// \brief Whether to accept an AST file with compiler errors. bool AllowASTWithCompilerErrors; + /// \brief Whether we are allowed to use the global module index. + bool UseGlobalIndex; + + /// \brief Whether we have tried loading the global module index yet. + bool TriedLoadingGlobalIndex; + /// \brief The current "generation" of the module file import stack, which /// indicates how many separate module file load operations have occurred. unsigned CurrentGeneration; @@ -727,6 +761,12 @@ private: /// \brief The total number of macros stored in the chain. unsigned TotalNumMacros; + /// \brief The number of lookups into identifier tables. + unsigned NumIdentifierLookups; + + /// \brief The number of lookups into identifier tables that succeed. + unsigned NumIdentifierLookupHits; + /// \brief The number of selectors that have been read. unsigned NumSelectorsRead; @@ -734,8 +774,20 @@ private: unsigned NumMethodPoolEntriesRead; /// \brief The number of times we have looked up a selector in the method - /// pool and not found anything interesting. - unsigned NumMethodPoolMisses; + /// pool. + unsigned NumMethodPoolLookups; + + /// \brief The number of times we have looked up a selector in the method + /// pool and found something. + unsigned NumMethodPoolHits; + + /// \brief The number of times we have looked up a selector in the method + /// pool within a specific module. + unsigned NumMethodPoolTableLookups; + + /// \brief The number of times we have looked up a selector in the method + /// pool within a specific module and found something. + unsigned NumMethodPoolTableHits; /// \brief The total number of method pool entries in the selector table. unsigned TotalNumMethodPoolEntries; @@ -761,19 +813,13 @@ private: /// Number of CXX base specifiers currently loaded unsigned NumCXXBaseSpecifiersLoaded; - /// \brief An IdentifierInfo that has been loaded but whose top-level - /// declarations of the same name have not (yet) been loaded. - struct PendingIdentifierInfo { - IdentifierInfo *II; - SmallVector<uint32_t, 4> DeclIDs; - }; - /// \brief The set of identifiers that were read while the AST reader was /// (recursively) loading declarations. /// /// The declarations on the identifier chain for these identifiers will be /// loaded once the recursive loading has completed. - std::deque<PendingIdentifierInfo> PendingIdentifierInfos; + llvm::MapVector<IdentifierInfo *, SmallVector<uint32_t, 4> > + PendingIdentifierInfos; /// \brief The generation number of each identifier, which keeps track of /// the last time we loaded information about this identifier. @@ -797,11 +843,26 @@ private: /// Each element is the global declaration ID of the first declaration in /// the chain. Elements in this vector should be unique; use /// PendingDeclChainsKnown to ensure uniqueness. - llvm::SmallVector<serialization::DeclID, 16> PendingDeclChains; + SmallVector<serialization::DeclID, 16> PendingDeclChains; /// \brief Keeps track of the elements added to PendingDeclChains. llvm::SmallSet<serialization::DeclID, 16> PendingDeclChainsKnown; + /// \brief The Decl IDs for the Sema/Lexical DeclContext of a Decl that has + /// been loaded but its DeclContext was not set yet. + struct PendingDeclContextInfo { + Decl *D; + serialization::GlobalDeclID SemaDC; + serialization::GlobalDeclID LexicalDC; + }; + + /// \brief The set of Decls that have been loaded but their DeclContexts are + /// not set yet. + /// + /// The DeclContexts for these Decls will be set once recursive loading has + /// been completed. + std::deque<PendingDeclContextInfo> PendingDeclContextInfos; + /// \brief The set of Objective-C categories that have been deserialized /// since the last time the declaration chains were linked. llvm::SmallPtrSet<ObjCCategoryDecl *, 16> CategoriesDeserialized; @@ -809,9 +870,9 @@ private: /// \brief The set of Objective-C class definitions that have already been /// loaded, for which we will need to check for categories whenever a new /// module is loaded. - llvm::SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded; + SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded; - typedef llvm::DenseMap<Decl *, llvm::SmallVector<serialization::DeclID, 2> > + typedef llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2> > MergedDeclsMap; /// \brief A mapping from canonical declarations to the set of additional @@ -820,7 +881,7 @@ private: MergedDeclsMap MergedDecls; typedef llvm::DenseMap<serialization::GlobalDeclID, - llvm::SmallVector<serialization::DeclID, 2> > + SmallVector<serialization::DeclID, 2> > StoredMergedDeclsMap; /// \brief A mapping from canonical declaration IDs to the set of additional @@ -883,11 +944,10 @@ private: /// \brief Reads a statement from the specified cursor. Stmt *ReadStmtFromStream(ModuleFile &F); - typedef llvm::PointerIntPair<const FileEntry *, 1, bool> InputFile; - /// \brief Retrieve the file entry and 'overridden' bit for an input /// file in the given module file. - InputFile getInputFile(ModuleFile &F, unsigned ID, bool Complain = true); + serialization::InputFile getInputFile(ModuleFile &F, unsigned ID, + bool Complain = true); /// \brief Get a FileEntry out of stored-in-PCH filename, making sure we take /// into account all the necessary relocations. @@ -895,12 +955,24 @@ private: void MaybeAddSystemRootToFilename(ModuleFile &M, std::string &Filename); + struct ImportedModule { + ModuleFile *Mod; + ModuleFile *ImportedBy; + SourceLocation ImportLoc; + + ImportedModule(ModuleFile *Mod, + ModuleFile *ImportedBy, + SourceLocation ImportLoc) + : Mod(Mod), ImportedBy(ImportedBy), ImportLoc(ImportLoc) { } + }; + ASTReadResult ReadASTCore(StringRef FileName, ModuleKind Type, - ModuleFile *ImportedBy, - llvm::SmallVectorImpl<ModuleFile *> &Loaded, + SourceLocation ImportLoc, ModuleFile *ImportedBy, + SmallVectorImpl<ImportedModule> &Loaded, + off_t ExpectedSize, time_t ExpectedModTime, unsigned ClientLoadCapabilities); ASTReadResult ReadControlBlock(ModuleFile &F, - llvm::SmallVectorImpl<ModuleFile *> &Loaded, + SmallVectorImpl<ImportedModule> &Loaded, unsigned ClientLoadCapabilities); bool ReadASTBlock(ModuleFile &F); bool ParseLineTable(ModuleFile &F, SmallVectorImpl<uint64_t> &Record); @@ -1034,6 +1106,14 @@ private: void finishPendingActions(); + void addPendingDeclContextInfo(Decl *D, + serialization::GlobalDeclID SemaDC, + serialization::GlobalDeclID LexicalDC) { + assert(D); + PendingDeclContextInfo Info = { D, SemaDC, LexicalDC }; + PendingDeclContextInfos.push_back(Info); + } + /// \brief Produce an error diagnostic and return true. /// /// This routine should only be used for fatal errors that have to @@ -1065,13 +1145,18 @@ public: /// \param AllowASTWithCompilerErrors If true, the AST reader will accept an /// AST file the was created out of an AST with compiler errors, /// otherwise it will reject it. + /// + /// \param UseGlobalIndex If true, the AST reader will try to load and use + /// the global module index. ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot = "", bool DisableValidation = false, - bool AllowASTWithCompilerErrors = false); + bool AllowASTWithCompilerErrors = false, + bool UseGlobalIndex = true); ~ASTReader(); SourceManager &getSourceManager() const { return SourceMgr; } + FileManager &getFileManager() const { return FileMgr; } /// \brief Flags that indicate what kind of AST loading failures the client /// of the AST reader can directly handle. @@ -1082,15 +1167,18 @@ public: /// \brief The client can't handle any AST loading failures. ARR_None = 0, /// \brief The client can handle an AST file that cannot load because it + /// is missing. + ARR_Missing = 0x1, + /// \brief The client can handle an AST file that cannot load because it /// is out-of-date relative to its input files. - ARR_OutOfDate = 0x1, + ARR_OutOfDate = 0x2, /// \brief The client can handle an AST file that cannot load because it /// was built with a different version of Clang. - ARR_VersionMismatch = 0x2, + ARR_VersionMismatch = 0x4, /// \brief The client can handle an AST file that cannot load because it's /// compiled configuration doesn't match that of the context it was /// loaded into. - ARR_ConfigurationMismatch = 0x4 + ARR_ConfigurationMismatch = 0x8 }; /// \brief Load the AST file designated by the given file name. @@ -1100,10 +1188,14 @@ public: /// \param Type The kind of AST being loaded, e.g., PCH, module, main file, /// or preamble. /// + /// \param ImportLoc the location where the module file will be considered as + /// imported from. For non-module AST types it should be invalid. + /// /// \param ClientLoadCapabilities The set of client load-failure /// capabilities, represented as a bitset of the enumerators of /// LoadFailureCapabilities. ASTReadResult ReadAST(const std::string &FileName, ModuleKind Type, + SourceLocation ImportLoc, unsigned ClientLoadCapabilities); /// \brief Make the entities in the given module and any of its (non-explicit) @@ -1113,11 +1205,17 @@ public: /// /// \param NameVisibility The level of visibility to give the names in the /// module. Visibility can only be increased over time. + /// + /// \param ImportLoc The location at which the import occurs. + /// + /// \param Complain Whether to complain about conflicting module imports. void makeModuleVisible(Module *Mod, - Module::NameVisibilityKind NameVisibility); + Module::NameVisibilityKind NameVisibility, + SourceLocation ImportLoc, + bool Complain); /// \brief Make the names within this set of hidden names visible. - void makeNamesVisible(const HiddenNames &Names); + void makeNamesVisible(const HiddenNames &Names, Module *Owner); /// \brief Set the AST callbacks listener. void setListener(ASTReaderListener *listener) { @@ -1127,6 +1225,18 @@ public: /// \brief Set the AST deserialization listener. void setDeserializationListener(ASTDeserializationListener *Listener); + /// \brief Determine whether this AST reader has a global index. + bool hasGlobalIndex() const { return GlobalIndex; } + + /// \brief Attempts to load the global index. + /// + /// \returns true if loading the global index has failed for any reason. + bool loadGlobalIndex(); + + /// \brief Determine whether we tried to load the global index, but failed, + /// e.g., because it is out-of-date or does not exist. + bool isGlobalIndexUnavailable() const; + /// \brief Initializes the ASTContext void InitializeContext(); @@ -1193,8 +1303,8 @@ public: /// \brief Optionally returns true or false if the preallocated preprocessed /// entity with index \p Index came from file \p FID. - virtual llvm::Optional<bool> isPreprocessedEntityInFileID(unsigned Index, - FileID FID); + virtual Optional<bool> isPreprocessedEntityInFileID(unsigned Index, + FileID FID); /// \brief Read the header file information for the given file entry. virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE); @@ -1297,7 +1407,7 @@ public: /// \brief Retrieve the module file that owns the given declaration, or NULL /// if the declaration is not from a module file. - ModuleFile *getOwningModuleFile(Decl *D); + ModuleFile *getOwningModuleFile(const Decl *D); /// \brief Returns the source location for the decl \p ID. SourceLocation getSourceLocationForDeclID(serialization::GlobalDeclID ID); @@ -1374,7 +1484,7 @@ public: /// \brief Finds all the visible declarations with a given name. /// The current implementation of this method just loads the entire /// lookup table as unmaterialized references. - virtual DeclContext::lookup_result + virtual bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); @@ -1459,6 +1569,9 @@ public: virtual void ReadKnownNamespaces( SmallVectorImpl<NamespaceDecl *> &Namespaces); + virtual void ReadUndefinedButUsed( + llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined); + virtual void ReadTentativeDefinitions( SmallVectorImpl<VarDecl *> &TentativeDefs); @@ -1472,7 +1585,7 @@ public: virtual void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls); - virtual void ReadLocallyScopedExternalDecls( + virtual void ReadLocallyScopedExternCDecls( SmallVectorImpl<NamedDecl *> &Decls); virtual void ReadReferencedSelectors( @@ -1493,7 +1606,7 @@ public: void SetIdentifierInfo(unsigned ID, IdentifierInfo *II); void SetGloballyVisibleDecls(IdentifierInfo *II, const SmallVectorImpl<uint32_t> &DeclIDs, - bool Nonrecursive = false); + SmallVectorImpl<Decl *> *Decls = 0); /// \brief Report a diagnostic. DiagnosticBuilder Diag(unsigned DiagID); @@ -1520,8 +1633,16 @@ public: serialization::IdentifierID getGlobalIdentifierID(ModuleFile &M, unsigned LocalID); + void resolvePendingMacro(IdentifierInfo *II, const PendingMacroInfo &PMInfo); + + void installPCHMacroDirectives(IdentifierInfo *II, + ModuleFile &M, uint64_t Offset); + + void installImportedMacro(IdentifierInfo *II, MacroDirective *MD, + Module *Owner); + /// \brief Retrieve the macro with the given ID. - MacroInfo *getMacro(serialization::MacroID ID, MacroInfo *Hint = 0); + MacroInfo *getMacro(serialization::MacroID ID); /// \brief Retrieve the global macro ID corresponding to the given local /// ID within the given module file. @@ -1530,6 +1651,10 @@ public: /// \brief Read the source location entry with index ID. virtual bool ReadSLocEntry(int ID); + /// \brief Retrieve the module import location and module name for the + /// given source manager entry ID. + virtual std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID); + /// \brief Retrieve the global submodule ID given a module and its local ID /// number. serialization::SubmoduleID @@ -1538,7 +1663,12 @@ public: /// \brief Retrieve the submodule that corresponds to a global submodule ID. /// Module *getSubmodule(serialization::SubmoduleID GlobalID); - + + /// \brief Retrieve the module that corresponds to the given module ID. + /// + /// Note: overrides method in ExternalASTSource + virtual Module *getModule(unsigned ID); + /// \brief Retrieve a selector from the given module with its local ID /// number. Selector getLocalSelector(ModuleFile &M, unsigned LocalID); @@ -1597,7 +1727,7 @@ public: unsigned &Idx); /// \brief Read a UnresolvedSet structure. - void ReadUnresolvedSet(ModuleFile &F, UnresolvedSetImpl &Set, + void ReadUnresolvedSet(ModuleFile &F, ASTUnresolvedSet &Set, const RecordData &Record, unsigned &Idx); /// \brief Read a C++ base specifier. @@ -1620,13 +1750,13 @@ public: /// \brief Read a source location. SourceLocation ReadSourceLocation(ModuleFile &ModuleFile, - const RecordData &Record, unsigned& Idx) { + const RecordData &Record, unsigned &Idx) { return ReadSourceLocation(ModuleFile, Record[Idx++]); } /// \brief Read a source range. SourceRange ReadSourceRange(ModuleFile &F, - const RecordData &Record, unsigned& Idx); + const RecordData &Record, unsigned &Idx); /// \brief Read an integral value llvm::APInt ReadAPInt(const RecordData &Record, unsigned &Idx); @@ -1635,7 +1765,8 @@ public: llvm::APSInt ReadAPSInt(const RecordData &Record, unsigned &Idx); /// \brief Read a floating-point value - llvm::APFloat ReadAPFloat(const RecordData &Record, unsigned &Idx); + llvm::APFloat ReadAPFloat(const RecordData &Record, + const llvm::fltSemantics &Sem, unsigned &Idx); // \brief Read a string static std::string ReadString(const RecordData &Record, unsigned &Idx); @@ -1670,20 +1801,32 @@ public: Expr *ReadSubExpr(); /// \brief Reads the macro record located at the given offset. - void ReadMacroRecord(ModuleFile &F, uint64_t Offset, MacroInfo *Hint = 0); + MacroInfo *ReadMacroRecord(ModuleFile &F, uint64_t Offset); /// \brief Determine the global preprocessed entity ID that corresponds to /// the given local ID within the given module. serialization::PreprocessedEntityID getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const; - /// \brief Note that the identifier has a macro history. + /// \brief Add a macro to resolve imported from a module. /// /// \param II The name of the macro. + /// \param M The module file. + /// \param GMacID The global macro ID that is associated with this identifier. + /// \param ImportLoc The location where the module is imported. + void addPendingMacroFromModule(IdentifierInfo *II, + ModuleFile *M, + serialization::GlobalMacroID GMacID, + SourceLocation ImportLoc); + + /// \brief Add a macro to deserialize its macro directive history from a PCH. /// - /// \param IDs The global macro IDs that are associated with this identifier. - void setIdentifierIsMacro(IdentifierInfo *II, - ArrayRef<serialization::MacroID> IDs); + /// \param II The name of the macro. + /// \param M The module file. + /// \param MacroDirectivesOffset Offset of the serialized macro directive + /// history. + void addPendingMacroFromPCH(IdentifierInfo *II, + ModuleFile *M, uint64_t MacroDirectivesOffset); /// \brief Read the set of macros defined by this external macro source. virtual void ReadDefinedMacros(); @@ -1734,7 +1877,7 @@ public: /// then restores it when destroyed. struct SavedStreamPosition { explicit SavedStreamPosition(llvm::BitstreamCursor &Cursor) - : Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) { } + : Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) { } ~SavedStreamPosition() { Cursor.JumpToBit(Offset); diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index ac81e21..2938dc7 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -14,20 +14,19 @@ #ifndef LLVM_CLANG_FRONTEND_AST_WRITER_H #define LLVM_CLANG_FRONTEND_AST_WRITER_H +#include "clang/AST/ASTMutationListener.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/TemplateBase.h" -#include "clang/AST/ASTMutationListener.h" -#include "clang/Lex/PPMutationListener.h" +#include "clang/Sema/SemaConsumer.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTDeserializationListener.h" -#include "clang/Sema/SemaConsumer.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Bitcode/BitstreamWriter.h" #include <map> #include <queue> @@ -48,12 +47,14 @@ class CXXCtorInitializer; class FileEntry; class FPOptions; class HeaderSearch; +class HeaderSearchOptions; class IdentifierResolver; class MacroDefinition; +class MacroDirective; +class MacroInfo; class OpaqueValueExpr; class OpenCLOptions; class ASTReader; -class MacroInfo; class Module; class PreprocessedEntity; class PreprocessingRecord; @@ -63,6 +64,7 @@ class SourceManager; class SwitchCase; class TargetInfo; class VersionTuple; +class ASTUnresolvedSet; namespace SrcMgr { class SLocEntry; } @@ -73,7 +75,6 @@ namespace SrcMgr { class SLocEntry; } /// data structures. This bitstream can be de-serialized via an /// instance of the ASTReader class. class ASTWriter : public ASTDeserializationListener, - public PPMutationListener, public ASTMutationListener { public: typedef SmallVector<uint64_t, 64> RecordData; @@ -231,6 +232,16 @@ private: /// \brief Map that provides the ID numbers of each macro. llvm::DenseMap<MacroInfo *, serialization::MacroID> MacroIDs; + struct MacroInfoToEmitData { + const IdentifierInfo *Name; + MacroInfo *MI; + serialization::MacroID ID; + }; + /// \brief The macro infos to emit. + std::vector<MacroInfoToEmitData> MacroInfosToEmit; + + llvm::DenseMap<const IdentifierInfo *, uint64_t> IdentMacroDirectivesOffsetMap; + /// @name FlushStmt Caches /// @{ @@ -266,11 +277,6 @@ private: /// table, indexed by the Selector ID (-1). std::vector<uint32_t> SelectorOffsets; - typedef llvm::MapVector<MacroInfo *, MacroUpdate> MacroUpdatesMap; - - /// \brief Updates to macro definitions that were loaded from an AST file. - MacroUpdatesMap MacroUpdates; - /// \brief Mapping from macro definitions (as they occur in the preprocessing /// record) to the macro IDs. llvm::DenseMap<const MacroDefinition *, serialization::PreprocessedEntityID> @@ -343,7 +349,7 @@ private: /// \brief The set of declarations that may have redeclaration chains that /// need to be serialized. - llvm::SetVector<Decl *, llvm::SmallVector<Decl *, 4>, + llvm::SetVector<Decl *, SmallVector<Decl *, 4>, llvm::SmallPtrSet<Decl *, 4> > Redeclarations; /// \brief Statements that we've encountered while serializing a @@ -415,7 +421,9 @@ private: void WriteBlockInfoBlock(); void WriteControlBlock(Preprocessor &PP, ASTContext &Context, StringRef isysroot, const std::string &OutputFile); - void WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot); + void WriteInputFiles(SourceManager &SourceMgr, + HeaderSearchOptions &HSOpts, + StringRef isysroot); void WriteSourceManagerBlock(SourceManager &SourceMgr, const Preprocessor &PP, StringRef isysroot); @@ -424,7 +432,8 @@ private: void WritePreprocessorDetail(PreprocessingRecord &PPRec); void WriteSubmodules(Module *WritingModule); - void WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag); + void WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, + bool isModule); void WriteCXXBaseSpecifiersOffsets(); void WriteType(QualType T); uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC); @@ -437,7 +446,6 @@ private: void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver, bool IsModule); void WriteAttributes(ArrayRef<const Attr*> Attrs, RecordDataImpl &Record); - void WriteMacroUpdates(); void ResolveDeclUpdatesBlocks(); void WriteDeclUpdatesBlocks(); void WriteDeclReplacementsBlock(); @@ -508,9 +516,6 @@ public: /// \brief Emit a reference to an identifier. void AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record); - /// \brief Emit a reference to a macro. - void addMacroRef(MacroInfo *MI, RecordDataImpl &Record); - /// \brief Emit a Selector (which is a smart pointer reference). void AddSelectorRef(Selector, RecordDataImpl &Record); @@ -529,7 +534,12 @@ public: serialization::IdentID getIdentifierRef(const IdentifierInfo *II); /// \brief Get the unique number used to refer to the given macro. - serialization::MacroID getMacroRef(MacroInfo *MI); + serialization::MacroID getMacroRef(MacroInfo *MI, const IdentifierInfo *Name); + + /// \brief Determine the ID of an already-emitted macro. + serialization::MacroID getMacroID(MacroInfo *MI); + + uint64_t getMacroDirectivesOffset(const IdentifierInfo *Name); /// \brief Emit a reference to a type. void AddTypeRef(QualType T, RecordDataImpl &Record); @@ -603,7 +613,7 @@ public: RecordDataImpl &Record); /// \brief Emit a UnresolvedSet structure. - void AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordDataImpl &Record); + void AddUnresolvedSet(const ASTUnresolvedSet &Set, RecordDataImpl &Record); /// \brief Emit a C++ base specifier. void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, @@ -640,6 +650,10 @@ public: /// source location. serialization::SubmoduleID inferSubmoduleIDFromLocation(SourceLocation Loc); + /// \brief Retrieve a submodule ID for this module. + /// Returns 0 If no ID has been associated with the module. + unsigned getExistingSubmoduleID(Module *Mod) const; + /// \brief Note that the identifier II occurs at the given offset /// within the identifier table. void SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset); @@ -699,9 +713,6 @@ public: MacroDefinition *MD); void ModuleRead(serialization::SubmoduleID ID, Module *Mod); - // PPMutationListener implementation. - virtual void UndefinedMacro(MacroInfo *MI); - // ASTMutationListener implementation. virtual void CompletedTagDefinition(const TagDecl *D); virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D); @@ -728,7 +739,7 @@ class PCHGenerator : public SemaConsumer { std::string isysroot; raw_ostream *Out; Sema *SemaPtr; - llvm::SmallVector<char, 128> Buffer; + SmallVector<char, 128> Buffer; llvm::BitstreamWriter Stream; ASTWriter Writer; @@ -743,7 +754,6 @@ public: ~PCHGenerator(); virtual void InitializeSema(Sema &S) { SemaPtr = &S; } virtual void HandleTranslationUnit(ASTContext &Ctx); - virtual PPMutationListener *GetPPMutationListener(); virtual ASTMutationListener *GetASTMutationListener(); virtual ASTDeserializationListener *GetASTDeserializationListener(); }; diff --git a/include/clang/Serialization/ContinuousRangeMap.h b/include/clang/Serialization/ContinuousRangeMap.h index d89cd02..f8ef8a1 100644 --- a/include/clang/Serialization/ContinuousRangeMap.h +++ b/include/clang/Serialization/ContinuousRangeMap.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_SERIALIZATION_CONTINUOUS_RANGE_MAP_H #define LLVM_CLANG_SERIALIZATION_CONTINUOUS_RANGE_MAP_H +#include "clang/Basic/LLVM.h" #include "llvm/ADT/SmallVector.h" #include <algorithm> #include <utility> diff --git a/include/clang/Serialization/GlobalModuleIndex.h b/include/clang/Serialization/GlobalModuleIndex.h new file mode 100644 index 0000000..eaf26d1 --- /dev/null +++ b/include/clang/Serialization/GlobalModuleIndex.h @@ -0,0 +1,194 @@ +//===--- GlobalModuleIndex.h - Global Module Index --------------*- 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 GlobalModuleIndex class, which manages a global index +// containing all of the identifiers known to the various modules within a given +// subdirectory of the module cache. It is used to improve the performance of +// queries such as "do any modules know about this identifier?" +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_SERIALIZATION_GLOBAL_MODULE_INDEX_H +#define LLVM_CLANG_SERIALIZATION_GLOBAL_MODULE_INDEX_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include <utility> + +namespace llvm { +class BitstreamCursor; +class MemoryBuffer; +} + +namespace clang { + +class DirectoryEntry; +class FileEntry; +class FileManager; + +namespace serialization { + class ModuleFile; +} + +using llvm::SmallVector; +using llvm::SmallVectorImpl; +using llvm::StringRef; +using serialization::ModuleFile; + +/// \brief A global index for a set of module files, providing information about +/// the identifiers within those module files. +/// +/// The global index is an aid for name lookup into modules, offering a central +/// place where one can look for identifiers determine which +/// module files contain any information about that identifier. This +/// allows the client to restrict the search to only those module files known +/// to have a information about that identifier, improving performance. Moreover, +/// the global module index may know about module files that have not been +/// imported, and can be queried to determine which modules the current +/// translation could or should load to fix a problem. +class GlobalModuleIndex { + /// \brief Buffer containing the index file, which is lazily accessed so long + /// as the global module index is live. + llvm::OwningPtr<llvm::MemoryBuffer> Buffer; + + /// \brief The hash table. + /// + /// This pointer actually points to a IdentifierIndexTable object, + /// but that type is only accessible within the implementation of + /// GlobalModuleIndex. + void *IdentifierIndex; + + /// \brief Information about a given module file. + struct ModuleInfo { + ModuleInfo() : File(), Size(), ModTime() { } + + /// \brief The module file, once it has been resolved. + ModuleFile *File; + + /// \brief The module file name. + std::string FileName; + + /// \brief Size of the module file at the time the global index was built. + off_t Size; + + /// \brief Modification time of the module file at the time the global + /// index was built. + time_t ModTime; + + /// \brief The module IDs on which this module directly depends. + /// FIXME: We don't really need a vector here. + llvm::SmallVector<unsigned, 4> Dependencies; + }; + + /// \brief A mapping from module IDs to information about each module. + /// + /// This vector may have gaps, if module files have been removed or have + /// been updated since the index was built. A gap is indicated by an empty + /// file name. + llvm::SmallVector<ModuleInfo, 16> Modules; + + /// \brief Lazily-populated mapping from module files to their + /// corresponding index into the \c Modules vector. + llvm::DenseMap<ModuleFile *, unsigned> ModulesByFile; + + /// \brief The set of modules that have not yet been resolved. + /// + /// The string is just the name of the module itself, which maps to the + /// module ID. + llvm::StringMap<unsigned> UnresolvedModules; + + /// \brief The number of identifier lookups we performed. + unsigned NumIdentifierLookups; + + /// \brief The number of identifier lookup hits, where we recognize the + /// identifier. + unsigned NumIdentifierLookupHits; + + /// \brief Internal constructor. Use \c readIndex() to read an index. + explicit GlobalModuleIndex(llvm::MemoryBuffer *Buffer, + llvm::BitstreamCursor Cursor); + + GlobalModuleIndex(const GlobalModuleIndex &) LLVM_DELETED_FUNCTION; + GlobalModuleIndex &operator=(const GlobalModuleIndex &) LLVM_DELETED_FUNCTION; + +public: + ~GlobalModuleIndex(); + + /// \brief An error code returned when trying to read an index. + enum ErrorCode { + /// \brief No error occurred. + EC_None, + /// \brief No index was found. + EC_NotFound, + /// \brief Some other process is currently building the index; it is not + /// available yet. + EC_Building, + /// \brief There was an unspecified I/O error reading or writing the index. + EC_IOError + }; + + /// \brief Read a global index file for the given directory. + /// + /// \param Path The path to the specific module cache where the module files + /// for the intended configuration reside. + /// + /// \returns A pair containing the global module index (if it exists) and + /// the error code. + static std::pair<GlobalModuleIndex *, ErrorCode> + readIndex(StringRef Path); + + /// \brief Retrieve the set of modules that have up-to-date indexes. + /// + /// \param ModuleFiles Will be populated with the set of module files that + /// have been indexed. + void getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles); + + /// \brief Retrieve the set of module files on which the given module file + /// directly depends. + void getModuleDependencies(ModuleFile *File, + SmallVectorImpl<ModuleFile *> &Dependencies); + + /// \brief A set of module files in which we found a result. + typedef llvm::SmallPtrSet<ModuleFile *, 4> HitSet; + + /// \brief Look for all of the module files with information about the given + /// identifier, e.g., a global function, variable, or type with that name. + /// + /// \param Name The identifier to look for. + /// + /// \param Hits Will be populated with the set of module files that have + /// information about this name. + /// + /// \returns true if the identifier is known to the index, false otherwise. + bool lookupIdentifier(StringRef Name, HitSet &Hits); + + /// \brief Note that the given module file has been loaded. + /// + /// \returns false if the global module index has information about this + /// module file, and true otherwise. + bool loadedModuleFile(ModuleFile *File); + + /// \brief Print statistics to standard error. + void printStats(); + + /// \brief Write a global index into the given + /// + /// \param FileMgr The file manager to use to load module files. + /// + /// \param Path The path to the directory containing module files, into + /// which the global index will be written. + static ErrorCode writeIndex(FileManager &FileMgr, StringRef Path); +}; + +} + +#endif diff --git a/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h index 39fa3d9..89c604f 100644 --- a/include/clang/Serialization/Module.h +++ b/include/clang/Serialization/Module.h @@ -15,9 +15,9 @@ #ifndef LLVM_CLANG_SERIALIZATION_MODULE_H #define LLVM_CLANG_SERIALIZATION_MODULE_H +#include "clang/Basic/SourceLocation.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ContinuousRangeMap.h" -#include "clang/Basic/SourceLocation.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SetVector.h" #include "llvm/Bitcode/BitstreamReader.h" @@ -55,6 +55,35 @@ struct DeclContextInfo { unsigned NumLexicalDecls; }; +/// \brief The input file that has been loaded from this AST file, along with +/// bools indicating whether this was an overridden buffer or if it was +/// out-of-date. +class InputFile { + enum { + Overridden = 1, + OutOfDate = 2 + }; + llvm::PointerIntPair<const FileEntry *, 2, unsigned> Val; + +public: + InputFile() {} + InputFile(const FileEntry *File, + bool isOverridden = false, bool isOutOfDate = false) { + assert(!(isOverridden && isOutOfDate) && + "an overridden cannot be out-of-date"); + unsigned intVal = 0; + if (isOverridden) + intVal = Overridden; + else if (isOutOfDate) + intVal = OutOfDate; + Val.setPointerAndInt(File, intVal); + } + + const FileEntry *getFile() const { return Val.getPointer(); } + bool isOverridden() const { return Val.getInt() == Overridden; } + bool isOutOfDate() const { return Val.getInt() == OutOfDate; } +}; + /// \brief Information about a module that has been loaded by the ASTReader. /// /// Each instance of the Module class corresponds to a single AST file, which @@ -69,6 +98,9 @@ public: // === General information === + /// \brief The index of this module in the list of modules. + unsigned Index; + /// \brief The type of this module. ModuleKind Kind; @@ -121,8 +153,15 @@ public: /// \brief The main bitstream cursor for the main block. llvm::BitstreamCursor Stream; + /// \brief The source location where the module was explicitly or implicitly + /// imported in the local translation unit. + /// + /// If module A depends on and imports module B, both modules will have the + /// same DirectImportLoc, but different ImportLoc (B's ImportLoc will be a + /// source location inside module A). + SourceLocation DirectImportLoc; + /// \brief The source location where this module was first imported. - /// FIXME: This is not properly initialized yet. SourceLocation ImportLoc; /// \brief The first source location in this module. @@ -135,10 +174,8 @@ public: /// \brief Offsets for all of the input file entries in the AST file. const uint32_t *InputFileOffsets; - /// \brief The input files that have been loaded from this AST file, along - /// with a bool indicating whether this was an overridden buffer. - std::vector<llvm::PointerIntPair<const FileEntry *, 1, bool> > - InputFilesLoaded; + /// \brief The input files that have been loaded from this AST file. + std::vector<InputFile> InputFilesLoaded; // === Source Locations === @@ -252,10 +289,6 @@ public: /// the header files. void *HeaderFileInfoTable; - /// \brief Actual data for the list of framework names used in the header - /// search information. - const char *HeaderFileFrameworkStrings; - // === Submodule information === /// \brief The number of submodules in this module. unsigned LocalNumSubmodules; diff --git a/include/clang/Serialization/ModuleManager.h b/include/clang/Serialization/ModuleManager.h index 6dcaa21..b2c4063 100644 --- a/include/clang/Serialization/ModuleManager.h +++ b/include/clang/Serialization/ModuleManager.h @@ -15,19 +15,22 @@ #ifndef LLVM_CLANG_SERIALIZATION_MODULE_MANAGER_H #define LLVM_CLANG_SERIALIZATION_MODULE_MANAGER_H -#include "clang/Serialization/Module.h" #include "clang/Basic/FileManager.h" +#include "clang/Serialization/Module.h" #include "llvm/ADT/DenseMap.h" namespace clang { +class GlobalModuleIndex; +class ModuleMap; + namespace serialization { - + /// \brief Manages the set of modules loaded by an AST reader. class ModuleManager { /// \brief The chain of AST files. The first entry is the one named by the /// user, the last one is the one that doesn't depend on anything further. - llvm::SmallVector<ModuleFile*, 2> Chain; + SmallVector<ModuleFile *, 2> Chain; /// \brief All loaded modules, indexed by name. llvm::DenseMap<const FileEntry *, ModuleFile *> Modules; @@ -38,7 +41,60 @@ class ModuleManager { /// \brief A lookup of in-memory (virtual file) buffers llvm::DenseMap<const FileEntry *, llvm::MemoryBuffer *> InMemoryBuffers; - + + /// \brief The visitation order. + SmallVector<ModuleFile *, 4> VisitOrder; + + /// \brief The list of module files that both we and the global module index + /// know about. + /// + /// Either the global index or the module manager may have modules that the + /// other does not know about, because the global index can be out-of-date + /// (in which case the module manager could have modules it does not) and + /// this particular translation unit might not have loaded all of the modules + /// known to the global index. + SmallVector<ModuleFile *, 4> ModulesInCommonWithGlobalIndex; + + /// \brief The global module index, if one is attached. + /// + /// The global module index will actually be owned by the ASTReader; this is + /// just an non-owning pointer. + GlobalModuleIndex *GlobalIndex; + + /// \brief State used by the "visit" operation to avoid malloc traffic in + /// calls to visit(). + struct VisitState { + explicit VisitState(unsigned N) + : VisitNumber(N, 0), NextVisitNumber(1), NextState(0) + { + Stack.reserve(N); + } + + ~VisitState() { + delete NextState; + } + + /// \brief The stack used when marking the imports of a particular module + /// as not-to-be-visited. + SmallVector<ModuleFile *, 4> Stack; + + /// \brief The visit number of each module file, which indicates when + /// this module file was last visited. + SmallVector<unsigned, 4> VisitNumber; + + /// \brief The next visit number to use to mark visited module files. + unsigned NextVisitNumber; + + /// \brief The next visit state. + VisitState *NextState; + }; + + /// \brief The first visit() state in the chain. + VisitState *FirstVisitState; + + VisitState *allocateVisitState(); + void returnVisitState(VisitState *State); + public: typedef SmallVector<ModuleFile*, 2>::iterator ModuleIterator; typedef SmallVector<ModuleFile*, 2>::const_iterator ModuleConstIterator; @@ -79,12 +135,28 @@ public: /// \brief Returns the module associated with the given name ModuleFile *lookup(StringRef Name); - + + /// \brief Returns the module associated with the given module file. + ModuleFile *lookup(const FileEntry *File); + /// \brief Returns the in-memory (virtual file) buffer with the given name llvm::MemoryBuffer *lookupBuffer(StringRef Name); /// \brief Number of modules loaded unsigned size() const { return Chain.size(); } + + /// \brief The result of attempting to add a new module. + enum AddModuleResult { + /// \brief The module file had already been loaded. + AlreadyLoaded, + /// \brief The module file was just loaded in response to this call. + NewlyLoaded, + /// \brief The module file is missing. + Missing, + /// \brief The module file is out-of-date. + OutOfDate + }; + /// \brief Attempts to create a new module and add it to the list of known /// modules. /// @@ -92,26 +164,48 @@ public: /// /// \param Type The kind of module being loaded. /// + /// \param ImportLoc The location at which the module is imported. + /// /// \param ImportedBy The module that is importing this module, or NULL if /// this module is imported directly by the user. /// /// \param Generation The generation in which this module was loaded. /// + /// \param ExpectedSize The expected size of the module file, used for + /// validation. This will be zero if unknown. + /// + /// \param ExpectedModTime The expected modification time of the module + /// file, used for validation. This will be zero if unknown. + /// + /// \param Module A pointer to the module file if the module was successfully + /// loaded. + /// /// \param ErrorStr Will be set to a non-empty string if any errors occurred /// while trying to load the module. /// /// \return A pointer to the module that corresponds to this file name, - /// and a boolean indicating whether the module was newly added. - std::pair<ModuleFile *, bool> - addModule(StringRef FileName, ModuleKind Type, ModuleFile *ImportedBy, - unsigned Generation, std::string &ErrorStr); + /// and a value indicating whether the module was loaded. + AddModuleResult addModule(StringRef FileName, ModuleKind Type, + SourceLocation ImportLoc, + ModuleFile *ImportedBy, unsigned Generation, + off_t ExpectedSize, time_t ExpectedModTime, + ModuleFile *&Module, + std::string &ErrorStr); /// \brief Remove the given set of modules. - void removeModules(ModuleIterator first, ModuleIterator last); + void removeModules(ModuleIterator first, ModuleIterator last, + ModuleMap *modMap); /// \brief Add an in-memory buffer the list of known buffers void addInMemoryBuffer(StringRef FileName, llvm::MemoryBuffer *Buffer); - + + /// \brief Set the global module index. + void setGlobalIndex(GlobalModuleIndex *Index); + + /// \brief Notification from the AST reader that the given module file + /// has been "accepted", and will not (can not) be unloaded. + void moduleFileAccepted(ModuleFile *MF); + /// \brief Visit each of the modules. /// /// This routine visits each of the modules, starting with the @@ -130,7 +224,13 @@ public: /// /// \param UserData User data associated with the visitor object, which /// will be passed along to the visitor. - void visit(bool (*Visitor)(ModuleFile &M, void *UserData), void *UserData); + /// + /// \param ModuleFilesHit If non-NULL, contains the set of module files + /// that we know we need to visit because the global module index told us to. + /// Any module that is known to both the global module index and the module + /// manager that is *not* in this set can be skipped. + void visit(bool (*Visitor)(ModuleFile &M, void *UserData), void *UserData, + llvm::SmallPtrSet<ModuleFile *, 4> *ModuleFilesHit = 0); /// \brief Visit each of the modules with a depth-first traversal. /// @@ -151,7 +251,29 @@ public: void visitDepthFirst(bool (*Visitor)(ModuleFile &M, bool Preorder, void *UserData), void *UserData); - + + /// \brief Attempt to resolve the given module file name to a file entry. + /// + /// \param FileName The name of the module file. + /// + /// \param ExpectedSize The size that the module file is expected to have. + /// If the actual size differs, the resolver should return \c true. + /// + /// \param ExpectedModTime The modification time that the module file is + /// expected to have. If the actual modification time differs, the resolver + /// should return \c true. + /// + /// \param File Will be set to the file if there is one, or null + /// otherwise. + /// + /// \returns True if a file exists but does not meet the size/ + /// modification time criteria, false if the file is either available and + /// suitable, or is missing. + bool lookupModuleFile(StringRef FileName, + off_t ExpectedSize, + time_t ExpectedModTime, + const FileEntry *&File); + /// \brief View the graphviz representation of the module graph. void viewGraph(); }; diff --git a/include/clang/StaticAnalyzer/Core/Analyses.def b/include/clang/StaticAnalyzer/Core/Analyses.def index 01a6ffd..dc79450 100644 --- a/include/clang/StaticAnalyzer/Core/Analyses.def +++ b/include/clang/StaticAnalyzer/Core/Analyses.def @@ -41,22 +41,12 @@ ANALYSIS_PURGE(PurgeStmt, "statement", "Purge symbols, bindings, and constraint ANALYSIS_PURGE(PurgeBlock, "block", "Purge symbols, bindings, and constraints before every basic block") ANALYSIS_PURGE(PurgeNone, "none", "Do not purge symbols, bindings, or constraints") -#ifndef ANALYSIS_IPA -#define ANALYSIS_IPA(NAME, CMDFLAG, DESC) -#endif - -ANALYSIS_IPA(None, "none", "Perform only intra-procedural analysis") -ANALYSIS_IPA(BasicInlining, "basic-inlining", "Inline C functions and blocks when their definitions are available") -ANALYSIS_IPA(Inlining, "inlining", "Inline callees when their definitions are available") -ANALYSIS_IPA(DynamicDispatch, "dynamic", "Experimental: Enable inlining of dynamically dispatched methods") -ANALYSIS_IPA(DynamicDispatchBifurcate, "dynamic-bifurcate", "Experimental: Enable inlining of dynamically dispatched methods, bifurcate paths when exact type info is unavailable") - #ifndef ANALYSIS_INLINING_MODE #define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) #endif -ANALYSIS_INLINING_MODE(All, "all", "Analyze all functions in the order defined in the TU") -ANALYSIS_INLINING_MODE(NoRedundancy, "noredundancy", "Do not analyze a function which has been previously inlined, use call graph to order") +ANALYSIS_INLINING_MODE(All, "all", "Analyze all functions as top level") +ANALYSIS_INLINING_MODE(NoRedundancy, "noredundancy", "Do not analyze a function which has been previously inlined") #undef ANALYSIS_STORE #undef ANALYSIS_CONSTRAINTS diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index fa0754a..6dbdbbf 100644 --- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -15,12 +15,12 @@ #ifndef LLVM_CLANG_ANALYZEROPTIONS_H #define LLVM_CLANG_ANALYZEROPTIONS_H -#include <string> -#include <vector> #include "clang/Basic/LLVM.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" +#include <string> +#include <vector> namespace clang { class ASTConsumer; @@ -64,13 +64,6 @@ enum AnalysisPurgeMode { NumPurgeModes }; -/// AnalysisIPAMode - Set of inter-procedural modes. -enum AnalysisIPAMode { -#define ANALYSIS_IPA(NAME, CMDFLAG, DESC) NAME, -#include "clang/StaticAnalyzer/Core/Analyses.def" -NumIPAModes -}; - /// AnalysisInlineFunctionSelection - Set of inlining function selection heuristics. enum AnalysisInliningMode { #define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) NAME, @@ -102,8 +95,28 @@ enum CXXInlineableMemberKind { CIMK_Destructors }; +/// \brief Describes the different modes of inter-procedural analysis. +enum IPAKind { + IPAK_NotSet = 0, + + /// Perform only intra-procedural analysis. + IPAK_None = 1, + + /// Inline C functions and blocks when their definitions are available. + IPAK_BasicInlining = 2, -class AnalyzerOptions : public llvm::RefCountedBase<AnalyzerOptions> { + /// Inline callees(C, C++, ObjC) when their definitions are available. + IPAK_Inlining = 3, + + /// Enable inlining of dynamically dispatched methods. + IPAK_DynamicDispatch = 4, + + /// Enable inlining of dynamically dispatched methods, bifurcate paths when + /// exact type info is unavailable. + IPAK_DynamicDispatchBifurcate = 5 +}; + +class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> { public: typedef llvm::StringMap<std::string> ConfigTable; @@ -117,14 +130,8 @@ public: AnalysisDiagClients AnalysisDiagOpt; AnalysisPurgeMode AnalysisPurgeOpt; - // \brief The interprocedural analysis mode. - AnalysisIPAMode IPAMode; - std::string AnalyzeSpecificFunction; - /// \brief The maximum number of exploded nodes the analyzer will generate. - unsigned MaxNodes; - /// \brief The maximum number of times the analyzer visits a block. unsigned maxBlockVisitOnPath; @@ -159,39 +166,71 @@ public: unsigned InlineMaxStackDepth; /// \brief The mode of function selection used during inlining. - unsigned InlineMaxFunctionSize; - - /// \brief The mode of function selection used during inlining. AnalysisInliningMode InliningMode; private: + /// \brief Describes the kinds for high-level analyzer mode. + enum UserModeKind { + UMK_NotSet = 0, + /// Perform shallow but fast analyzes. + UMK_Shallow = 1, + /// Perform deep analyzes. + UMK_Deep = 2 + }; + + /// Controls the high-level analyzer mode, which influences the default + /// settings for some of the lower-level config options (such as IPAMode). + /// \sa getUserMode + UserModeKind UserMode; + + /// Controls the mode of inter-procedural analysis. + IPAKind IPAMode; + /// Controls which C++ member functions will be considered for inlining. CXXInlineableMemberKind CXXMemberInliningMode; /// \sa includeTemporaryDtorsInCFG - llvm::Optional<bool> IncludeTemporaryDtorsInCFG; + Optional<bool> IncludeTemporaryDtorsInCFG; /// \sa mayInlineCXXStandardLibrary - llvm::Optional<bool> InlineCXXStandardLibrary; + Optional<bool> InlineCXXStandardLibrary; /// \sa mayInlineTemplateFunctions - llvm::Optional<bool> InlineTemplateFunctions; + Optional<bool> InlineTemplateFunctions; + + /// \sa mayInlineCXXContainerCtorsAndDtors + Optional<bool> InlineCXXContainerCtorsAndDtors; /// \sa mayInlineObjCMethod - llvm::Optional<bool> ObjCInliningMode; + Optional<bool> ObjCInliningMode; // Cache of the "ipa-always-inline-size" setting. // \sa getAlwaysInlineSize - llvm::Optional<unsigned> AlwaysInlineSize; + Optional<unsigned> AlwaysInlineSize; - /// \sa shouldPruneNullReturnPaths - llvm::Optional<bool> PruneNullReturnPaths; + /// \sa shouldSuppressNullReturnPaths + Optional<bool> SuppressNullReturnPaths; + + // \sa getMaxInlinableSize + Optional<unsigned> MaxInlinableSize; /// \sa shouldAvoidSuppressingNullArgumentPaths - llvm::Optional<bool> AvoidSuppressingNullArgumentPaths; - + Optional<bool> AvoidSuppressingNullArgumentPaths; + + /// \sa shouldSuppressInlinedDefensiveChecks + Optional<bool> SuppressInlinedDefensiveChecks; + + /// \sa shouldSuppressFromCXXStandardLibrary + Optional<bool> SuppressFromCXXStandardLibrary; + /// \sa getGraphTrimInterval - llvm::Optional<unsigned> GraphTrimInterval; + Optional<unsigned> GraphTrimInterval; + + /// \sa getMaxTimesInlineLarge + Optional<unsigned> MaxTimesInlineLarge; + + /// \sa getMaxNodesPerTopLevelFunction + Optional<unsigned> MaxNodesPerTopLevelFunction; /// Interprets an option's string value as a boolean. /// @@ -200,13 +239,20 @@ private: bool getBooleanOption(StringRef Name, bool DefaultVal); /// Variant that accepts a Optional value to cache the result. - bool getBooleanOption(llvm::Optional<bool> &V, StringRef Name, - bool DefaultVal); - + bool getBooleanOption(Optional<bool> &V, StringRef Name, bool DefaultVal); + /// Interprets an option's string value as an integer value. - int getOptionAsInteger(llvm::StringRef Name, int DefaultVal); + int getOptionAsInteger(StringRef Name, int DefaultVal); public: + /// \brief Retrieves and sets the UserMode. This is a high-level option, + /// which is used to set other low-level options. It is not accessible + /// outside of AnalyzerOptions. + UserModeKind getUserMode(); + + /// \brief Returns the inter-procedural analysis mode. + IPAKind getIPAMode(); + /// Returns the option controlling which C++ member functions will be /// considered for inlining. /// @@ -238,6 +284,13 @@ public: /// accepts the values "true" and "false". bool mayInlineTemplateFunctions(); + /// Returns whether or not constructors and destructors of C++ container + /// objects may be considered for inlining. + /// + /// This is controlled by the 'c++-container-inlining' config option, which + /// accepts the values "true" and "false". + bool mayInlineCXXContainerCtorsAndDtors(); + /// Returns whether or not paths that go through null returns should be /// suppressed. /// @@ -246,12 +299,12 @@ public: /// /// This is controlled by the 'suppress-null-return-paths' config option, /// which accepts the values "true" and "false". - bool shouldPruneNullReturnPaths(); + bool shouldSuppressNullReturnPaths(); /// Returns whether a bug report should \em not be suppressed if its path /// includes a call with a null argument, even if that call has a null return. /// - /// This option has no effect when #shouldPruneNullReturnPaths() is false. + /// This option has no effect when #shouldSuppressNullReturnPaths() is false. /// /// This is a counter-heuristic to avoid false negatives. /// @@ -259,12 +312,43 @@ public: /// option, which accepts the values "true" and "false". bool shouldAvoidSuppressingNullArgumentPaths(); + /// Returns whether or not diagnostics containing inlined defensive NULL + /// checks should be suppressed. + /// + /// This is controlled by the 'suppress-inlined-defensive-checks' config + /// option, which accepts the values "true" and "false". + bool shouldSuppressInlinedDefensiveChecks(); + + /// Returns whether or not diagnostics reported within the C++ standard + /// library should be suppressed. + /// + /// This is controlled by the 'suppress-c++-stdlib' config option, + /// which accepts the values "true" and "false". + bool shouldSuppressFromCXXStandardLibrary(); + + /// Returns whether irrelevant parts of a bug report path should be pruned + /// out of the final output. + /// + /// This is controlled by the 'prune-paths' config option, which accepts the + /// values "true" and "false". + bool shouldPrunePaths(); + + /// Returns true if 'static' initializers should be in conditional logic + /// in the CFG. + bool shouldConditionalizeStaticInitializers(); + // Returns the size of the functions (in basic blocks), which should be // considered to be small enough to always inline. // // This is controlled by "ipa-always-inline-size" analyzer-config option. unsigned getAlwaysInlineSize(); - + + // Returns the bound on the number of basic blocks in an inlined function + // (50 by default). + // + // This is controlled by "-analyzer-config max-inlinable-size" option. + unsigned getMaxInlinableSize(); + /// Returns true if the analyzer engine should synthesize fake bodies /// for well-known functions. bool shouldSynthesizeBodies(); @@ -276,32 +360,45 @@ public: /// node reclamation, set the option to "0". unsigned getGraphTrimInterval(); + /// Returns the maximum times a large function could be inlined. + /// + /// This is controlled by the 'max-times-inline-large' config option. + unsigned getMaxTimesInlineLarge(); + + /// Returns the maximum number of nodes the analyzer can generate while + /// exploring a top level function (for each exploded graph). + /// 150000 is default; 0 means no limit. + /// + /// This is controlled by the 'max-nodes' config option. + unsigned getMaxNodesPerTopLevelFunction(); + public: - AnalyzerOptions() : CXXMemberInliningMode() { - AnalysisStoreOpt = RegionStoreModel; - AnalysisConstraintsOpt = RangeConstraintsModel; - AnalysisDiagOpt = PD_HTML; - AnalysisPurgeOpt = PurgeStmt; - IPAMode = DynamicDispatchBifurcate; - ShowCheckerHelp = 0; - AnalyzeAll = 0; - AnalyzerDisplayProgress = 0; - AnalyzeNestedBlocks = 0; - eagerlyAssumeBinOpBifurcation = 0; - TrimGraph = 0; - visualizeExplodedGraphWithGraphViz = 0; - visualizeExplodedGraphWithUbiGraph = 0; - UnoptimizedCFG = 0; - PrintStats = 0; - NoRetryExhausted = 0; + AnalyzerOptions() : + AnalysisStoreOpt(RegionStoreModel), + AnalysisConstraintsOpt(RangeConstraintsModel), + AnalysisDiagOpt(PD_HTML), + AnalysisPurgeOpt(PurgeStmt), + ShowCheckerHelp(0), + AnalyzeAll(0), + AnalyzerDisplayProgress(0), + AnalyzeNestedBlocks(0), + eagerlyAssumeBinOpBifurcation(0), + TrimGraph(0), + visualizeExplodedGraphWithGraphViz(0), + visualizeExplodedGraphWithUbiGraph(0), + UnoptimizedCFG(0), + PrintStats(0), + NoRetryExhausted(0), // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls). - InlineMaxStackDepth = 5; - InlineMaxFunctionSize = 200; - InliningMode = NoRedundancy; - } + InlineMaxStackDepth(5), + InliningMode(NoRedundancy), + UserMode(UMK_NotSet), + IPAMode(IPAK_NotSet), + CXXMemberInliningMode() {} + }; -typedef llvm::IntrusiveRefCntPtr<AnalyzerOptions> AnalyzerOptionsRef; +typedef IntrusiveRefCntPtr<AnalyzerOptions> AnalyzerOptionsRef; } diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index b5a88ba..7a87e47 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -19,12 +19,12 @@ #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/ilist.h" -#include "llvm/ADT/ilist_node.h" #include "llvm/ADT/ImmutableSet.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" namespace clang { @@ -75,6 +75,8 @@ protected: std::string Description; PathDiagnosticLocation Location; PathDiagnosticLocation UniqueingLocation; + const Decl *UniqueingDecl; + const ExplodedNode *ErrorNode; SmallVector<SourceRange, 4> Ranges; ExtraTextList ExtraText; @@ -87,14 +89,14 @@ protected: /// diagnostics to include when constructing the final path diagnostic. /// The stack is largely used by BugReporter when generating PathDiagnostics /// for multiple PathDiagnosticConsumers. - llvm::SmallVector<Symbols *, 2> interestingSymbols; + SmallVector<Symbols *, 2> interestingSymbols; /// A (stack of) set of regions that are registered with this report as being /// "interesting", and thus used to help decide which diagnostics /// to include when constructing the final path diagnostic. /// The stack is largely used by BugReporter when generating PathDiagnostics /// for multiple PathDiagnosticConsumers. - llvm::SmallVector<Regions *, 2> interestingRegions; + SmallVector<Regions *, 2> interestingRegions; /// A set of location contexts that correspoind to call sites which should be /// considered "interesting". @@ -162,9 +164,10 @@ public: /// for uniquing reports. For example, memory leaks checker, could set this to /// the allocation site, rather then the location where the bug is reported. BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode, - PathDiagnosticLocation LocationToUnique) + PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique) : BT(bt), DeclWithIssue(0), Description(desc), UniqueingLocation(LocationToUnique), + UniqueingDecl(DeclToUnique), ErrorNode(errornode), ConfigurationChangeToken(0), DoNotPrunePath(false) {} @@ -260,6 +263,16 @@ public: /// This location is used by clients rendering diagnostics. virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const; + /// \brief Get the location on which the report should be uniqued. + PathDiagnosticLocation getUniqueingLocation() const { + return UniqueingLocation; + } + + /// \brief Get the declaration containing the uniqueing location. + const Decl *getUniqueingDecl() const { + return UniqueingDecl; + } + const Stmt *getStmt() const; /// \brief Add a range to a bug report. @@ -440,8 +453,7 @@ public: return true; } - bool RemoveUneededCalls(PathPieces &pieces, BugReport *R, - PathDiagnosticCallPiece *CallWithLoc = 0); + bool RemoveUnneededCalls(PathPieces &pieces, BugReport *R); void Register(BugType *BT); diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h index 78e35ca..2e5f207 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h @@ -55,8 +55,8 @@ public: /// /// The last parameter can be used to register a new visitor with the given /// BugReport while processing a node. - virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, - const ExplodedNode *PrevN, + virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ, + const ExplodedNode *Pred, BugReporterContext &BRC, BugReport &BR) = 0; @@ -99,26 +99,24 @@ class FindLastStoreBRVisitor { const MemRegion *R; SVal V; - bool satisfied; + bool Satisfied; -public: - /// \brief Convenience method to create a visitor given only the MemRegion. - /// Returns NULL if the visitor cannot be created. For example, when the - /// corresponding value is unknown. - static BugReporterVisitor *createVisitorObject(const ExplodedNode *N, - const MemRegion *R); + /// If the visitor is tracking the value directly responsible for the + /// bug, we are going to employ false positive suppression. + bool EnableNullFPSuppression; +public: /// Creates a visitor for every VarDecl inside a Stmt and registers it with /// the BugReport. - static void registerStatementVarDecls(BugReport &BR, const Stmt *S); + static void registerStatementVarDecls(BugReport &BR, const Stmt *S, + bool EnableNullFPSuppression); - FindLastStoreBRVisitor(SVal v, const MemRegion *r) - : R(r), V(v), satisfied(false) { - assert (!V.isUnknown() && "Cannot track unknown value."); - - // TODO: Does it make sense to allow undef values here? - // (If not, also see UndefCapturedBlockVarChecker)? - } + FindLastStoreBRVisitor(KnownSVal V, const MemRegion *R, + bool InEnableNullFPSuppression) + : R(R), + V(V), + Satisfied(false), + EnableNullFPSuppression(InEnableNullFPSuppression) {} void Profile(llvm::FoldingSetNodeID &ID) const; @@ -132,12 +130,14 @@ class TrackConstraintBRVisitor : public BugReporterVisitorImpl<TrackConstraintBRVisitor> { DefinedSVal Constraint; - const bool Assumption; - bool isSatisfied; + bool Assumption; + bool IsSatisfied; + bool IsZeroCheck; public: TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption) - : Constraint(constraint), Assumption(assumption), isSatisfied(false) {} + : Constraint(constraint), Assumption(assumption), IsSatisfied(false), + IsZeroCheck(!Assumption && Constraint.getAs<Loc>()) {} void Profile(llvm::FoldingSetNodeID &ID) const; @@ -149,12 +149,19 @@ public: const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR); + +private: + /// Checks if the constraint is valid in the current state. + bool isUnderconstrained(const ExplodedNode *N) const; + }; +/// \class NilReceiverBRVisitor +/// \brief Prints path notes when a message is sent to a nil receiver. class NilReceiverBRVisitor - : public BugReporterVisitorImpl<NilReceiverBRVisitor> -{ + : public BugReporterVisitorImpl<NilReceiverBRVisitor> { public: + void Profile(llvm::FoldingSetNodeID &ID) const { static int x = 0; ID.AddPointer(&x); @@ -164,6 +171,10 @@ public: const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR); + + /// If the statement is a message send expression with nil receiver, returns + /// the receiver expression. Returns NULL otherwise. + static const Expr *getNilReceiver(const Stmt *S, const ExplodedNode *N); }; /// Visitor that tries to report interesting diagnostics from conditions. @@ -223,11 +234,38 @@ public: const ExplodedNode *N); bool patternMatch(const Expr *Ex, - llvm::raw_ostream &Out, + raw_ostream &Out, BugReporterContext &BRC, BugReport &R, const ExplodedNode *N, - llvm::Optional<bool> &prunable); + Optional<bool> &prunable); +}; + +/// \brief Suppress reports that might lead to known false positives. +/// +/// Currently this suppresses reports based on locations of bugs. +class LikelyFalsePositiveSuppressionBRVisitor + : public BugReporterVisitorImpl<LikelyFalsePositiveSuppressionBRVisitor> { +public: + static void *getTag() { + static int Tag = 0; + return static_cast<void *>(&Tag); + } + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddPointer(getTag()); + } + + virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, + const ExplodedNode *Prev, + BugReporterContext &BRC, + BugReport &BR) { + return 0; + } + + virtual PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, + const ExplodedNode *N, + BugReport &BR); }; /// \brief When a region containing undefined value or '0' value is passed @@ -256,6 +294,38 @@ public: BugReport &BR); }; +class SuppressInlineDefensiveChecksVisitor +: public BugReporterVisitorImpl<SuppressInlineDefensiveChecksVisitor> +{ + /// The symbolic value for which we are tracking constraints. + /// This value is constrained to null in the end of path. + DefinedSVal V; + + /// Track if we found the node where the constraint was first added. + bool IsSatisfied; + + /// Since the visitors can be registered on nodes previous to the last + /// node in the BugReport, but the path traversal always starts with the last + /// node, the visitor invariant (that we start with a node in which V is null) + /// might not hold when node visitation starts. We are going to start tracking + /// from the last node in which the value is null. + bool IsTrackingTurnedOn; + +public: + SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N); + + void Profile(llvm::FoldingSetNodeID &ID) const; + + /// Return the tag associated with this visitor. This tag will be used + /// to make all PathDiagnosticPieces created by this visitor. + static const char *getTag(); + + PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ, + const ExplodedNode *Pred, + BugReporterContext &BRC, + BugReport &BR); +}; + namespace bugreporter { /// Attempts to add visitors to trace a null or undefined value back to its @@ -268,14 +338,17 @@ namespace bugreporter { /// \param IsArg Whether the statement is an argument to an inlined function. /// If this is the case, \p N \em must be the CallEnter node for /// the function. +/// \param EnableNullFPSuppression Whether we should employ false positive +/// suppression (inlined defensive checks, returned null). /// /// \return Whether or not the function was able to add visitors for this /// statement. Note that returning \c true does not actually imply /// that any visitors were added. bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, - bool IsArg = false); + bool IsArg = false, + bool EnableNullFPSuppression = true); -const Stmt *GetDerefExpr(const ExplodedNode *N); +const Expr *getDerefExpr(const Stmt *S); const Stmt *GetDenomExpr(const ExplodedNode *N); const Stmt *GetRetValExpr(const ExplodedNode *N); bool isDeclRefExprToReference(const Expr *E); diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h index cb49122..644aa31 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_ANALYSIS_BUGTYPE #define LLVM_CLANG_ANALYSIS_BUGTYPE +#include "clang/Basic/LLVM.h" #include "llvm/ADT/FoldingSet.h" #include <string> diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index 6dc26e6..3f0a1b1 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -14,12 +14,12 @@ #ifndef LLVM_CLANG_PATH_DIAGNOSTIC_H #define LLVM_CLANG_PATH_DIAGNOSTIC_H -#include "clang/Basic/SourceLocation.h" #include "clang/Analysis/ProgramPoint.h" +#include "clang/Basic/SourceLocation.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerUnion.h" #include <deque> #include <iterator> #include <string> @@ -341,7 +341,7 @@ protected: public: virtual ~PathDiagnosticPiece(); - llvm::StringRef getString() const { return str; } + StringRef getString() const { return str; } /// Tag this PathDiagnosticPiece with the given C-string. void setTag(const char *tag) { Tag = tag; } @@ -461,13 +461,13 @@ public: }; class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece { - llvm::Optional<bool> IsPrunable; + Optional<bool> IsPrunable; /// If the event occurs in a different frame than the final diagnostic, /// supply a message that will be used to construct an extra hint on the /// returns from all the calls on the stack from this event to the final /// diagnostic. - llvm::OwningPtr<StackHintGenerator> CallStackHint; + OwningPtr<StackHintGenerator> CallStackHint; public: PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, @@ -670,13 +670,19 @@ class PathDiagnostic : public llvm::FoldingSetNode { std::deque<std::string> OtherDesc; PathDiagnosticLocation Loc; PathPieces pathImpl; - llvm::SmallVector<PathPieces *, 3> pathStack; + SmallVector<PathPieces *, 3> pathStack; - PathDiagnostic(); // Do not implement. + /// \brief Important bug uniqueing location. + /// The location info is useful to differentiate between bugs. + PathDiagnosticLocation UniqueingLoc; + const Decl *UniqueingDecl; + + PathDiagnostic() LLVM_DELETED_FUNCTION; public: PathDiagnostic(const Decl *DeclWithIssue, StringRef bugtype, StringRef verboseDesc, StringRef shortDesc, - StringRef category); + StringRef category, PathDiagnosticLocation LocationToUnique, + const Decl *DeclToUnique); ~PathDiagnostic(); @@ -738,6 +744,16 @@ public: return Loc; } + /// \brief Get the location on which the report should be uniqued. + PathDiagnosticLocation getUniqueingLoc() const { + return UniqueingLoc; + } + + /// \brief Get the declaration containing the uniqueing location. + const Decl *getUniqueingDecl() const { + return UniqueingDecl; + } + void flattenLocations() { Loc.flatten(); for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end(); diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h index 9eb1248..0dbaab0 100644 --- a/include/clang/StaticAnalyzer/Core/Checker.h +++ b/include/clang/StaticAnalyzer/Core/Checker.h @@ -34,11 +34,11 @@ class ASTDecl { template <typename CHECKER> static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr, BugReporter &BR) { - ((const CHECKER *)checker)->checkASTDecl(llvm::cast<DECL>(D), mgr, BR); + ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR); } static bool _handlesDecl(const Decl *D) { - return llvm::isa<DECL>(D); + return isa<DECL>(D); } public: template <typename CHECKER> @@ -86,11 +86,11 @@ template <typename STMT> class PreStmt { template <typename CHECKER> static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { - ((const CHECKER *)checker)->checkPreStmt(llvm::cast<STMT>(S), C); + ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C); } static bool _handlesStmt(const Stmt *S) { - return llvm::isa<STMT>(S); + return isa<STMT>(S); } public: template <typename CHECKER> @@ -105,11 +105,11 @@ template <typename STMT> class PostStmt { template <typename CHECKER> static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { - ((const CHECKER *)checker)->checkPostStmt(llvm::cast<STMT>(S), C); + ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C); } static bool _handlesStmt(const Stmt *S) { - return llvm::isa<STMT>(S); + return isa<STMT>(S); } public: template <typename CHECKER> @@ -227,18 +227,18 @@ public: } }; -class EndPath { +class EndFunction { template <typename CHECKER> - static void _checkEndPath(void *checker, - CheckerContext &C) { - ((const CHECKER *)checker)->checkEndPath(C); + static void _checkEndFunction(void *checker, + CheckerContext &C) { + ((const CHECKER *)checker)->checkEndFunction(C); } public: template <typename CHECKER> static void _register(CHECKER *checker, CheckerManager &mgr) { - mgr._registerForEndPath( - CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>)); + mgr._registerForEndFunction( + CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>)); } }; @@ -293,7 +293,7 @@ class RegionChanges { static ProgramStateRef _checkRegionChanges(void *checker, ProgramStateRef state, - const StoreManager::InvalidatedSymbols *invalidated, + const InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> Explicits, ArrayRef<const MemRegion *> Regions, const CallEvent *Call) { @@ -317,6 +317,59 @@ public: } }; +class PointerEscape { + template <typename CHECKER> + static ProgramStateRef + _checkPointerEscape(void *checker, + ProgramStateRef State, + const InvalidatedSymbols &Escaped, + const CallEvent *Call, + PointerEscapeKind Kind, + bool IsConst) { + if (!IsConst) + return ((const CHECKER *)checker)->checkPointerEscape(State, + Escaped, + Call, + Kind); + return State; + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPointerEscape( + CheckerManager::CheckPointerEscapeFunc(checker, + _checkPointerEscape<CHECKER>)); + } +}; + +class ConstPointerEscape { + template <typename CHECKER> + static ProgramStateRef + _checkConstPointerEscape(void *checker, + ProgramStateRef State, + const InvalidatedSymbols &Escaped, + const CallEvent *Call, + PointerEscapeKind Kind, + bool IsConst) { + if (IsConst) + return ((const CHECKER *)checker)->checkConstPointerEscape(State, + Escaped, + Call, + Kind); + return State; + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPointerEscape( + CheckerManager::CheckPointerEscapeFunc(checker, + _checkConstPointerEscape<CHECKER>)); + } +}; + + template <typename EVENT> class Event { template <typename CHECKER> @@ -448,6 +501,14 @@ struct ImplicitNullDerefEvent { BugReporter *BR; }; +/// \brief A helper class which wraps a boolean value set to false by default. +struct DefaultBool { + bool val; + DefaultBool() : val(false) {} + operator bool() const { return val; } + DefaultBool &operator=(bool b) { val = b; return *this; } +}; + } // end ento namespace } // end clang namespace diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index 7ae8e53..6f99fc1 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -14,12 +14,12 @@ #ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H #define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H +#include "clang/Analysis/ProgramPoint.h" #include "clang/Basic/LangOptions.h" -#include "llvm/ADT/SmallVector.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" -#include "clang/Analysis/ProgramPoint.h" +#include "llvm/ADT/SmallVector.h" #include <vector> namespace clang { @@ -112,6 +112,26 @@ public: RET operator()() const { return Fn(Checker); } }; +/// \brief Describes the different reasons a pointer escapes +/// during analysis. +enum PointerEscapeKind { + /// A pointer escapes due to binding its value to a location + /// that the analyzer cannot track. + PSK_EscapeOnBind, + + /// The pointer has been passed to a function call directly. + PSK_DirectEscapeOnCall, + + /// The pointer has been passed to a function indirectly. + /// For example, the pointer is accessible through an + /// argument to a function. + PSK_IndirectEscapeOnCall, + + /// The reason for pointer escape is unknown. For example, + /// a region containing this pointer is invalidated. + PSK_EscapeOther +}; + class CheckerManager { const LangOptions LangOpts; @@ -264,11 +284,11 @@ public: void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, ExprEngine &Eng); - /// \brief Run checkers for end of path. - void runCheckersForEndPath(NodeBuilderContext &BC, - ExplodedNodeSet &Dst, - ExplodedNode *Pred, - ExprEngine &Eng); + /// \brief Run checkers on end of function. + void runCheckersForEndFunction(NodeBuilderContext &BC, + ExplodedNodeSet &Dst, + ExplodedNode *Pred, + ExprEngine &Eng); /// \brief Run checkers for branch condition. void runCheckersForBranchCondition(const Stmt *condition, @@ -310,14 +330,34 @@ public: /// by a call. ProgramStateRef runCheckersForRegionChanges(ProgramStateRef state, - const StoreManager::InvalidatedSymbols *invalidated, + const InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, const CallEvent *Call); + /// \brief Run checkers when pointers escape. + /// + /// This notifies the checkers about pointer escape, which occurs whenever + /// the analyzer cannot track the symbol any more. For example, as a + /// result of assigning a pointer into a global or when it's passed to a + /// function call the analyzer cannot model. + /// + /// \param State The state at the point of escape. + /// \param Escaped The list of escaped symbols. + /// \param Call The corresponding CallEvent, if the symbols escape as + /// parameters to the given call. + /// \param IsConst Specifies if the pointer is const. + /// \returns Checkers can modify the state by returning a new one. + ProgramStateRef + runCheckersForPointerEscape(ProgramStateRef State, + const InvalidatedSymbols &Escaped, + const CallEvent *Call, + PointerEscapeKind Kind, + bool IsConst = false); + /// \brief Run checkers for handling assumptions on symbolic values. ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, - SVal Cond, bool Assumption); + SVal Cond, bool Assumption); /// \brief Run checkers for evaluating a call. /// @@ -382,7 +422,7 @@ public: CheckEndAnalysisFunc; typedef CheckerFn<void (CheckerContext &)> - CheckEndPathFunc; + CheckEndFunctionFunc; typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckBranchConditionFunc; @@ -393,13 +433,20 @@ public: typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc; typedef CheckerFn<ProgramStateRef (ProgramStateRef, - const StoreManager::InvalidatedSymbols *symbols, + const InvalidatedSymbols *symbols, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, const CallEvent *Call)> CheckRegionChangesFunc; typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc; + + typedef CheckerFn<ProgramStateRef (ProgramStateRef, + const InvalidatedSymbols &Escaped, + const CallEvent *Call, + PointerEscapeKind Kind, + bool IsConst)> + CheckPointerEscapeFunc; typedef CheckerFn<ProgramStateRef (ProgramStateRef, const SVal &cond, bool assumption)> @@ -430,7 +477,7 @@ public: void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); - void _registerForEndPath(CheckEndPathFunc checkfn); + void _registerForEndFunction(CheckEndFunctionFunc checkfn); void _registerForBranchCondition(CheckBranchConditionFunc checkfn); @@ -441,6 +488,10 @@ public: void _registerForRegionChanges(CheckRegionChangesFunc checkfn, WantsRegionChangeUpdateFunc wantUpdateFn); + void _registerForPointerEscape(CheckPointerEscapeFunc checkfn); + + void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn); + void _registerForEvalAssume(EvalAssumeFunc checkfn); void _registerForEvalCall(EvalCallFunc checkfn); @@ -552,7 +603,7 @@ private: std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers; - std::vector<CheckEndPathFunc> EndPathCheckers; + std::vector<CheckEndFunctionFunc> EndFunctionCheckers; std::vector<CheckBranchConditionFunc> BranchConditionCheckers; @@ -566,6 +617,8 @@ private: }; std::vector<RegionChangesCheckerInfo> RegionChangesCheckers; + std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers; + std::vector<EvalAssumeFunc> EvalAssumeCheckers; std::vector<EvalCallFunc> EvalCallCheckers; diff --git a/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h b/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h index 6ce5b3c..e981871 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h +++ b/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_STATICANALYZER_CORE_CHECKEROPTINFO_H #include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" namespace clang { namespace ento { diff --git a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h index 1452d45..4557aa4 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h +++ b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h @@ -10,8 +10,8 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRY_H #define LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRY_H -#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/Basic/LLVM.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include <vector> // FIXME: move this information to an HTML file in docs/. diff --git a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h index 3aab648..b856de7 100644 --- a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h +++ b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h @@ -19,6 +19,7 @@ namespace clang { +class AnalyzerOptions; class Preprocessor; namespace ento { @@ -26,21 +27,18 @@ namespace ento { class PathDiagnosticConsumer; typedef std::vector<PathDiagnosticConsumer*> PathDiagnosticConsumers; -void createHTMLDiagnosticConsumer(PathDiagnosticConsumers &C, - const std::string& prefix, - const Preprocessor &PP); +#define CREATE_CONSUMER(NAME)\ +void create ## NAME ## DiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,\ + PathDiagnosticConsumers &C,\ + const std::string& prefix,\ + const Preprocessor &PP); -void createPlistDiagnosticConsumer(PathDiagnosticConsumers &C, - const std::string& prefix, - const Preprocessor &PP); +CREATE_CONSUMER(HTML) +CREATE_CONSUMER(Plist) +CREATE_CONSUMER(PlistMultiFile) +CREATE_CONSUMER(TextPath) -void createPlistMultiFileDiagnosticConsumer(PathDiagnosticConsumers &C, - const std::string& prefix, - const Preprocessor &PP); - -void createTextPathDiagnosticConsumer(PathDiagnosticConsumers &C, - const std::string& prefix, - const Preprocessor &PP); +#undef CREATE_CONSUMER } // end 'ento' namespace } // end 'clang' namespace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h index 27f3677..9502900 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h @@ -81,9 +81,12 @@ public: /// Tests whether a given value is losslessly representable using this type. /// - /// Note that signedness conversions will be rejected, even with the same bit - /// pattern. For example, -1s8 is not in range for 'unsigned char' (u8). - RangeTestResultKind testInRange(const llvm::APSInt &Val) const LLVM_READONLY; + /// \param Val The value to test. + /// \param AllowMixedSign Whether or not to allow signedness conversions. + /// This determines whether -1s8 is considered in range + /// for 'unsigned char' (u8). + RangeTestResultKind testInRange(const llvm::APSInt &Val, + bool AllowMixedSign) const LLVM_READONLY; bool operator==(const APSIntType &Other) const { return BitWidth == Other.BitWidth && IsUnsigned == Other.IsUnsigned; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index 9038ae5..458c896 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -100,7 +100,7 @@ public: } bool shouldInlineCall() const { - return options.IPAMode != None; + return options.getIPAMode() != IPAK_None; } CFG *getCFG(Decl const *D) { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index fb39354..1135b51 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -16,9 +16,10 @@ #ifndef LLVM_CLANG_GR_BASICVALUEFACTORY_H #define LLVM_CLANG_GR_BASICVALUEFACTORY_H +#include "clang/AST/ASTContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" namespace clang { namespace ento { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index a6a91e2..f990b8d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -16,11 +16,11 @@ #ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_CALL #define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_CALL -#include "clang/Basic/SourceManager.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/Analysis/AnalysisContext.h" +#include "clang/Basic/SourceManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/ADT/PointerIntPair.h" @@ -162,11 +162,11 @@ protected: } - typedef SmallVectorImpl<const MemRegion *> RegionList; + typedef SmallVectorImpl<SVal> ValueList; /// \brief Used to specify non-argument regions that will be invalidated as a /// result of this call. - virtual void getExtraInvalidatedRegions(RegionList &Regions) const {} + virtual void getExtraInvalidatedValues(ValueList &Values) const {} public: virtual ~CallEvent() {} @@ -181,7 +181,7 @@ public: } /// \brief The state in which the call is being evaluated. - ProgramStateRef getState() const { + const ProgramStateRef &getState() const { return State; } @@ -228,6 +228,11 @@ public: return false; } + /// \brief Returns true if this is a call to a variadic function or method. + virtual bool isVariadic() const { + return false; + } + /// \brief Returns a source range for the entire call, suitable for /// outputting in diagnostics. virtual SourceRange getSourceRange() const { @@ -331,7 +336,9 @@ public: /// of some kind. static bool isCallStmt(const Stmt *S); - /// \brief Returns the result type of a function, method declaration. + /// \brief Returns the result type of a function or method declaration. + /// + /// This will return a null QualType if the result type cannot be determined. static QualType getDeclaredResultType(const Decl *D); // Iterator access to formal parameters and their types. @@ -416,6 +423,10 @@ public: return RuntimeDefinition(); } + virtual bool isVariadic() const { + return getDecl()->isVariadic(); + } + virtual bool argumentsMayEscape() const; virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, @@ -493,7 +504,7 @@ protected: BlockCall(const BlockCall &Other) : SimpleCall(Other) {} virtual void cloneTo(void *Dest) const { new (Dest) BlockCall(*this); } - virtual void getExtraInvalidatedRegions(RegionList &Regions) const; + virtual void getExtraInvalidatedValues(ValueList &Values) const; public: /// \brief Returns the region associated with this instance of the block. @@ -516,6 +527,10 @@ public: return RuntimeDefinition(getBlockDecl()); } + virtual bool isVariadic() const { + return getBlockDecl()->isVariadic(); + } + virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, BindingsTy &Bindings) const; @@ -533,7 +548,7 @@ public: /// it is written. class CXXInstanceCall : public AnyFunctionCall { protected: - virtual void getExtraInvalidatedRegions(RegionList &Regions) const; + virtual void getExtraInvalidatedValues(ValueList &Values) const; CXXInstanceCall(const CallExpr *CE, ProgramStateRef St, const LocationContext *LCtx) @@ -716,7 +731,7 @@ protected: CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){} virtual void cloneTo(void *Dest) const { new (Dest) CXXConstructorCall(*this); } - virtual void getExtraInvalidatedRegions(RegionList &Regions) const; + virtual void getExtraInvalidatedValues(ValueList &Values) const; public: virtual const CXXConstructExpr *getOriginExpr() const { @@ -815,7 +830,7 @@ protected: ObjCMethodCall(const ObjCMethodCall &Other) : CallEvent(Other) {} virtual void cloneTo(void *Dest) const { new (Dest) ObjCMethodCall(*this); } - virtual void getExtraInvalidatedRegions(RegionList &Regions) const; + virtual void getExtraInvalidatedValues(ValueList &Values) const; /// Check if the selector may have multiple definitions (may have overrides). virtual bool canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl, @@ -834,6 +849,9 @@ public: virtual const Expr *getArgExpr(unsigned Index) const { return getOriginExpr()->getArg(Index); } + virtual bool isVariadic() const { + return getDecl()->isVariadic(); + } bool isInstanceMessage() const { return getOriginExpr()->isInstanceMessage(); @@ -1024,7 +1042,7 @@ namespace llvm { typedef const T *SimpleType; static SimpleType - getSimplifiedValue(const clang::ento::CallEventRef<T>& Val) { + getSimplifiedValue(clang::ento::CallEventRef<T> Val) { return Val.getPtr(); } }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index 4558cd9..cda1366 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -119,7 +119,7 @@ public: /// the state of the program before the checker ran. Note, checkers should /// not retain the node in their state since the nodes might get invalidated. ExplodedNode *getPredecessor() { return Pred; } - ProgramStateRef getState() const { return Pred->getState(); } + const ProgramStateRef &getState() const { return Pred->getState(); } /// \brief Check if the checker changed the state of the execution; ex: added /// a new transition or a bug report. @@ -185,7 +185,7 @@ public: /// example, for finding variables that the given symbol was assigned to. static const MemRegion *getLocationRegionIfPostStore(const ExplodedNode *N) { ProgramPoint L = N->getLocation(); - if (const PostStore *PSL = dyn_cast<PostStore>(&L)) + if (Optional<PostStore> PSL = L.getAs<PostStore>()) return reinterpret_cast<const MemRegion*>(PSL->getLocationValue()); return 0; } @@ -303,14 +303,6 @@ private: } }; -/// \brief A helper class which wraps a boolean value set to false by default. -struct DefaultBool { - bool Val; - DefaultBool() : Val(false) {} - operator bool() const { return Val; } - DefaultBool &operator=(bool b) { Val = b; return *this; } -}; - } // end GR namespace } // end clang namespace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h index 4a78849..1e76ea6 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h @@ -14,8 +14,8 @@ #ifndef LLVM_CLANG_GR_CONSTRAINT_MANAGER_H #define LLVM_CLANG_GR_CONSTRAINT_MANAGER_H -#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" #include "llvm/Support/SaveAndRestore.h" namespace llvm { @@ -28,7 +28,7 @@ namespace ento { class SubEngine; class ConditionTruthVal { - llvm::Optional<bool> Val; + Optional<bool> Val; public: /// Construct a ConditionTruthVal indicating the constraint is constrained /// to either true or false, depending on the boolean value provided. @@ -78,9 +78,13 @@ public: // If StTrue is infeasible, asserting the falseness of Cond is unnecessary // because the existing constraints already establish this. if (!StTrue) { - // FIXME: This is fairly expensive and should be disabled even in - // Release+Asserts builds. +#ifndef __OPTIMIZE__ + // This check is expensive and should be disabled even in Release+Asserts + // builds. + // FIXME: __OPTIMIZE__ is a GNU extension that Clang implements but MSVC + // does not. Is there a good equivalent there? assert(assume(State, Cond, false) && "System is over constrained."); +#endif return ProgramStatePair((ProgramStateRef)NULL, State); } @@ -118,7 +122,7 @@ public: /// Convenience method to query the state to see if a symbol is null or /// not null, or if neither assumption can be made. ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym) { - llvm::SaveAndRestore<bool> DisableNotify(NotifyAssumeClients, false); + SaveAndRestore<bool> DisableNotify(NotifyAssumeClients, false); return checkNull(State, Sym); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index b668640..a2e211e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -17,10 +17,10 @@ #include "clang/AST/Expr.h" #include "clang/Analysis/AnalysisContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" #include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h" #include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h" #include "llvm/ADT/OwningPtr.h" namespace clang { @@ -96,6 +96,10 @@ private: void HandleBranch(const Stmt *Cond, const Stmt *Term, const CFGBlock *B, ExplodedNode *Pred); + /// Handle conditional logic for running static initializers. + void HandleStaticInit(const DeclStmt *DS, const CFGBlock *B, + ExplodedNode *Pred); + private: CoreEngine(const CoreEngine &) LLVM_DELETED_FUNCTION; void operator=(const CoreEngine &) LLVM_DELETED_FUNCTION; @@ -463,7 +467,7 @@ public: bool operator!=(const iterator &X) const { return I != X.I; } const LabelDecl *getLabel() const { - return llvm::cast<LabelStmt>((*I)->getLabel())->getDecl(); + return cast<LabelStmt>((*I)->getLabel())->getDecl(); } const CFGBlock *getBlock() const { @@ -510,7 +514,7 @@ public: bool operator==(const iterator &X) const { return I == X.I; } const CaseStmt *getCase() const { - return llvm::cast<CaseStmt>((*I)->getLabel()); + return cast<CaseStmt>((*I)->getLabel()); } const CFGBlock *getBlock() const { @@ -522,7 +526,7 @@ public: iterator end() { return iterator(Src->succ_rend()); } const SwitchStmt *getSwitch() const { - return llvm::cast<SwitchStmt>(Src->getTerminator()); + return cast<SwitchStmt>(Src->getTerminator()); } ExplodedNode *generateCaseStmtNode(const iterator &I, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h index eb9bd85..f3a582d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h @@ -33,9 +33,6 @@ class SValBuilder; /// other things. class EnvironmentEntry : public std::pair<const Stmt*, const StackFrameContext *> { - friend class EnvironmentManager; - EnvironmentEntry makeLocation() const; - public: EnvironmentEntry(const Stmt *s, const LocationContext *L); @@ -118,13 +115,6 @@ public: /// Bind a symbolic value to the given environment entry. Environment bindExpr(Environment Env, const EnvironmentEntry &E, SVal V, bool Invalidate); - - /// Bind the location 'location' and value 'V' to the specified - /// environment entry. - Environment bindExprAndLocation(Environment Env, - const EnvironmentEntry &E, - SVal location, - SVal V); Environment removeDeadBindings(Environment Env, SymbolReaper &SymReaper, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index b112e66..5211916 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -19,19 +19,19 @@ #ifndef LLVM_CLANG_GR_EXPLODEDGRAPH #define LLVM_CLANG_GR_EXPLODEDGRAPH -#include "clang/Analysis/ProgramPoint.h" -#include "clang/Analysis/AnalysisContext.h" #include "clang/AST/Decl.h" -#include "llvm/ADT/SmallVector.h" +#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/ProgramPoint.h" +#include "clang/Analysis/Support/BumpVector.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/Support/Casting.h" -#include "clang/Analysis/Support/BumpVector.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include <vector> namespace clang { @@ -152,10 +152,12 @@ public: return *getLocationContext()->getAnalysis<T>(); } - ProgramStateRef getState() const { return State; } + const ProgramStateRef &getState() const { return State; } template <typename T> - const T* getLocationAs() const { return llvm::dyn_cast<T>(&Location); } + Optional<T> getLocationAs() const LLVM_LVALUE_FUNCTION { + return Location.getAs<T>(); + } static void Profile(llvm::FoldingSetNodeID &ID, const ProgramPoint &Loc, @@ -167,7 +169,8 @@ public: } void Profile(llvm::FoldingSetNodeID& ID) const { - Profile(ID, getLocation(), getState(), isSink()); + // We avoid copy constructors by not using accessors. + Profile(ID, Location, State, isSink()); } /// addPredeccessor - Adds a predecessor to the current node, and @@ -236,18 +239,8 @@ private: void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); } }; -// FIXME: Is this class necessary? -class InterExplodedGraphMap { - virtual void anchor(); - llvm::DenseMap<const ExplodedNode*, ExplodedNode*> M; - friend class ExplodedGraph; - -public: - ExplodedNode *getMappedNode(const ExplodedNode *N) const; - - InterExplodedGraphMap() {} - virtual ~InterExplodedGraphMap() {} -}; +typedef llvm::DenseMap<const ExplodedNode *, const ExplodedNode *> + InterExplodedGraphMap; class ExplodedGraph { protected: @@ -365,14 +358,19 @@ public: typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> NodeMap; - std::pair<ExplodedGraph*, InterExplodedGraphMap*> - Trim(const NodeTy* const* NBeg, const NodeTy* const* NEnd, - llvm::DenseMap<const void*, const void*> *InverseMap = 0) const; - - ExplodedGraph* TrimInternal(const ExplodedNode* const * NBeg, - const ExplodedNode* const * NEnd, - InterExplodedGraphMap *M, - llvm::DenseMap<const void*, const void*> *InverseMap) const; + /// Creates a trimmed version of the graph that only contains paths leading + /// to the given nodes. + /// + /// \param Nodes The nodes which must appear in the final graph. Presumably + /// these are end-of-path nodes (i.e. they have no successors). + /// \param[out] ForwardMap A optional map from nodes in this graph to nodes in + /// the returned graph. + /// \param[out] InverseMap An optional map from nodes in the returned graph to + /// nodes in this graph. + /// \returns The trimmed graph + ExplodedGraph *trim(ArrayRef<const NodeTy *> Nodes, + InterExplodedGraphMap *ForwardMap = 0, + InterExplodedGraphMap *InverseMap = 0) const; /// Enable tracking of recently allocated nodes for potential reclamation /// when calling reclaimRecentlyAllocatedNodes(). @@ -384,6 +382,10 @@ public: /// was called. void reclaimRecentlyAllocatedNodes(); + /// \brief Returns true if nodes for the given expression kind are always + /// kept around. + static bool isInterestingLValueExpr(const Expr *Ex); + private: bool shouldCollect(const ExplodedNode *node); void collectNode(ExplodedNode *node); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 78b2542..33e4431 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -16,15 +16,15 @@ #ifndef LLVM_CLANG_GR_EXPRENGINE #define LLVM_CLANG_GR_EXPRENGINE +#include "clang/AST/Expr.h" +#include "clang/AST/Type.h" #include "clang/Analysis/DomainSpecific/ObjCNoReturn.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" -#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" -#include "clang/AST/Expr.h" -#include "clang/AST/Type.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" namespace clang { @@ -44,8 +44,19 @@ namespace ento { class AnalysisManager; class CallEvent; class SimpleCall; +class CXXConstructorCall; class ExprEngine : public SubEngine { +public: + /// The modes of inlining, which override the default analysis-wide settings. + enum InliningModes { + /// Follow the default settings for inlining callees. + Inline_Regular = 0, + /// Do minimal inlining of callees. + Inline_Minimal = 0x1 + }; + +private: AnalysisManager &AMgr; AnalysisDeclContextManager &AnalysisDeclContexts; @@ -64,15 +75,6 @@ class ExprEngine : public SubEngine { /// svalBuilder - SValBuilder object that creates SVals from expressions. SValBuilder &svalBuilder; - /// EntryNode - The immediate predecessor node. - ExplodedNode *EntryNode; - - /// CleanedState - The state for EntryNode "cleaned" of all dead - /// variables and symbols (as determined by a liveness analysis). - ProgramStateRef CleanedState; - - /// currStmt - The current block-level statement. - const Stmt *currStmt; unsigned int currStmtIdx; const NodeBuilderContext *currBldrCtx; @@ -92,10 +94,14 @@ class ExprEngine : public SubEngine { /// AnalysisConsumer. It can be null. SetOfConstDecls *VisitedCallees; + /// The flag, which specifies the mode of inlining for the engine. + InliningModes HowToInline; + public: ExprEngine(AnalysisManager &mgr, bool gcEnabled, SetOfConstDecls *VisitedCalleesIn, - FunctionSummariesTy *FS); + FunctionSummariesTy *FS, + InliningModes HowToInlineIn); ~ExprEngine(); @@ -140,11 +146,12 @@ public: void enqueueEndOfPath(ExplodedNodeSet &S); void GenerateCallExitNode(ExplodedNode *N); - /// ViewGraph - Visualize the ExplodedGraph created by executing the - /// simulation. + /// Visualize the ExplodedGraph created by executing the simulation. void ViewGraph(bool trim = false); - void ViewGraph(ExplodedNode** Beg, ExplodedNode** End); + /// Visualize a trimmed ExplodedGraph that only contains paths to the given + /// nodes. + void ViewGraph(ArrayRef<const ExplodedNode*> Nodes); /// getInitialState - Return the initial state used for the root vertex /// in the ExplodedGraph. @@ -154,26 +161,33 @@ public: const ExplodedGraph& getGraph() const { return G; } /// \brief Run the analyzer's garbage collection - remove dead symbols and - /// bindings. + /// bindings from the state. /// - /// \param Node - The predecessor node, from which the processing should - /// start. - /// \param Out - The returned set of output nodes. - /// \param ReferenceStmt - Run garbage collection using the symbols, - /// which are live before the given statement. - /// \param LC - The location context of the ReferenceStmt. - /// \param DiagnosticStmt - the statement used to associate the diagnostic - /// message, if any warnings should occur while removing the dead (leaks - /// are usually reported here). - /// \param K - In some cases it is possible to use PreStmt kind. (Do - /// not use it unless you know what you are doing.) - /// If the ReferenceStmt is NULL, everything is this and parent contexts is - /// considered live. - /// If the stack frame context is NULL, everything on stack is considered - /// dead. + /// Checkers can participate in this process with two callbacks: + /// \c checkLiveSymbols and \c checkDeadSymbols. See the CheckerDocumentation + /// class for more information. + /// + /// \param Node The predecessor node, from which the processing should start. + /// \param Out The returned set of output nodes. + /// \param ReferenceStmt The statement which is about to be processed. + /// Everything needed for this statement should be considered live. + /// A null statement means that everything in child LocationContexts + /// is dead. + /// \param LC The location context of the \p ReferenceStmt. A null location + /// context means that we have reached the end of analysis and that + /// all statements and local variables should be considered dead. + /// \param DiagnosticStmt Used as a location for any warnings that should + /// occur while removing the dead (e.g. leaks). By default, the + /// \p ReferenceStmt is used. + /// \param K Denotes whether this is a pre- or post-statement purge. This + /// must only be ProgramPoint::PostStmtPurgeDeadSymbolsKind if an + /// entire location context is being cleared, in which case the + /// \p ReferenceStmt must either be a ReturnStmt or \c NULL. Otherwise, + /// it must be ProgramPoint::PreStmtPurgeDeadSymbolsKind (the default) + /// and \p ReferenceStmt must be valid (non-null). void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out, - const Stmt *ReferenceStmt, const StackFrameContext *LC, - const Stmt *DiagnosticStmt, + const Stmt *ReferenceStmt, const LocationContext *LC, + const Stmt *DiagnosticStmt = 0, ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind); /// processCFGElement - Called by CoreEngine. Used to generate new successor @@ -210,6 +224,15 @@ public: const CFGBlock *DstT, const CFGBlock *DstF); + /// Called by CoreEngine. Used to processing branching behavior + /// at static initalizers. + void processStaticInitializer(const DeclStmt *DS, + NodeBuilderContext& BuilderCtx, + ExplodedNode *Pred, + ExplodedNodeSet &Dst, + const CFGBlock *DstT, + const CFGBlock *DstF); + /// processIndirectGoto - Called by CoreEngine. Used to generate successor /// nodes by processing the 'effects' of a computed goto jump. void processIndirectGoto(IndirectGotoNodeBuilder& builder); @@ -218,8 +241,8 @@ public: /// nodes by processing the 'effects' of a switch statement. void processSwitch(SwitchNodeBuilder& builder); - /// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path - /// nodes when the control reaches the end of a function. + /// Called by CoreEngine. Used to generate end-of-path + /// nodes when the control reaches the end of a function. void processEndOfFunction(NodeBuilderContext& BC, ExplodedNode *Pred); @@ -250,7 +273,7 @@ public: /// to the store. Used to update checkers that track region values. ProgramStateRef processRegionChanges(ProgramStateRef state, - const StoreManager::InvalidatedSymbols *invalidated, + const InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, const CallEvent *Call); @@ -416,11 +439,11 @@ public: geteagerlyAssumeBinOpBifurcationTags(); SVal evalMinus(SVal X) { - return X.isValid() ? svalBuilder.evalMinus(cast<NonLoc>(X)) : X; + return X.isValid() ? svalBuilder.evalMinus(X.castAs<NonLoc>()) : X; } SVal evalComplement(SVal X) { - return X.isValid() ? svalBuilder.evalComplement(cast<NonLoc>(X)) : X; + return X.isValid() ? svalBuilder.evalComplement(X.castAs<NonLoc>()) : X; } public: @@ -432,7 +455,8 @@ public: SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc L, SVal R, QualType T) { - return R.isValid() ? svalBuilder.evalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R; + return R.isValid() ? svalBuilder.evalBinOpNN(state, op, L, + R.castAs<NonLoc>(), T) : R; } SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op, @@ -447,6 +471,20 @@ protected: SVal location, SVal Val, bool atDeclInit = false, const ProgramPoint *PP = 0); + /// Call PointerEscape callback when a value escapes as a result of bind. + ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, + SVal Loc, SVal Val); + /// Call PointerEscape callback when a value escapes as a result of + /// region invalidation. + /// \param[in] IsConst Specifies that the pointer is const. + ProgramStateRef notifyCheckersOfPointerEscape( + ProgramStateRef State, + const InvalidatedSymbols *Invalidated, + ArrayRef<const MemRegion *> ExplicitRegions, + ArrayRef<const MemRegion *> Regions, + const CallEvent *Call, + bool IsConst); + public: // FIXME: 'tag' should be removed, and a LocationContext should be used // instead. @@ -506,7 +544,10 @@ private: void examineStackFrames(const Decl *D, const LocationContext *LCtx, bool &IsRecursive, unsigned &StackDepth); - bool shouldInlineDecl(const Decl *D, ExplodedNode *Pred); + /// Checks our policies and decides weither the given call should be inlined. + bool shouldInlineCall(const CallEvent &Call, const Decl *D, + const ExplodedNode *Pred); + bool inlineCall(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr, ExplodedNode *Pred, ProgramStateRef State); @@ -522,6 +563,22 @@ private: ExplodedNode *Pred); bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC); + + /// Models a trivial copy or move constructor or trivial assignment operator + /// call with a simple bind. + void performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, + const CallEvent &Call); + + /// If the value of the given expression is a NonLoc, copy it into a new + /// temporary object region, and replace the value of the expression with + /// that. + /// + /// If \p ResultE is provided, the new region will be bound to this expression + /// instead of \p E. + ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State, + const LocationContext *LC, + const Expr *E, + const Expr *ResultE = 0); }; /// Traits for storing the call processing policy inside GDM. @@ -531,7 +588,7 @@ private: struct ReplayWithoutInlining{}; template <> struct ProgramStateTrait<ReplayWithoutInlining> : - public ProgramStatePartialTrait<void*> { + public ProgramStatePartialTrait<const void*> { static void *GDMIndex() { static int index = 0; return &index; } }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h index cf4a692..169af93 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h @@ -7,94 +7,126 @@ // //===----------------------------------------------------------------------===// // -// This file defines a summary of a function gathered/used by static analyzes. +// This file defines a summary of a function gathered/used by static analysis. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_GR_FUNCTIONSUMMARY_H #define LLVM_CLANG_GR_FUNCTIONSUMMARY_H -#include <deque> -#include "clang/AST/Decl.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallBitVector.h" +#include <deque> namespace clang { +class Decl; + namespace ento { typedef std::deque<Decl*> SetOfDecls; typedef llvm::DenseSet<const Decl*> SetOfConstDecls; class FunctionSummariesTy { - struct FunctionSummary { - /// True if this function has reached a max block count while inlined from - /// at least one call site. - bool MayReachMaxBlockCount; + class FunctionSummary { + public: + /// Marks the IDs of the basic blocks visited during the analyzes. + llvm::SmallBitVector VisitedBasicBlocks; /// Total number of blocks in the function. - unsigned TotalBasicBlocks; + unsigned TotalBasicBlocks : 30; - /// Marks the IDs of the basic blocks visited during the analyzes. - llvm::BitVector VisitedBasicBlocks; + /// True if this function has been checked against the rules for which + /// functions may be inlined. + unsigned InlineChecked : 1; + + /// True if this function may be inlined. + unsigned MayInline : 1; + + /// The number of times the function has been inlined. + unsigned TimesInlined : 32; FunctionSummary() : - MayReachMaxBlockCount(false), TotalBasicBlocks(0), - VisitedBasicBlocks(0) {} + InlineChecked(0), + TimesInlined(0) {} }; - typedef llvm::DenseMap<const Decl*, FunctionSummary*> MapTy; + typedef llvm::DenseMap<const Decl *, FunctionSummary> MapTy; MapTy Map; public: - ~FunctionSummariesTy(); - MapTy::iterator findOrInsertSummary(const Decl *D) { MapTy::iterator I = Map.find(D); if (I != Map.end()) return I; - FunctionSummary *DS = new FunctionSummary(); - I = Map.insert(std::pair<const Decl*, FunctionSummary*>(D, DS)).first; + + typedef std::pair<const Decl *, FunctionSummary> KVPair; + I = Map.insert(KVPair(D, FunctionSummary())).first; assert(I != Map.end()); return I; } - void markReachedMaxBlockCount(const Decl* D) { + void markMayInline(const Decl *D) { MapTy::iterator I = findOrInsertSummary(D); - I->second->MayReachMaxBlockCount = true; + I->second.InlineChecked = 1; + I->second.MayInline = 1; } - bool hasReachedMaxBlockCount(const Decl* D) { - MapTy::const_iterator I = Map.find(D); - if (I != Map.end()) - return I->second->MayReachMaxBlockCount; - return false; + void markShouldNotInline(const Decl *D) { + MapTy::iterator I = findOrInsertSummary(D); + I->second.InlineChecked = 1; + I->second.MayInline = 0; + } + + void markReachedMaxBlockCount(const Decl *D) { + markShouldNotInline(D); + } + + Optional<bool> mayInline(const Decl *D) { + MapTy::const_iterator I = Map.find(D); + if (I != Map.end() && I->second.InlineChecked) + return I->second.MayInline; + return None; } void markVisitedBasicBlock(unsigned ID, const Decl* D, unsigned TotalIDs) { MapTy::iterator I = findOrInsertSummary(D); - llvm::BitVector &Blocks = I->second->VisitedBasicBlocks; + llvm::SmallBitVector &Blocks = I->second.VisitedBasicBlocks; assert(ID < TotalIDs); if (TotalIDs > Blocks.size()) { Blocks.resize(TotalIDs); - I->second->TotalBasicBlocks = TotalIDs; + I->second.TotalBasicBlocks = TotalIDs; } - Blocks[ID] = true; + Blocks.set(ID); } unsigned getNumVisitedBasicBlocks(const Decl* D) { MapTy::const_iterator I = Map.find(D); - if (I != Map.end()) - return I->second->VisitedBasicBlocks.count(); + if (I != Map.end()) + return I->second.VisitedBasicBlocks.count(); return 0; } + unsigned getNumTimesInlined(const Decl* D) { + MapTy::const_iterator I = Map.find(D); + if (I != Map.end()) + return I->second.TimesInlined; + return 0; + } + + void bumpNumTimesInlined(const Decl* D) { + MapTy::iterator I = findOrInsertSummary(D); + I->second.TimesInlined++; + } + /// Get the percentage of the reachable blocks. unsigned getPercentBlocksReachable(const Decl *D) { MapTy::const_iterator I = Map.find(D); if (I != Map.end()) - return ((I->second->VisitedBasicBlocks.count() * 100) / - I->second->TotalBasicBlocks); + return ((I->second.VisitedBasicBlocks.count() * 100) / + I->second.TotalBasicBlocks); return 0; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 34fbc3c..af2f365 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -22,8 +22,8 @@ #include "clang/AST/ExprObjC.h" #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/ErrorHandling.h" #include <string> namespace llvm { @@ -642,26 +642,20 @@ public: explicit referenced_vars_iterator(const MemRegion * const *r, const MemRegion * const *originalR) : R(r), OriginalR(originalR) {} - - operator const MemRegion * const *() const { - return R; - } - - const MemRegion *getCapturedRegion() const { - return *R; - } - const MemRegion *getOriginalRegion() const { - return *OriginalR; - } - const VarRegion* operator*() const { + const VarRegion *getCapturedRegion() const { return cast<VarRegion>(*R); } - + const VarRegion *getOriginalRegion() const { + return cast<VarRegion>(*OriginalR); + } + bool operator==(const referenced_vars_iterator &I) const { + assert((R == 0) == (I.R == 0)); return I.R == R; } bool operator!=(const referenced_vars_iterator &I) const { + assert((R == 0) == (I.R == 0)); return I.R != R; } referenced_vars_iterator &operator++() { @@ -670,6 +664,10 @@ public: return *this; } }; + + /// Return the original region for a captured region, if + /// one exists. + const VarRegion *getOriginalRegion(const VarRegion *VR) const; referenced_vars_iterator referenced_vars_begin() const; referenced_vars_iterator referenced_vars_end() const; @@ -686,6 +684,8 @@ public: } private: void LazyInitializeReferencedVars(); + std::pair<const VarRegion *, const VarRegion *> + getCaptureRegions(const VarDecl *VD); }; /// SymbolicRegion - A special, "non-concrete" region. Unlike other region @@ -952,6 +952,9 @@ public: const ObjCIvarDecl *getDecl() const; QualType getValueType() const; + bool canPrintPretty() const; + void printPretty(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const; static bool classof(const MemRegion* R) { @@ -993,8 +996,8 @@ class ElementRegion : public TypedValueRegion { ElementRegion(QualType elementType, NonLoc Idx, const MemRegion* sReg) : TypedValueRegion(sReg, ElementRegionKind), ElementType(elementType), Index(Idx) { - assert((!isa<nonloc::ConcreteInt>(&Idx) || - cast<nonloc::ConcreteInt>(&Idx)->getValue().isSigned()) && + assert((!Idx.getAs<nonloc::ConcreteInt>() || + Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) && "The index must be signed"); } @@ -1057,16 +1060,18 @@ public: class CXXBaseObjectRegion : public TypedValueRegion { friend class MemRegionManager; - const CXXRecordDecl *decl; + llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Data; - CXXBaseObjectRegion(const CXXRecordDecl *d, const MemRegion *sReg) - : TypedValueRegion(sReg, CXXBaseObjectRegionKind), decl(d) {} + CXXBaseObjectRegion(const CXXRecordDecl *RD, bool IsVirtual, + const MemRegion *SReg) + : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) {} - static void ProfileRegion(llvm::FoldingSetNodeID &ID, - const CXXRecordDecl *decl, const MemRegion *sReg); + static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD, + bool IsVirtual, const MemRegion *SReg); public: - const CXXRecordDecl *getDecl() const { return decl; } + const CXXRecordDecl *getDecl() const { return Data.getPointer(); } + bool isVirtual() const { return Data.getInt(); } QualType getValueType() const; @@ -1216,15 +1221,21 @@ public: const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex, LocationContext const *LC); - const CXXBaseObjectRegion *getCXXBaseObjectRegion(const CXXRecordDecl *decl, - const MemRegion *superRegion); + /// Create a CXXBaseObjectRegion with the given base class for region + /// \p Super. + /// + /// The type of \p Super is assumed be a class deriving from \p BaseClass. + const CXXBaseObjectRegion * + getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const MemRegion *Super, + bool IsVirtual); /// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different /// super region. const CXXBaseObjectRegion * getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg, const MemRegion *superRegion) { - return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion); + return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion, + baseReg->isVirtual()); } const FunctionTextRegion *getFunctionTextRegion(const NamedDecl *FD); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 86c94de..6ea7211 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -18,13 +18,13 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h" #include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" #include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h" -#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableMap.h" +#include "llvm/ADT/PointerIntPair.h" namespace llvm { class APSInt; @@ -170,19 +170,30 @@ public: // If no new state is feasible, NULL is returned. // + /// Assumes that the value of \p cond is zero (if \p assumption is "false") + /// or non-zero (if \p assumption is "true"). + /// + /// This returns a new state with the added constraint on \p cond. + /// If no new state is feasible, NULL is returned. ProgramStateRef assume(DefinedOrUnknownSVal cond, bool assumption) const; - /// This method assumes both "true" and "false" for 'cond', and - /// returns both corresponding states. It's shorthand for doing - /// 'assume' twice. - std::pair<ProgramStateRef , ProgramStateRef > + /// Assumes both "true" and "false" for \p cond, and returns both + /// corresponding states (respectively). + /// + /// This is more efficient than calling assume() twice. Note that one (but not + /// both) of the returned states may be NULL. + std::pair<ProgramStateRef, ProgramStateRef> assume(DefinedOrUnknownSVal cond) const; ProgramStateRef assumeInBound(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound, bool assumption, QualType IndexType = QualType()) const; - + + /// \brief Check if the given SVal is constrained to zero or is a zero + /// constant. + ConditionTruthVal isNull(SVal V) const; + /// Utility method for getting regions. const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const; @@ -203,12 +214,6 @@ public: ProgramStateRef BindExpr(const Stmt *S, const LocationContext *LCtx, SVal V, bool Invalidate = true) const; - /// Create a new state by binding the value 'V' and location 'locaton' to the - /// statement 'S' in the state's environment. - ProgramStateRef bindExprAndLocation(const Stmt *S, - const LocationContext *LCtx, - SVal location, SVal V) const; - ProgramStateRef bindLoc(Loc location, SVal V, bool notifyChanges = true) const; @@ -219,14 +224,38 @@ public: ProgramStateRef killBinding(Loc LV) const; - /// invalidateRegions - Returns the state with bindings for the given regions - /// cleared from the store. The regions are provided as a continuous array - /// from Begin to End. Optionally invalidates global regions as well. - ProgramStateRef invalidateRegions(ArrayRef<const MemRegion *> Regions, - const Expr *E, unsigned BlockCount, - const LocationContext *LCtx, - StoreManager::InvalidatedSymbols *IS = 0, - const CallEvent *Call = 0) const; + /// \brief Returns the state with bindings for the given regions + /// cleared from the store. + /// + /// Optionally invalidates global regions as well. + /// + /// \param Regions the set of regions to be invalidated. + /// \param E the expression that caused the invalidation. + /// \param BlockCount The number of times the current basic block has been + // visited. + /// \param CausesPointerEscape the flag is set to true when + /// the invalidation entails escape of a symbol (representing a + /// pointer). For example, due to it being passed as an argument in a + /// call. + /// \param IS the set of invalidated symbols. + /// \param Call if non-null, the invalidated regions represent parameters to + /// the call and should be considered directly invalidated. + /// \param ConstRegions the set of regions whose contents are accessible, + /// even though the regions themselves should not be invalidated. + ProgramStateRef + invalidateRegions(ArrayRef<const MemRegion *> Regions, const Expr *E, + unsigned BlockCount, const LocationContext *LCtx, + bool CausesPointerEscape, InvalidatedSymbols *IS = 0, + const CallEvent *Call = 0, + ArrayRef<const MemRegion *> ConstRegions = + ArrayRef<const MemRegion *>()) const; + + ProgramStateRef + invalidateRegions(ArrayRef<SVal> Regions, const Expr *E, + unsigned BlockCount, const LocationContext *LCtx, + bool CausesPointerEscape, InvalidatedSymbols *IS = 0, + const CallEvent *Call = 0, + ArrayRef<SVal> ConstRegions = ArrayRef<SVal>()) const; /// enterStackFrame - Returns the state for entry to the given stack frame, /// preserving the current state. @@ -396,13 +425,17 @@ public: private: friend void ProgramStateRetain(const ProgramState *state); friend void ProgramStateRelease(const ProgramState *state); - - ProgramStateRef - invalidateRegionsImpl(ArrayRef<const MemRegion *> Regions, + + /// \sa invalidateValues() + /// \sa invalidateRegions() + ProgramStateRef + invalidateRegionsImpl(ArrayRef<SVal> Values, const Expr *E, unsigned BlockCount, const LocationContext *LCtx, - StoreManager::InvalidatedSymbols &IS, - const CallEvent *Call) const; + bool ResultsInSymbolEscape, + InvalidatedSymbols &IS, + const CallEvent *Call, + ArrayRef<SVal> ConstValues) const; }; //===----------------------------------------------------------------------===// @@ -611,22 +644,24 @@ inline ProgramStateRef ProgramState::assume(DefinedOrUnknownSVal Cond, bool Assumption) const { if (Cond.isUnknown()) return this; - - return getStateManager().ConstraintMgr->assume(this, cast<DefinedSVal>(Cond), - Assumption); + + return getStateManager().ConstraintMgr + ->assume(this, Cond.castAs<DefinedSVal>(), Assumption); } inline std::pair<ProgramStateRef , ProgramStateRef > ProgramState::assume(DefinedOrUnknownSVal Cond) const { if (Cond.isUnknown()) return std::make_pair(this, this); - - return getStateManager().ConstraintMgr->assumeDual(this, - cast<DefinedSVal>(Cond)); + + return getStateManager().ConstraintMgr + ->assumeDual(this, Cond.castAs<DefinedSVal>()); } inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const { - return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V); + if (Optional<Loc> L = LV.getAs<Loc>()) + return bindLoc(*L, V); + return this; } inline Loc ProgramState::getLValue(const VarDecl *VD, @@ -660,7 +695,7 @@ inline SVal ProgramState::getLValue(const IndirectFieldDecl *D, } inline SVal ProgramState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{ - if (NonLoc *N = dyn_cast<NonLoc>(&Idx)) + if (Optional<NonLoc> N = Idx.getAs<NonLoc>()) return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base); return UnknownVal(); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h index ea2a852..eb52ae4 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h @@ -18,6 +18,8 @@ #ifndef LLVM_CLANG_GR_PROGRAMSTATETRAIT_H #define LLVM_CLANG_GR_PROGRAMSTATETRAIT_H +#include "llvm/Support/DataTypes.h" + namespace llvm { class BumpPtrAllocator; template <typename K, typename D, typename I> class ImmutableMap; @@ -165,7 +167,7 @@ namespace ento { } static inline void *MakeVoidPtr(data_type D) { - return (void*) D.getInternalPointer(); + return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer()); } static inline context_type MakeContext(void *p) { @@ -221,7 +223,20 @@ namespace ento { } }; -} // end GR namespace + // Partial specialization for const void *. + template <> struct ProgramStatePartialTrait<const void *> { + typedef const void *data_type; + + static inline data_type MakeData(void * const *p) { + return p ? *p : data_type(); + } + + static inline void *MakeVoidPtr(data_type d) { + return const_cast<void *>(d); + } + }; + +} // end ento namespace } // end clang namespace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index 5d72e73..f7e49a3 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -17,11 +17,10 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" namespace clang { @@ -124,7 +123,7 @@ public: ProgramStateManager &getStateManager() { return StateMgr; } QualType getConditionType() const { - return getContext().IntTy; + return Context.getLangOpts().CPlusPlus ? Context.BoolTy : Context.IntTy; } QualType getArrayIndexType() const { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index c2134cf..1c5519e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -16,8 +16,8 @@ #define LLVM_CLANG_GR_RVALUE_H #include "clang/Basic/LLVM.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" #include "llvm/ADT/ImmutableList.h" //==------------------------------------------------------------------------==// @@ -33,7 +33,7 @@ class LazyCompoundValData; class ProgramState; class BasicValueFactory; class MemRegion; -class TypedRegion; +class TypedValueRegion; class MemRegionManager; class ProgramStateManager; class SValBuilder; @@ -69,6 +69,29 @@ protected: public: explicit SVal() : Data(0), Kind(0) {} + /// \brief Convert to the specified SVal type, asserting that this SVal is of + /// the desired type. + template<typename T> + T castAs() const { + assert(T::isKind(*this)); + T t; + SVal& sv = t; + sv = *this; + return t; + } + + /// \brief Convert to the specified SVal type, returning None if this SVal is + /// not of the desired type. + template<typename T> + Optional<T> getAs() const { + if (!T::isKind(*this)) + return None; + T t; + SVal& sv = t; + sv = *this; + return t; + } + /// BufferTy - A temporary buffer to hold a set of SVals. typedef SmallVector<SVal,5> BufferTy; @@ -161,29 +184,32 @@ class UndefinedVal : public SVal { public: UndefinedVal() : SVal(UndefinedKind) {} - static inline bool classof(const SVal* V) { - return V->getBaseKind() == UndefinedKind; +private: + friend class SVal; + static bool isKind(const SVal& V) { + return V.getBaseKind() == UndefinedKind; } }; class DefinedOrUnknownSVal : public SVal { private: - // Do not implement. We want calling these methods to be a compiler - // error since they are tautologically false. - bool isUndef() const; - bool isValid() const; + // We want calling these methods to be a compiler error since they are + // tautologically false. + bool isUndef() const LLVM_DELETED_FUNCTION; + bool isValid() const LLVM_DELETED_FUNCTION; protected: + DefinedOrUnknownSVal() {} explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind) : SVal(d, isLoc, ValKind) {} explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL) : SVal(k, D) {} -public: - // Implement isa<T> support. - static inline bool classof(const SVal *V) { - return !V->isUndef(); +private: + friend class SVal; + static bool isKind(const SVal& V) { + return !V.isUndef(); } }; @@ -191,61 +217,79 @@ class UnknownVal : public DefinedOrUnknownSVal { public: explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {} - static inline bool classof(const SVal *V) { - return V->getBaseKind() == UnknownKind; +private: + friend class SVal; + static bool isKind(const SVal &V) { + return V.getBaseKind() == UnknownKind; } }; class DefinedSVal : public DefinedOrUnknownSVal { private: - // Do not implement. We want calling these methods to be a compiler - // error since they are tautologically true/false. - bool isUnknown() const; - bool isUnknownOrUndef() const; - bool isValid() const; + // We want calling these methods to be a compiler error since they are + // tautologically true/false. + bool isUnknown() const LLVM_DELETED_FUNCTION; + bool isUnknownOrUndef() const LLVM_DELETED_FUNCTION; + bool isValid() const LLVM_DELETED_FUNCTION; protected: + DefinedSVal() {} explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind) : DefinedOrUnknownSVal(d, isLoc, ValKind) {} -public: - // Implement isa<T> support. - static inline bool classof(const SVal *V) { - return !V->isUnknownOrUndef(); +private: + friend class SVal; + static bool isKind(const SVal& V) { + return !V.isUnknownOrUndef(); + } +}; + + +/// \brief Represents an SVal that is guaranteed to not be UnknownVal. +class KnownSVal : public SVal { + KnownSVal() {} + friend class SVal; + static bool isKind(const SVal &V) { + return !V.isUnknown(); } +public: + KnownSVal(const DefinedSVal &V) : SVal(V) {} + KnownSVal(const UndefinedVal &V) : SVal(V) {} }; class NonLoc : public DefinedSVal { protected: + NonLoc() {} explicit NonLoc(unsigned SubKind, const void *d) : DefinedSVal(d, false, SubKind) {} public: void dumpToStream(raw_ostream &Out) const; - // Implement isa<T> support. - static inline bool classof(const SVal* V) { - return V->getBaseKind() == NonLocKind; +private: + friend class SVal; + static bool isKind(const SVal& V) { + return V.getBaseKind() == NonLocKind; } }; class Loc : public DefinedSVal { protected: + Loc() {} explicit Loc(unsigned SubKind, const void *D) : DefinedSVal(const_cast<void*>(D), true, SubKind) {} public: void dumpToStream(raw_ostream &Out) const; - Loc(const Loc& X) : DefinedSVal(X.Data, true, X.getSubKind()) {} - - // Implement isa<T> support. - static inline bool classof(const SVal* V) { - return V->getBaseKind() == LocKind; - } - static inline bool isLocType(QualType T) { return T->isAnyPointerType() || T->isBlockPointerType() || T->isReferenceType(); } + +private: + friend class SVal; + static bool isKind(const SVal& V) { + return V.getBaseKind() == LocKind; + } }; //==------------------------------------------------------------------------==// @@ -266,17 +310,20 @@ public: return (const SymExpr*) Data; } - bool isExpression() { + bool isExpression() const { return !isa<SymbolData>(getSymbol()); } - static inline bool classof(const SVal* V) { - return V->getBaseKind() == NonLocKind && - V->getSubKind() == SymbolValKind; +private: + friend class SVal; + SymbolVal() {} + static bool isKind(const SVal& V) { + return V.getBaseKind() == NonLocKind && + V.getSubKind() == SymbolValKind; } - static inline bool classof(const NonLoc* V) { - return V->getSubKind() == SymbolValKind; + static bool isKind(const NonLoc& V) { + return V.getSubKind() == SymbolValKind; } }; @@ -297,38 +344,40 @@ public: ConcreteInt evalMinus(SValBuilder &svalBuilder) const; - // Implement isa<T> support. - static inline bool classof(const SVal* V) { - return V->getBaseKind() == NonLocKind && - V->getSubKind() == ConcreteIntKind; +private: + friend class SVal; + ConcreteInt() {} + static bool isKind(const SVal& V) { + return V.getBaseKind() == NonLocKind && + V.getSubKind() == ConcreteIntKind; } - static inline bool classof(const NonLoc* V) { - return V->getSubKind() == ConcreteIntKind; + static bool isKind(const NonLoc& V) { + return V.getSubKind() == ConcreteIntKind; } }; class LocAsInteger : public NonLoc { friend class ento::SValBuilder; - explicit LocAsInteger(const std::pair<SVal, uintptr_t>& data) : - NonLoc(LocAsIntegerKind, &data) { - assert (isa<Loc>(data.first)); - } + explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data) + : NonLoc(LocAsIntegerKind, &data) { + assert (data.first.getAs<Loc>()); + } public: Loc getLoc() const { const std::pair<SVal, uintptr_t> *D = static_cast<const std::pair<SVal, uintptr_t> *>(Data); - return cast<Loc>(D->first); + return D->first.castAs<Loc>(); } - const Loc& getPersistentLoc() const { + Loc getPersistentLoc() const { const std::pair<SVal, uintptr_t> *D = static_cast<const std::pair<SVal, uintptr_t> *>(Data); const SVal& V = D->first; - return cast<Loc>(V); + return V.castAs<Loc>(); } unsigned getNumBits() const { @@ -337,14 +386,16 @@ public: return D->second; } - // Implement isa<T> support. - static inline bool classof(const SVal* V) { - return V->getBaseKind() == NonLocKind && - V->getSubKind() == LocAsIntegerKind; +private: + friend class SVal; + LocAsInteger() {} + static bool isKind(const SVal& V) { + return V.getBaseKind() == NonLocKind && + V.getSubKind() == LocAsIntegerKind; } - static inline bool classof(const NonLoc* V) { - return V->getSubKind() == LocAsIntegerKind; + static bool isKind(const NonLoc& V) { + return V.getSubKind() == LocAsIntegerKind; } }; @@ -362,12 +413,15 @@ public: iterator begin() const; iterator end() const; - static bool classof(const SVal* V) { - return V->getBaseKind() == NonLocKind && V->getSubKind() == CompoundValKind; +private: + friend class SVal; + CompoundVal() {} + static bool isKind(const SVal& V) { + return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind; } - static bool classof(const NonLoc* V) { - return V->getSubKind() == CompoundValKind; + static bool isKind(const NonLoc& V) { + return V.getSubKind() == CompoundValKind; } }; @@ -381,14 +435,17 @@ public: return static_cast<const LazyCompoundValData*>(Data); } const void *getStore() const; - const TypedRegion *getRegion() const; + const TypedValueRegion *getRegion() const; - static bool classof(const SVal *V) { - return V->getBaseKind() == NonLocKind && - V->getSubKind() == LazyCompoundValKind; +private: + friend class SVal; + LazyCompoundVal() {} + static bool isKind(const SVal& V) { + return V.getBaseKind() == NonLocKind && + V.getSubKind() == LazyCompoundValKind; } - static bool classof(const NonLoc *V) { - return V->getSubKind() == LazyCompoundValKind; + static bool isKind(const NonLoc& V) { + return V.getSubKind() == LazyCompoundValKind; } }; @@ -410,12 +467,15 @@ public: return static_cast<const LabelDecl*>(Data); } - static inline bool classof(const SVal* V) { - return V->getBaseKind() == LocKind && V->getSubKind() == GotoLabelKind; +private: + friend class SVal; + GotoLabel() {} + static bool isKind(const SVal& V) { + return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind; } - static inline bool classof(const Loc* V) { - return V->getSubKind() == GotoLabelKind; + static bool isKind(const Loc& V) { + return V.getSubKind() == GotoLabelKind; } }; @@ -434,7 +494,7 @@ public: template <typename REGION> const REGION* getRegionAs() const { - return llvm::dyn_cast<REGION>(getRegion()); + return dyn_cast<REGION>(getRegion()); } inline bool operator==(const MemRegionVal& R) const { @@ -445,14 +505,16 @@ public: return getRegion() != R.getRegion(); } - // Implement isa<T> support. - static inline bool classof(const SVal* V) { - return V->getBaseKind() == LocKind && - V->getSubKind() == MemRegionKind; +private: + friend class SVal; + MemRegionVal() {} + static bool isKind(const SVal& V) { + return V.getBaseKind() == LocKind && + V.getSubKind() == MemRegionKind; } - static inline bool classof(const Loc* V) { - return V->getSubKind() == MemRegionKind; + static bool isKind(const Loc& V) { + return V.getSubKind() == MemRegionKind; } }; @@ -468,19 +530,22 @@ public: SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op, const ConcreteInt& R) const; - // Implement isa<T> support. - static inline bool classof(const SVal* V) { - return V->getBaseKind() == LocKind && - V->getSubKind() == ConcreteIntKind; +private: + friend class SVal; + ConcreteInt() {} + static bool isKind(const SVal& V) { + return V.getBaseKind() == LocKind && + V.getSubKind() == ConcreteIntKind; } - static inline bool classof(const Loc* V) { - return V->getSubKind() == ConcreteIntKind; + static bool isKind(const Loc& V) { + return V.getSubKind() == ConcreteIntKind; } }; } // end ento::loc namespace -} // end GR namespace + +} // end ento namespace } // end clang namespace @@ -491,6 +556,11 @@ static inline raw_ostream &operator<<(raw_ostream &os, return os; } +template <typename T> struct isPodLike; +template <> struct isPodLike<clang::ento::SVal> { + static const bool value = true; +}; + } // end llvm namespace #endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index 979546b..bbfd579 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -14,9 +14,9 @@ #ifndef LLVM_CLANG_GR_STORE_H #define LLVM_CLANG_GR_STORE_H -#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Optional.h" @@ -35,6 +35,8 @@ class ProgramState; class ProgramStateManager; class ScanReachableSymbols; +typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols; + class StoreManager { protected: SValBuilder &svalBuilder; @@ -134,7 +136,8 @@ public: SVal evalDerivedToBase(SVal Derived, const CXXBasePath &CastPath); /// Evaluates a derived-to-base cast through a single level of derivation. - SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType); + SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType, + bool IsVirtual); /// \brief Evaluates C++ dynamic_cast cast. /// The callback may result in the following 3 scenarios: @@ -168,7 +171,6 @@ public: /// associated with the object is recycled. virtual void decrementReferenceCount(Store store) {} - typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols; typedef SmallVector<const MemRegion *, 8> InvalidatedRegions; /// invalidateRegions - Clears out the specified regions from the store, @@ -176,26 +178,40 @@ public: /// invalidate additional regions that may have changed based on accessing /// the given regions. Optionally, invalidates non-static globals as well. /// \param[in] store The initial store - /// \param[in] Regions The regions to invalidate. + /// \param[in] Values The values to invalidate. + /// \param[in] ConstValues The values to invalidate; these are known to be + /// const, so only regions accesible from them should be invalidated. /// \param[in] E The current statement being evaluated. Used to conjure /// symbols to mark the values of invalidated regions. /// \param[in] Count The current block count. Used to conjure /// symbols to mark the values of invalidated regions. - /// \param[in,out] IS A set to fill with any symbols that are no longer - /// accessible. Pass \c NULL if this information will not be used. /// \param[in] Call The call expression which will be used to determine which /// globals should get invalidated. + /// \param[in,out] IS A set to fill with any symbols that are no longer + /// accessible. Pass \c NULL if this information will not be used. + /// \param[in,out] ConstIS A set to fill with any symbols corresponding to + /// the ConstValues. + /// \param[in,out] InvalidatedTopLevel A vector to fill with regions + //// explicitely being invalidated. Pass \c NULL if this + /// information will not be used. + /// \param[in,out] InvalidatedTopLevelConst A vector to fill with const + //// regions explicitely being invalidated. Pass \c NULL if this + /// information will not be used. /// \param[in,out] Invalidated A vector to fill with any regions being /// invalidated. This should include any regions explicitly invalidated /// even if they do not currently have bindings. Pass \c NULL if this /// information will not be used. virtual StoreRef invalidateRegions(Store store, - ArrayRef<const MemRegion *> Regions, - const Expr *E, unsigned Count, - const LocationContext *LCtx, - InvalidatedSymbols &IS, - const CallEvent *Call, - InvalidatedRegions *Invalidated) = 0; + ArrayRef<SVal> Values, + ArrayRef<SVal> ConstValues, + const Expr *E, unsigned Count, + const LocationContext *LCtx, + const CallEvent *Call, + InvalidatedSymbols &IS, + InvalidatedSymbols &ConstIS, + InvalidatedRegions *InvalidatedTopLevel, + InvalidatedRegions *InvalidatedTopLevelConst, + InvalidatedRegions *Invalidated) = 0; /// enterStackFrame - Let the StoreManager to do something when execution /// engine is about to execute into a callee. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h index 1e71077..d410063 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -72,6 +72,15 @@ public: const CFGBlock *DstT, const CFGBlock *DstF) = 0; + /// Called by CoreEngine. Used to processing branching behavior + /// at static initalizers. + virtual void processStaticInitializer(const DeclStmt *DS, + NodeBuilderContext& BuilderCtx, + ExplodedNode *Pred, + ExplodedNodeSet &Dst, + const CFGBlock *DstT, + const CFGBlock *DstF) = 0; + /// Called by CoreEngine. Used to generate successor /// nodes by processing the 'effects' of a computed goto jump. virtual void processIndirectGoto(IndirectGotoNodeBuilder& builder) = 0; @@ -104,7 +113,7 @@ public: /// made to the store. Used to update checkers that track region values. virtual ProgramStateRef processRegionChanges(ProgramStateRef state, - const StoreManager::InvalidatedSymbols *invalidated, + const InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, const CallEvent *Call) = 0; @@ -116,6 +125,17 @@ public: return processRegionChanges(state, 0, MR, MR, 0); } + virtual ProgramStateRef + processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val) = 0; + + virtual ProgramStateRef + notifyCheckersOfPointerEscape(ProgramStateRef State, + const InvalidatedSymbols *Invalidated, + ArrayRef<const MemRegion *> ExplicitRegions, + ArrayRef<const MemRegion *> Regions, + const CallEvent *Call, + bool IsConst = false) = 0; + /// printState - Called by ProgramStateManager to print checker-specific data. virtual void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) = 0; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index 873f773..56afca2 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -20,10 +20,10 @@ #include "clang/Analysis/AnalysisContext.h" #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class BumpPtrAllocator; @@ -96,7 +96,7 @@ public: }; typedef const SymExpr* SymbolRef; -typedef llvm::SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy; +typedef SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy; typedef unsigned SymbolID; /// \brief A symbol representing data which can be stored in a memory location diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h index c274cea..4c58d4b 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h @@ -14,7 +14,11 @@ #ifndef LLVM_CLANG_TAINTMANAGER_H #define LLVM_CLANG_TAINTMANAGER_H +#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" #include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h" +#include "llvm/ADT/ImmutableMap.h" namespace clang { namespace ento { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h index 51aa753..d12a151 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h @@ -16,7 +16,8 @@ #define LLVM_CLANG_GR_WORKLIST #include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h" -#include <cstddef> +#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" +#include <cassert> namespace clang { @@ -24,9 +25,6 @@ class CFGBlock; namespace ento { -class ExplodedNode; -class ExplodedNodeImpl; - class WorkListUnit { ExplodedNode *node; BlockCounter counter; diff --git a/include/clang/Tooling/CommonOptionsParser.h b/include/clang/Tooling/CommonOptionsParser.h index a1bad12..6775934 100644 --- a/include/clang/Tooling/CommonOptionsParser.h +++ b/include/clang/Tooling/CommonOptionsParser.h @@ -53,8 +53,8 @@ namespace tooling { /// /// int main(int argc, const char **argv) { /// CommonOptionsParser OptionsParser(argc, argv); -/// ClangTool Tool(OptionsParser.GetCompilations(), -/// OptionsParser.GetSourcePathListi()); +/// ClangTool Tool(OptionsParser.getCompilations(), +/// OptionsParser.getSourcePathListi()); /// return Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>()); /// } /// \endcode @@ -67,19 +67,19 @@ public: CommonOptionsParser(int &argc, const char **argv); /// Returns a reference to the loaded compilations database. - CompilationDatabase &GetCompilations() { + CompilationDatabase &getCompilations() { return *Compilations; } /// Returns a list of source file paths to process. - std::vector<std::string> GetSourcePathList() { + std::vector<std::string> getSourcePathList() { return SourcePathList; } static const char *const HelpMessage; private: - llvm::OwningPtr<CompilationDatabase> Compilations; + OwningPtr<CompilationDatabase> Compilations; std::vector<std::string> SourcePathList; }; diff --git a/include/clang/Tooling/CompilationDatabase.h b/include/clang/Tooling/CompilationDatabase.h index a40bffe..7a8054f 100644 --- a/include/clang/Tooling/CompilationDatabase.h +++ b/include/clang/Tooling/CompilationDatabase.h @@ -33,7 +33,6 @@ #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" - #include <string> #include <vector> @@ -106,6 +105,10 @@ public: /// \brief Returns the list of all files available in the compilation database. virtual std::vector<std::string> getAllFiles() const = 0; + + /// \brief Returns all compile commands for all the files in the compilation + /// database. + virtual std::vector<CompileCommand> getAllCompileCommands() const = 0; }; /// \brief Interface for compilation database plugins. @@ -149,7 +152,7 @@ public: /// The argument list is meant to be compatible with normal llvm command line /// parsing in main methods. /// int main(int argc, char **argv) { - /// llvm::OwningPtr<FixedCompilationDatabase> Compilations( + /// OwningPtr<FixedCompilationDatabase> Compilations( /// FixedCompilationDatabase::loadFromCommandLine(argc, argv)); /// cl::ParseCommandLineOptions(argc, argv); /// ... @@ -181,6 +184,12 @@ public: /// Note: This is always an empty list for the fixed compilation database. virtual std::vector<std::string> getAllFiles() const; + /// \brief Returns all compile commands for all the files in the compilation + /// database. + /// + /// Note: This is always an empty list for the fixed compilation database. + virtual std::vector<CompileCommand> getAllCompileCommands() const; + private: /// This is built up to contain a single entry vector to be returned from /// getCompileCommands after adding the positional argument. diff --git a/include/clang/Tooling/FileMatchTrie.h b/include/clang/Tooling/FileMatchTrie.h index ff988be..e531854 100644 --- a/include/clang/Tooling/FileMatchTrie.h +++ b/include/clang/Tooling/FileMatchTrie.h @@ -18,7 +18,6 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" - #include <string> #include <vector> @@ -77,7 +76,7 @@ public: /// matches, an empty \c StringRef is returned and a corresponding message /// written to 'Error'. StringRef findEquivalent(StringRef FileName, - llvm::raw_ostream &Error) const; + raw_ostream &Error) const; private: FileMatchTrieNode *Root; OwningPtr<PathComparator> Comparator; diff --git a/include/clang/Tooling/JSONCompilationDatabase.h b/include/clang/Tooling/JSONCompilationDatabase.h index d62ab5c..e3f149b 100644 --- a/include/clang/Tooling/JSONCompilationDatabase.h +++ b/include/clang/Tooling/JSONCompilationDatabase.h @@ -75,6 +75,10 @@ public: /// These are the 'file' entries of the JSON objects. virtual std::vector<std::string> getAllFiles() const; + /// \brief Returns all compile commands for all the files in the compilation + /// database. + virtual std::vector<CompileCommand> getAllCompileCommands() const; + private: /// \brief Constructs a JSON compilation database on a memory buffer. JSONCompilationDatabase(llvm::MemoryBuffer *Database) @@ -91,12 +95,16 @@ private: typedef std::pair<llvm::yaml::ScalarNode*, llvm::yaml::ScalarNode*> CompileCommandRef; + /// \brief Converts the given array of CompileCommandRefs to CompileCommands. + void getCommands(ArrayRef<CompileCommandRef> CommandsRef, + std::vector<CompileCommand> &Commands) const; + // Maps file paths to the compile command lines for that file. llvm::StringMap< std::vector<CompileCommandRef> > IndexByFile; FileMatchTrie MatchTrie; - llvm::OwningPtr<llvm::MemoryBuffer> Database; + OwningPtr<llvm::MemoryBuffer> Database; llvm::SourceMgr SM; llvm::yaml::Stream YAMLStream; }; diff --git a/include/clang/Tooling/Refactoring.h b/include/clang/Tooling/Refactoring.h index aaffc1a..079ce74 100644 --- a/include/clang/Tooling/Refactoring.h +++ b/include/clang/Tooling/Refactoring.h @@ -19,9 +19,9 @@ #ifndef LLVM_CLANG_TOOLING_REFACTORING_H #define LLVM_CLANG_TOOLING_REFACTORING_H -#include "llvm/ADT/StringRef.h" #include "clang/Basic/SourceLocation.h" #include "clang/Tooling/Tooling.h" +#include "llvm/ADT/StringRef.h" #include <set> #include <string> @@ -47,22 +47,22 @@ public: /// \param FilePath A source file accessible via a SourceManager. /// \param Offset The byte offset of the start of the range in the file. /// \param Length The length of the range in bytes. - Replacement(llvm::StringRef FilePath, unsigned Offset, - unsigned Length, llvm::StringRef ReplacementText); + Replacement(StringRef FilePath, unsigned Offset, + unsigned Length, StringRef ReplacementText); /// \brief Creates a Replacement of the range [Start, Start+Length) with /// ReplacementText. Replacement(SourceManager &Sources, SourceLocation Start, unsigned Length, - llvm::StringRef ReplacementText); + StringRef ReplacementText); /// \brief Creates a Replacement of the given range with ReplacementText. Replacement(SourceManager &Sources, const CharSourceRange &Range, - llvm::StringRef ReplacementText); + StringRef ReplacementText); /// \brief Creates a Replacement of the node with ReplacementText. template <typename Node> Replacement(SourceManager &Sources, const Node &NodeToReplace, - llvm::StringRef ReplacementText); + StringRef ReplacementText); /// \brief Returns whether this replacement can be applied to a file. /// @@ -91,9 +91,9 @@ public: private: void setFromSourceLocation(SourceManager &Sources, SourceLocation Start, - unsigned Length, llvm::StringRef ReplacementText); + unsigned Length, StringRef ReplacementText); void setFromSourceRange(SourceManager &Sources, const CharSourceRange &Range, - llvm::StringRef ReplacementText); + StringRef ReplacementText); std::string FilePath; unsigned Offset; @@ -105,41 +105,54 @@ public: /// FIXME: Change to a vector and deduplicate in the RefactoringTool. typedef std::set<Replacement, Replacement::Less> Replacements; -/// \brief Apply all replacements on the Rewriter. +/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite. +/// +/// Replacement applications happen independently of the success of +/// other applications. /// -/// If at least one Apply returns false, ApplyAll returns false. Every -/// Apply will be executed independently of the result of other -/// Apply operations. +/// \returns true if all replacements apply. false otherwise. bool applyAllReplacements(Replacements &Replaces, Rewriter &Rewrite); /// \brief A tool to run refactorings. /// -/// This is a refactoring specific version of \see ClangTool. -/// All text replacements added to getReplacements() during the run of the -/// tool will be applied and saved after all translation units have been -/// processed. -class RefactoringTool { +/// This is a refactoring specific version of \see ClangTool. FrontendActions +/// passed to run() and runAndSave() should add replacements to +/// getReplacements(). +class RefactoringTool : public ClangTool { public: /// \see ClangTool::ClangTool. RefactoringTool(const CompilationDatabase &Compilations, ArrayRef<std::string> SourcePaths); - /// \brief Returns a set of replacements. All replacements added during the - /// run of the tool will be applied after all translation units have been - /// processed. + /// \brief Returns the set of replacements to which replacements should + /// be added during the run of the tool. Replacements &getReplacements(); - /// \see ClangTool::run. - int run(FrontendActionFactory *ActionFactory); + /// \brief Call run(), apply all generated replacements, and immediately save + /// the results to disk. + /// + /// \returns 0 upon success. Non-zero upon failure. + int runAndSave(FrontendActionFactory *ActionFactory); + + /// \brief Apply all stored replacements to the given Rewriter. + /// + /// Replacement applications happen independently of the success of other + /// applications. + /// + /// \returns true if all replacements apply. false otherwise. + bool applyAllReplacements(Rewriter &Rewrite); + +private: + /// \brief Write all refactored files to disk. + int saveRewrittenFiles(Rewriter &Rewrite); private: - ClangTool Tool; Replacements Replace; }; template <typename Node> Replacement::Replacement(SourceManager &Sources, const Node &NodeToReplace, - llvm::StringRef ReplacementText) { + StringRef ReplacementText) { const CharSourceRange Range = CharSourceRange::getTokenRange(NodeToReplace->getSourceRange()); setFromSourceRange(Sources, Range, ReplacementText); @@ -149,4 +162,3 @@ Replacement::Replacement(SourceManager &Sources, const Node &NodeToReplace, } // end namespace clang #endif // end namespace LLVM_CLANG_TOOLING_REFACTORING_H - diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h index a03bcb1..27e5a0a 100644 --- a/include/clang/Tooling/Tooling.h +++ b/include/clang/Tooling/Tooling.h @@ -30,14 +30,14 @@ #ifndef LLVM_CLANG_TOOLING_TOOLING_H #define LLVM_CLANG_TOOLING_TOOLING_H -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/Twine.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/LLVM.h" #include "clang/Driver/Util.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Tooling/ArgumentsAdjusters.h" #include "clang/Tooling/CompilationDatabase.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Twine.h" #include <string> #include <vector> @@ -151,11 +151,10 @@ class ToolInvocation { bool runInvocation(const char *BinaryName, clang::driver::Compilation *Compilation, - clang::CompilerInvocation *Invocation, - const clang::driver::ArgStringList &CC1Args); + clang::CompilerInvocation *Invocation); std::vector<std::string> CommandLine; - llvm::OwningPtr<FrontendAction> ToolAction; + OwningPtr<FrontendAction> ToolAction; FileManager *Files; // Maps <file name> -> <file content>. llvm::StringMap<StringRef> MappedFileContents; @@ -179,6 +178,8 @@ class ClangTool { ClangTool(const CompilationDatabase &Compilations, ArrayRef<std::string> SourcePaths); + virtual ~ClangTool() {} + /// \brief Map a virtual file to be used while running the tool. /// /// \param FilePath The path at which the content will be mapped. @@ -195,7 +196,7 @@ class ClangTool { /// \param ActionFactory Factory generating the frontend actions. The function /// takes ownership of this parameter. A new action is generated for every /// processed translation unit. - int run(FrontendActionFactory *ActionFactory); + virtual int run(FrontendActionFactory *ActionFactory); /// \brief Returns the file manager used in the tool. /// @@ -210,7 +211,7 @@ class ClangTool { // Contains a list of pairs (<file name>, <file content>). std::vector< std::pair<StringRef, StringRef> > MappedFileContents; - llvm::OwningPtr<ArgumentsAdjuster> ArgsAdjuster; + OwningPtr<ArgumentsAdjuster> ArgsAdjuster; }; template <typename T> @@ -244,7 +245,7 @@ inline FrontendActionFactory *newFrontendActionFactory( : ConsumerFactory(ConsumerFactory), EndCallback(EndCallback) {} clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &, - llvm::StringRef) { + StringRef) { return ConsumerFactory->newASTConsumer(); } |