diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:02:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:02:28 +0000 |
commit | 7442d6faa2719e4e7d33a7021c406c5a4facd74d (patch) | |
tree | c72b9241553fc9966179aba84f90f17bfa9235c3 /include/clang | |
parent | b52119637f743680a99710ce5fdb6646da2772af (diff) | |
download | src-7442d6faa2719e4e7d33a7021c406c5a4facd74d.tar.gz src-7442d6faa2719e4e7d33a7021c406c5a4facd74d.zip |
Vendor import of clang trunk r300422:vendor/clang/clang-trunk-r300422
Notes
Notes:
svn path=/vendor/clang/dist/; revision=317019
svn path=/vendor/clang/clang-trunk-r300422/; revision=317020; tag=vendor/clang/clang-trunk-r300422
Diffstat (limited to 'include/clang')
137 files changed, 6495 insertions, 1405 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 1c9ce821438d..474cf2c0e3f3 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -39,6 +39,7 @@ #include "clang/Basic/SanitizerBlacklist.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" +#include "clang/Basic/XRayLists.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" @@ -66,6 +67,7 @@ #include <memory> #include <new> #include <string> +#include <type_traits> #include <utility> #include <vector> @@ -167,18 +169,20 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable llvm::FoldingSet<DependentUnaryTransformType> DependentUnaryTransformTypes; mutable llvm::FoldingSet<AutoType> AutoTypes; + mutable llvm::FoldingSet<DeducedTemplateSpecializationType> + DeducedTemplateSpecializationTypes; mutable llvm::FoldingSet<AtomicType> AtomicTypes; llvm::FoldingSet<AttributedType> AttributedTypes; mutable llvm::FoldingSet<PipeType> PipeTypes; mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; - mutable llvm::FoldingSet<SubstTemplateTemplateParmStorage> + mutable llvm::FoldingSet<SubstTemplateTemplateParmStorage> SubstTemplateTemplateParms; mutable llvm::ContextualFoldingSet<SubstTemplateTemplateParmPackStorage, - ASTContext&> + ASTContext&> SubstTemplateTemplateParmPacks; - + /// \brief The set of nested name specifiers. /// /// This set is managed by the NestedNameSpecifier class. @@ -200,17 +204,17 @@ class ASTContext : public RefCountedBase<ASTContext> { /// \brief A cache mapping from CXXRecordDecls to key functions. llvm::DenseMap<const CXXRecordDecl*, LazyDeclPtr> KeyFunctions; - + /// \brief Mapping from ObjCContainers to their ObjCImplementations. llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls; - + /// \brief Mapping from ObjCMethod to its duplicate declaration in the same /// interface. llvm::DenseMap<const ObjCMethodDecl*,const ObjCMethodDecl*> ObjCMethodRedecls; /// \brief Mapping from __block VarDecls to their copy initialization expr. llvm::DenseMap<const VarDecl*, Expr*> BlockVarCopyInits; - + /// \brief Mapping from class scope functions specialization to their /// template patterns. llvm::DenseMap<const FunctionDecl*, FunctionDecl*> @@ -226,21 +230,21 @@ class ASTContext : public RefCountedBase<ASTContext> { /// is used in canonical template names. class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode { TemplateTemplateParmDecl *Parm; - + public: - CanonicalTemplateTemplateParm(TemplateTemplateParmDecl *Parm) + CanonicalTemplateTemplateParm(TemplateTemplateParmDecl *Parm) : Parm(Parm) { } - + TemplateTemplateParmDecl *getParam() const { return Parm; } - + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Parm); } - - static void Profile(llvm::FoldingSetNodeID &ID, + + static void Profile(llvm::FoldingSetNodeID &ID, TemplateTemplateParmDecl *Parm); }; mutable llvm::FoldingSet<CanonicalTemplateTemplateParm> CanonTemplateTemplateParms; - + TemplateTemplateParmDecl * getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const; @@ -259,7 +263,7 @@ class ASTContext : public RefCountedBase<ASTContext> { /// \brief The typedef for the predefined \c id type. mutable TypedefDecl *ObjCIdDecl; - + /// \brief The typedef for the predefined \c SEL type. mutable TypedefDecl *ObjCSelDecl; @@ -268,7 +272,7 @@ class ASTContext : public RefCountedBase<ASTContext> { /// \brief The typedef for the predefined \c Protocol class in Objective-C. mutable ObjCInterfaceDecl *ObjCProtocolClassDecl; - + /// \brief The typedef for the predefined 'BOOL' type. mutable TypedefDecl *BOOLDecl; @@ -298,12 +302,12 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable TypedefDecl *CFConstantStringTypeDecl; mutable QualType ObjCSuperType; - + QualType ObjCNSStringType; /// \brief The typedef declaration for the Objective-C "instancetype" type. TypedefDecl *ObjCInstanceTypeDecl; - + /// \brief The type for the C FILE type. TypeDecl *FILEDecl; @@ -451,11 +455,11 @@ private: /// \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; - ParameterIndexTable ParamIndices; - + ParameterIndexTable ParamIndices; + ImportDecl *FirstLocalImport; ImportDecl *LastLocalImport; - + TranslationUnitDecl *TUDecl; mutable ExternCContextDecl *ExternCContext; mutable BuiltinTemplateDecl *MakeIntegerSeqDecl; @@ -472,6 +476,10 @@ private: /// entities should not be instrumented. std::unique_ptr<SanitizerBlacklist> SanitizerBL; + /// \brief Function filtering mechanism to determine whether a given function + /// should be imbued with the XRay "always" or "never" attributes. + std::unique_ptr<XRayFunctionFilter> XRayFilter; + /// \brief The allocator used to create AST objects. /// /// AST objects are never destructed; rather, all memory associated with the @@ -488,7 +496,7 @@ private: /// \brief The logical -> physical address space map. const LangAS::Map *AddrSpaceMap; - /// \brief Address space map mangling must be used with language specific + /// \brief Address space map mangling must be used with language specific /// address spaces (e.g. OpenCL/CUDA) bool AddrSpaceMapMangling; @@ -500,7 +508,7 @@ private: const TargetInfo *Target; const TargetInfo *AuxTarget; clang::PrintingPolicy PrintingPolicy; - + public: IdentifierTable &Idents; SelectorTable &Selectors; @@ -604,7 +612,7 @@ public: void setPrintingPolicy(const clang::PrintingPolicy &Policy) { PrintingPolicy = Policy; } - + SourceManager& getSourceManager() { return SourceMgr; } const SourceManager& getSourceManager() const { return SourceMgr; } @@ -619,7 +627,7 @@ public: return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T))); } void Deallocate(void *Ptr) const { } - + /// Return the total amount of physical memory allocated for representing /// AST nodes and type information. size_t getASTAllocatedMemory() const { @@ -627,7 +635,7 @@ public: } /// Return the total memory used for various side tables. size_t getSideTableAllocatedMemory() const; - + PartialDiagnostic::StorageAllocator &getDiagAllocator() { return DiagAllocator; } @@ -647,13 +655,17 @@ public: QualType getRealTypeForBitwidth(unsigned DestWidth) const; bool AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const; - + const LangOptions& getLangOpts() const { return LangOpts; } const SanitizerBlacklist &getSanitizerBlacklist() const { return *SanitizerBL; } + const XRayFunctionFilter &getXRayFilter() const { + return *XRayFilter; + } + DiagnosticsEngine &getDiagnostics() const; FullSourceLoc getFullLoc(SourceLocation Loc) const { @@ -862,7 +874,7 @@ public: FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field); void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl); - + // Access to the set of methods overridden by the given C++ method. typedef CXXMethodVector::const_iterator overridden_cxx_method_iterator; overridden_cxx_method_iterator @@ -878,7 +890,7 @@ public: /// \brief Note that the given C++ \p Method overrides the given \p /// Overridden method. - void addOverriddenMethod(const CXXMethodDecl *Method, + void addOverriddenMethod(const CXXMethodDecl *Method, const CXXMethodDecl *Overridden); /// \brief Return C++ or ObjC overridden methods for the given \p Method. @@ -891,7 +903,7 @@ public: void getOverriddenMethods( const NamedDecl *Method, SmallVectorImpl<const NamedDecl *> &Overridden) const; - + /// \brief Notify the AST context that a new import declaration has been /// parsed or implicitly created within this translation unit. void addedLocalImportDecl(ImportDecl *Import); @@ -899,7 +911,7 @@ public: static ImportDecl *getNextLocalImport(ImportDecl *Import) { return Import->NextLocalImport; } - + typedef llvm::iterator_range<import_iterator> import_range; import_range local_imports() const { return import_range(import_iterator(FirstLocalImport), import_iterator()); @@ -973,7 +985,7 @@ public: CanQualType SingletonId; #include "clang/Basic/OpenCLImageTypes.def" CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy; - CanQualType OCLQueueTy, OCLNDRangeTy, OCLReserveIDTy; + CanQualType OCLQueueTy, OCLReserveIDTy; CanQualType OMPArraySectionTy; // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand. @@ -1179,15 +1191,15 @@ public: /// Returns true iff we need copy/dispose helpers for the given type. 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. + /// 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) @@ -1231,7 +1243,7 @@ public: QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals) const; - + /// \brief Returns a vla type where known sizes are replaced with [*]. QualType getVariableArrayDecayedType(QualType Ty) const; @@ -1355,6 +1367,8 @@ public: ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args) const; + TemplateArgument getInjectedTemplateArg(NamedDecl *ParamDecl); + /// Get a template argument list with one argument per template parameter /// in a template parameter list, such as for the injected class name of /// a class template. @@ -1380,7 +1394,7 @@ public: QualType getObjCTypeParamType(const ObjCTypeParamDecl *Decl, ArrayRef<ObjCProtocolDecl *> protocols, QualType Canonical = QualType()) const; - + bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl); /// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in /// QT's qualified-id protocol list adopt all protocols in IDecl's list @@ -1412,6 +1426,11 @@ public: /// \brief C++11 deduction pattern for 'auto &&' type. QualType getAutoRRefDeductType() const; + /// \brief C++1z deduced class template specialization type. + QualType getDeducedTemplateSpecializationType(TemplateName Template, + QualType DeducedType, + bool IsDependent) const; + /// \brief Return the unique reference to the type for the specified TagDecl /// (struct/union/class/enum) decl. QualType getTagDeclType(const TagDecl *Decl) const; @@ -1471,11 +1490,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 { @@ -1496,11 +1515,11 @@ public: QualType getObjCNSStringType() const { return ObjCNSStringType; } - + void setObjCNSStringType(QualType T) { ObjCNSStringType = T; } - + /// \brief Retrieve the type that \c id has been defined to, which may be /// different from the built-in \c id if \c id has been typedef'd. QualType getObjCIdRedefinitionType() const { @@ -1508,7 +1527,7 @@ public: return getObjCIdType(); return ObjCIdRedefinitionType; } - + /// \brief Set the user-written type that redefines \c id. void setObjCIdRedefinitionType(QualType RedefType) { ObjCIdRedefinitionType = RedefType; @@ -1521,7 +1540,7 @@ public: return getObjCClassType(); return ObjCClassRedefinitionType; } - + /// \brief Set the user-written type that redefines 'SEL'. void setObjCClassRedefinitionType(QualType RedefType) { ObjCClassRedefinitionType = RedefType; @@ -1534,7 +1553,7 @@ public: return getObjCSelType(); return ObjCSelRedefinitionType; } - + /// \brief Set the user-written type that redefines 'SEL'. void setObjCSelRedefinitionType(QualType RedefType) { ObjCSelRedefinitionType = RedefType; @@ -1586,7 +1605,7 @@ public: /// \brief Retrieve the typedef declaration corresponding to the Objective-C /// "instancetype" type. TypedefDecl *getObjCInstanceTypeDecl(); - + /// \brief Set the type for the C FILE type. void setFILEDecl(TypeDecl *FILEDecl) { this->FILEDecl = FILEDecl; } @@ -1671,7 +1690,7 @@ public: /// \brief Return the encoded type for this block declaration. std::string getObjCEncodingForBlock(const BlockExpr *blockExpr) const; - + /// getObjCEncodingForPropertyDecl - Return the encoded type for /// this method declaration. If non-NULL, Container must be either /// an ObjCCategoryImplDecl or ObjCImplementationDecl; it should @@ -1681,7 +1700,7 @@ public: bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, ObjCProtocolDecl *rProto) const; - + ObjCPropertyImplDecl *getObjCPropertyImplDeclForPropertyDecl( const ObjCPropertyDecl *PD, const Decl *Container) const; @@ -1693,7 +1712,7 @@ public: /// \brief Retrieve the typedef corresponding to the predefined \c id type /// in Objective-C. TypedefDecl *getObjCIdDecl() const; - + /// \brief Represents the Objective-CC \c id type. /// /// This is set up lazily, by Sema. \c id is always a (typedef for a) @@ -1705,26 +1724,26 @@ public: /// \brief Retrieve the typedef corresponding to the predefined 'SEL' type /// in Objective-C. TypedefDecl *getObjCSelDecl() const; - + /// \brief Retrieve the type that corresponds to the predefined Objective-C /// 'SEL' type. - QualType getObjCSelType() const { + QualType getObjCSelType() const { return getTypeDeclType(getObjCSelDecl()); } /// \brief Retrieve the typedef declaration corresponding to the predefined /// Objective-C 'Class' type. TypedefDecl *getObjCClassDecl() const; - + /// \brief Represents the Objective-C \c Class type. /// /// This is set up lazily, by Sema. \c Class is always a (typedef for a) /// pointer type, a pointer to a struct. - QualType getObjCClassType() const { + QualType getObjCClassType() const { return getTypeDeclType(getObjCClassDecl()); } - /// \brief Retrieve the Objective-C class declaration corresponding to + /// \brief Retrieve the Objective-C class declaration corresponding to /// the predefined \c Protocol class. ObjCInterfaceDecl *getObjCProtocolDecl() const; @@ -1742,12 +1761,12 @@ public: QualType getBOOLType() const { return getTypeDeclType(getBOOLDecl()); } - + /// \brief Retrieve the type of the Objective-C \c Protocol class. QualType getObjCProtoType() const { return getObjCInterfaceType(getObjCProtocolDecl()); } - + /// \brief Retrieve the C type declaration corresponding to the predefined /// \c __builtin_va_list type. TypedefDecl *getBuiltinVaListDecl() const; @@ -1810,7 +1829,7 @@ public: qs.addObjCLifetime(lifetime); return getQualifiedType(type, qs); } - + /// getUnqualifiedObjCPointerType - Returns version of /// Objective-C pointer type with lifetime qualifier removed. QualType getUnqualifiedObjCPointerType(QualType type) const { @@ -1821,7 +1840,7 @@ public: Qs.removeObjCLifetime(); return getQualifiedType(type.getUnqualifiedType(), Qs); } - + DeclarationNameInfo getNameForTemplate(TemplateName Name, SourceLocation NameLoc) const; @@ -1840,7 +1859,7 @@ public: TemplateName replacement) const; TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param, const TemplateArgument &ArgPack) const; - + enum GetBuiltinTypeError { GE_None, ///< No error GE_Missing_stdio, ///< Missing a type from <stdio.h> @@ -1905,7 +1924,7 @@ public: uint64_t getCharWidth() const { return getTypeSize(CharTy); } - + /// \brief Convert a size in bits to a size in characters. CharUnits toCharUnitsFromBits(int64_t BitSize) const; @@ -1927,11 +1946,11 @@ public: /// example, from alignment attributes). unsigned getTypeAlignIfKnown(QualType T) const; - /// \brief Return the ABI-specified alignment of a (complete) type \p T, in + /// \brief Return the ABI-specified alignment of a (complete) type \p T, in /// characters. CharUnits getTypeAlignInChars(QualType T) const; CharUnits getTypeAlignInChars(const Type *T) const; - + // getTypeInfoDataSizeInChars - Return the size of a type, in chars. If the // type is a record, its data size is returned. std::pair<CharUnits, CharUnits> getTypeInfoDataSizeInChars(QualType T) const; @@ -2036,10 +2055,10 @@ public: VTableContextBase *getVTableContext(); MangleContext *createMangleContext(); - + void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass, SmallVectorImpl<const ObjCIvarDecl*> &Ivars) const; - + unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI) const; void CollectInheritedProtocols(const Decl *CDecl, llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols); @@ -2115,7 +2134,7 @@ public: *SubTnullability == NullabilityKind::Unspecified || *SuperTnullability == NullabilityKind::Unspecified) return true; - + if (IsParam) { // Ok for the superclass method parameter to be "nonnull" and the subclass // method parameter to be "nullable" @@ -2134,9 +2153,9 @@ public: bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, const ObjCMethodDecl *MethodImp); - + bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2); - + /// \brief Retrieves the "canonical" nested name specifier for a /// given nested name specifier. /// @@ -2190,7 +2209,7 @@ public: /// \brief Determine whether the given template names refer to the same /// template. bool hasSameTemplateName(TemplateName X, TemplateName Y); - + /// \brief Retrieve the "canonical" template argument. /// /// The canonical template argument is the simplest template argument @@ -2217,7 +2236,7 @@ public: const { return dyn_cast_or_null<DependentSizedArrayType>(getAsArrayType(T)); } - + /// \brief Return the innermost element type of an array type. /// /// For example, will return "int" for int[m][n] @@ -2236,14 +2255,14 @@ public: /// parameter type used by semantic analysis (C99 6.7.5.3p[7,8], /// C++ [dcl.fct]p3). The adjusted parameter type is returned. QualType getAdjustedParameterType(QualType T) const; - + /// \brief Retrieve the parameter type as adjusted for use in the signature /// of a function, decaying array and function types and removing top-level /// cv-qualifiers. QualType getSignatureParameterType(QualType T) const; - + QualType getExceptionObjectType(QualType T) const; - + /// \brief Return the properly qualified result of decaying the specified /// array type to a pointer. /// @@ -2269,7 +2288,7 @@ public: /// promotion occurs. QualType isPromotableBitField(Expr *E) const; - /// \brief Return the highest ranked integer type, see C99 6.3.1.8p1. + /// \brief Return the highest ranked integer type, see C99 6.3.1.8p1. /// /// If \p LHS > \p RHS, returns 1. If \p LHS == \p RHS, returns 0. If /// \p LHS < \p RHS, return -1. @@ -2298,12 +2317,7 @@ public: return getTargetAddressSpace(Q.getAddressSpace()); } - unsigned getTargetAddressSpace(unsigned AS) const { - if (AS < LangAS::Offset || AS >= LangAS::Offset + LangAS::Count) - return AS; - else - return (*AddrSpaceMap)[AS - LangAS::Offset]; - } + unsigned getTargetAddressSpace(unsigned AS) const; /// Get target-dependent integer value for null pointer which is used for /// constant folding. @@ -2311,8 +2325,7 @@ public: bool addressSpaceMapManglingFor(unsigned AS) const { return AddrSpaceMapMangling || - AS < LangAS::Offset || - AS >= LangAS::Offset + LangAS::Count; + AS >= LangAS::Count; } private: @@ -2325,11 +2338,11 @@ public: //===--------------------------------------------------------------------===// /// Compatibility predicates used to check assignment expressions. - bool typesAreCompatible(QualType T1, QualType T2, + bool typesAreCompatible(QualType T1, QualType T2, bool CompareUnqualified = false); // C99 6.2.7p1 - bool propertyTypesAreCompatible(QualType, QualType); - bool typesAreBlockPointerCompatible(QualType, QualType); + bool propertyTypesAreCompatible(QualType, QualType); + bool typesAreBlockPointerCompatible(QualType, QualType); bool isObjCIdType(QualType T) const { return T == getObjCIdType(); @@ -2344,7 +2357,7 @@ public: bool ForCompare); bool ObjCQualifiedClassTypesAreCompatible(QualType LHS, QualType RHS); - + // Check the safety of assignment from LHS to RHS bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT); @@ -2370,9 +2383,9 @@ public: QualType mergeTransparentUnionType(QualType, QualType, bool OfBlockPointer=false, bool Unqualified = false); - + QualType mergeObjCGCQualifiers(QualType, QualType); - + bool doFunctionTypesMatchOnExtParameterInfos( const FunctionProtoType *FromFunctionType, const FunctionProtoType *ToFunctionType); @@ -2442,7 +2455,7 @@ public: /// an Objective-C method/property/ivar etc. that is part of an interface, /// otherwise returns null. const ObjCInterfaceDecl *getObjContainingInterface(const NamedDecl *ND) const; - + /// \brief Set the copy inialization expression of a block var decl. void setBlockVarCopyInits(VarDecl*VD, Expr* Init); /// \brief Get the copy initialization expression of the VarDecl \p VD, or @@ -2466,10 +2479,10 @@ public: /// initialized to a given location, which defaults to the empty /// location. TypeSourceInfo * - getTrivialTypeSourceInfo(QualType T, + getTrivialTypeSourceInfo(QualType T, SourceLocation Loc = SourceLocation()) const; - /// \brief Add a deallocation callback that will be invoked when the + /// \brief Add a deallocation callback that will be invoked when the /// ASTContext is destroyed. /// /// \param Callback A callback function that will be invoked on destruction. @@ -2478,6 +2491,16 @@ public: /// when it is called. void AddDeallocation(void (*Callback)(void*), void *Data); + /// If T isn't trivially destructible, calls AddDeallocation to register it + /// for destruction. + template <typename T> + void addDestruction(T *Ptr) { + if (!std::is_trivially_destructible<T>::value) { + auto DestroyPtr = [](void *V) { static_cast<T *>(V)->~T(); }; + AddDeallocation(DestroyPtr, Ptr); + } + } + GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const; GVALinkage GetGVALinkageForVariable(const VarDecl *VD); @@ -2534,15 +2557,15 @@ public: /// \brief The number of implicitly-declared default constructors. static unsigned NumImplicitDefaultConstructors; - - /// \brief The number of implicitly-declared default constructors for + + /// \brief The number of implicitly-declared default constructors for /// which declarations were built. static unsigned NumImplicitDefaultConstructorsDeclared; /// \brief The number of implicitly-declared copy constructors. static unsigned NumImplicitCopyConstructors; - - /// \brief The number of implicitly-declared copy constructors for + + /// \brief The number of implicitly-declared copy constructors for /// which declarations were built. static unsigned NumImplicitCopyConstructorsDeclared; @@ -2555,25 +2578,25 @@ public: /// \brief The number of implicitly-declared copy assignment operators. static unsigned NumImplicitCopyAssignmentOperators; - - /// \brief The number of implicitly-declared copy assignment operators for + + /// \brief The number of implicitly-declared copy assignment operators for /// which declarations were built. static unsigned NumImplicitCopyAssignmentOperatorsDeclared; /// \brief The number of implicitly-declared move assignment operators. static unsigned NumImplicitMoveAssignmentOperators; - - /// \brief The number of implicitly-declared move assignment operators for + + /// \brief The number of implicitly-declared move assignment operators for /// which declarations were built. static unsigned NumImplicitMoveAssignmentOperatorsDeclared; /// \brief The number of implicitly-declared destructors. static unsigned NumImplicitDestructors; - - /// \brief The number of implicitly-declared destructors for which + + /// \brief The number of implicitly-declared destructors for which /// declarations were built. static unsigned NumImplicitDestructorsDeclared; - + public: /// \brief Initialize built-in types. /// diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h index 9ae5fd62c65a..717a9e9dff34 100644 --- a/include/clang/AST/ASTVector.h +++ b/include/clang/AST/ASTVector.h @@ -22,6 +22,7 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/type_traits.h" #include <algorithm> +#include <cstddef> #include <cstring> #include <memory> diff --git a/include/clang/AST/BuiltinTypes.def b/include/clang/AST/BuiltinTypes.def index c0c6819280d2..181131aba07f 100644 --- a/include/clang/AST/BuiltinTypes.def +++ b/include/clang/AST/BuiltinTypes.def @@ -169,9 +169,6 @@ BUILTIN_TYPE(OCLClkEvent, OCLClkEventTy) // OpenCL queue_t. BUILTIN_TYPE(OCLQueue, OCLQueueTy) -// OpenCL ndrange_t. -BUILTIN_TYPE(OCLNDRange, OCLNDRangeTy) - // OpenCL reserve_id_t. BUILTIN_TYPE(OCLReserveID, OCLReserveIDTy) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 8b52891af2f8..ad723a3e2b8f 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -838,7 +838,7 @@ protected: /// Describes the kind of default argument for this parameter. By default /// this is none. If this is normal, then the default argument is stored in - /// the \c VarDecl initalizer expression unless we were unble to parse + /// the \c VarDecl initializer expression unless we were unable to parse /// (even an invalid) expression for the default argument. unsigned DefaultArgKind : 2; @@ -1605,9 +1605,14 @@ private: // FIXME: This can be packed into the bitfields in DeclContext. // NOTE: VC++ packs bitfields poorly if the types differ. - unsigned SClass : 2; + unsigned SClass : 3; unsigned IsInline : 1; unsigned IsInlineSpecified : 1; +protected: + // This is shared by CXXConstructorDecl, CXXConversionDecl, and + // CXXDeductionGuideDecl. + unsigned IsExplicitSpecified : 1; +private: unsigned IsVirtualAsWritten : 1; unsigned IsPure : 1; unsigned HasInheritedPrototype : 1; @@ -1708,8 +1713,9 @@ protected: StartLoc), DeclContext(DK), redeclarable_base(C), ParamInfo(nullptr), Body(), SClass(S), IsInline(isInlineSpecified), - IsInlineSpecified(isInlineSpecified), IsVirtualAsWritten(false), - IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), + IsInlineSpecified(isInlineSpecified), IsExplicitSpecified(false), + IsVirtualAsWritten(false), IsPure(false), + HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), IsDefaulted(false), IsExplicitlyDefaulted(false), HasImplicitReturnZero(false), IsLateTemplateParsed(false), IsConstexpr(isConstexprSpecified), @@ -2635,12 +2641,17 @@ class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> { typedef std::pair<TypeSourceInfo*, QualType> ModedTInfo; llvm::PointerUnion<TypeSourceInfo*, ModedTInfo*> MaybeModedTInfo; + // FIXME: This can be packed into the bitfields in Decl. + /// If 0, we have not computed IsTransparentTag. + /// Otherwise, IsTransparentTag is (CacheIsTransparentTag >> 1). + mutable unsigned CacheIsTransparentTag : 2; + protected: TypedefNameDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) : TypeDecl(DK, DC, IdLoc, Id, StartLoc), redeclarable_base(C), - MaybeModedTInfo(TInfo) {} + MaybeModedTInfo(TInfo), CacheIsTransparentTag(0) {} typedef Redeclarable<TypedefNameDecl> redeclarable_base; TypedefNameDecl *getNextRedeclarationImpl() override { @@ -2693,11 +2704,22 @@ public: /// this typedef declaration. TagDecl *getAnonDeclWithTypedefName(bool AnyRedecl = false) const; + /// Determines if this typedef shares a name and spelling location with its + /// underlying tag type, as is the case with the NS_ENUM macro. + bool isTransparentTag() const { + if (CacheIsTransparentTag) + return CacheIsTransparentTag & 0x2; + return isTransparentTagSlow(); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstTypedefName && K <= lastTypedefName; } + +private: + bool isTransparentTagSlow() const; }; /// TypedefDecl - Represents the declaration of a typedef-name via the 'typedef' @@ -3229,6 +3251,18 @@ public: return isCompleteDefinition() || isFixed(); } + /// Returns true if this enum is either annotated with + /// enum_extensibility(closed) or isn't annotated with enum_extensibility. + bool isClosed() const; + + /// Returns true if this enum is annotated with flag_enum and isn't annotated + /// with enum_extensibility(open). + bool isClosedFlag() const; + + /// Returns true if this enum is annotated with neither flag_enum nor + /// enum_extensibility(open). + bool isClosedNonFlag() const; + /// \brief Retrieve the enum definition from which this enumeration could /// be instantiated, if it is an instantiation (rather than a non-template). EnumDecl *getTemplateInstantiationPattern() const; diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 5de1d0588e80..c88cb6a8fd1e 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -654,20 +654,19 @@ public: /// a precompiled header or module) rather than having been parsed. bool isFromASTFile() const { return FromASTFile; } - /// \brief Retrieve the global declaration ID associated with this - /// declaration, which specifies where in the - unsigned getGlobalID() const { + /// \brief Retrieve the global declaration ID associated with this + /// declaration, which specifies where this Decl was loaded from. + unsigned getGlobalID() const { if (isFromASTFile()) return *((const unsigned*)this - 1); return 0; } - + /// \brief Retrieve the global ID of the module that owns this particular /// declaration. unsigned getOwningModuleID() const { if (isFromASTFile()) return *((const unsigned*)this - 2); - return 0; } @@ -1030,7 +1029,7 @@ public: void dump() const; // Same as dump(), but forces color printing. void dumpColor() const; - void dump(raw_ostream &Out) const; + void dump(raw_ostream &Out, bool Deserialize = false) const; /// \brief Looks through the Decl's underlying type to extract a FunctionType /// when possible. Will return null if the type underlying the Decl does not @@ -1811,7 +1810,8 @@ public: void dumpDeclContext() const; void dumpLookups() const; - void dumpLookups(llvm::raw_ostream &OS, bool DumpDecls = false) const; + void dumpLookups(llvm::raw_ostream &OS, bool DumpDecls = false, + bool Deserialize = false) const; private: void reconcileExternalVisibleStorage() const; diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 0ca08db16299..13921a132cfb 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -203,6 +203,11 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } + /// \brief Get the location at which the base class type was written. + SourceLocation getBaseTypeLoc() const LLVM_READONLY { + return BaseTypeInfo->getTypeLoc().getLocStart(); + } + /// \brief Determines whether the base class is a virtual base class (or not). bool isVirtual() const { return Virtual; } @@ -436,9 +441,10 @@ class CXXRecordDecl : public RecordDecl { /// either by the user or implicitly. unsigned DeclaredSpecialMembers : 6; - /// \brief Whether an implicit copy constructor would have a const-qualified - /// parameter. - unsigned ImplicitCopyConstructorHasConstParam : 1; + /// \brief Whether an implicit copy constructor could have a const-qualified + /// parameter, for initializing virtual bases and for other subobjects. + unsigned ImplicitCopyConstructorCanHaveConstParamForVBase : 1; + unsigned ImplicitCopyConstructorCanHaveConstParamForNonVBase : 1; /// \brief Whether an implicit copy assignment operator would have a /// const-qualified parameter. @@ -458,6 +464,11 @@ class CXXRecordDecl : public RecordDecl { /// \brief Whether we are currently parsing base specifiers. unsigned IsParsingBaseSpecifiers : 1; + unsigned HasODRHash : 1; + + /// \brief A hash of parts of the class to help in ODR checking. + unsigned ODRHash; + /// \brief The number of base class specifiers in Bases. unsigned NumBases; @@ -703,6 +714,8 @@ public: return data().IsParsingBaseSpecifiers; } + unsigned getODRHash() const; + /// \brief Sets the base classes of this struct or class. void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases); @@ -871,7 +884,9 @@ public: /// \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; + return data().ImplicitCopyConstructorCanHaveConstParamForNonVBase && + (isAbstract() || + data().ImplicitCopyConstructorCanHaveConstParamForVBase); } /// \brief Determine whether this class has a copy constructor with @@ -1738,6 +1753,58 @@ public: friend class ASTWriter; }; +/// \brief Represents a C++ deduction guide declaration. +/// +/// \code +/// template<typename T> struct A { A(); A(T); }; +/// A() -> A<int>; +/// \endcode +/// +/// In this example, there will be an explicit deduction guide from the +/// second line, and implicit deduction guide templates synthesized from +/// the constructors of \c A. +class CXXDeductionGuideDecl : public FunctionDecl { + void anchor() override; +private: + CXXDeductionGuideDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + bool IsExplicit, const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, + SourceLocation EndLocation) + : FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo, + SC_None, false, false) { + if (EndLocation.isValid()) + setRangeEnd(EndLocation); + IsExplicitSpecified = IsExplicit; + } + +public: + static CXXDeductionGuideDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, bool IsExplicit, + const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, + SourceLocation EndLocation); + + static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + /// Whether this deduction guide is explicit. + bool isExplicit() const { return IsExplicitSpecified; } + + /// Whether this deduction guide was declared with the 'explicit' specifier. + bool isExplicitSpecified() const { return IsExplicitSpecified; } + + /// Get the template for which this guide performs deduction. + TemplateDecl *getDeducedTemplate() const { + return getDeclName().getCXXDeductionGuideTemplate(); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == CXXDeductionGuide; } + + friend class ASTDeclReader; + friend class ASTDeclWriter; +}; + /// \brief Represents a static or instance method of a struct/union/class. /// /// In the terminology of the C++ Standard, these are the (static and @@ -2161,13 +2228,9 @@ class CXXConstructorDecl final /// \{ /// \brief The arguments used to initialize the base or member. LazyCXXCtorInitializersPtr CtorInitializers; - unsigned NumCtorInitializers : 30; + unsigned NumCtorInitializers : 31; /// \} - /// \brief Whether this constructor declaration has the \c explicit keyword - /// specified. - unsigned IsExplicitSpecified : 1; - /// \brief Whether this constructor declaration is an implicitly-declared /// inheriting constructor. unsigned IsInheritingConstructor : 1; @@ -2181,11 +2244,11 @@ class CXXConstructorDecl final : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, isConstexpr, SourceLocation()), CtorInitializers(nullptr), NumCtorInitializers(0), - IsExplicitSpecified(isExplicitSpecified), IsInheritingConstructor((bool)Inherited) { setImplicit(isImplicitlyDeclared); if (Inherited) *getTrailingObjects<InheritedConstructor>() = Inherited; + IsExplicitSpecified = isExplicitSpecified; } public: @@ -2198,15 +2261,6 @@ public: bool isConstexpr, InheritedConstructor Inherited = InheritedConstructor()); - /// \brief Determine whether this constructor declaration has the - /// \c explicit keyword specified. - bool isExplicitSpecified() const { return IsExplicitSpecified; } - - /// \brief Determine whether this constructor was marked "explicit" or not. - bool isExplicit() const { - return cast<CXXConstructorDecl>(getFirstDecl())->isExplicitSpecified(); - } - /// \brief Iterates through the member/base initializer list. typedef CXXCtorInitializer **init_iterator; @@ -2270,6 +2324,14 @@ public: CtorInitializers = Initializers; } + /// Whether this function is marked as explicit explicitly. + bool isExplicitSpecified() const { return IsExplicitSpecified; } + + /// Whether this function is explicit. + bool isExplicit() const { + return getCanonicalDecl()->isExplicitSpecified(); + } + /// \brief Determine whether this constructor is a delegating constructor. bool isDelegatingConstructor() const { return (getNumCtorInitializers() == 1) && @@ -2405,7 +2467,14 @@ public: void setOperatorDelete(FunctionDecl *OD); const FunctionDecl *getOperatorDelete() const { - return cast<CXXDestructorDecl>(getFirstDecl())->OperatorDelete; + return getCanonicalDecl()->OperatorDelete; + } + + CXXDestructorDecl *getCanonicalDecl() override { + return cast<CXXDestructorDecl>(FunctionDecl::getCanonicalDecl()); + } + const CXXDestructorDecl *getCanonicalDecl() const { + return const_cast<CXXDestructorDecl*>(this)->getCanonicalDecl(); } // Implement isa/cast/dyncast/etc. @@ -2428,19 +2497,16 @@ public: /// \endcode class CXXConversionDecl : public CXXMethodDecl { void anchor() override; - /// Whether this conversion function declaration is marked - /// "explicit", meaning that it can only be applied when the user - /// explicitly wrote a cast. This is a C++11 feature. - bool IsExplicitSpecified : 1; CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isExplicitSpecified, - bool isConstexpr, SourceLocation EndLocation) - : CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, isConstexpr, EndLocation), - IsExplicitSpecified(isExplicitSpecified) { } + const DeclarationNameInfo &NameInfo, QualType T, + TypeSourceInfo *TInfo, bool isInline, + bool isExplicitSpecified, bool isConstexpr, + SourceLocation EndLocation) + : CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo, + SC_None, isInline, isConstexpr, EndLocation) { + IsExplicitSpecified = isExplicitSpecified; + } public: static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, @@ -2452,17 +2518,12 @@ public: SourceLocation EndLocation); static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID); - /// Whether this conversion function declaration is marked - /// "explicit", meaning that it can only be used for direct initialization - /// (including explitly written casts). This is a C++11 feature. + /// Whether this function is marked as explicit explicitly. bool isExplicitSpecified() const { return IsExplicitSpecified; } - /// \brief Whether this is an explicit conversion operator (C++11 and later). - /// - /// Explicit conversion operators are only considered for direct - /// initialization, e.g., when the user has explicitly written a cast. + /// Whether this function is explicit. bool isExplicit() const { - return cast<CXXConversionDecl>(getFirstDecl())->isExplicitSpecified(); + return getCanonicalDecl()->isExplicitSpecified(); } /// \brief Returns the type that this conversion function is converting to. @@ -2474,6 +2535,13 @@ public: /// a lambda closure type to a block pointer. bool isLambdaToBlockPointerConversion() const; + CXXConversionDecl *getCanonicalDecl() override { + return cast<CXXConversionDecl>(FunctionDecl::getCanonicalDecl()); + } + const CXXConversionDecl *getCanonicalDecl() const { + return const_cast<CXXConversionDecl*>(this)->getCanonicalDecl(); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == CXXConversion; } diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index ff37758c2551..eb86526e8eca 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -131,7 +131,7 @@ public: } else { DeclsTy &Vec = *getAsVector(); Vec.erase(std::remove_if(Vec.begin(), Vec.end(), - std::mem_fun(&Decl::isFromASTFile)), + [](Decl *D) { return D->isFromASTFile(); }), Vec.end()); // Don't have any external decls any more. Data = DeclsAndHasExternalTy(&Vec, false); diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index f5098f06a9f6..26c0cbe82d17 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -381,15 +381,17 @@ public: ArrayRef<SourceLocation> SelLocs = llvm::None); // Iterator access to parameter types. - typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun; - typedef llvm::mapped_iterator<param_const_iterator, deref_fun> - param_type_iterator; + struct GetTypeFn { + QualType operator()(const ParmVarDecl *PD) const { return PD->getType(); } + }; + typedef llvm::mapped_iterator<param_const_iterator, GetTypeFn> + param_type_iterator; param_type_iterator param_type_begin() const { - return llvm::map_iterator(param_begin(), deref_fun(&ParmVarDecl::getType)); + return llvm::map_iterator(param_begin(), GetTypeFn()); } param_type_iterator param_type_end() const { - return llvm::map_iterator(param_end(), deref_fun(&ParmVarDecl::getType)); + return llvm::map_iterator(param_end(), GetTypeFn()); } /// createImplicitParams - Used to lazily create the self and cmd @@ -743,6 +745,8 @@ private: Selector GetterName; // getter name of NULL if no getter Selector SetterName; // setter name of NULL if no setter + SourceLocation GetterNameLoc; // location of the getter attribute's value + SourceLocation SetterNameLoc; // location of the setter attribute's value ObjCMethodDecl *GetterMethodDecl; // Declaration of getter instance method ObjCMethodDecl *SetterMethodDecl; // Declaration of setter instance method @@ -855,10 +859,18 @@ public: } Selector getGetterName() const { return GetterName; } - void setGetterName(Selector Sel) { GetterName = Sel; } + SourceLocation getGetterNameLoc() const { return GetterNameLoc; } + void setGetterName(Selector Sel, SourceLocation Loc = SourceLocation()) { + GetterName = Sel; + GetterNameLoc = Loc; + } Selector getSetterName() const { return SetterName; } - void setSetterName(Selector Sel) { SetterName = Sel; } + SourceLocation getSetterNameLoc() const { return SetterNameLoc; } + void setSetterName(Selector Sel, SourceLocation Loc = SourceLocation()) { + SetterName = Sel; + SetterNameLoc = Loc; + } ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; } void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; } @@ -2320,11 +2332,9 @@ class ObjCImplDecl : public ObjCContainerDecl { protected: ObjCImplDecl(Kind DK, DeclContext *DC, ObjCInterfaceDecl *classInterface, + IdentifierInfo *Id, SourceLocation nameLoc, SourceLocation atStartLoc) - : ObjCContainerDecl(DK, DC, - classInterface? classInterface->getIdentifier() - : nullptr, - nameLoc, atStartLoc), + : ObjCContainerDecl(DK, DC, Id, nameLoc, atStartLoc), ClassInterface(classInterface) {} public: @@ -2386,9 +2396,6 @@ public: class ObjCCategoryImplDecl : public ObjCImplDecl { void anchor() override; - // Category name - IdentifierInfo *Id; - // Category name location SourceLocation CategoryNameLoc; @@ -2396,8 +2403,9 @@ class ObjCCategoryImplDecl : public ObjCImplDecl { ObjCInterfaceDecl *classInterface, SourceLocation nameLoc, SourceLocation atStartLoc, SourceLocation CategoryNameLoc) - : ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, nameLoc, atStartLoc), - Id(Id), CategoryNameLoc(CategoryNameLoc) {} + : ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, Id, + nameLoc, atStartLoc), + CategoryNameLoc(CategoryNameLoc) {} public: static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, @@ -2407,37 +2415,10 @@ public: SourceLocation CategoryNameLoc); static ObjCCategoryImplDecl *CreateDeserialized(ASTContext &C, unsigned ID); - /// getIdentifier - Get the identifier that names the category - /// interface associated with this implementation. - /// FIXME: This is a bad API, we are hiding NamedDecl::getIdentifier() - /// with a different meaning. For example: - /// ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier() - /// returns the class interface name, whereas - /// ((ObjCCategoryImplDecl *)SomeCategoryImplDecl)->getIdentifier() - /// returns the category name. - IdentifierInfo *getIdentifier() const { - return Id; - } - void setIdentifier(IdentifierInfo *II) { Id = II; } - ObjCCategoryDecl *getCategoryDecl() const; SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; } - /// getName - Get the name of identifier for the class interface associated - /// with this implementation as a StringRef. - // - // FIXME: This is a bad API, we are hiding NamedDecl::getName with a different - // meaning. - StringRef getName() const { return Id ? Id->getName() : StringRef(); } - - /// @brief Get the name of the class associated with this interface. - // - // FIXME: Deprecated, move clients to getName(). - std::string getNameAsString() const { - return getName(); - } - static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCCategoryImpl;} @@ -2493,7 +2474,10 @@ class ObjCImplementationDecl : public ObjCImplDecl { SourceLocation superLoc = SourceLocation(), SourceLocation IvarLBraceLoc=SourceLocation(), SourceLocation IvarRBraceLoc=SourceLocation()) - : ObjCImplDecl(ObjCImplementation, DC, classInterface, nameLoc, atStartLoc), + : ObjCImplDecl(ObjCImplementation, DC, classInterface, + classInterface ? classInterface->getIdentifier() + : nullptr, + nameLoc, atStartLoc), SuperClass(superDecl), SuperLoc(superLoc), IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc), IvarInitializers(nullptr), NumIvarInitializers(0), diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index dc50a190de42..2879452f2404 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -344,6 +344,32 @@ public: // Kinds of Templates //===----------------------------------------------------------------------===// +/// \brief Stores the template parameter list and associated constraints for +/// \c TemplateDecl objects that track associated constraints. +class ConstrainedTemplateDeclInfo { + friend TemplateDecl; + +public: + ConstrainedTemplateDeclInfo() : TemplateParams(), AssociatedConstraints() {} + + TemplateParameterList *getTemplateParameters() const { + return TemplateParams; + } + + Expr *getAssociatedConstraints() const { return AssociatedConstraints; } + +protected: + void setTemplateParameters(TemplateParameterList *TParams) { + TemplateParams = TParams; + } + + void setAssociatedConstraints(Expr *AC) { AssociatedConstraints = AC; } + + TemplateParameterList *TemplateParams; + Expr *AssociatedConstraints; +}; + + /// \brief The base class of all kinds of template declarations (e.g., /// class, function, etc.). /// @@ -352,33 +378,53 @@ public: class TemplateDecl : public NamedDecl { void anchor() override; protected: - // This is probably never used. - TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name) + // Construct a template decl with the given name and parameters. + // Used when there is no templated element (e.g., for tt-params). + TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC, + SourceLocation L, DeclarationName Name, + TemplateParameterList *Params) : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr, false), - TemplateParams(nullptr) {} + TemplateParams(CTDI) { + this->setTemplateParameters(Params); + } - // Construct a template decl with the given name and parameters. - // Used when there is not templated element (tt-params). TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr, false), - TemplateParams(Params) {} + : TemplateDecl(nullptr, DK, DC, L, Name, Params) {} // Construct a template decl with name, parameters, and templated element. - TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC, + SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl, false), - TemplateParams(Params) {} + TemplateParams(CTDI) { + this->setTemplateParameters(Params); + } + + TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl) + : TemplateDecl(nullptr, DK, DC, L, Name, Params, Decl) {} public: /// Get the list of template parameters TemplateParameterList *getTemplateParameters() const { - return TemplateParams; + const auto *const CTDI = + TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>(); + return CTDI ? CTDI->getTemplateParameters() + : TemplateParams.get<TemplateParameterList *>(); } /// Get the constraint-expression from the associated requires-clause (if any) const Expr *getRequiresClause() const { - return TemplateParams ? TemplateParams->getRequiresClause() : nullptr; + const TemplateParameterList *const TP = getTemplateParameters(); + return TP ? TP->getRequiresClause() : nullptr; + } + + Expr *getAssociatedConstraints() const { + const TemplateDecl *const C = cast<TemplateDecl>(getCanonicalDecl()); + const auto *const CTDI = + C->TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>(); + return CTDI ? CTDI->getAssociatedConstraints() : nullptr; } /// Get the underlying, templated declaration. @@ -391,7 +437,7 @@ public: } SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(TemplateParams->getTemplateLoc(), + return SourceRange(getTemplateParameters()->getTemplateLoc(), TemplatedDecl.getPointer()->getSourceRange().getEnd()); } @@ -407,7 +453,29 @@ protected: /// (function or variable) is a concept. llvm::PointerIntPair<NamedDecl *, 1, bool> TemplatedDecl; - TemplateParameterList* TemplateParams; + /// \brief The template parameter list and optional requires-clause + /// associated with this declaration; alternatively, a + /// \c ConstrainedTemplateDeclInfo if the associated constraints of the + /// template are being tracked by this particular declaration. + llvm::PointerUnion<TemplateParameterList *, + ConstrainedTemplateDeclInfo *> + TemplateParams; + + void setTemplateParameters(TemplateParameterList *TParams) { + if (auto *const CTDI = + TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>()) { + CTDI->setTemplateParameters(TParams); + } else { + TemplateParams = TParams; + } + } + + void setAssociatedConstraints(Expr *AC) { + assert(isCanonicalDecl() && + "Attaching associated constraints to non-canonical Decl"); + TemplateParams.get<ConstrainedTemplateDeclInfo *>() + ->setAssociatedConstraints(AC); + } public: /// \brief Initialize the underlying templated declaration and @@ -737,11 +805,17 @@ protected: virtual CommonBase *newCommon(ASTContext &C) const = 0; // Construct a template decl with name, parameters, and templated element. + RedeclarableTemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, + ASTContext &C, DeclContext *DC, SourceLocation L, + DeclarationName Name, TemplateParameterList *Params, + NamedDecl *Decl) + : TemplateDecl(CTDI, DK, DC, L, Name, Params, Decl), redeclarable_base(C), + Common() {} + RedeclarableTemplateDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) - : TemplateDecl(DK, DC, L, Name, Params, Decl), redeclarable_base(C), - Common() {} + : RedeclarableTemplateDecl(nullptr, DK, C, DC, L, Name, Params, Decl) {} public: template <class decl_type> friend class RedeclarableTemplate; @@ -863,8 +937,6 @@ SpecEntryTraits<FunctionTemplateSpecializationInfo> { /// Declaration of a template function. class FunctionTemplateDecl : public RedeclarableTemplateDecl { - static void DeallocateCommon(void *Ptr); - protected: /// \brief Data that is common to all of the declarations of a given /// function template. @@ -1407,7 +1479,9 @@ public: unsigned NumExpansions); using TemplateParmPosition::getDepth; + using TemplateParmPosition::setDepth; using TemplateParmPosition::getPosition; + using TemplateParmPosition::setPosition; using TemplateParmPosition::getIndex; /// \brief Whether this template template parameter is a template @@ -1960,8 +2034,6 @@ public: /// Declaration of a class template. class ClassTemplateDecl : public RedeclarableTemplateDecl { - static void DeallocateCommon(void *Ptr); - protected: /// \brief Data that is common to all of the declarations of a given /// class template. @@ -1997,10 +2069,16 @@ protected: llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> & getPartialSpecializations(); + ClassTemplateDecl(ConstrainedTemplateDeclInfo *CTDI, ASTContext &C, + DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl) + : RedeclarableTemplateDecl(CTDI, ClassTemplate, C, DC, L, Name, Params, + Decl) {} + ClassTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) - : RedeclarableTemplateDecl(ClassTemplate, C, DC, L, Name, Params, Decl) {} + : ClassTemplateDecl(nullptr, C, DC, L, Name, Params, Decl) {} CommonBase *newCommon(ASTContext &C) const override; @@ -2023,12 +2101,14 @@ public: return getTemplatedDecl()->isThisDeclarationADefinition(); } + // FIXME: remove default argument for AssociatedConstraints /// \brief Create a class template node. static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl); + NamedDecl *Decl, + Expr *AssociatedConstraints = nullptr); /// \brief Create an empty class template node. static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -2247,8 +2327,6 @@ public: /// template \<typename T> using V = std::map<T*, int, MyCompare<T>>; /// \endcode class TypeAliasTemplateDecl : public RedeclarableTemplateDecl { - static void DeallocateCommon(void *Ptr); - protected: typedef CommonBase Common; @@ -2773,8 +2851,6 @@ public: /// Declaration of a variable template. class VarTemplateDecl : public RedeclarableTemplateDecl { - static void DeallocateCommon(void *Ptr); - protected: /// \brief Data that is common to all of the declarations of a given /// variable template. @@ -2946,6 +3022,16 @@ inline NamedDecl *getAsNamedDecl(TemplateParameter P) { return P.get<TemplateTemplateParmDecl*>(); } +inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) { + auto *TD = dyn_cast<TemplateDecl>(D); + return TD && (isa<ClassTemplateDecl>(TD) || + isa<ClassTemplatePartialSpecializationDecl>(TD) || + isa<TypeAliasTemplateDecl>(TD) || + isa<TemplateTemplateParmDecl>(TD)) + ? TD + : nullptr; +} + } /* end of namespace clang */ #endif diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 2d3cfe27a165..5e773c968384 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -23,6 +23,7 @@ namespace llvm { namespace clang { class ASTContext; + class CXXDeductionGuideNameExtra; class CXXLiteralOperatorIdName; class CXXOperatorIdName; class CXXSpecialName; @@ -32,6 +33,7 @@ namespace clang { enum OverloadedOperatorKind : int; struct PrintingPolicy; class QualType; + class TemplateDecl; class Type; class TypeSourceInfo; class UsingDirectiveDecl; @@ -56,6 +58,7 @@ public: CXXConstructorName, CXXDestructorName, CXXConversionFunctionName, + CXXDeductionGuideName, CXXOperatorName, CXXLiteralOperatorName, CXXUsingDirective @@ -118,42 +121,36 @@ private: CXXSpecialName *getAsCXXSpecialName() const { NameKind Kind = getNameKind(); if (Kind >= CXXConstructorName && Kind <= CXXConversionFunctionName) - return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask); + return reinterpret_cast<CXXSpecialName *>(getExtra()); + return nullptr; + } + + /// If the stored pointer is actually a CXXDeductionGuideNameExtra, returns a + /// pointer to it. Otherwise, returns a NULL pointer. + CXXDeductionGuideNameExtra *getAsCXXDeductionGuideNameExtra() const { + if (getNameKind() == CXXDeductionGuideName) + return reinterpret_cast<CXXDeductionGuideNameExtra *>(getExtra()); return nullptr; } /// getAsCXXOperatorIdName CXXOperatorIdName *getAsCXXOperatorIdName() const { if (getNameKind() == CXXOperatorName) - return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask); + return reinterpret_cast<CXXOperatorIdName *>(getExtra()); return nullptr; } CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const { if (getNameKind() == CXXLiteralOperatorName) - return reinterpret_cast<CXXLiteralOperatorIdName *>(Ptr & ~PtrMask); + return reinterpret_cast<CXXLiteralOperatorIdName *>(getExtra()); return nullptr; } // Construct a declaration name from the name of a C++ constructor, // destructor, or conversion function. - DeclarationName(CXXSpecialName *Name) - : Ptr(reinterpret_cast<uintptr_t>(Name)) { - assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXSpecialName"); - Ptr |= StoredDeclarationNameExtra; - } - - // Construct a declaration name from the name of a C++ overloaded - // operator. - DeclarationName(CXXOperatorIdName *Name) + DeclarationName(DeclarationNameExtra *Name) : Ptr(reinterpret_cast<uintptr_t>(Name)) { - assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXOperatorId"); - Ptr |= StoredDeclarationNameExtra; - } - - DeclarationName(CXXLiteralOperatorIdName *Name) - : Ptr(reinterpret_cast<uintptr_t>(Name)) { - assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXLiteralOperatorId"); + assert((Ptr & PtrMask) == 0 && "Improperly aligned DeclarationNameExtra"); Ptr |= StoredDeclarationNameExtra; } @@ -252,6 +249,10 @@ public: /// type associated with that name. QualType getCXXNameType() const; + /// If this name is the name of a C++ deduction guide, return the + /// template associated with that name. + TemplateDecl *getCXXDeductionGuideTemplate() const; + /// getCXXOverloadedOperator - If this name is the name of an /// overloadable operator in C++ (e.g., @c operator+), retrieve the /// kind of overloaded operator. @@ -346,6 +347,7 @@ class DeclarationNameTable { void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> * CXXOperatorIdName *CXXOperatorNames; // Operator names void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName* + void *CXXDeductionGuideNames; // FoldingSet<CXXDeductionGuideNameExtra> * DeclarationNameTable(const DeclarationNameTable&) = delete; void operator=(const DeclarationNameTable&) = delete; @@ -368,6 +370,9 @@ public: /// for the given Type. DeclarationName getCXXDestructorName(CanQualType Ty); + /// Returns the name of a C++ deduction guide for the given template. + DeclarationName getCXXDeductionGuideName(TemplateDecl *TD); + /// getCXXConversionFunctionName - Returns the name of a C++ /// conversion function for the given Type. DeclarationName getCXXConversionFunctionName(CanQualType Ty); diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 56b99ccd8971..986145e62a52 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -115,6 +115,7 @@ protected: ExprBits.InstantiationDependent = ID; ExprBits.ValueKind = VK; ExprBits.ObjectKind = OK; + assert(ExprBits.ObjectKind == OK && "truncated kind"); ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; setType(T); } @@ -907,6 +908,10 @@ public: return child_range(child_iterator(), child_iterator()); } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + /// The source expression of an opaque value expression is the /// expression which originally generated the value. This is /// provided as a convenience for analyses that don't wish to @@ -1167,6 +1172,10 @@ public: return child_range(child_iterator(), child_iterator()); } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + friend TrailingObjects; friend class ASTStmtReader; friend class ASTStmtWriter; @@ -1222,6 +1231,9 @@ public: // Iterators child_range children() { return child_range(&FnName, &FnName + 1); } + const_child_range children() const { + return const_child_range(&FnName, &FnName + 1); + } friend class ASTStmtReader; }; @@ -1315,6 +1327,9 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; class CharacterLiteral : public Expr { @@ -1365,6 +1380,9 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; class FloatingLiteral : public Expr, private APFloatStorage { @@ -1429,6 +1447,9 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; /// ImaginaryLiteral - We support imaginary integer and floating point literals, @@ -1461,6 +1482,9 @@ public: // Iterators child_range children() { return child_range(&Val, &Val+1); } + const_child_range children() const { + return const_child_range(&Val, &Val + 1); + } }; /// StringLiteral - This represents a string literal expression, e.g. "foo" @@ -1628,6 +1652,9 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; /// ParenExpr - This represents a parethesized expression, e.g. "(1)". This @@ -1669,6 +1696,9 @@ public: // Iterators child_range children() { return child_range(&Val, &Val+1); } + const_child_range children() const { + return const_child_range(&Val, &Val + 1); + } }; /// UnaryOperator - This represents the unary-expression's (except sizeof and @@ -1778,6 +1808,9 @@ public: // Iterators child_range children() { return child_range(&Val, &Val+1); } + const_child_range children() const { + return const_child_range(&Val, &Val + 1); + } }; /// Helper class for OffsetOfExpr. @@ -1981,6 +2014,11 @@ public: Stmt **begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>()); return child_range(begin, begin + NumExprs); } + const_child_range children() const { + Stmt *const *begin = + reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>()); + return const_child_range(begin, begin + NumExprs); + } friend TrailingObjects; }; @@ -2069,6 +2107,7 @@ public: // Iterators child_range children(); + const_child_range children() const; }; //===----------------------------------------------------------------------===// @@ -2153,6 +2192,9 @@ public: child_range children() { return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); } + const_child_range children() const { + return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR); + } }; /// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]). @@ -2313,6 +2355,11 @@ public: return child_range(&SubExprs[0], &SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START); } + + const_child_range children() const { + return const_child_range(&SubExprs[0], &SubExprs[0] + NumArgs + + getNumPreArgs() + PREARGS_START); + } }; /// Extra data stored in some MemberExpr objects. @@ -2567,6 +2614,9 @@ public: // Iterators child_range children() { return child_range(&Base, &Base+1); } + const_child_range children() const { + return const_child_range(&Base, &Base + 1); + } friend TrailingObjects; friend class ASTReader; @@ -2639,6 +2689,9 @@ public: // Iterators child_range children() { return child_range(&Init, &Init+1); } + const_child_range children() const { + return const_child_range(&Init, &Init + 1); + } }; /// CastExpr - Base class for type casts, including both implicit @@ -2725,6 +2778,7 @@ public: // Iterators child_range children() { return child_range(&Op, &Op+1); } + const_child_range children() const { return const_child_range(&Op, &Op + 1); } }; /// ImplicitCastExpr - Allows us to explicitly represent implicit type @@ -2917,11 +2971,9 @@ public: private: unsigned Opc : 6; - // Records the FP_CONTRACT pragma status at the point that this binary - // operator was parsed. This bit is only meaningful for operations on - // floating point types. For all other types it should default to - // false. - unsigned FPContractable : 1; + // This is only meaningful for operations on floating point types and 0 + // otherwise. + unsigned FPFeatures : 2; SourceLocation OpLoc; enum { LHS, RHS, END_EXPR }; @@ -2930,7 +2982,7 @@ public: BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, - SourceLocation opLoc, bool fpContractable) + SourceLocation opLoc, FPOptions FPFeatures) : Expr(BinaryOperatorClass, ResTy, VK, OK, lhs->isTypeDependent() || rhs->isTypeDependent(), lhs->isValueDependent() || rhs->isValueDependent(), @@ -2938,7 +2990,7 @@ public: rhs->isInstantiationDependent()), (lhs->containsUnexpandedParameterPack() || rhs->containsUnexpandedParameterPack())), - Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) { + Opc(opc), FPFeatures(FPFeatures.getInt()), OpLoc(opLoc) { SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; assert(!isCompoundAssignmentOp() && @@ -3070,19 +3122,26 @@ public: child_range children() { return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); } + const_child_range children() const { + return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR); + } // Set the FP contractability status of this operator. Only meaningful for // operations on floating point types. - void setFPContractable(bool FPC) { FPContractable = FPC; } + void setFPFeatures(FPOptions F) { FPFeatures = F.getInt(); } + + FPOptions getFPFeatures() const { return FPOptions(FPFeatures); } // Get the FP contractability status of this operator. Only meaningful for // operations on floating point types. - bool isFPContractable() const { return FPContractable; } + bool isFPContractableWithinStatement() const { + return FPOptions(FPFeatures).allowFPContractWithinStatement(); + } protected: BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, - SourceLocation opLoc, bool fpContractable, bool dead2) + SourceLocation opLoc, FPOptions FPFeatures, bool dead2) : Expr(CompoundAssignOperatorClass, ResTy, VK, OK, lhs->isTypeDependent() || rhs->isTypeDependent(), lhs->isValueDependent() || rhs->isValueDependent(), @@ -3090,7 +3149,7 @@ protected: rhs->isInstantiationDependent()), (lhs->containsUnexpandedParameterPack() || rhs->containsUnexpandedParameterPack())), - Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) { + Opc(opc), FPFeatures(FPFeatures.getInt()), OpLoc(opLoc) { SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; } @@ -3112,8 +3171,8 @@ public: CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType, ExprValueKind VK, ExprObjectKind OK, QualType CompLHSType, QualType CompResultType, - SourceLocation OpLoc, bool fpContractable) - : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, fpContractable, + SourceLocation OpLoc, FPOptions FPFeatures) + : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, FPFeatures, true), ComputationLHSType(CompLHSType), ComputationResultType(CompResultType) { @@ -3246,6 +3305,9 @@ public: child_range children() { return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); } + const_child_range children() const { + return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR); + } }; /// BinaryConditionalOperator - The GNU extension to the conditional @@ -3331,6 +3393,9 @@ public: child_range children() { return child_range(SubExprs, SubExprs + NUM_SUBEXPRS); } + const_child_range children() const { + return const_child_range(SubExprs, SubExprs + NUM_SUBEXPRS); + } }; inline Expr *AbstractConditionalOperator::getCond() const { @@ -3385,6 +3450,9 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; /// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}). @@ -3427,6 +3495,9 @@ public: // Iterators child_range children() { return child_range(&SubStmt, &SubStmt+1); } + const_child_range children() const { + return const_child_range(&SubStmt, &SubStmt + 1); + } }; /// ShuffleVectorExpr - clang-specific builtin-in function @@ -3495,6 +3566,9 @@ public: child_range children() { return child_range(&SubExprs[0], &SubExprs[0]+NumExprs); } + const_child_range children() const { + return const_child_range(&SubExprs[0], &SubExprs[0] + NumExprs); + } }; /// ConvertVectorExpr - Clang builtin function __builtin_convertvector @@ -3549,6 +3623,9 @@ public: // Iterators child_range children() { return child_range(&SrcExpr, &SrcExpr+1); } + const_child_range children() const { + return const_child_range(&SrcExpr, &SrcExpr + 1); + } }; /// ChooseExpr - GNU builtin-in function __builtin_choose_expr. @@ -3629,6 +3706,9 @@ public: child_range children() { return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); } + const_child_range children() const { + return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR); + } }; /// GNUNullExpr - Implements the GNU __null extension, which is a name @@ -3665,6 +3745,9 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; /// Represents a call to the builtin function \c __builtin_va_arg. @@ -3712,6 +3795,9 @@ public: // Iterators child_range children() { return child_range(&Val, &Val+1); } + const_child_range children() const { + return const_child_range(&Val, &Val + 1); + } }; /// @brief Describes an C or C++ initializer list. @@ -3936,10 +4022,16 @@ public: // Iterators child_range children() { + const_child_range CCR = const_cast<const InitListExpr *>(this)->children(); + return child_range(cast_away_const(CCR.begin()), + cast_away_const(CCR.end())); + } + + const_child_range children() const { // FIXME: This does not include the array filler expression. if (InitExprs.empty()) - return child_range(child_iterator(), child_iterator()); - return child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size()); + return const_child_range(const_child_iterator(), const_child_iterator()); + return const_child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size()); } typedef InitExprsTy::iterator iterator; @@ -4254,6 +4346,10 @@ public: Stmt **begin = getTrailingObjects<Stmt *>(); return child_range(begin, begin + NumSubExprs); } + const_child_range children() const { + Stmt * const *begin = getTrailingObjects<Stmt *>(); + return const_child_range(begin, begin + NumSubExprs); + } friend TrailingObjects; }; @@ -4287,6 +4383,9 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; // In cases like: @@ -4332,6 +4431,10 @@ public: child_range children() { return child_range(&BaseAndUpdaterExprs[0], &BaseAndUpdaterExprs[0] + 2); } + const_child_range children() const { + return const_child_range(&BaseAndUpdaterExprs[0], + &BaseAndUpdaterExprs[0] + 2); + } }; /// \brief Represents a loop initializing the elements of an array. @@ -4393,6 +4496,9 @@ public: child_range children() { return child_range(SubExprs, SubExprs + 2); } + const_child_range children() const { + return const_child_range(SubExprs, SubExprs + 2); + } friend class ASTReader; friend class ASTStmtReader; @@ -4421,6 +4527,9 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } friend class ASTReader; friend class ASTStmtReader; @@ -4455,6 +4564,9 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; class ParenListExpr : public Expr { @@ -4501,6 +4613,9 @@ public: child_range children() { return child_range(&Exprs[0], &Exprs[0]+NumExprs); } + const_child_range children() const { + return const_child_range(&Exprs[0], &Exprs[0] + NumExprs); + } friend class ASTStmtReader; friend class ASTStmtWriter; @@ -4621,7 +4736,9 @@ public: child_range children() { return child_range(SubExprs, SubExprs+END_EXPR+NumAssocs); } - + const_child_range children() const { + return const_child_range(SubExprs, SubExprs + END_EXPR + NumAssocs); + } friend class ASTStmtReader; }; @@ -4690,6 +4807,9 @@ public: // Iterators child_range children() { return child_range(&Base, &Base+1); } + const_child_range children() const { + return const_child_range(&Base, &Base + 1); + } }; /// BlockExpr - Adaptor class for mixing a BlockDecl with expressions. @@ -4731,6 +4851,9 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; /// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2] @@ -4776,6 +4899,9 @@ public: // Iterators child_range children() { return child_range(&SrcExpr, &SrcExpr+1); } + const_child_range children() const { + return const_child_range(&SrcExpr, &SrcExpr + 1); + } }; /// PseudoObjectExpr - An expression which accesses a pseudo-object @@ -4914,8 +5040,15 @@ public: } child_range children() { - Stmt **cs = reinterpret_cast<Stmt**>(getSubExprsBuffer()); - return child_range(cs, cs + getNumSubExprs()); + const_child_range CCR = + const_cast<const PseudoObjectExpr *>(this)->children(); + return child_range(cast_away_const(CCR.begin()), + cast_away_const(CCR.end())); + } + const_child_range children() const { + Stmt *const *cs = const_cast<Stmt *const *>( + reinterpret_cast<const Stmt *const *>(getSubExprsBuffer())); + return const_child_range(cs, cs + getNumSubExprs()); } static bool classof(const Stmt *T) { @@ -5021,6 +5154,9 @@ public: child_range children() { return child_range(SubExprs, SubExprs+NumSubExprs); } + const_child_range children() const { + return const_child_range(SubExprs, SubExprs + NumSubExprs); + } }; /// TypoExpr - Internal placeholder for expressions where typo correction @@ -5039,6 +5175,10 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 37e59771a723..79d2c58099c4 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -54,18 +54,16 @@ class CXXOperatorCallExpr : public CallExpr { OverloadedOperatorKind Operator; SourceRange Range; - // Record the FP_CONTRACT state that applies to this operator call. Only - // meaningful for floating point types. For other types this value can be - // set to false. - unsigned FPContractable : 1; + // Only meaningful for floating point types. + FPOptions FPFeatures; SourceRange getSourceRangeImpl() const LLVM_READONLY; public: CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn, ArrayRef<Expr*> args, QualType t, ExprValueKind VK, - SourceLocation operatorloc, bool fpContractable) + SourceLocation operatorloc, FPOptions FPFeatures) : CallExpr(C, CXXOperatorCallExprClass, fn, args, t, VK, operatorloc), - Operator(Op), FPContractable(fpContractable) { + Operator(Op), FPFeatures(FPFeatures) { Range = getSourceRangeImpl(); } explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) : @@ -113,11 +111,15 @@ public: // Set the FP contractability status of this operator. Only meaningful for // operations on floating point types. - void setFPContractable(bool FPC) { FPContractable = FPC; } + void setFPFeatures(FPOptions F) { FPFeatures = F; } + + FPOptions getFPFeatures() const { return FPFeatures; } // Get the FP contractability status of this operator. Only meaningful for // operations on floating point types. - bool isFPContractable() const { return FPContractable; } + bool isFPContractableWithinStatement() const { + return FPFeatures.allowFPContractWithinStatement(); + } friend class ASTStmtReader; friend class ASTStmtWriter; @@ -1470,7 +1472,8 @@ class CXXTemporaryObjectExpr : public CXXConstructExpr { public: CXXTemporaryObjectExpr(const ASTContext &C, CXXConstructorDecl *Cons, - TypeSourceInfo *Type, + QualType Type, + TypeSourceInfo *TSI, ArrayRef<Expr *> Args, SourceRange ParenOrBraceRange, bool HadMultipleCandidates, @@ -4122,16 +4125,18 @@ class CoroutineSuspendExpr : public Expr { enum SubExpr { Common, Ready, Suspend, Resume, Count }; Stmt *SubExprs[SubExpr::Count]; + OpaqueValueExpr *OpaqueValue = nullptr; friend class ASTStmtReader; public: CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Common, - Expr *Ready, Expr *Suspend, Expr *Resume) + Expr *Ready, Expr *Suspend, Expr *Resume, + OpaqueValueExpr *OpaqueValue) : Expr(SC, Resume->getType(), Resume->getValueKind(), Resume->getObjectKind(), Resume->isTypeDependent(), Resume->isValueDependent(), Common->isInstantiationDependent(), Common->containsUnexpandedParameterPack()), - KeywordLoc(KeywordLoc) { + KeywordLoc(KeywordLoc), OpaqueValue(OpaqueValue) { SubExprs[SubExpr::Common] = Common; SubExprs[SubExpr::Ready] = Ready; SubExprs[SubExpr::Suspend] = Suspend; @@ -4160,6 +4165,8 @@ public: Expr *getCommonExpr() const { return static_cast<Expr*>(SubExprs[SubExpr::Common]); } + /// \brief getOpaqueValue - Return the opaque value placeholder. + OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; } Expr *getReadyExpr() const { return static_cast<Expr*>(SubExprs[SubExpr::Ready]); @@ -4193,11 +4200,17 @@ class CoawaitExpr : public CoroutineSuspendExpr { friend class ASTStmtReader; public: CoawaitExpr(SourceLocation CoawaitLoc, Expr *Operand, Expr *Ready, - Expr *Suspend, Expr *Resume) + Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue, + bool IsImplicit = false) : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Operand, Ready, - Suspend, Resume) {} - CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand) - : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand) {} + Suspend, Resume, OpaqueValue) { + CoawaitBits.IsImplicit = IsImplicit; + } + CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand, + bool IsImplicit = false) + : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand) { + CoawaitBits.IsImplicit = IsImplicit; + } CoawaitExpr(EmptyShell Empty) : CoroutineSuspendExpr(CoawaitExprClass, Empty) {} @@ -4206,19 +4219,67 @@ public: return getCommonExpr(); } + bool isImplicit() const { return CoawaitBits.IsImplicit; } + void setIsImplicit(bool value = true) { CoawaitBits.IsImplicit = value; } + static bool classof(const Stmt *T) { return T->getStmtClass() == CoawaitExprClass; } }; +/// \brief Represents a 'co_await' expression while the type of the promise +/// is dependent. +class DependentCoawaitExpr : public Expr { + SourceLocation KeywordLoc; + Stmt *SubExprs[2]; + + friend class ASTStmtReader; + +public: + DependentCoawaitExpr(SourceLocation KeywordLoc, QualType Ty, Expr *Op, + UnresolvedLookupExpr *OpCoawait) + : Expr(DependentCoawaitExprClass, Ty, VK_RValue, OK_Ordinary, + /*TypeDependent*/ true, /*ValueDependent*/ true, + /*InstantiationDependent*/ true, + Op->containsUnexpandedParameterPack()), + KeywordLoc(KeywordLoc) { + // NOTE: A co_await expression is dependent on the coroutines promise + // type and may be dependent even when the `Op` expression is not. + assert(Ty->isDependentType() && + "wrong constructor for non-dependent co_await/co_yield expression"); + SubExprs[0] = Op; + SubExprs[1] = OpCoawait; + } + + DependentCoawaitExpr(EmptyShell Empty) + : Expr(DependentCoawaitExprClass, Empty) {} + + Expr *getOperand() const { return cast<Expr>(SubExprs[0]); } + UnresolvedLookupExpr *getOperatorCoawaitLookup() const { + return cast<UnresolvedLookupExpr>(SubExprs[1]); + } + SourceLocation getKeywordLoc() const { return KeywordLoc; } + + SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + return getOperand()->getLocEnd(); + } + + child_range children() { return child_range(SubExprs, SubExprs + 2); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == DependentCoawaitExprClass; + } +}; + /// \brief Represents a 'co_yield' expression. class CoyieldExpr : public CoroutineSuspendExpr { friend class ASTStmtReader; public: CoyieldExpr(SourceLocation CoyieldLoc, Expr *Operand, Expr *Ready, - Expr *Suspend, Expr *Resume) + Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue) : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Operand, Ready, - Suspend, Resume) {} + Suspend, Resume, OpaqueValue) {} CoyieldExpr(SourceLocation CoyieldLoc, QualType Ty, Expr *Operand) : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Ty, Operand) {} CoyieldExpr(EmptyShell Empty) diff --git a/include/clang/AST/ExternalASTMerger.h b/include/clang/AST/ExternalASTMerger.h new file mode 100644 index 000000000000..51d0c30ad23b --- /dev/null +++ b/include/clang/AST/ExternalASTMerger.h @@ -0,0 +1,51 @@ +//===--- ExternalASTMerger.h - Merging External AST 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 declares the ExternalASTMerger, which vends a combination of ASTs +// from several different ASTContext/FileManager pairs +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_EXTERNALASTMERGER_H +#define LLVM_CLANG_AST_EXTERNALASTMERGER_H + +#include "clang/AST/ASTImporter.h" +#include "clang/AST/ExternalASTSource.h" + +namespace clang { + +class ExternalASTMerger : public ExternalASTSource { +public: + struct ImporterPair { + std::unique_ptr<ASTImporter> Forward; + std::unique_ptr<ASTImporter> Reverse; + }; + +private: + std::vector<ImporterPair> Importers; + +public: + struct ImporterEndpoint { + ASTContext &AST; + FileManager &FM; + }; + ExternalASTMerger(const ImporterEndpoint &Target, + llvm::ArrayRef<ImporterEndpoint> Sources); + + bool FindExternalVisibleDeclsByName(const DeclContext *DC, + DeclarationName Name) override; + + void + FindExternalLexicalDecls(const DeclContext *DC, + llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, + SmallVectorImpl<Decl *> &Result) override; +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 2e99f395f495..d8dd18ecb8d3 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -16,6 +16,7 @@ #include "clang/AST/CharUnits.h" #include "clang/AST/DeclBase.h" +#include "clang/Basic/Module.h" #include "llvm/ADT/DenseMap.h" namespace clang { @@ -149,26 +150,30 @@ public: StringRef PCHModuleName; StringRef Path; StringRef ASTFile; - uint64_t Signature = 0; + ASTFileSignature Signature; const Module *ClangModule = nullptr; public: ASTSourceDescriptor(){}; ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile, - uint64_t Signature) + ASTFileSignature Signature) : PCHModuleName(std::move(Name)), Path(std::move(Path)), ASTFile(std::move(ASTFile)), Signature(Signature){}; ASTSourceDescriptor(const Module &M); std::string getModuleName() const; StringRef getPath() const { return Path; } StringRef getASTFile() const { return ASTFile; } - uint64_t getSignature() const { return Signature; } + ASTFileSignature getSignature() const { return Signature; } const Module *getModuleOrNull() const { return ClangModule; } }; /// Return a descriptor for the corresponding module, if one exists. virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID); + enum ExtKind { EK_Always, EK_Never, EK_ReplyHazy }; + + virtual ExtKind hasExternalDefinitions(const Decl *D); + /// \brief Finds all declarations lexically contained within the given /// DeclContext, after applying an optional filter predicate. /// diff --git a/include/clang/AST/ODRHash.h b/include/clang/AST/ODRHash.h new file mode 100644 index 000000000000..9af8488fca10 --- /dev/null +++ b/include/clang/AST/ODRHash.h @@ -0,0 +1,84 @@ +//===-- ODRHash.h - Hashing to diagnose ODR failures ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the declaration of the ODRHash class, which calculates +/// a hash based on AST nodes, which is stable across different runs. +/// +//===----------------------------------------------------------------------===// + +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Type.h" +#include "clang/AST/TemplateBase.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + +class Decl; +class IdentifierInfo; +class NestedNameSpecifer; +class Stmt; +class TemplateParameterList; + +// ODRHash is used to calculate a hash based on AST node contents that +// does not rely on pointer addresses. This allows the hash to not vary +// between runs and is usable to detect ODR problems in modules. To use, +// construct an ODRHash object, then call Add* methods over the nodes that +// need to be hashed. Then call CalculateHash to get the hash value. +// Typically, only one Add* call is needed. clear can be called to reuse the +// object. +class ODRHash { + // Use DenseMaps to convert between Decl and Type pointers and an index value. + llvm::DenseMap<const Decl*, unsigned> DeclMap; + llvm::DenseMap<const Type*, unsigned> TypeMap; + + // Save space by processing bools at the end. + llvm::SmallVector<bool, 128> Bools; + + llvm::FoldingSetNodeID ID; + +public: + ODRHash() {} + + // Use this for ODR checking classes between modules. This method compares + // more information than the AddDecl class. + void AddCXXRecordDecl(const CXXRecordDecl *Record); + + // Process SubDecls of the main Decl. This method calls the DeclVisitor + // while AddDecl does not. + void AddSubDecl(const Decl *D); + + // Reset the object for reuse. + void clear(); + + // Add booleans to ID and uses it to calculate the hash. + unsigned CalculateHash(); + + // Add AST nodes that need to be processed. + void AddDecl(const Decl *D); + void AddType(const Type *T); + void AddQualType(QualType T); + void AddStmt(const Stmt *S); + void AddIdentifierInfo(const IdentifierInfo *II); + void AddNestedNameSpecifier(const NestedNameSpecifier *NNS); + void AddTemplateName(TemplateName Name); + void AddDeclarationName(DeclarationName Name); + void AddTemplateArgument(TemplateArgument TA); + void AddTemplateParameterList(const TemplateParameterList *TPL); + + // Save booleans until the end to lower the size of data to process. + void AddBoolean(bool value); + + static bool isWhitelistedDecl(const Decl* D, const CXXRecordDecl *Record); +}; + +} // end namespace clang diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index 3e4c4bc7ea40..f977e63e04f6 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -76,10 +76,17 @@ class OMPClauseWithPreInit { friend class OMPClauseReader; /// Pre-initialization statement for the clause. Stmt *PreInit; + /// Region that captures the associated stmt. + OpenMPDirectiveKind CaptureRegion; + protected: /// Set pre-initialization statement for the clause. - void setPreInitStmt(Stmt *S) { PreInit = S; } - OMPClauseWithPreInit(const OMPClause *This) : PreInit(nullptr) { + void setPreInitStmt(Stmt *S, OpenMPDirectiveKind ThisRegion = OMPD_unknown) { + PreInit = S; + CaptureRegion = ThisRegion; + } + OMPClauseWithPreInit(const OMPClause *This) + : PreInit(nullptr), CaptureRegion(OMPD_unknown) { assert(get(This) && "get is not tuned for pre-init."); } @@ -88,6 +95,8 @@ public: const Stmt *getPreInitStmt() const { return PreInit; } /// Get pre-initialization statement for the clause. Stmt *getPreInitStmt() { return PreInit; } + /// Get capture region for the stmt in the clause. + OpenMPDirectiveKind getCaptureRegion() { return CaptureRegion; } static OMPClauseWithPreInit *get(OMPClause *C); static const OMPClauseWithPreInit *get(const OMPClause *C); }; @@ -194,7 +203,7 @@ public: /// In this example directive '#pragma omp parallel' has simple 'if' clause with /// condition 'a > 5' and directive name modifier 'parallel'. /// -class OMPIfClause : public OMPClause { +class OMPIfClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; /// \brief Location of '('. SourceLocation LParenLoc; @@ -225,26 +234,31 @@ public: /// /// \param NameModifier [OpenMP 4.1] Directive name modifier of clause. /// \param Cond Condition of the clause. + /// \param HelperCond Helper condition for the clause. + /// \param CaptureRegion Innermost OpenMP region where expressions in this + /// clause must be captured. /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param NameModifierLoc Location of directive name modifier. /// \param ColonLoc [OpenMP 4.1] Location of ':'. /// \param EndLoc Ending location of the clause. /// - OMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Cond, - SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation NameModifierLoc, SourceLocation ColonLoc, - SourceLocation EndLoc) - : OMPClause(OMPC_if, StartLoc, EndLoc), LParenLoc(LParenLoc), - Condition(Cond), ColonLoc(ColonLoc), NameModifier(NameModifier), - NameModifierLoc(NameModifierLoc) {} + OMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Cond, Stmt *HelperCond, + OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation NameModifierLoc, + SourceLocation ColonLoc, SourceLocation EndLoc) + : OMPClause(OMPC_if, StartLoc, EndLoc), OMPClauseWithPreInit(this), + LParenLoc(LParenLoc), Condition(Cond), ColonLoc(ColonLoc), + NameModifier(NameModifier), NameModifierLoc(NameModifierLoc) { + setPreInitStmt(HelperCond, CaptureRegion); + } /// \brief Build an empty clause. /// OMPIfClause() - : OMPClause(OMPC_if, SourceLocation(), SourceLocation()), LParenLoc(), - Condition(nullptr), ColonLoc(), NameModifier(OMPD_unknown), - NameModifierLoc() {} + : OMPClause(OMPC_if, SourceLocation(), SourceLocation()), + OMPClauseWithPreInit(this), LParenLoc(), Condition(nullptr), ColonLoc(), + NameModifier(OMPD_unknown), NameModifierLoc() {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } @@ -331,7 +345,7 @@ public: /// In this example directive '#pragma omp parallel' has simple 'num_threads' /// clause with number of threads '6'. /// -class OMPNumThreadsClause : public OMPClause { +class OMPNumThreadsClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; /// \brief Location of '('. SourceLocation LParenLoc; @@ -346,20 +360,29 @@ public: /// \brief Build 'num_threads' clause with condition \a NumThreads. /// /// \param NumThreads Number of threads for the construct. + /// \param HelperNumThreads Helper Number of threads for the construct. + /// \param CaptureRegion Innermost OpenMP region where expressions in this + /// clause must be captured. /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// - OMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_num_threads, StartLoc, EndLoc), LParenLoc(LParenLoc), - NumThreads(NumThreads) {} + OMPNumThreadsClause(Expr *NumThreads, Stmt *HelperNumThreads, + OpenMPDirectiveKind CaptureRegion, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(OMPC_num_threads, StartLoc, EndLoc), + OMPClauseWithPreInit(this), LParenLoc(LParenLoc), + NumThreads(NumThreads) { + setPreInitStmt(HelperNumThreads, CaptureRegion); + } /// \brief Build an empty clause. /// OMPNumThreadsClause() : OMPClause(OMPC_num_threads, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), NumThreads(nullptr) {} + OMPClauseWithPreInit(this), LParenLoc(SourceLocation()), + NumThreads(nullptr) {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } @@ -3456,7 +3479,7 @@ public: /// In this example directive '#pragma omp teams' has clause 'num_teams' /// with single expression 'n'. /// -class OMPNumTeamsClause : public OMPClause { +class OMPNumTeamsClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; /// \brief Location of '('. SourceLocation LParenLoc; @@ -3472,20 +3495,27 @@ public: /// \brief Build 'num_teams' clause. /// /// \param E Expression associated with this clause. + /// \param HelperE Helper Expression associated with this clause. + /// \param CaptureRegion Innermost OpenMP region where expressions in this + /// clause must be captured. /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// - OMPNumTeamsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, + OMPNumTeamsClause(Expr *E, Stmt *HelperE, OpenMPDirectiveKind CaptureRegion, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_num_teams, StartLoc, EndLoc), LParenLoc(LParenLoc), - NumTeams(E) {} + : OMPClause(OMPC_num_teams, StartLoc, EndLoc), OMPClauseWithPreInit(this), + LParenLoc(LParenLoc), NumTeams(E) { + setPreInitStmt(HelperE, CaptureRegion); + } /// \brief Build an empty clause. /// OMPNumTeamsClause() - : OMPClause(OMPC_num_teams, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), NumTeams(nullptr) {} + : OMPClause(OMPC_num_teams, SourceLocation(), SourceLocation()), + OMPClauseWithPreInit(this), LParenLoc(SourceLocation()), + NumTeams(nullptr) {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } /// \brief Returns the location of '('. @@ -3511,7 +3541,7 @@ public: /// In this example directive '#pragma omp teams' has clause 'thread_limit' /// with single expression 'n'. /// -class OMPThreadLimitClause : public OMPClause { +class OMPThreadLimitClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; /// \brief Location of '('. SourceLocation LParenLoc; @@ -3527,20 +3557,28 @@ public: /// \brief Build 'thread_limit' clause. /// /// \param E Expression associated with this clause. + /// \param HelperE Helper Expression associated with this clause. + /// \param CaptureRegion Innermost OpenMP region where expressions in this + /// clause must be captured. /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// - OMPThreadLimitClause(Expr *E, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_thread_limit, StartLoc, EndLoc), LParenLoc(LParenLoc), - ThreadLimit(E) {} + OMPThreadLimitClause(Expr *E, Stmt *HelperE, + OpenMPDirectiveKind CaptureRegion, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(OMPC_thread_limit, StartLoc, EndLoc), + OMPClauseWithPreInit(this), LParenLoc(LParenLoc), ThreadLimit(E) { + setPreInitStmt(HelperE, CaptureRegion); + } /// \brief Build an empty clause. /// OMPThreadLimitClause() : OMPClause(OMPC_thread_limit, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), ThreadLimit(nullptr) {} + OMPClauseWithPreInit(this), LParenLoc(SourceLocation()), + ThreadLimit(nullptr) {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } /// \brief Returns the location of '('. diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 10a930abe6fb..1b5850a05b37 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -774,6 +774,11 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo( TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc())); break; + case DeclarationName::CXXDeductionGuideName: + TRY_TO(TraverseTemplateName( + TemplateName(NameInfo.getName().getCXXDeductionGuideTemplate()))); + break; + case DeclarationName::Identifier: case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: @@ -1008,6 +1013,10 @@ DEF_TRAVERSE_TYPE(UnaryTransformType, { }) DEF_TRAVERSE_TYPE(AutoType, { TRY_TO(TraverseType(T->getDeducedType())); }) +DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, { + TRY_TO(TraverseTemplateName(T->getTemplateName())); + TRY_TO(TraverseType(T->getDeducedType())); +}) DEF_TRAVERSE_TYPE(RecordType, {}) DEF_TRAVERSE_TYPE(EnumType, {}) @@ -1232,6 +1241,11 @@ DEF_TRAVERSE_TYPELOC(AutoType, { TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); }) +DEF_TRAVERSE_TYPELOC(DeducedTemplateSpecializationType, { + TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName())); + TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); +}) + DEF_TRAVERSE_TYPELOC(RecordType, {}) DEF_TRAVERSE_TYPELOC(EnumType, {}) DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {}) @@ -1932,6 +1946,13 @@ DEF_TRAVERSE_DECL(FunctionDecl, { ReturnValue = TraverseFunctionHelper(D); }) +DEF_TRAVERSE_DECL(CXXDeductionGuideDecl, { + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + ShouldVisitChildren = false; + ReturnValue = TraverseFunctionHelper(D); +}) + DEF_TRAVERSE_DECL(CXXMethodDecl, { // We skip decls_begin/decls_end, which are already covered by // TraverseFunctionHelper(). @@ -2495,6 +2516,12 @@ DEF_TRAVERSE_STMT(CoawaitExpr, { ShouldVisitChildren = false; } }) +DEF_TRAVERSE_STMT(DependentCoawaitExpr, { + if (!getDerived().shouldVisitImplicitCode()) { + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand()); + ShouldVisitChildren = false; + } +}) DEF_TRAVERSE_STMT(CoyieldExpr, { if (!getDerived().shouldVisitImplicitCode()) { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand()); @@ -2711,6 +2738,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPClauseWithPostUpdate( template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) { + TRY_TO(VisitOMPClauseWithPreInit(C)); TRY_TO(TraverseStmt(C->getCondition())); return true; } @@ -2724,6 +2752,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) { template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { + TRY_TO(VisitOMPClauseWithPreInit(C)); TRY_TO(TraverseStmt(C->getNumThreads())); return true; } @@ -2993,6 +3022,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPMapClause(OMPMapClause *C) { template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPNumTeamsClause( OMPNumTeamsClause *C) { + TRY_TO(VisitOMPClauseWithPreInit(C)); TRY_TO(TraverseStmt(C->getNumTeams())); return true; } @@ -3000,6 +3030,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPNumTeamsClause( template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPThreadLimitClause( OMPThreadLimitClause *C) { + TRY_TO(VisitOMPClauseWithPreInit(C)); TRY_TO(TraverseStmt(C->getThreadLimit())); return true; } diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index e28675d6a828..c210bd1cec2e 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -39,6 +39,7 @@ namespace clang { class Expr; class IdentifierInfo; class LabelDecl; + class ODRHash; class ParmVarDecl; class PrinterHelper; struct PrintingPolicy; @@ -126,13 +127,13 @@ protected: unsigned : NumStmtBits; unsigned ValueKind : 2; - unsigned ObjectKind : 2; + unsigned ObjectKind : 3; unsigned TypeDependent : 1; unsigned ValueDependent : 1; unsigned InstantiationDependent : 1; unsigned ContainsUnexpandedParameterPack : 1; }; - enum { NumExprBits = 16 }; + enum { NumExprBits = 17 }; class CharacterLiteralBitfields { friend class CharacterLiteral; @@ -252,6 +253,14 @@ protected: unsigned NumArgs : 32 - 8 - 1 - NumExprBits; }; + class CoawaitExprBitfields { + friend class CoawaitExpr; + + unsigned : NumExprBits; + + unsigned IsImplicit : 1; + }; + union { StmtBitfields StmtBits; CompoundStmtBitfields CompoundStmtBits; @@ -268,6 +277,7 @@ protected: ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits; InitListExprBitfields InitListExprBits; TypeTraitExprBitfields TypeTraitExprBits; + CoawaitExprBitfields CoawaitBits; }; friend class ASTStmtReader; @@ -340,6 +350,8 @@ protected: public: Stmt(StmtClass SC) { + static_assert(sizeof(*this) == sizeof(void *), + "changing bitfields changed sizeof(Stmt)"); static_assert(sizeof(*this) % alignof(void *) == 0, "Insufficient alignment!"); StmtBits.sClass = SC; @@ -436,6 +448,15 @@ public: /// written in the source. void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical) const; + + /// \brief Calculate a unique representation for a statement that is + /// stable across compiler invocations. + /// + /// \param ID profile information will be stored in ID. + /// + /// \param Hash an ODRHash object which will be called where pointers would + /// have been used in the Profile function. + void ProcessODRHash(llvm::FoldingSetNodeID &ID, ODRHash& Hash) const; }; /// DeclStmt - Adaptor class for mixing declarations with statements and diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index 8eef34cb21b3..56bfce987f5b 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -296,7 +296,9 @@ public: /// \brief Represents the body of a coroutine. This wraps the normal function /// body and holds the additional semantic context required to set up and tear /// down the coroutine frame. -class CoroutineBodyStmt : public Stmt { +class CoroutineBodyStmt final + : public Stmt, + private llvm::TrailingObjects<CoroutineBodyStmt, Stmt *> { enum SubStmt { Body, ///< The body of the coroutine. Promise, ///< The promise statement. @@ -307,65 +309,100 @@ class CoroutineBodyStmt : public Stmt { Allocate, ///< Coroutine frame memory allocation. Deallocate, ///< Coroutine frame memory deallocation. ReturnValue, ///< Return value for thunk function. + ReturnStmtOnAllocFailure, ///< Return statement if allocation failed. FirstParamMove ///< First offset for move construction of parameter copies. }; - Stmt *SubStmts[SubStmt::FirstParamMove]; + unsigned NumParams; friend class ASTStmtReader; + friend TrailingObjects; + + Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); } + + Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); } + +public: + + struct CtorArgs { + Stmt *Body = nullptr; + Stmt *Promise = nullptr; + Expr *InitialSuspend = nullptr; + Expr *FinalSuspend = nullptr; + Stmt *OnException = nullptr; + Stmt *OnFallthrough = nullptr; + Expr *Allocate = nullptr; + Expr *Deallocate = nullptr; + Stmt *ReturnValue = nullptr; + Stmt *ReturnStmtOnAllocFailure = nullptr; + ArrayRef<Stmt *> ParamMoves; + }; + +private: + + CoroutineBodyStmt(CtorArgs const& Args); + public: - CoroutineBodyStmt(Stmt *Body, Stmt *Promise, Stmt *InitSuspend, - Stmt *FinalSuspend, Stmt *OnException, Stmt *OnFallthrough, - Expr *Allocate, Stmt *Deallocate, - Expr *ReturnValue, ArrayRef<Expr *> ParamMoves) - : Stmt(CoroutineBodyStmtClass) { - SubStmts[CoroutineBodyStmt::Body] = Body; - SubStmts[CoroutineBodyStmt::Promise] = Promise; - SubStmts[CoroutineBodyStmt::InitSuspend] = InitSuspend; - SubStmts[CoroutineBodyStmt::FinalSuspend] = FinalSuspend; - SubStmts[CoroutineBodyStmt::OnException] = OnException; - SubStmts[CoroutineBodyStmt::OnFallthrough] = OnFallthrough; - SubStmts[CoroutineBodyStmt::Allocate] = Allocate; - SubStmts[CoroutineBodyStmt::Deallocate] = Deallocate; - SubStmts[CoroutineBodyStmt::ReturnValue] = ReturnValue; - // FIXME: Tail-allocate space for parameter move expressions and store them. - assert(ParamMoves.empty() && "not implemented yet"); + static CoroutineBodyStmt *Create(const ASTContext &C, CtorArgs const &Args); + + bool hasDependentPromiseType() const { + return getPromiseDecl()->getType()->isDependentType(); } /// \brief Retrieve the body of the coroutine as written. This will be either /// a CompoundStmt or a TryStmt. Stmt *getBody() const { - return SubStmts[SubStmt::Body]; + return getStoredStmts()[SubStmt::Body]; } - Stmt *getPromiseDeclStmt() const { return SubStmts[SubStmt::Promise]; } + Stmt *getPromiseDeclStmt() const { + return getStoredStmts()[SubStmt::Promise]; + } VarDecl *getPromiseDecl() const { return cast<VarDecl>(cast<DeclStmt>(getPromiseDeclStmt())->getSingleDecl()); } - Stmt *getInitSuspendStmt() const { return SubStmts[SubStmt::InitSuspend]; } - Stmt *getFinalSuspendStmt() const { return SubStmts[SubStmt::FinalSuspend]; } + Stmt *getInitSuspendStmt() const { + return getStoredStmts()[SubStmt::InitSuspend]; + } + Stmt *getFinalSuspendStmt() const { + return getStoredStmts()[SubStmt::FinalSuspend]; + } - Stmt *getExceptionHandler() const { return SubStmts[SubStmt::OnException]; } + Stmt *getExceptionHandler() const { + return getStoredStmts()[SubStmt::OnException]; + } Stmt *getFallthroughHandler() const { - return SubStmts[SubStmt::OnFallthrough]; + return getStoredStmts()[SubStmt::OnFallthrough]; } - Expr *getAllocate() const { return cast<Expr>(SubStmts[SubStmt::Allocate]); } - Stmt *getDeallocate() const { return SubStmts[SubStmt::Deallocate]; } + Expr *getAllocate() const { + return cast_or_null<Expr>(getStoredStmts()[SubStmt::Allocate]); + } + Expr *getDeallocate() const { + return cast_or_null<Expr>(getStoredStmts()[SubStmt::Deallocate]); + } Expr *getReturnValueInit() const { - return cast<Expr>(SubStmts[SubStmt::ReturnValue]); + return cast_or_null<Expr>(getStoredStmts()[SubStmt::ReturnValue]); + } + Stmt *getReturnStmtOnAllocFailure() const { + return getStoredStmts()[SubStmt::ReturnStmtOnAllocFailure]; + } + ArrayRef<Stmt const *> getParamMoves() const { + return {getStoredStmts() + SubStmt::FirstParamMove, NumParams}; } SourceLocation getLocStart() const LLVM_READONLY { - return getBody()->getLocStart(); + return getBody() ? getBody()->getLocStart() + : getPromiseDecl()->getLocStart(); } SourceLocation getLocEnd() const LLVM_READONLY { - return getBody()->getLocEnd(); + return getBody() ? getBody()->getLocEnd() : getPromiseDecl()->getLocEnd(); } child_range children() { - return child_range(SubStmts, SubStmts + SubStmt::FirstParamMove); + return child_range(getStoredStmts(), + getStoredStmts() + SubStmt::FirstParamMove + NumParams); } static bool classof(const Stmt *T) { @@ -390,10 +427,14 @@ class CoreturnStmt : public Stmt { enum SubStmt { Operand, PromiseCall, Count }; Stmt *SubStmts[SubStmt::Count]; + bool IsImplicit : 1; + friend class ASTStmtReader; public: - CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall) - : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc) { + CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall, + bool IsImplicit = false) + : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc), + IsImplicit(IsImplicit) { SubStmts[SubStmt::Operand] = Operand; SubStmts[SubStmt::PromiseCall] = PromiseCall; } @@ -411,6 +452,9 @@ public: return static_cast<Expr*>(SubStmts[PromiseCall]); } + bool isImplicit() const { return IsImplicit; } + void setIsImplicit(bool value = true) { IsImplicit = value; } + SourceLocation getLocStart() const LLVM_READONLY { return CoreturnLoc; } SourceLocation getLocEnd() const LLVM_READONLY { return getOperand() ? getOperand()->getLocEnd() : getLocStart(); diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h index 81f8ad4344a9..5d3bce8d83ba 100644 --- a/include/clang/AST/StmtIterator.h +++ b/include/clang/AST/StmtIterator.h @@ -118,6 +118,8 @@ public: REFERENCE operator->() const { return operator*(); } }; +struct ConstStmtIterator; + struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> { explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {} @@ -128,6 +130,13 @@ struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> { StmtIterator(const VariableArrayType *t) : StmtIteratorImpl<StmtIterator,Stmt*&>(t) {} + +private: + StmtIterator(const StmtIteratorBase &RHS) + : StmtIteratorImpl<StmtIterator, Stmt *&>(RHS) {} + + inline friend StmtIterator + cast_away_const(const ConstStmtIterator &RHS); }; struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator, @@ -137,8 +146,15 @@ struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator, ConstStmtIterator(const StmtIterator& RHS) : StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {} + + ConstStmtIterator(Stmt * const *S) + : StmtIteratorImpl<ConstStmtIterator, const Stmt *>( + const_cast<Stmt **>(S)) {} }; +inline StmtIterator cast_away_const(const ConstStmtIterator &RHS) { + return RHS; +} } // end namespace clang #endif diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h index ec532ecd5881..13af142ca3ab 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -198,6 +198,26 @@ public: return const_cast<Stmt *>(*child_begin()); } + /// \brief Returns the captured statement associated with the + /// component region within the (combined) directive. + // + // \param RegionKind Component region kind. + CapturedStmt *getCapturedStmt(OpenMPDirectiveKind RegionKind) const { + SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; + getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind()); + assert(std::any_of( + CaptureRegions.begin(), CaptureRegions.end(), + [=](const OpenMPDirectiveKind K) { return K == RegionKind; }) && + "RegionKind not found in OpenMP CaptureRegions."); + auto *CS = cast<CapturedStmt>(getAssociatedStmt()); + for (auto ThisCaptureRegion : CaptureRegions) { + if (ThisCaptureRegion == RegionKind) + return CS; + CS = cast<CapturedStmt>(CS->getCapturedStmt()); + } + llvm_unreachable("Incorrect RegionKind specified for directive."); + } + OpenMPDirectiveKind getDirectiveKind() const { return Kind; } static bool classof(const Stmt *S) { @@ -304,6 +324,11 @@ class OMPLoopDirective : public OMPExecutableDirective { /// allocated: loop counters, their updates and final values. /// PrevLowerBound and PrevUpperBound are used to communicate blocking /// information in composite constructs which require loop blocking + /// DistInc is used to generate the increment expression for the distribute + /// loop when combined with a further nested loop + /// PrevEnsureUpperBound is used as the EnsureUpperBound expression for the + /// for loop when combined with a previous distribute loop in the same pragma + /// (e.g. 'distribute parallel for') /// enum { AssociatedStmtOffset = 0, @@ -319,7 +344,7 @@ class OMPLoopDirective : public OMPExecutableDirective { // specify the offset to the end (and start of the following counters/ // updates/finals arrays). DefaultEnd = 9, - // The following 7 exprs are used by worksharing loops only. + // The following 12 exprs are used by worksharing and distribute loops only. IsLastIterVariableOffset = 9, LowerBoundVariableOffset = 10, UpperBoundVariableOffset = 11, @@ -330,9 +355,11 @@ class OMPLoopDirective : public OMPExecutableDirective { NumIterationsOffset = 16, PrevLowerBoundVariableOffset = 17, PrevUpperBoundVariableOffset = 18, + DistIncOffset = 19, + PrevEnsureUpperBoundOffset = 20, // Offset to the end (and start of the following counters/updates/finals // arrays) for worksharing loop directives. - WorksharingEnd = 19, + WorksharingEnd = 21, }; /// \brief Get the counters storage. @@ -501,6 +528,20 @@ protected: "expected worksharing loop directive"); *std::next(child_begin(), PrevUpperBoundVariableOffset) = PrevUB; } + void setDistInc(Expr *DistInc) { + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && + "expected worksharing loop directive"); + *std::next(child_begin(), DistIncOffset) = DistInc; + } + void setPrevEnsureUpperBound(Expr *PrevEUB) { + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && + "expected worksharing loop directive"); + *std::next(child_begin(), PrevEnsureUpperBoundOffset) = PrevEUB; + } void setCounters(ArrayRef<Expr *> A); void setPrivateCounters(ArrayRef<Expr *> A); void setInits(ArrayRef<Expr *> A); @@ -535,7 +576,7 @@ public: Expr *UB; /// \brief Stride - local variable passed to runtime. Expr *ST; - /// \brief EnsureUpperBound -- expression LB = min(LB, NumIterations). + /// \brief EnsureUpperBound -- expression UB = min(UB, NumIterations). Expr *EUB; /// \brief Update of LowerBound for statically sheduled 'omp for' loops. Expr *NLB; @@ -547,6 +588,16 @@ public: /// \brief PreviousUpperBound - local variable passed to runtime in the /// enclosing schedule or null if that does not apply. Expr *PrevUB; + /// \brief DistInc - increment expression for distribute loop when found + /// combined with a further loop level (e.g. in 'distribute parallel for') + /// expression IV = IV + ST + Expr *DistInc; + /// \brief PrevEUB - expression similar to EUB but to be used when loop + /// scheduling uses PrevLB and PrevUB (e.g. in 'distribute parallel for' + /// when ensuring that the UB is either the calculated UB by the runtime or + /// the end of the assigned distribute chunk) + /// expression UB = min (UB, PrevUB) + Expr *PrevEUB; /// \brief Counters Loop counters. SmallVector<Expr *, 4> Counters; /// \brief PrivateCounters Loop counters. @@ -588,6 +639,8 @@ public: NumIterations = nullptr; PrevLB = nullptr; PrevUB = nullptr; + DistInc = nullptr; + PrevEUB = nullptr; Counters.resize(Size); PrivateCounters.resize(Size); Inits.resize(Size); @@ -719,6 +772,22 @@ public: return const_cast<Expr *>(reinterpret_cast<const Expr *>( *std::next(child_begin(), PrevUpperBoundVariableOffset))); } + Expr *getDistInc() const { + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), DistIncOffset))); + } + Expr *getPrevEnsureUpperBound() const { + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), PrevEnsureUpperBoundOffset))); + } const Stmt *getBody() const { // This relies on the loop form is already checked by Sema. Stmt *Body = getAssociatedStmt()->IgnoreContainers(true); diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 7f289862578d..84fbcda6e087 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -119,10 +119,7 @@ private: public: /// \brief Construct an empty, invalid template argument. - TemplateArgument() { - TypeOrValue.Kind = Null; - TypeOrValue.V = 0; - } + constexpr TemplateArgument() : TypeOrValue({Null, 0}) {} /// \brief Construct a template type argument. TemplateArgument(QualType T, bool isNullPtr = false) { @@ -388,8 +385,8 @@ private: }; public: - TemplateArgumentLocInfo(); - + constexpr TemplateArgumentLocInfo() : Template({nullptr, nullptr, 0, 0}) {} + TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {} TemplateArgumentLocInfo(Expr *E) : Expression(E) {} @@ -433,7 +430,7 @@ class TemplateArgumentLoc { TemplateArgumentLocInfo LocInfo; public: - TemplateArgumentLoc() {} + constexpr TemplateArgumentLoc() {} TemplateArgumentLoc(const TemplateArgument &Argument, TemplateArgumentLocInfo Opaque) @@ -578,6 +575,7 @@ struct ASTTemplateArgumentListInfo final TemplateArgumentLoc> { private: friend TrailingObjects; + friend class ASTNodeImporter; ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index a50e054f9b28..bd30aad10f27 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -333,6 +333,20 @@ public: bool hasAddressSpace() const { return Mask & AddressSpaceMask; } unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; } + /// Get the address space attribute value to be printed by diagnostics. + unsigned getAddressSpaceAttributePrintValue() const { + auto Addr = getAddressSpace(); + // This function is not supposed to be used with language specific + // address spaces. If that happens, the diagnostic message should consider + // printing the QualType instead of the address space value. + assert(Addr == 0 || Addr >= LangAS::Count); + if (Addr) + return Addr - LangAS::Count; + // TODO: The diagnostic messages where Addr may be 0 should be fixed + // since it cannot differentiate the situation where 0 denotes the default + // address space or user specified __attribute__((address_space(0))). + return 0; + } void setAddressSpace(unsigned space) { assert(space <= MaxAddressSpace); Mask = (Mask & ~AddressSpaceMask) @@ -1020,6 +1034,9 @@ public: return getQualifiers().hasStrongOrWeakObjCLifetime(); } + // true when Type is objc's weak and weak is enabled but ARC isn't. + bool isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const; + enum DestructionKind { DK_none, DK_cxx_destructor, @@ -1744,7 +1761,6 @@ public: bool isEventT() const; // OpenCL event_t bool isClkEventT() const; // OpenCL clk_event_t bool isQueueT() const; // OpenCL queue_t - bool isNDRangeT() const; // OpenCL ndrange_t bool isReserveIDT() const; // OpenCL reserve_id_t bool isPipeType() const; // OpenCL pipe type @@ -1785,7 +1801,8 @@ public: } /// \brief Determine whether this type is an undeduced type, meaning that - /// it somehow involves a C++11 'auto' type which has not yet been deduced. + /// it somehow involves a C++11 'auto' type or similar which has not yet been + /// deduced. bool isUndeducedType() const; /// \brief Whether this type is a variably-modified type (C99 6.7.5). @@ -1862,10 +1879,22 @@ public: /// not refer to a CXXRecordDecl, returns NULL. const CXXRecordDecl *getPointeeCXXRecordDecl() const; + /// Get the DeducedType whose type will be deduced for a variable with + /// an initializer of this type. This looks through declarators like pointer + /// types, but not through decltype or typedefs. + DeducedType *getContainedDeducedType() const; + /// Get the AutoType whose type will be deduced for a variable with /// an initializer of this type. This looks through declarators like pointer /// types, but not through decltype or typedefs. - AutoType *getContainedAutoType() const; + AutoType *getContainedAutoType() const { + return dyn_cast_or_null<AutoType>(getContainedDeducedType()); + } + + /// Determine whether this type was written with a leading 'auto' + /// corresponding to a trailing return type (possibly for a nested + /// function type within a pointer to function type or similar). + bool hasAutoForTrailingReturnType() const; /// Member-template getAs<specific type>'. Look through sugar for /// an instance of \<specific type>. This scheme will eventually @@ -1875,6 +1904,13 @@ public: /// immediately following this class. template <typename T> const T *getAs() const; + /// Member-template getAsAdjusted<specific type>. Look through specific kinds + /// of sugar (parens, attributes, etc) for an instance of \<specific type>. + /// This is used when you need to walk over sugar nodes that represent some + /// kind of type adjustment from a type that was written as a \<specific type> + /// to another type that is still canonically a \<specific type>. + template <typename T> const T *getAsAdjusted() const; + /// A variant of getAs<> for array types which silently discards /// qualifiers from the outermost type. const ArrayType *getAsArrayTypeUnsafe() const; @@ -2057,7 +2093,7 @@ public: : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent), /*InstantiationDependent=*/(K == Dependent), /*VariablyModified=*/false, - /*Unexpanded paramter pack=*/false) { + /*Unexpanded parameter pack=*/false) { BuiltinTypeBits.Kind = K; } @@ -3097,9 +3133,11 @@ public: class ExtParameterInfo { enum { ABIMask = 0x0F, - IsConsumed = 0x10 + IsConsumed = 0x10, + HasPassObjSize = 0x20, }; unsigned char Data; + public: ExtParameterInfo() : Data(0) {} @@ -3128,6 +3166,15 @@ public: return copy; } + bool hasPassObjectSize() const { + return Data & HasPassObjSize; + } + ExtParameterInfo withHasPassObjectSize() const { + ExtParameterInfo Copy = *this; + Copy.Data |= HasPassObjSize; + return Copy; + } + unsigned char getOpaqueValue() const { return Data; } static ExtParameterInfo getFromOpaqueValue(unsigned char data) { ExtParameterInfo result; @@ -4089,43 +4136,41 @@ public: } }; -/// \brief Represents a C++11 auto or C++14 decltype(auto) type. +/// \brief Common base class for placeholders for types that get replaced by +/// placeholder type deduction: C++11 auto, C++14 decltype(auto), C++17 deduced +/// class template types, and (eventually) constrained type names from the C++ +/// Concepts TS. /// /// These types are usually a placeholder for a deduced type. However, before /// the initializer is attached, or (usually) if the initializer is -/// type-dependent, there is no deduced type and an auto type is canonical. In +/// type-dependent, there is no deduced type and the type is canonical. In /// the latter case, it is also a dependent type. -class AutoType : public Type, public llvm::FoldingSetNode { - AutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent) - : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType, - /*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent, - /*VariablyModified=*/false, /*ContainsParameterPack=*/false) { - if (!DeducedType.isNull()) { - if (DeducedType->isDependentType()) +class DeducedType : public Type { +protected: + DeducedType(TypeClass TC, QualType DeducedAsType, bool IsDependent, + bool IsInstantiationDependent, bool ContainsParameterPack) + : Type(TC, + // FIXME: Retain the sugared deduced type? + DeducedAsType.isNull() ? QualType(this, 0) + : DeducedAsType.getCanonicalType(), + IsDependent, IsInstantiationDependent, + /*VariablyModified=*/false, ContainsParameterPack) { + if (!DeducedAsType.isNull()) { + if (DeducedAsType->isDependentType()) setDependent(); - if (DeducedType->isInstantiationDependentType()) + if (DeducedAsType->isInstantiationDependentType()) setInstantiationDependent(); - if (DeducedType->containsUnexpandedParameterPack()) + if (DeducedAsType->containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); } - AutoTypeBits.Keyword = (unsigned)Keyword; } - friend class ASTContext; // ASTContext creates these - public: - bool isDecltypeAuto() const { - return getKeyword() == AutoTypeKeyword::DecltypeAuto; - } - AutoTypeKeyword getKeyword() const { - return (AutoTypeKeyword)AutoTypeBits.Keyword; - } - bool isSugared() const { return !isCanonicalUnqualified(); } QualType desugar() const { return getCanonicalTypeInternal(); } - /// \brief Get the type deduced for this auto type, or null if it's either - /// not been deduced or was deduced to a dependent type. + /// \brief Get the type deduced for this placeholder type, or null if it's + /// either not been deduced or was deduced to a dependent type. QualType getDeducedType() const { return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType(); } @@ -4133,6 +4178,31 @@ public: return !isCanonicalUnqualified() || isDependentType(); } + static bool classof(const Type *T) { + return T->getTypeClass() == Auto || + T->getTypeClass() == DeducedTemplateSpecialization; + } +}; + +/// \brief Represents a C++11 auto or C++14 decltype(auto) type. +class AutoType : public DeducedType, public llvm::FoldingSetNode { + AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword, + bool IsDeducedAsDependent) + : DeducedType(Auto, DeducedAsType, IsDeducedAsDependent, + IsDeducedAsDependent, /*ContainsPack=*/false) { + AutoTypeBits.Keyword = (unsigned)Keyword; + } + + friend class ASTContext; // ASTContext creates these + +public: + bool isDecltypeAuto() const { + return getKeyword() == AutoTypeKeyword::DecltypeAuto; + } + AutoTypeKeyword getKeyword() const { + return (AutoTypeKeyword)AutoTypeBits.Keyword; + } + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getDeducedType(), getKeyword(), isDependentType()); } @@ -4149,6 +4219,43 @@ public: } }; +/// \brief Represents a C++17 deduced template specialization type. +class DeducedTemplateSpecializationType : public DeducedType, + public llvm::FoldingSetNode { + /// The name of the template whose arguments will be deduced. + TemplateName Template; + + DeducedTemplateSpecializationType(TemplateName Template, + QualType DeducedAsType, + bool IsDeducedAsDependent) + : DeducedType(DeducedTemplateSpecialization, DeducedAsType, + IsDeducedAsDependent || Template.isDependent(), + IsDeducedAsDependent || Template.isInstantiationDependent(), + Template.containsUnexpandedParameterPack()), + Template(Template) {} + + friend class ASTContext; // ASTContext creates these + +public: + /// Retrieve the name of the template that we are deducing. + TemplateName getTemplateName() const { return Template;} + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getTemplateName(), getDeducedType(), isDependentType()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Template, + QualType Deduced, bool IsDependent) { + Template.Profile(ID); + ID.AddPointer(Deduced.getAsOpaquePtr()); + ID.AddBoolean(IsDependent); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == DeducedTemplateSpecialization; + } +}; + /// \brief Represents a type template specialization; the template /// must be a class template, a type alias template, or a template /// template parameter. A template which cannot be resolved to one of @@ -4345,6 +4452,9 @@ public: const TemplateSpecializationType *getInjectedTST() const { return cast<TemplateSpecializationType>(InjectedType.getTypePtr()); } + TemplateName getTemplateName() const { + return getInjectedTST()->getTemplateName(); + } CXXRecordDecl *getDecl() const; @@ -5718,10 +5828,6 @@ inline bool Type::isQueueT() const { return isSpecificBuiltinType(BuiltinType::OCLQueue); } -inline bool Type::isNDRangeT() const { - return isSpecificBuiltinType(BuiltinType::OCLNDRange); -} - inline bool Type::isReserveIDT() const { return isSpecificBuiltinType(BuiltinType::OCLReserveID); } @@ -5739,7 +5845,7 @@ inline bool Type::isPipeType() const { inline bool Type::isOpenCLSpecificType() const { return isSamplerT() || isEventT() || isImageType() || isClkEventT() || - isQueueT() || isNDRangeT() || isReserveIDT() || isPipeType(); + isQueueT() || isReserveIDT() || isPipeType(); } inline bool Type::isTemplateTypeParmType() const { @@ -5849,8 +5955,8 @@ inline bool Type::isBooleanType() const { } inline bool Type::isUndeducedType() const { - const AutoType *AT = getContainedAutoType(); - return AT && !AT->isDeduced(); + auto *DT = getContainedDeducedType(); + return DT && !DT->isDeduced(); } /// \brief Determines whether this is a type for which one can define @@ -5932,6 +6038,38 @@ template <typename T> const T *Type::getAs() const { return cast<T>(getUnqualifiedDesugaredType()); } +template <typename T> const T *Type::getAsAdjusted() const { + static_assert(!TypeIsArrayType<T>::value, "ArrayType cannot be used with getAsAdjusted!"); + + // If this is directly a T type, return it. + if (const T *Ty = dyn_cast<T>(this)) + return Ty; + + // If the canonical form of this type isn't the right kind, reject it. + if (!isa<T>(CanonicalType)) + return nullptr; + + // Strip off type adjustments that do not modify the underlying nature of the + // type. + const Type *Ty = this; + while (Ty) { + if (const auto *A = dyn_cast<AttributedType>(Ty)) + Ty = A->getModifiedType().getTypePtr(); + else if (const auto *E = dyn_cast<ElaboratedType>(Ty)) + Ty = E->desugar().getTypePtr(); + else if (const auto *P = dyn_cast<ParenType>(Ty)) + Ty = P->desugar().getTypePtr(); + else if (const auto *A = dyn_cast<AdjustedType>(Ty)) + Ty = A->desugar().getTypePtr(); + else + break; + } + + // Just because the canonical type is correct does not mean we can use cast<>, + // since we may not have stripped off all the sugar down to the base type. + return dyn_cast<T>(Ty); +} + inline const ArrayType *Type::getAsArrayTypeUnsafe() const { // If this is directly an array type, return it. if (const ArrayType *arr = dyn_cast<ArrayType>(this)) diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 5b7d9e6e3ce1..525f848a9fab 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -70,6 +70,13 @@ public: return t; } + /// \brief Convert to the specified TypeLoc type, returning a null TypeLoc if + /// this TypeLock is not of the desired type. It will consider type + /// adjustments from a type that wad written as a T to another type that is + /// still canonically a T (ignores parens, attributes, elaborated types, etc). + template <typename T> + T getAsAdjusted() const; + /// The kinds of TypeLocs. Equivalent to the Type::TypeClass enum, /// except it also defines a Qualified enum that corresponds to the /// QualifiedLoc class. @@ -1827,9 +1834,25 @@ public: } }; -class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - AutoTypeLoc, - AutoType> { +class DeducedTypeLoc + : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DeducedTypeLoc, + DeducedType> {}; + +class AutoTypeLoc + : public InheritingConcreteTypeLoc<DeducedTypeLoc, AutoTypeLoc, AutoType> { +}; + +class DeducedTemplateSpecializationTypeLoc + : public InheritingConcreteTypeLoc<DeducedTypeLoc, + DeducedTemplateSpecializationTypeLoc, + DeducedTemplateSpecializationType> { +public: + SourceLocation getTemplateNameLoc() const { + return getNameLoc(); + } + void setTemplateNameLoc(SourceLocation Loc) { + setNameLoc(Loc); + } }; struct ElaboratedLocInfo { @@ -2172,6 +2195,24 @@ public: QualType getInnerType() const { return this->getTypePtr()->getElementType(); } }; + +template <typename T> +inline T TypeLoc::getAsAdjusted() const { + TypeLoc Cur = *this; + while (!T::isKind(Cur)) { + if (auto PTL = Cur.getAs<ParenTypeLoc>()) + Cur = PTL.getInnerLoc(); + else if (auto ATL = Cur.getAs<AttributedTypeLoc>()) + Cur = ATL.getModifiedLoc(); + else if (auto ETL = Cur.getAs<ElaboratedTypeLoc>()) + Cur = ETL.getNamedTypeLoc(); + else if (auto ATL = Cur.getAs<AdjustedTypeLoc>()) + Cur = ATL.getOriginalLoc(); + else + break; + } + return Cur.getAs<T>(); +} } #endif diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 27ab21bf7fcb..9d1d09e2cc66 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -96,7 +96,9 @@ DEPENDENT_TYPE(TemplateTypeParm, Type) NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) -TYPE(Auto, Type) +ABSTRACT_TYPE(Deduced, Type) +TYPE(Auto, DeducedType) +TYPE(DeducedTemplateSpecialization, DeducedType) DEPENDENT_TYPE(InjectedClassName, Type) DEPENDENT_TYPE(DependentName, Type) DEPENDENT_TYPE(DependentTemplateSpecialization, Type) diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h index 392e544d90c1..fa64fae8824f 100644 --- a/include/clang/AST/TypeOrdering.h +++ b/include/clang/AST/TypeOrdering.h @@ -26,7 +26,7 @@ namespace clang { /// \brief Function object that provides a total ordering on QualType values. -struct QualTypeOrdering : std::binary_function<QualType, QualType, bool> { +struct QualTypeOrdering { bool operator()(QualType T1, QualType T2) const { return std::less<void*>()(T1.getAsOpaquePtr(), T2.getAsOpaquePtr()); } diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 6a5224febab5..fb029470c830 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -180,6 +180,16 @@ const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl> /// matches "using Y = int", but not "typedef int X" const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl> typeAliasDecl; +/// \brief Matches type alias template declarations. +/// +/// typeAliasTemplateDecl() matches +/// \code +/// template <typename T> +/// using Y = X<T>; +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasTemplateDecl> + typeAliasTemplateDecl; + /// \brief Matches AST nodes that were expanded within the main-file. /// /// Example matches X but not Y @@ -1118,6 +1128,69 @@ const internal::VariadicDynCastAllOfMatcher< Decl, ObjCInterfaceDecl> objcInterfaceDecl; +/// \brief Matches Objective-C protocol declarations. +/// +/// Example matches FooDelegate +/// \code +/// @protocol FooDelegate +/// @end +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Decl, + ObjCProtocolDecl> objcProtocolDecl; + +/// \brief Matches Objective-C category declarations. +/// +/// Example matches Foo (Additions) +/// \code +/// @interface Foo (Additions) +/// @end +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Decl, + ObjCCategoryDecl> objcCategoryDecl; + +/// \brief Matches Objective-C method declarations. +/// +/// Example matches both declaration and definition of -[Foo method] +/// \code +/// @interface Foo +/// - (void)method; +/// @end +/// +/// @implementation Foo +/// - (void)method {} +/// @end +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Decl, + ObjCMethodDecl> objcMethodDecl; + +/// \brief Matches Objective-C instance variable declarations. +/// +/// Example matches _enabled +/// \code +/// @implementation Foo { +/// BOOL _enabled; +/// } +/// @end +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Decl, + ObjCIvarDecl> objcIvarDecl; + +/// \brief Matches Objective-C property declarations. +/// +/// Example matches enabled +/// \code +/// @interface Foo +/// @property BOOL enabled; +/// @end +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Decl, + ObjCPropertyDecl> objcPropertyDecl; + /// \brief Matches expressions that introduce cleanups to be run at the end /// of the sub-expression's evaluation. /// @@ -2522,7 +2595,7 @@ AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>, /// \brief Matches on the receiver of an ObjectiveC Message expression. /// /// Example -/// matcher = objCMessageExpr(hasRecieverType(asString("UIWebView *"))); +/// matcher = objCMessageExpr(hasReceiverType(asString("UIWebView *"))); /// matches the [webView ...] message invocation. /// \code /// NSString *webViewJavaScript = ... @@ -5507,7 +5580,7 @@ AST_MATCHER_FUNCTION(internal::Matcher<Expr>, nullPointerConstant) { integerLiteral(equals(0), hasParent(expr(hasType(pointerType()))))); } -/// \brief Matches declaration of the function the statemenet belongs to +/// \brief Matches declaration of the function the statement belongs to /// /// Given: /// \code diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h index 2c80b5137320..c5426dd75ef5 100644 --- a/include/clang/ASTMatchers/Dynamic/VariantValue.h +++ b/include/clang/ASTMatchers/Dynamic/VariantValue.h @@ -56,7 +56,7 @@ class ArgKind { /// \param To the requested destination type. /// /// \param Specificity value corresponding to the "specificity" of the - /// convertion. + /// conversion. bool isConvertibleTo(ArgKind To, unsigned *Specificity) const; bool operator<(const ArgKind &Other) const { @@ -182,7 +182,7 @@ public: /// \param Kind the requested destination type. /// /// \param Specificity value corresponding to the "specificity" of the - /// convertion. + /// conversion. bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity) const { if (Value) @@ -281,7 +281,7 @@ public: /// \param Kind the requested destination type. /// /// \param Specificity value corresponding to the "specificity" of the - /// convertion. + /// conversion. bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const; /// \brief Determines if the contained value can be converted to any kind @@ -290,7 +290,7 @@ public: /// \param Kinds the requested destination types. /// /// \param Specificity value corresponding to the "specificity" of the - /// convertion. It is the maximum specificity of all the possible + /// conversion. It is the maximum specificity of all the possible /// conversions. bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const; diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h index b8ae67cbba49..a2a27a8e47c7 100644 --- a/include/clang/Analysis/CallGraph.h +++ b/include/clang/Analysis/CallGraph.h @@ -98,7 +98,7 @@ public: 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) && FD->isThisDeclarationADefinition()) { // Add all blocks declared inside this function to the graph. addNodesForBlocks(FD); // If this function has external linkage, anything could call it. diff --git a/include/clang/Analysis/CloneDetection.h b/include/clang/Analysis/CloneDetection.h index 51cad7a96d6f..3b8173558408 100644 --- a/include/clang/Analysis/CloneDetection.h +++ b/include/clang/Analysis/CloneDetection.h @@ -16,9 +16,7 @@ #define LLVM_CLANG_AST_CLONEDETECTION_H #include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/Hashing.h" -#include "llvm/ADT/StringMap.h" - +#include "llvm/ADT/SmallVector.h" #include <vector> namespace clang { @@ -29,7 +27,7 @@ class VarDecl; class ASTContext; class CompoundStmt; -/// \brief Identifies a list of statements. +/// Identifies a list of statements. /// /// Can either identify a single arbitrary Stmt object, a continuous sequence of /// child statements inside a CompoundStmt or no statements at all. @@ -39,8 +37,8 @@ class StmtSequence { /// Stmt, then S is a pointer to this Stmt. const Stmt *S; - /// The related ASTContext for S. - ASTContext *Context; + /// The declaration that contains the statements. + const Decl *D; /// If EndIndex is non-zero, then S is a CompoundStmt and this StmtSequence /// instance is representing the CompoundStmt children inside the array @@ -49,7 +47,7 @@ class StmtSequence { unsigned EndIndex; public: - /// \brief Constructs a StmtSequence holding multiple statements. + /// Constructs a StmtSequence holding multiple statements. /// /// The resulting StmtSequence identifies a continuous sequence of statements /// in the body of the given CompoundStmt. Which statements of the body should @@ -57,20 +55,20 @@ public: /// that describe a non-empty sub-array in the body of the given CompoundStmt. /// /// \param Stmt A CompoundStmt that contains all statements in its body. - /// \param Context The ASTContext for the given CompoundStmt. + /// \param D The Decl containing this Stmt. /// \param StartIndex The inclusive start index in the children array of /// \p Stmt /// \param EndIndex The exclusive end index in the children array of \p Stmt. - StmtSequence(const CompoundStmt *Stmt, ASTContext &Context, - unsigned StartIndex, unsigned EndIndex); + StmtSequence(const CompoundStmt *Stmt, const Decl *D, unsigned StartIndex, + unsigned EndIndex); - /// \brief Constructs a StmtSequence holding a single statement. + /// Constructs a StmtSequence holding a single statement. /// /// \param Stmt An arbitrary Stmt. - /// \param Context The ASTContext for the given Stmt. - StmtSequence(const Stmt *Stmt, ASTContext &Context); + /// \param D The Decl containing this Stmt. + StmtSequence(const Stmt *Stmt, const Decl *D); - /// \brief Constructs an empty StmtSequence. + /// Constructs an empty StmtSequence. StmtSequence(); typedef const Stmt *const *iterator; @@ -110,9 +108,12 @@ public: bool empty() const { return size() == 0; } /// Returns the related ASTContext for the stored Stmts. - ASTContext &getASTContext() const { - assert(Context); - return *Context; + ASTContext &getASTContext() const; + + /// Returns the declaration that contains the stored Stmts. + const Decl *getContainingDecl() const { + assert(D); + return D; } /// Returns true if this objects holds a list of statements. @@ -150,106 +151,215 @@ public: bool contains(const StmtSequence &Other) const; }; -/// \brief Searches for clones in source code. +/// Searches for similar subtrees in the AST. /// -/// First, this class needs a translation unit which is passed via -/// \p analyzeTranslationUnit . It will then generate and store search data -/// for all statements inside the given translation unit. -/// Afterwards the generated data can be used to find code clones by calling -/// \p findClones . +/// First, this class needs several declarations with statement bodies which +/// can be passed via analyzeCodeBody. Afterwards all statements can be +/// searched for clones by calling findClones with a given list of constraints +/// that should specify the wanted properties of the clones. +/// +/// The result of findClones can be further constrained with the constrainClones +/// method. /// /// This class only searches for clones in exectuable source code /// (e.g. function bodies). Other clones (e.g. cloned comments or declarations) /// are not supported. class CloneDetector { + public: - typedef unsigned DataPiece; - - /// Holds the data about a StmtSequence that is needed during the search for - /// code clones. - struct CloneSignature { - /// \brief The hash code of the StmtSequence. - /// - /// The initial clone groups that are formed during the search for clones - /// consist only of Sequences that share the same hash code. This makes this - /// value the central part of this heuristic that is needed to find clones - /// in a performant way. For this to work, the type of this variable - /// always needs to be small and fast to compare. - /// - /// Also, StmtSequences that are clones of each others have to share - /// the same hash code. StmtSequences that are not clones of each other - /// shouldn't share the same hash code, but if they do, it will only - /// degrade the performance of the hash search but doesn't influence - /// the correctness of the result. - size_t Hash; - - /// \brief The complexity of the StmtSequence. - /// - /// This value gives an approximation on how many direct or indirect child - /// statements are contained in the related StmtSequence. In general, the - /// greater this value, the greater the amount of statements. However, this - /// is only an approximation and the actual amount of statements can be - /// higher or lower than this value. Statements that are generated by the - /// compiler (e.g. macro expansions) for example barely influence the - /// complexity value. - /// - /// The main purpose of this value is to filter clones that are too small - /// and therefore probably not interesting enough for the user. - unsigned Complexity; - - /// \brief Creates an empty CloneSignature without any data. - CloneSignature() : Complexity(1) {} - - CloneSignature(llvm::hash_code Hash, unsigned Complexity) - : Hash(Hash), Complexity(Complexity) {} - }; + /// A collection of StmtSequences that share an arbitrary property. + typedef llvm::SmallVector<StmtSequence, 8> CloneGroup; - /// Holds group of StmtSequences that are clones of each other and the - /// complexity value (see CloneSignature::Complexity) that all stored - /// StmtSequences have in common. - struct CloneGroup { - std::vector<StmtSequence> Sequences; - CloneSignature Signature; + /// Generates and stores search data for all statements in the body of + /// the given Decl. + void analyzeCodeBody(const Decl *D); - CloneGroup() {} + /// Constrains the given list of clone groups with the given constraint. + /// + /// The constraint is expected to have a method with the signature + /// `void constrain(std::vector<CloneDetector::CloneGroup> &Sequences)` + /// as this is the interface that the CloneDetector uses for applying the + /// constraint. The constraint is supposed to directly modify the passed list + /// so that all clones in the list fulfill the specific property this + /// constraint ensures. + template <typename T> + static void constrainClones(std::vector<CloneGroup> &CloneGroups, T C) { + C.constrain(CloneGroups); + } - CloneGroup(const StmtSequence &Seq, CloneSignature Signature) - : Signature(Signature) { - Sequences.push_back(Seq); - } + /// Constrains the given list of clone groups with the given list of + /// constraints. + /// + /// The constraints are applied in sequence in the order in which they are + /// passed to this function. + template <typename T1, typename... Ts> + static void constrainClones(std::vector<CloneGroup> &CloneGroups, T1 C, + Ts... ConstraintList) { + constrainClones(CloneGroups, C); + constrainClones(CloneGroups, ConstraintList...); + } - /// \brief Returns false if and only if this group should be skipped when - /// searching for clones. - bool isValid() const { - // A clone group with only one member makes no sense, so we skip them. - return Sequences.size() > 1; + /// Searches for clones in all previously passed statements. + /// \param Result Output parameter to which all created clone groups are + /// added. + /// \param ConstraintList The constraints that should be applied to the + // result. + template <typename... Ts> + void findClones(std::vector<CloneGroup> &Result, Ts... ConstraintList) { + // The initial assumption is that there is only one clone group and every + // statement is a clone of the others. This clone group will then be + // split up with the help of the constraints. + CloneGroup AllClones; + AllClones.reserve(Sequences.size()); + for (const auto &C : Sequences) { + AllClones.push_back(C); } - }; - /// \brief Generates and stores search data for all statements in the body of - /// the given Decl. - void analyzeCodeBody(const Decl *D); + Result.push_back(AllClones); - /// \brief Stores the CloneSignature to allow future querying. - void add(const StmtSequence &S, const CloneSignature &Signature); + constrainClones(Result, ConstraintList...); + } - /// \brief Searches the provided statements for clones. +private: + CloneGroup Sequences; +}; + +/// This class is a utility class that contains utility functions for building +/// custom constraints. +class CloneConstraint { +public: + /// Removes all groups by using a filter function. + /// \param CloneGroups The list of CloneGroups that is supposed to be + /// filtered. + /// \param Filter The filter function that should return true for all groups + /// that should be removed from the list. + static void + filterGroups(std::vector<CloneDetector::CloneGroup> &CloneGroups, + std::function<bool(const CloneDetector::CloneGroup &)> Filter) { + CloneGroups.erase( + std::remove_if(CloneGroups.begin(), CloneGroups.end(), Filter), + CloneGroups.end()); + } + + /// Splits the given CloneGroups until the given Compare function returns true + /// for all clones in a single group. + /// \param CloneGroups A list of CloneGroups that should be modified. + /// \param Compare The comparison function that all clones are supposed to + /// pass. Should return true if and only if two clones belong + /// to the same CloneGroup. + static void splitCloneGroups( + std::vector<CloneDetector::CloneGroup> &CloneGroups, + std::function<bool(const StmtSequence &, const StmtSequence &)> Compare); +}; + +/// Searches all children of the given clones for type II clones (i.e. they are +/// identical in every aspect beside the used variable names). +class RecursiveCloneTypeIIConstraint { + + /// Generates and saves a hash code for the given Stmt. + /// \param S The given Stmt. + /// \param D The Decl containing S. + /// \param StmtsByHash Output parameter that will contain the hash codes for + /// each StmtSequence in the given Stmt. + /// \return The hash code of the given Stmt. /// - /// \param Result Output parameter that is filled with a list of found - /// clone groups. Each group contains multiple StmtSequences - /// that were identified to be clones of each other. - /// \param MinGroupComplexity Only return clones which have at least this - /// complexity value. - /// \param CheckPatterns Returns only clone groups in which the referenced - /// variables follow the same pattern. - void findClones(std::vector<CloneGroup> &Result, unsigned MinGroupComplexity, - bool CheckPatterns = true); - - /// \brief Describes two clones that reference their variables in a different - /// pattern which could indicate a programming error. + /// If the given Stmt is a CompoundStmt, this method will also generate + /// hashes for all possible StmtSequences in the children of this Stmt. + size_t saveHash(const Stmt *S, const Decl *D, + std::vector<std::pair<size_t, StmtSequence>> &StmtsByHash); + +public: + void constrain(std::vector<CloneDetector::CloneGroup> &Sequences); +}; + +/// Ensures that every clone has at least the given complexity. +/// +/// Complexity is here defined as the total amount of children of a statement. +/// This constraint assumes the first statement in the group is representative +/// for all other statements in the group in terms of complexity. +class MinComplexityConstraint { + unsigned MinComplexity; + +public: + MinComplexityConstraint(unsigned MinComplexity) + : MinComplexity(MinComplexity) {} + + size_t calculateStmtComplexity(const StmtSequence &Seq, + const std::string &ParentMacroStack = ""); + + void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) { + CloneConstraint::filterGroups( + CloneGroups, [this](const CloneDetector::CloneGroup &A) { + if (!A.empty()) + return calculateStmtComplexity(A.front()) < MinComplexity; + else + return false; + }); + } +}; + +/// Ensures that all clone groups contain at least the given amount of clones. +class MinGroupSizeConstraint { + unsigned MinGroupSize; + +public: + MinGroupSizeConstraint(unsigned MinGroupSize = 2) + : MinGroupSize(MinGroupSize) {} + + void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) { + CloneConstraint::filterGroups(CloneGroups, + [this](const CloneDetector::CloneGroup &A) { + return A.size() < MinGroupSize; + }); + } +}; + +/// Ensures that no clone group fully contains another clone group. +struct OnlyLargestCloneConstraint { + void constrain(std::vector<CloneDetector::CloneGroup> &Result); +}; + +/// Analyzes the pattern of the referenced variables in a statement. +class VariablePattern { + + /// Describes an occurence of a variable reference in a statement. + struct VariableOccurence { + /// The index of the associated VarDecl in the Variables vector. + size_t KindID; + /// The statement in the code where the variable was referenced. + const Stmt *Mention; + + VariableOccurence(size_t KindID, const Stmt *Mention) + : KindID(KindID), Mention(Mention) {} + }; + + /// All occurences of referenced variables in the order of appearance. + std::vector<VariableOccurence> Occurences; + /// List of referenced variables in the order of appearance. + /// Every item in this list is unique. + std::vector<const VarDecl *> Variables; + + /// Adds a new variable referenced to this pattern. + /// \param VarDecl The declaration of the variable that is referenced. + /// \param Mention The SourceRange where this variable is referenced. + void addVariableOccurence(const VarDecl *VarDecl, const Stmt *Mention); + + /// Adds each referenced variable from the given statement. + void addVariables(const Stmt *S); + +public: + /// Creates an VariablePattern object with information about the given + /// StmtSequence. + VariablePattern(const StmtSequence &Sequence) { + for (const Stmt *S : Sequence) + addVariables(S); + } + + /// Describes two clones that reference their variables in a different pattern + /// which could indicate a programming error. struct SuspiciousClonePair { - /// \brief Utility class holding the relevant information about a single - /// clone in this pair. + /// Utility class holding the relevant information about a single + /// clone in this pair. struct SuspiciousCloneInfo { /// The variable which referencing in this clone was against the pattern. const VarDecl *Variable; @@ -270,17 +380,37 @@ public: SuspiciousCloneInfo SecondCloneInfo; }; - /// \brief Searches the provided statements for pairs of clones that don't - /// follow the same pattern when referencing variables. - /// \param Result Output parameter that will contain the clone pairs. - /// \param MinGroupComplexity Only clone pairs in which the clones have at - /// least this complexity value. - void findSuspiciousClones(std::vector<SuspiciousClonePair> &Result, - unsigned MinGroupComplexity); + /// Counts the differences between this pattern and the given one. + /// \param Other The given VariablePattern to compare with. + /// \param FirstMismatch Output parameter that will be filled with information + /// about the first difference between the two patterns. This parameter + /// can be a nullptr, in which case it will be ignored. + /// \return Returns the number of differences between the pattern this object + /// is following and the given VariablePattern. + /// + /// For example, the following statements all have the same pattern and this + /// function would return zero: + /// + /// if (a < b) return a; return b; + /// if (x < y) return x; return y; + /// if (u2 < u1) return u2; return u1; + /// + /// But the following statement has a different pattern (note the changed + /// variables in the return statements) and would have two differences when + /// compared with one of the statements above. + /// + /// if (a < b) return b; return a; + /// + /// This function should only be called if the related statements of the given + /// pattern and the statements of this objects are clones of each other. + unsigned countPatternDifferences( + const VariablePattern &Other, + VariablePattern::SuspiciousClonePair *FirstMismatch = nullptr); +}; -private: - /// Stores all encountered StmtSequences alongside their CloneSignature. - std::vector<std::pair<CloneSignature, StmtSequence>> Sequences; +/// Ensures that all clones reference variables in the same pattern. +struct MatchingVariablePatternConstraint { + void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups); }; } // end namespace clang diff --git a/include/clang/Basic/AddressSpaces.h b/include/clang/Basic/AddressSpaces.h index 63df61bedbc6..0ec5aafd64b6 100644 --- a/include/clang/Basic/AddressSpaces.h +++ b/include/clang/Basic/AddressSpaces.h @@ -20,24 +20,32 @@ namespace clang { namespace LangAS { -/// \brief Defines the set of possible language-specific address spaces. +/// \brief Defines the address space values used by the address space qualifier +/// of QualType. /// -/// This uses a high starting offset so as not to conflict with any address -/// space used by a target. enum ID { - Offset = 0x7FFF00, - - opencl_global = Offset, + // The default value 0 is the value used in QualType for the the situation + // where there is no address space qualifier. For most languages, this also + // corresponds to the situation where there is no address space qualifier in + // the source code, except for OpenCL, where the address space value 0 in + // QualType represents private address space in OpenCL source code. + Default = 0, + + // OpenCL specific address spaces. + opencl_global, opencl_local, opencl_constant, opencl_generic, + // CUDA specific address spaces. cuda_device, cuda_constant, cuda_shared, - Last, - Count = Last-Offset + // This denotes the count of language-specific address spaces and also + // the offset added to the target-specific address spaces, which are usually + // specified by address space attributes __attribute__(address_space(n))). + Count }; /// The type of a lookup table which maps from language-specific address spaces diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index fa60d512a6ff..c5d2c7fc618b 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -258,6 +258,7 @@ class TargetArch<list<string> arches> { list<string> CXXABIs; } def TargetARM : TargetArch<["arm", "thumb", "armeb", "thumbeb"]>; +def TargetAVR : TargetArch<["avr"]>; def TargetMips : TargetArch<["mips", "mipsel"]>; def TargetMSP430 : TargetArch<["msp430"]>; def TargetX86 : TargetArch<["x86"]>; @@ -301,6 +302,9 @@ class Attr { // Set to true if this attribute can be duplicated on a subject when merging // attributes. By default, attributes are not merged. bit DuplicatesAllowedWhileMerging = 0; + // Set to true if this attribute meaningful when applied to or inherited + // in a class template definition. + bit MeaningfulToClassTemplateDefinition = 0; // Lists language options, one of which is required to be true for the // attribute to be applicable. If empty, no language options are required. list<LangOpt> LangOpts = []; @@ -340,7 +344,7 @@ class TargetSpecificAttr<TargetArch target> { // should contain a shared value between the attributes. // // Target-specific attributes which use this feature should ensure that the - // spellings match exactly betweeen the attributes, and if the arguments or + // spellings match exactly between the attributes, and if the arguments or // subjects differ, should specify HasCustomParsing = 1 and implement their // own parsing and semantic handling requirements as-needed. string ParseKind; @@ -372,6 +376,7 @@ def AbiTag : Attr { let Args = [VariadicStringArgument<"Tags">]; let Subjects = SubjectList<[Struct, Var, Function, Namespace], ErrorDiag, "ExpectedStructClassVariableFunctionOrInlineNamespace">; + let MeaningfulToClassTemplateDefinition = 1; let Documentation = [AbiTagsDocs]; } @@ -449,6 +454,15 @@ def XRayInstrument : InheritableAttr { let Documentation = [XRayDocs]; } +def XRayLogArgs : InheritableAttr { + let Spellings = [GNU<"xray_log_args">, CXX11<"clang", "xray_log_args">]; + let Subjects = SubjectList< + [CXXMethod, ObjCMethod, Function], WarnDiag, "ExpectedFunctionOrMethod" + >; + let Args = [UnsignedArgument<"ArgumentCount">]; + let Documentation = [XRayDocs]; +} + def TLSModel : InheritableAttr { let Spellings = [GCC<"tls_model">]; let Subjects = SubjectList<[TLSVar], ErrorDiag, "ExpectedTLSVar">; @@ -480,6 +494,19 @@ def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> { let Documentation = [ARMInterruptDocs]; } +def AVRInterrupt : InheritableAttr, TargetSpecificAttr<TargetAVR> { + let Spellings = [GNU<"interrupt">]; + let Subjects = SubjectList<[Function]>; + let ParseKind = "Interrupt"; + let Documentation = [AVRInterruptDocs]; +} + +def AVRSignal : InheritableAttr, TargetSpecificAttr<TargetAVR> { + let Spellings = [GNU<"signal">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [AVRSignalDocs]; +} + def AsmLabel : InheritableAttr { let Spellings = [Keyword<"asm">, Keyword<"__asm__">]; let Args = [StringArgument<"Label">]; @@ -513,6 +540,17 @@ def Availability : InheritableAttr { let Documentation = [AvailabilityDocs]; } +def ExternalSourceSymbol : InheritableAttr { + let Spellings = [GNU<"external_source_symbol">, + CXX11<"clang", "external_source_symbol">]; + let Args = [StringArgument<"language", 1>, + StringArgument<"definedIn", 1>, + BoolArgument<"generatedDeclaration", 1>]; + let HasCustomParsing = 1; +// let Subjects = SubjectList<[Named]>; + let Documentation = [ExternalSourceSymbolDocs]; +} + def Blocks : InheritableAttr { let Spellings = [GNU<"blocks">]; let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>]; @@ -771,6 +809,7 @@ def Deprecated : InheritableAttr { // An optional string argument that enables us to provide a // Fix-It. StringArgument<"Replacement", 1>]; + let MeaningfulToClassTemplateDefinition = 1; let Documentation = [DeprecatedDocs]; } @@ -847,7 +886,15 @@ def FlagEnum : InheritableAttr { let Spellings = [GNU<"flag_enum">]; let Subjects = SubjectList<[Enum]>; let Documentation = [FlagEnumDocs]; - let LangOpts = [COnly]; +} + +def EnumExtensibility : InheritableAttr { + let Spellings = [GNU<"enum_extensibility">, + CXX11<"clang", "enum_extensibility">]; + let Subjects = SubjectList<[Enum]>; + let Args = [EnumArgument<"Extensibility", "Kind", + ["closed", "open"], ["Closed", "Open"]>]; + let Documentation = [EnumExtensibilityDocs]; } def Flatten : InheritableAttr { @@ -1115,7 +1162,7 @@ def NoSplitStack : InheritableAttr { let Documentation = [NoSplitStackDocs]; } -def NonNull : InheritableAttr { +def NonNull : InheritableParamAttr { let Spellings = [GCC<"nonnull">]; let Subjects = SubjectList<[ObjCMethod, HasFunctionProto, ParmVar], WarnDiag, "ExpectedFunctionMethodOrParameter">; @@ -1178,6 +1225,14 @@ def AssumeAligned : InheritableAttr { let Documentation = [AssumeAlignedDocs]; } +def AllocAlign : InheritableAttr { + let Spellings = [GCC<"alloc_align">]; + let Subjects = SubjectList<[HasFunctionProto], WarnDiag, + "ExpectedFunctionWithProtoType">; + let Args = [IntArgument<"ParamIndex">]; + let Documentation = [AllocAlignDocs]; +} + def NoReturn : InheritableAttr { let Spellings = [GCC<"noreturn">, Declspec<"noreturn">]; // FIXME: Does GCC allow this on the function instead? @@ -1498,6 +1553,12 @@ def SwiftIndirectResult : ParameterABIAttr { let Documentation = [SwiftIndirectResultDocs]; } +def Suppress : StmtAttr { + let Spellings = [CXX11<"gsl", "suppress">]; + let Args = [VariadicStringArgument<"DiagnosticIdentifiers">]; + let Documentation = [SuppressDocs]; +} + def SysVABI : InheritableAttr { let Spellings = [GCC<"sysv_abi">]; // let Subjects = [Function, ObjCMethod]; @@ -1681,6 +1742,7 @@ def Visibility : InheritableAttr { let Args = [EnumArgument<"Visibility", "VisibilityType", ["default", "hidden", "internal", "protected"], ["Default", "Hidden", "Hidden", "Protected"]>]; + let MeaningfulToClassTemplateDefinition = 1; let Documentation = [Undocumented]; } diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index 8f6a7ea601b3..71cfe36a8fa4 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -244,6 +244,36 @@ An example of how to use ``alloc_size`` }]; } +def AllocAlignDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Use ``__attribute__((alloc_align(<alignment>))`` on a function +declaration to specify that the return value of the function (which must be a +pointer type) is at least as aligned as the value of the indicated parameter. The +parameter is given by its index in the list of formal parameters; the first +parameter has index 1 unless the function is a C++ non-static member function, +in which case the first parameter has index 2 to account for the implicit ``this`` +parameter. + +.. code-block:: c++ + + // The returned pointer has the alignment specified by the first parameter. + void *a(size_t align) __attribute__((alloc_align(1))); + + // The returned pointer has the alignment specified by the second parameter. + void *b(void *v, size_t align) __attribute__((alloc_align(2))); + + // The returned pointer has the alignment specified by the second visible + // parameter, however it must be adjusted for the implicit 'this' parameter. + void *Foo::b(void *v, size_t align) __attribute__((alloc_align(3))); + +Note that this attribute merely informs the compiler that a function always +returns a sufficiently aligned pointer. It does not cause the compiler to +emit code to enforce that alignment. The behavior is undefined if the returned +poitner is not sufficiently aligned. + }]; +} + def EnableIfDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -960,6 +990,63 @@ When one method overrides another, the overriding method can be more widely avai }]; } +def ExternalSourceSymbolDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``external_source_symbol`` attribute specifies that a declaration originates +from an external source and describes the nature of that source. + +The fact that Clang is capable of recognizing declarations that were defined +externally can be used to provide better tooling support for mixed-language +projects or projects that rely on auto-generated code. For instance, an IDE that +uses Clang and that supports mixed-language projects can use this attribute to +provide a correct 'jump-to-definition' feature. For a concrete example, +consider a protocol that's defined in a Swift file: + +.. code-block:: swift + + @objc public protocol SwiftProtocol { + func method() + } + +This protocol can be used from Objective-C code by including a header file that +was generated by the Swift compiler. The declarations in that header can use +the ``external_source_symbol`` attribute to make Clang aware of the fact +that ``SwiftProtocol`` actually originates from a Swift module: + +.. code-block:: objc + + __attribute__((external_source_symbol(language="Swift",defined_in="module"))) + @protocol SwiftProtocol + @required + - (void) method; + @end + +Consequently, when 'jump-to-definition' is performed at a location that +references ``SwiftProtocol``, the IDE can jump to the original definition in +the Swift source file rather than jumping to the Objective-C declaration in the +auto-generated header file. + +The ``external_source_symbol`` attribute is a comma-separated list that includes +clauses that describe the origin and the nature of the particular declaration. +Those clauses can be: + +language=\ *string-literal* + The name of the source language in which this declaration was defined. + +defined_in=\ *string-literal* + The name of the source container in which the declaration was defined. The + exact definition of source container is language-specific, e.g. Swift's + source containers are modules, so ``defined_in`` should specify the Swift + module name. + +generated_declaration + This declaration was automatically generated by some tool. + +The clauses can be specified in any order. The clauses that are listed above are +all optional, but the attribute has to have at least one clause. + }]; +} def RequireConstantInitDocs : Documentation { let Category = DocCatVariable; @@ -1182,6 +1269,33 @@ The semantics are as follows: }]; } +def AVRInterruptDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang supports the GNU style ``__attribute__((interrupt))`` attribute on +AVR targets. This attribute may be attached to a function definition and instructs +the backend to generate appropriate function entry/exit code so that it can be used +directly as an interrupt service routine. + +On the AVR, the hardware globally disables interrupts when an interrupt is executed. +The first instruction of an interrupt handler declared with this attribute is a SEI +instruction to re-enable interrupts. See also the signal attribute that +does not insert a SEI instruction. + }]; +} + +def AVRSignalDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang supports the GNU style ``__attribute__((signal))`` attribute on +AVR targets. This attribute may be attached to a function definition and instructs +the backend to generate appropriate function entry/exit code so that it can be used +directly as an interrupt service routine. + +Interrupt handler functions defined with the signal attribute do not re-enable interrupts. +}]; +} + def TargetDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -1879,6 +1993,55 @@ manipulating bits of the enumerator when issuing warnings. }]; } +def EnumExtensibilityDocs : Documentation { + let Category = DocCatType; + let Content = [{ +Attribute ``enum_extensibility`` is used to distinguish between enum definitions +that are extensible and those that are not. The attribute can take either +``closed`` or ``open`` as an argument. ``closed`` indicates a variable of the +enum type takes a value that corresponds to one of the enumerators listed in the +enum definition or, when the enum is annotated with ``flag_enum``, a value that +can be constructed using values corresponding to the enumerators. ``open`` +indicates a variable of the enum type can take any values allowed by the +standard and instructs clang to be more lenient when issuing warnings. + +.. code-block:: c + + enum __attribute__((enum_extensibility(closed))) ClosedEnum { + A0, A1 + }; + + enum __attribute__((enum_extensibility(open))) OpenEnum { + B0, B1 + }; + + enum __attribute__((enum_extensibility(closed),flag_enum)) ClosedFlagEnum { + C0 = 1 << 0, C1 = 1 << 1 + }; + + enum __attribute__((enum_extensibility(open),flag_enum)) OpenFlagEnum { + D0 = 1 << 0, D1 = 1 << 1 + }; + + void foo1() { + enum ClosedEnum ce; + enum OpenEnum oe; + enum ClosedFlagEnum cfe; + enum OpenFlagEnum ofe; + + ce = A1; // no warnings + ce = 100; // warning issued + oe = B1; // no warnings + oe = 100; // no warnings + cfe = C0 | C1; // no warnings + cfe = C0 | C1 | 4; // warning issued + ofe = D0 | D1; // no warnings + ofe = D0 | D1 | 4; // no warnings + } + + }]; +} + def EmptyBasesDocs : Documentation { let Category = DocCatType; let Content = [{ @@ -2638,6 +2801,32 @@ optimizations like C++'s named return value optimization (NRVO). }]; } +def SuppressDocs : Documentation { + let Category = DocCatStmt; + let Content = [{ +The ``[[gsl::suppress]]`` attribute suppresses specific +clang-tidy diagnostics for rules of the `C++ Core Guidelines`_ in a portable +way. The attribute can be attached to declarations, statements, and at +namespace scope. + +.. code-block:: c++ + + [[gsl::suppress("Rh-public")]] + void f_() { + int *p; + [[gsl::suppress("type")]] { + p = reinterpret_cast<int*>(7); + } + } + namespace N { + [[clang::suppress("type", "bounds")]]; + ... + } + +.. _`C++ Core Guidelines`: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#inforce-enforcement + }]; +} + def AbiTagsDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -2777,13 +2966,15 @@ See the RenderScript_ documentation for more information. def XRayDocs : Documentation { let Category = DocCatFunction; - let Heading = "xray_always_instrument (clang::xray_always_instrument), xray_never_instrument (clang::xray_never_instrument)"; + let Heading = "xray_always_instrument (clang::xray_always_instrument), xray_never_instrument (clang::xray_never_instrument), xray_log_args (clang::xray_log_args)"; let Content = [{ ``__attribute__((xray_always_instrument))`` or ``[[clang::xray_always_instrument]]`` is used to mark member functions (in C++), methods (in Objective C), and free functions (in C, C++, and Objective C) to be instrumented with XRay. This will cause the function to always have space at the beginning and exit points to allow for runtime patching. Conversely, ``__attribute__((xray_never_instrument))`` or ``[[clang::xray_never_instrument]]`` will inhibit the insertion of these instrumentation points. If a function has neither of these attributes, they become subject to the XRay heuristics used to determine whether a function should be instrumented or otherwise. + +``__attribute__((xray_log_args(N)))`` or ``[[clang::xray_log_args(N)]]`` is used to preserve N function arguments for the logging function. Currently, only N==1 is supported. }]; } diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 326a8fa66360..816ea156f979 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -756,11 +756,11 @@ LANGBUILTIN(_InterlockedOr, "LiLiD*Li", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedXor8, "ccD*c", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedXor16, "ssD*s", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedXor, "LiLiD*Li", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandset, "UcLiD*Li", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__popcnt16, "UsUs", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__popcnt, "UiUi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__popcnt64, "ULLiULLi", "nc", ALL_MS_LANGUAGES) -LANGBUILTIN(__readfsdword, "ULiULi", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_ReturnAddress, "v*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_rotl8, "UcUcUc", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_rotl16, "UsUsUc", "n", ALL_MS_LANGUAGES) @@ -773,6 +773,7 @@ LANGBUILTIN(_rotr, "UiUii", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_lrotr, "ULiULii", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_rotr64, "ULLiULLii", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES) +LANGBUILTIN(__fastfail, "vUi", "nr", ALL_MS_LANGUAGES) // Microsoft library builtins. LIBBUILTIN(_setjmpex, "iJ", "fj", "setjmpex.h", ALL_MS_LANGUAGES) @@ -1086,9 +1087,11 @@ LIBBUILTIN(ilogb, "id", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(ilogbf, "if", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(ilogbl, "iLd", "fne", "math.h", ALL_LANGUAGES) -LIBBUILTIN(lgamma, "dd", "fne", "math.h", ALL_LANGUAGES) -LIBBUILTIN(lgammaf, "ff", "fne", "math.h", ALL_LANGUAGES) -LIBBUILTIN(lgammal, "LdLd", "fne", "math.h", ALL_LANGUAGES) +// POSIX math.h declares a global, signgam, that lgamma writes to, so these +// shouldn't have "e" or "c" attributes +LIBBUILTIN(lgamma, "dd", "fn", "math.h", ALL_LANGUAGES) +LIBBUILTIN(lgammaf, "ff", "fn", "math.h", ALL_LANGUAGES) +LIBBUILTIN(lgammal, "LdLd", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(llrint, "LLid", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(llrintf, "LLif", "fne", "math.h", ALL_LANGUAGES) @@ -1362,7 +1365,7 @@ BUILTIN(__builtin_coro_free, "v*v*", "n") BUILTIN(__builtin_coro_id, "v*Iiv*v*v*", "n") BUILTIN(__builtin_coro_alloc, "b", "n") BUILTIN(__builtin_coro_begin, "v*v*", "n") -BUILTIN(__builtin_coro_end, "vv*Ib", "n") +BUILTIN(__builtin_coro_end, "bv*Ib", "n") BUILTIN(__builtin_coro_suspend, "cIb", "n") BUILTIN(__builtin_coro_param, "bv*v*", "n") // OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions. diff --git a/include/clang/Basic/BuiltinsAMDGPU.def b/include/clang/Basic/BuiltinsAMDGPU.def index f0f63fa73a79..a8ab657c379e 100644 --- a/include/clang/Basic/BuiltinsAMDGPU.def +++ b/include/clang/Basic/BuiltinsAMDGPU.def @@ -35,8 +35,14 @@ BUILTIN(__builtin_amdgcn_workitem_id_z, "Ui", "nc") //===----------------------------------------------------------------------===// // Instruction builtins. //===----------------------------------------------------------------------===// +BUILTIN(__builtin_amdgcn_s_getreg, "UiIi", "n") +BUILTIN(__builtin_amdgcn_s_waitcnt, "vIi", "n") +BUILTIN(__builtin_amdgcn_s_sendmsg, "vIiUi", "n") +BUILTIN(__builtin_amdgcn_s_sendmsghalt, "vIiUi", "n") BUILTIN(__builtin_amdgcn_s_barrier, "v", "n") BUILTIN(__builtin_amdgcn_wave_barrier, "v", "n") +BUILTIN(__builtin_amdgcn_s_dcache_inv, "v", "n") +BUILTIN(__builtin_amdgcn_buffer_wbinvl1, "v", "n") BUILTIN(__builtin_amdgcn_div_scale, "dddbb*", "n") BUILTIN(__builtin_amdgcn_div_scalef, "fffbb*", "n") BUILTIN(__builtin_amdgcn_div_fmas, "ddddb", "nc") @@ -80,6 +86,11 @@ BUILTIN(__builtin_amdgcn_sicmpl, "LUiLiLiIi", "nc") BUILTIN(__builtin_amdgcn_fcmp, "LUiddIi", "nc") BUILTIN(__builtin_amdgcn_fcmpf, "LUiffIi", "nc") BUILTIN(__builtin_amdgcn_ds_swizzle, "iiIi", "nc") +BUILTIN(__builtin_amdgcn_ds_permute, "iii", "nc") +BUILTIN(__builtin_amdgcn_ds_bpermute, "iii", "nc") +BUILTIN(__builtin_amdgcn_readfirstlane, "ii", "nc") +BUILTIN(__builtin_amdgcn_readlane, "iii", "nc") +BUILTIN(__builtin_amdgcn_fmed3f, "ffff", "nc") //===----------------------------------------------------------------------===// // VI+ only builtins. @@ -96,6 +107,13 @@ TARGET_BUILTIN(__builtin_amdgcn_frexp_exph, "sh", "nc", "16-bit-insts") TARGET_BUILTIN(__builtin_amdgcn_fracth, "hh", "nc", "16-bit-insts") TARGET_BUILTIN(__builtin_amdgcn_classh, "bhi", "nc", "16-bit-insts") TARGET_BUILTIN(__builtin_amdgcn_s_memrealtime, "LUi", "n", "s-memrealtime") +TARGET_BUILTIN(__builtin_amdgcn_mov_dpp, "iiIiIiIiIb", "nc", "dpp") + +//===----------------------------------------------------------------------===// +// GFX9+ only builtins. +//===----------------------------------------------------------------------===// + +TARGET_BUILTIN(__builtin_amdgcn_fmed3h, "hhhh", "nc", "gfx9-insts") //===----------------------------------------------------------------------===// // Special builtins. diff --git a/include/clang/Basic/BuiltinsNVPTX.def b/include/clang/Basic/BuiltinsNVPTX.def index b6329fbd4251..afea6cb0f1b2 100644 --- a/include/clang/Basic/BuiltinsNVPTX.def +++ b/include/clang/Basic/BuiltinsNVPTX.def @@ -64,24 +64,10 @@ BUILTIN(__nvvm_read_ptx_sreg_pm3, "i", "n") // MISC -BUILTIN(__nvvm_clz_i, "ii", "") -BUILTIN(__nvvm_clz_ll, "iLLi", "") -BUILTIN(__nvvm_popc_i, "ii", "") -BUILTIN(__nvvm_popc_ll, "iLLi", "") BUILTIN(__nvvm_prmt, "UiUiUiUi", "") // Min Max -BUILTIN(__nvvm_min_i, "iii", "") -BUILTIN(__nvvm_min_ui, "UiUiUi", "") -BUILTIN(__nvvm_min_ll, "LLiLLiLLi", "") -BUILTIN(__nvvm_min_ull, "ULLiULLiULLi", "") - -BUILTIN(__nvvm_max_i, "iii", "") -BUILTIN(__nvvm_max_ui, "UiUiUi", "") -BUILTIN(__nvvm_max_ll, "LLiLLiLLi", "") -BUILTIN(__nvvm_max_ull, "ULLiULLiULLi", "") - BUILTIN(__nvvm_fmax_ftz_f, "fff", "") BUILTIN(__nvvm_fmax_f, "fff", "") BUILTIN(__nvvm_fmin_ftz_f, "fff", "") @@ -133,11 +119,6 @@ BUILTIN(__nvvm_div_rz_d, "ddd", "") BUILTIN(__nvvm_div_rm_d, "ddd", "") BUILTIN(__nvvm_div_rp_d, "ddd", "") -// Brev - -BUILTIN(__nvvm_brev32, "UiUi", "") -BUILTIN(__nvvm_brev64, "ULLiULLi", "") - // Sad BUILTIN(__nvvm_sad_i, "iiii", "") @@ -155,9 +136,6 @@ BUILTIN(__nvvm_ceil_d, "dd", "") // Abs -BUILTIN(__nvvm_abs_i, "ii", "") -BUILTIN(__nvvm_abs_ll, "LLiLLi", "") - BUILTIN(__nvvm_fabs_ftz_f, "ff", "") BUILTIN(__nvvm_fabs_f, "ff", "") BUILTIN(__nvvm_fabs_d, "dd", "") @@ -385,8 +363,6 @@ BUILTIN(__nvvm_ull2d_rp, "dULLi", "") BUILTIN(__nvvm_f2h_rn_ftz, "Usf", "") BUILTIN(__nvvm_f2h_rn, "Usf", "") -BUILTIN(__nvvm_h2f, "fUs", "") - // Bitcast BUILTIN(__nvvm_bitcast_f2i, "if", "") diff --git a/include/clang/Basic/BuiltinsWebAssembly.def b/include/clang/Basic/BuiltinsWebAssembly.def index 97b59a1fd86c..de56908be83c 100644 --- a/include/clang/Basic/BuiltinsWebAssembly.def +++ b/include/clang/Basic/BuiltinsWebAssembly.def @@ -16,9 +16,9 @@ // The format of this database matches clang/Basic/Builtins.def. -// Note that current_memory is not "c" (readnone) because it must be sequenced with -// respect to grow_memory calls. +// Note that current_memory is not "c" (readnone) because it must be sequenced +// with respect to grow_memory calls. BUILTIN(__builtin_wasm_current_memory, "z", "n") -BUILTIN(__builtin_wasm_grow_memory, "vz", "n") +BUILTIN(__builtin_wasm_grow_memory, "zz", "n") #undef BUILTIN diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index e53992bbf50e..c8a3c2f4d3ab 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -391,7 +391,6 @@ TARGET_BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2dIi", "", "sse4.1") TARGET_BUILTIN(__builtin_ia32_roundpd, "V2dV2dIi", "", "sse4.1") TARGET_BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fIc", "", "sse4.1") TARGET_BUILTIN(__builtin_ia32_dppd, "V2dV2dV2dIc", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_movntdqa, "V2LLiV2LLiC*", "", "sse4.1") TARGET_BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "", "sse4.1") TARGET_BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "", "sse4.1") TARGET_BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "", "sse4.1") @@ -576,7 +575,6 @@ TARGET_BUILTIN(__builtin_ia32_psrldi256, "V8iV8ii", "", "avx2") TARGET_BUILTIN(__builtin_ia32_psrld256, "V8iV8iV4i", "", "avx2") TARGET_BUILTIN(__builtin_ia32_psrlqi256, "V4LLiV4LLii", "", "avx2") TARGET_BUILTIN(__builtin_ia32_psrlq256, "V4LLiV4LLiV2LLi", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_movntdqa256, "V4LLiV4LLiC*", "", "avx2") TARGET_BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "", "avx2") TARGET_BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8i", "", "avx2") TARGET_BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIc", "", "avx2") @@ -832,8 +830,6 @@ TARGET_BUILTIN(__builtin_ia32_vphaddudq, "V2LLiV4i", "", "xop") TARGET_BUILTIN(__builtin_ia32_vphsubbw, "V8sV16c", "", "xop") TARGET_BUILTIN(__builtin_ia32_vphsubwd, "V4iV8s", "", "xop") TARGET_BUILTIN(__builtin_ia32_vphsubdq, "V2LLiV4i", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcmov, "V2LLiV2LLiV2LLiV2LLi", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcmov_256, "V4LLiV4LLiV4LLiV4LLi", "", "xop") TARGET_BUILTIN(__builtin_ia32_vpperm, "V16cV16cV16cV16c", "", "xop") TARGET_BUILTIN(__builtin_ia32_vprotb, "V16cV16cV16c", "", "xop") TARGET_BUILTIN(__builtin_ia32_vprotw, "V8sV8sV8s", "", "xop") @@ -997,22 +993,22 @@ TARGET_BUILTIN(__builtin_ia32_vpermt2varq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", TARGET_BUILTIN(__builtin_ia32_vpermt2varps512_mask, "V16fV16iV16fV16fUs", "", "avx512f") TARGET_BUILTIN(__builtin_ia32_vpermt2varpd512_mask, "V8dV8LLiV8dV8dUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2ddC*V2LLiUci","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2LLiV2LLiLLiC*V2LLiUci","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4ddC*V4LLiUci","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V4LLiV4LLiLLiC*V4LLiUci","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4sf, "V4fV4ffC*V2LLiUci","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4si, "V4iV4iiC*V2LLiUci","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div8sf, "V4fV4ffC*V4LLiUci","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div8si, "V4iV4iiC*V4LLiUci","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv2df, "V2dV2ddC*V4iUci","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V2LLiV2LLiLLiC*V4iUci","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4df, "V4dV4ddC*V4iUci","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V4LLiV4LLiLLiC*V4iUci","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4sf, "V4fV4ffC*V4iUci","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4si, "V4iV4iiC*V4iUci","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv8sf, "V8fV8ffC*V8iUci","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv8si, "V8iV8iiC*V8iUci","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2ddC*V2LLiUcIi","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2LLiV2LLiLLiC*V2LLiUcIi","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4ddC*V4LLiUcIi","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V4LLiV4LLiLLiC*V4LLiUcIi","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4sf, "V4fV4ffC*V2LLiUcIi","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4si, "V4iV4iiC*V2LLiUcIi","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div8sf, "V4fV4ffC*V4LLiUcIi","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div8si, "V4iV4iiC*V4LLiUcIi","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv2df, "V2dV2ddC*V4iUcIi","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V2LLiV2LLiLLiC*V4iUcIi","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4df, "V4dV4ddC*V4iUcIi","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V4LLiV4LLiLLiC*V4iUcIi","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4sf, "V4fV4ffC*V4iUcIi","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4si, "V4iV4iiC*V4iUcIi","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv8sf, "V8fV8ffC*V8iUcIi","","avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv8si, "V8iV8iiC*V8iUcIi","","avx512vl") TARGET_BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8ddC*V8iUcIi", "", "avx512f") TARGET_BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16ffC*V16fUsIi", "", "avx512f") TARGET_BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8ddC*V8LLiUcIi", "", "avx512f") @@ -1068,10 +1064,10 @@ TARGET_BUILTIN(__builtin_ia32_ucmpw512_mask, "UiV32sV32sIiUi", "", "avx512bw") TARGET_BUILTIN(__builtin_ia32_pabsb512_mask, "V64cV64cV64cULLi", "", "avx512bw") TARGET_BUILTIN(__builtin_ia32_pabsw512_mask, "V32sV32sV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_packssdw512_mask, "V32sV16iV16iV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_packsswb512_mask, "V64cV32sV32sV64cULLi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_packusdw512_mask, "V32sV16iV16iV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_packuswb512_mask, "V64cV32sV32sV64cULLi", "", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_packssdw512, "V32sV16iV16i", "", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_packsswb512, "V64cV32sV32s", "", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_packusdw512, "V32sV16iV16i", "", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_packuswb512, "V64cV32sV32s", "", "avx512bw") TARGET_BUILTIN(__builtin_ia32_paddsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw") TARGET_BUILTIN(__builtin_ia32_paddsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw") TARGET_BUILTIN(__builtin_ia32_paddusb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw") @@ -1590,27 +1586,15 @@ TARGET_BUILTIN(__builtin_ia32_cvtq2mask128, "UcV2LLi","","avx512dq,avx512vl") TARGET_BUILTIN(__builtin_ia32_cvtq2mask256, "UcV4LLi","","avx512dq,avx512vl") TARGET_BUILTIN(__builtin_ia32_broadcastmb512, "V8LLiUc","","avx512cd") TARGET_BUILTIN(__builtin_ia32_broadcastmw512, "V16iUs","","avx512cd") -TARGET_BUILTIN(__builtin_ia32_broadcastf32x4_512, "V16fV4fV16fUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_broadcastf64x4_512, "V8dV4dV8dUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_broadcasti32x4_512, "V16iV4iV16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_broadcasti64x4_512, "V8LLiV4LLiV8LLiUc","","avx512f") TARGET_BUILTIN(__builtin_ia32_broadcastmb128, "V2LLiUc","","avx512cd,avx512vl") TARGET_BUILTIN(__builtin_ia32_broadcastmb256, "V4LLiUc","","avx512cd,avx512vl") TARGET_BUILTIN(__builtin_ia32_broadcastmw128, "V4iUs","","avx512cd,avx512vl") TARGET_BUILTIN(__builtin_ia32_broadcastmw256, "V8iUs","","avx512cd,avx512vl") TARGET_BUILTIN(__builtin_ia32_broadcastf32x2_512_mask, "V16fV4fV16fUs","","avx512dq") -TARGET_BUILTIN(__builtin_ia32_broadcastf32x8_512_mask, "V16fV8fV16fUs","","avx512dq") -TARGET_BUILTIN(__builtin_ia32_broadcastf64x2_512_mask, "V8dV2dV8dUc","","avx512dq") TARGET_BUILTIN(__builtin_ia32_broadcasti32x2_512_mask, "V16iV4iV16iUs","","avx512dq") -TARGET_BUILTIN(__builtin_ia32_broadcasti32x8_512_mask, "V16iV8iV16iUs","","avx512dq") -TARGET_BUILTIN(__builtin_ia32_broadcasti64x2_512_mask, "V8LLiV2LLiV8LLiUc","","avx512dq") TARGET_BUILTIN(__builtin_ia32_broadcastf32x2_256_mask, "V8fV4fV8fUc","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_broadcastf64x2_256_mask, "V4dV2dV4dUc","","avx512dq,avx512vl") TARGET_BUILTIN(__builtin_ia32_broadcasti32x2_128_mask, "V4iV4iV4iUc","","avx512dq,avx512vl") TARGET_BUILTIN(__builtin_ia32_broadcasti32x2_256_mask, "V8iV4iV8iUc","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_broadcasti64x2_256_mask, "V4LLiV2LLiV4LLiUc","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_broadcastf32x4_256_mask, "V8fV4fV8fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_broadcasti32x4_256_mask, "V8iV4iV8iUc","","avx512vl") TARGET_BUILTIN(__builtin_ia32_pbroadcastw512_gpr_mask, "V32shV32sUi","","avx512bw") TARGET_BUILTIN(__builtin_ia32_pbroadcastw256_gpr_mask, "V16shV16sUs","","avx512bw,avx512vl") TARGET_BUILTIN(__builtin_ia32_pbroadcastw128_gpr_mask, "V8ssV8sUc","","avx512bw,avx512vl") @@ -1761,7 +1745,6 @@ TARGET_BUILTIN(__builtin_ia32_kortestzhi, "iUsUs","","avx512f") TARGET_BUILTIN(__builtin_ia32_kunpckhi, "UsUsUs","","avx512f") TARGET_BUILTIN(__builtin_ia32_kxnorhi, "UsUsUs","","avx512f") TARGET_BUILTIN(__builtin_ia32_kxorhi, "UsUsUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_movntdqa512, "V8LLiV8LLi*","","avx512f") TARGET_BUILTIN(__builtin_ia32_palignr512_mask, "V64cV64cV64cIiV64cULLi","","avx512bw") TARGET_BUILTIN(__builtin_ia32_dbpsadbw128_mask, "V8sV16cV16cIiV8sUc","","avx512bw,avx512vl") TARGET_BUILTIN(__builtin_ia32_dbpsadbw256_mask, "V16sV32cV32cIiV16sUs","","avx512bw,avx512vl") @@ -1826,6 +1809,9 @@ TARGET_BUILTIN(__builtin_ia32_selectpd_512, "V8dUcV8dV8d", "", "") TARGET_BUILTIN(__builtin_ia32_monitorx, "vv*UiUi", "", "mwaitx") TARGET_BUILTIN(__builtin_ia32_mwaitx, "vUiUiUi", "", "mwaitx") +// CLZERO +TARGET_BUILTIN(__builtin_ia32_clzero, "vv*", "", "clzero") + // MSVC TARGET_HEADER_BUILTIN(_BitScanForward, "UcULi*ULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_BitScanReverse, "UcULi*ULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") @@ -1840,6 +1826,18 @@ TARGET_HEADER_BUILTIN(__emulu, "ULLiUiUi", "nh", "intrin.h", ALL_MS_LANGUAGES, " TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(__stosb, "vUc*Ucz", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__int2c, "v", "nr", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__ud2, "v", "nr", "intrin.h", ALL_MS_LANGUAGES, "") + +TARGET_HEADER_BUILTIN(__readfsbyte, "UcULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__readfsword, "UsULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__readfsdword, "ULiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__readfsqword, "ULLiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") + +TARGET_HEADER_BUILTIN(__readgsbyte, "UcULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__readgsword, "UsULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__readgsdword, "ULiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__readgsqword, "ULLiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") #undef BUILTIN #undef TARGET_BUILTIN diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td index 7b581d3eec0f..3298a80e5134 100644 --- a/include/clang/Basic/DeclNodes.td +++ b/include/clang/Basic/DeclNodes.td @@ -45,6 +45,7 @@ def Named : Decl<1>; def ObjCAtDefsField : DDecl<Field>; def MSProperty : DDecl<Declarator>; def Function : DDecl<Declarator>, DeclContext; + def CXXDeductionGuide : DDecl<Function>; def CXXMethod : DDecl<Function>; def CXXConstructor : DDecl<CXXMethod>; def CXXDestructor : DDecl<CXXMethod>; diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index b83ef4d44b24..a8e11bcb8927 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -29,6 +29,7 @@ #include <cassert> #include <cstdint> #include <list> +#include <map> #include <memory> #include <string> #include <type_traits> @@ -222,6 +223,9 @@ private: void setMapping(diag::kind Diag, DiagnosticMapping Info) { DiagMap[Diag] = Info; } + DiagnosticMapping lookupMapping(diag::kind Diag) const { + return DiagMap.lookup(Diag); + } DiagnosticMapping &getOrAddMapping(diag::kind Diag); @@ -232,59 +236,97 @@ private: /// \brief Keeps and automatically disposes all DiagStates that we create. std::list<DiagState> DiagStates; - /// \brief Represents a point in source where the diagnostic state was - /// modified because of a pragma. - /// - /// 'Loc' can be null if the point represents the diagnostic state - /// modifications done through the command-line. - struct DiagStatePoint { - DiagState *State; - FullSourceLoc Loc; - DiagStatePoint(DiagState *State, FullSourceLoc Loc) - : State(State), Loc(Loc) { } - - bool operator<(const DiagStatePoint &RHS) const { - // If Loc is invalid it means it came from <command-line>, in which case - // we regard it as coming before any valid source location. - if (RHS.Loc.isInvalid()) - return false; - if (Loc.isInvalid()) - return true; - return Loc.isBeforeInTranslationUnitThan(RHS.Loc); + /// A mapping from files to the diagnostic states for those files. Lazily + /// built on demand for files in which the diagnostic state has not changed. + class DiagStateMap { + public: + /// Add an initial diagnostic state. + void appendFirst(DiagState *State); + /// Add a new latest state point. + void append(SourceManager &SrcMgr, SourceLocation Loc, DiagState *State); + /// Look up the diagnostic state at a given source location. + DiagState *lookup(SourceManager &SrcMgr, SourceLocation Loc) const; + /// Determine whether this map is empty. + bool empty() const { return Files.empty(); } + /// Clear out this map. + void clear() { + Files.clear(); + FirstDiagState = CurDiagState = nullptr; + CurDiagStateLoc = SourceLocation(); } + + /// Grab the most-recently-added state point. + DiagState *getCurDiagState() const { return CurDiagState; } + /// Get the location at which a diagnostic state was last added. + SourceLocation getCurDiagStateLoc() const { return CurDiagStateLoc; } + + private: + /// \brief Represents a point in source where the diagnostic state was + /// modified because of a pragma. + /// + /// 'Loc' can be null if the point represents the diagnostic state + /// modifications done through the command-line. + struct DiagStatePoint { + DiagState *State; + unsigned Offset; + DiagStatePoint(DiagState *State, unsigned Offset) + : State(State), Offset(Offset) { } + }; + + /// Description of the diagnostic states and state transitions for a + /// particular FileID. + struct File { + /// The diagnostic state for the parent file. This is strictly redundant, + /// as looking up the DecomposedIncludedLoc for the FileID in the Files + /// map would give us this, but we cache it here for performance. + File *Parent = nullptr; + /// The offset of this file within its parent. + unsigned ParentOffset = 0; + /// Whether this file has any local (not imported from an AST file) + /// diagnostic state transitions. + bool HasLocalTransitions = false; + /// The points within the file where the state changes. There will always + /// be at least one of these (the state on entry to the file). + llvm::SmallVector<DiagStatePoint, 4> StateTransitions; + + DiagState *lookup(unsigned Offset) const; + }; + + /// The diagnostic states for each file. + mutable std::map<FileID, File> Files; + + /// The initial diagnostic state. + DiagState *FirstDiagState; + /// The current diagnostic state. + DiagState *CurDiagState; + /// The location at which the current diagnostic state was established. + SourceLocation CurDiagStateLoc; + + /// Get the diagnostic state information for a file. + File *getFile(SourceManager &SrcMgr, FileID ID) const; + + friend class ASTReader; + friend class ASTWriter; }; - /// \brief A sorted vector of all DiagStatePoints representing changes in - /// diagnostic state due to diagnostic pragmas. - /// - /// The vector is always sorted according to the SourceLocation of the - /// DiagStatePoint. - typedef std::vector<DiagStatePoint> DiagStatePointsTy; - mutable DiagStatePointsTy DiagStatePoints; + DiagStateMap DiagStatesByLoc; /// \brief Keeps the DiagState that was active during each diagnostic 'push' /// so we can get back at it when we 'pop'. std::vector<DiagState *> DiagStateOnPushStack; DiagState *GetCurDiagState() const { - assert(!DiagStatePoints.empty()); - return DiagStatePoints.back().State; + return DiagStatesByLoc.getCurDiagState(); } - void PushDiagStatePoint(DiagState *State, SourceLocation L) { - FullSourceLoc Loc(L, getSourceManager()); - // Make sure that DiagStatePoints is always sorted according to Loc. - assert(Loc.isValid() && "Adding invalid loc point"); - assert(!DiagStatePoints.empty() && - (DiagStatePoints.back().Loc.isInvalid() || - DiagStatePoints.back().Loc.isBeforeInTranslationUnitThan(Loc)) && - "Previous point loc comes after or is the same as new one"); - DiagStatePoints.push_back(DiagStatePoint(State, Loc)); - } + void PushDiagStatePoint(DiagState *State, SourceLocation L); /// \brief Finds the DiagStatePoint that contains the diagnostic state of /// the given source location. - DiagStatePointsTy::iterator GetDiagStatePointForLoc(SourceLocation Loc) const; + DiagState *GetDiagStateForLoc(SourceLocation Loc) const { + return SourceMgr ? DiagStatesByLoc.lookup(*SourceMgr, Loc) + : DiagStatesByLoc.getCurDiagState(); + } /// \brief Sticky flag set to \c true when an error is emitted. bool ErrorOccurred; @@ -390,7 +432,11 @@ public: assert(SourceMgr && "SourceManager not set!"); return *SourceMgr; } - void setSourceManager(SourceManager *SrcMgr) { SourceMgr = SrcMgr; } + void setSourceManager(SourceManager *SrcMgr) { + assert(DiagStatesByLoc.empty() && + "Leftover diag state from a different SourceManager."); + SourceMgr = SrcMgr; + } //===--------------------------------------------------------------------===// // DiagnosticsEngine characterization methods, used by a client to customize diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td index 03ed8aa74597..652d06278557 100644 --- a/include/clang/Basic/DiagnosticASTKinds.td +++ b/include/clang/Basic/DiagnosticASTKinds.td @@ -44,7 +44,8 @@ def note_constexpr_non_global : Note< def note_constexpr_uninitialized : Note< "%select{|sub}0object of type %1 is not initialized">; def note_constexpr_array_index : Note<"cannot refer to element %0 of " - "%select{array of %2 elements|non-array object}1 in a constant expression">; + "%select{array of %2 element%plural{1:|:s}2|non-array object}1 " + "in a constant expression">; def note_constexpr_float_arithmetic : Note< "floating point arithmetic produces %select{an infinity|a NaN}0">; def note_constexpr_pointer_subtraction_not_same_array : Note< diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index af0612a829e1..98fd3c4d57ac 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -45,7 +45,9 @@ def err_expected_colon_after_setter_name : Error< "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">; + "for optional message in 'availability' attribute|" + "for %select{language|source container}1 name in " + "'external_source_symbol' attribute}0">; def err_invalid_string_udl : Error< "string literal with user-defined suffix cannot be used here">; def err_invalid_character_udl : Error< @@ -88,10 +90,10 @@ def err_module_unavailable : Error< "module '%0' %select{is incompatible with|requires}1 feature '%2'">; def err_module_header_missing : Error< "%select{|umbrella }0header '%1' not found">; -def err_module_lock_failure : Error< - "could not acquire lock file for module '%0': %1">, DefaultFatal; -def err_module_lock_timeout : Error< - "timed out waiting to acquire lock file for module '%0'">, DefaultFatal; +def remark_module_lock_failure : Remark< + "could not acquire lock file for module '%0': %1">, InGroup<ModuleBuild>; +def remark_module_lock_timeout : Remark< + "timed out waiting to acquire lock file for module '%0'">, InGroup<ModuleBuild>; def err_module_cycle : Error<"cyclic dependency in module '%0': %1">, DefaultFatal; def err_module_prebuilt : Error< diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 2fcd3a5a2fba..3980805ef9bc 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -85,6 +85,8 @@ def err_drv_clang_unsupported : Error< "the clang compiler does not support '%0'">; def err_drv_clang_unsupported_opt_cxx_darwin_i386 : Error< "the clang compiler does not support '%0' for C++ on Darwin/i386">; +def err_drv_clang_unsupported_opt_faltivec : Error< + "the clang compiler does not support '%0', %1">; def err_drv_command_failed : Error< "%0 command failed with exit code %1 (use -v to see invocation)">; def err_drv_compilationdatabase : Error< @@ -92,7 +94,7 @@ def err_drv_compilationdatabase : Error< 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">; + "failing because %select{environment variable 'FORCE_CLANG_DIAGNOSTICS_CRASH' is set|'-gen-reproducer' is used}0">; def err_drv_invalid_mfloat_abi : Error< "invalid float ABI '%0'">; def err_drv_invalid_libcxx_deployment : Error< @@ -133,6 +135,7 @@ def err_drv_invalid_gcc_output_type : Error< "invalid output type '%0' for use with gcc tool">; def err_drv_cc_print_options_failure : Error< "unable to open CC_PRINT_OPTIONS file: %0">; +def err_drv_lto_without_lld : Error<"LTO requires -fuse-ld=lld">; def err_drv_preamble_format : Error< "incorrect format for -preamble-bytes=N,END">; def err_drv_conflicting_deployment_targets : Error< @@ -230,6 +233,7 @@ def note_drv_t_option_is_global : Note< "The last /TC or /TP option takes precedence over earlier instances">; def note_drv_address_sanitizer_debug_runtime : Note< "AddressSanitizer doesn't support linking with debug runtime libraries yet">; +def note_drv_use_standard : Note<"use '%0' for '%1' standard">; def err_analyzer_config_no_value : Error< "analyzer-config option '%0' has a key but no value">; @@ -247,6 +251,10 @@ def err_test_module_file_extension_format : Error< def warn_drv_invoking_fallback : Warning<"falling back to %0">, InGroup<Fallback>; +def warn_slash_u_filename : Warning<"'/U%0' treated as the '/U' option">, + InGroup<DiagGroup<"slash-u-filename">>; +def note_use_dashdash : Note<"Use '--' to treat subsequent arguments as filenames">; + def err_drv_ropi_rwpi_incompatible_with_pic : Error< "embedded and GOT-based position independence are incompatible">; def err_drv_ropi_incompatible_with_cxx : Error< @@ -277,4 +285,8 @@ def warn_drv_ps4_sdk_dir : Warning< def err_drv_unsupported_linker : Error<"unsupported value '%0' for -linker option">; def err_drv_defsym_invalid_format : Error<"defsym must be of the form: sym=value: %0">; def err_drv_defsym_invalid_symval : Error<"Value is not an integer: %0">; +def warn_drv_msvc_not_found : Warning< + "unable to find a Visual Studio installation; " + "try running Clang from a developer command prompt">, + InGroup<DiagGroup<"msvc-not-found">>; } diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 4173d03de9f0..9f5f9888a819 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -34,7 +34,9 @@ def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">; def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">; def GNUCompoundLiteralInitializer : DiagGroup<"gnu-compound-literal-initializer">; def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion">; +def BitFieldEnumConversion : DiagGroup<"bitfield-enum-conversion">; def BitFieldWidth : DiagGroup<"bitfield-width">; +def Coroutine : DiagGroup<"coroutine">; def ConstantConversion : DiagGroup<"constant-conversion", [ BitFieldConstantConversion ] >; def LiteralConversion : DiagGroup<"literal-conversion">; @@ -175,6 +177,8 @@ def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic", def CXX11Narrowing : DiagGroup<"c++11-narrowing">; +def CXX11WarnOverrideDestructor : + DiagGroup<"inconsistent-missing-destructor-override">; def CXX11WarnOverrideMethod : DiagGroup<"inconsistent-missing-override">; // Original name of this warning in Clang @@ -355,6 +359,7 @@ def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">; def Sentinel : DiagGroup<"sentinel">; def MissingMethodReturnType : DiagGroup<"missing-method-return-type">; +def ShadowField : DiagGroup<"shadow-field">; def ShadowFieldInConstructorModified : DiagGroup<"shadow-field-in-constructor-modified">; def ShadowFieldInConstructor : DiagGroup<"shadow-field-in-constructor", [ShadowFieldInConstructorModified]>; @@ -366,7 +371,7 @@ def ShadowUncapturedLocal : DiagGroup<"shadow-uncaptured-local">; def Shadow : DiagGroup<"shadow", [ShadowFieldInConstructorModified, ShadowIvar]>; def ShadowAll : DiagGroup<"shadow-all", [Shadow, ShadowFieldInConstructor, - ShadowUncapturedLocal]>; + ShadowUncapturedLocal, ShadowField]>; def Shorten64To32 : DiagGroup<"shorten-64-to-32">; def : DiagGroup<"sign-promo">; @@ -480,6 +485,7 @@ def UnusedFunction : DiagGroup<"unused-function", [UnneededInternalDecl]>; def UnusedMemberFunction : DiagGroup<"unused-member-function", [UnneededMemberFunction]>; def UnusedLabel : DiagGroup<"unused-label">; +def UnusedLambdaCapture : DiagGroup<"unused-lambda-capture">; def UnusedParameter : DiagGroup<"unused-parameter">; def UnusedResult : DiagGroup<"unused-result">; def PotentiallyEvaluatedExpression : DiagGroup<"potentially-evaluated-expression">; @@ -602,6 +608,7 @@ def Conversion : DiagGroup<"conversion", [BoolConversion, ConstantConversion, EnumConversion, + BitFieldEnumConversion, FloatConversion, Shorten64To32, IntConversion, @@ -617,8 +624,9 @@ def Unused : DiagGroup<"unused", [UnusedArgument, UnusedFunction, UnusedLabel, // UnusedParameter, (matches GCC's behavior) // UnusedMemberFunction, (clean-up llvm before enabling) - UnusedPrivateField, UnusedLocalTypedef, - UnusedValue, UnusedVariable, UnusedPropertyIvar]>, + UnusedPrivateField, UnusedLambdaCapture, + UnusedLocalTypedef, UnusedValue, UnusedVariable, + UnusedPropertyIvar]>, DiagCategory<"Unused Entity Issue">; // Format settings. @@ -881,7 +889,7 @@ def BackendOptimizationFailure : DiagGroup<"pass-failed">; def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">; def ProfileInstrUnprofiled : DiagGroup<"profile-instr-unprofiled">; -// AddressSanitizer frontent instrumentation remarks. +// AddressSanitizer frontend instrumentation remarks. def SanitizeAddressRemarks : DiagGroup<"sanitize-address">; // Issues with serialized diagnostics. diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h index fcd04a0be187..f5f70cb5e7d3 100644 --- a/include/clang/Basic/DiagnosticIDs.h +++ b/include/clang/Basic/DiagnosticIDs.h @@ -84,6 +84,7 @@ class DiagnosticMapping { unsigned IsPragma : 1; unsigned HasNoWarningAsError : 1; unsigned HasNoErrorAsFatal : 1; + unsigned WasUpgradedFromWarning : 1; public: static DiagnosticMapping Make(diag::Severity Severity, bool IsUser, @@ -94,6 +95,7 @@ public: Result.IsPragma = IsPragma; Result.HasNoWarningAsError = 0; Result.HasNoErrorAsFatal = 0; + Result.WasUpgradedFromWarning = 0; return Result; } @@ -103,11 +105,33 @@ public: bool isUser() const { return IsUser; } bool isPragma() const { return IsPragma; } + bool isErrorOrFatal() const { + return getSeverity() == diag::Severity::Error || + getSeverity() == diag::Severity::Fatal; + } + bool hasNoWarningAsError() const { return HasNoWarningAsError; } void setNoWarningAsError(bool Value) { HasNoWarningAsError = Value; } bool hasNoErrorAsFatal() const { return HasNoErrorAsFatal; } void setNoErrorAsFatal(bool Value) { HasNoErrorAsFatal = Value; } + + /// Whether this mapping attempted to map the diagnostic to a warning, but + /// was overruled because the diagnostic was already mapped to an error or + /// fatal error. + bool wasUpgradedFromWarning() const { return WasUpgradedFromWarning; } + void setUpgradedFromWarning(bool Value) { WasUpgradedFromWarning = Value; } + + /// Serialize the bits that aren't based on context. + unsigned serializeBits() const { + return (WasUpgradedFromWarning << 3) | Severity; + } + static diag::Severity deserializeSeverity(unsigned Bits) { + return (diag::Severity)(Bits & 0x7); + } + static bool deserializeUpgradedFromWarning(unsigned Bits) { + return Bits >> 3; + } }; /// \brief Used for handling and querying diagnostic IDs. diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 0943feae950e..aebf8a9f3574 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -176,6 +176,9 @@ def warn_gcc_attribute_location : Warning< def warn_attribute_no_decl : Warning< "attribute %0 ignored, because it is not attached to a declaration">, InGroup<IgnoredAttributes>; +def err_ms_attributes_not_enabled : Error< + "'__declspec' attributes are not enabled; use '-fdeclspec' or " + "'-fms-extensions' to enable support for __declspec attributes">; def err_expected_method_body : Error<"expected method body">; def err_declspec_after_virtspec : Error< "'%0' qualifier may not appear after the virtual specifier '%1'">; @@ -361,8 +364,6 @@ def ext_decomp_decl_empty : ExtWarn< /// Objective-C parser diagnostics def err_expected_minus_or_plus : Error< "method type specifier must start with '-' or '+'">; -def err_objc_no_attributes_on_category : Error< - "attributes may not be specified on a category">; def err_objc_missing_end : Error<"missing '@end'">; def note_objc_container_start : Note< "%select{class|protocol|category|class extension|implementation" @@ -435,6 +436,13 @@ def err_declaration_does_not_declare_param : Error< "declaration does not declare a parameter">; def err_no_matching_param : Error<"parameter named %0 is missing">; +/// Objective-C++ parser diagnostics +def err_expected_token_instead_of_objcxx_keyword : Error< + "expected %0; %1 is a keyword in Objective-C++">; +def err_expected_member_name_or_semi_objcxx_keyword : Error< + "expected member name or ';' after declaration specifiers; " + "%0 is a keyword in Objective-C++">; + /// C++ parser diagnostics def err_invalid_operator_on_type : Error< "cannot use %select{dot|arrow}0 operator on a type">; @@ -669,9 +677,6 @@ def warn_static_inline_explicit_inst_ignored : Warning< // Constructor template diagnostics. def err_out_of_line_constructor_template_id : Error< "out-of-line constructor for %0 cannot have template arguments">; -def err_out_of_line_template_id_type_names_constructor : Error< - "qualified reference to %0 is a constructor name rather than a " - "%select{template name|type}1 wherever a constructor can be declared">; def err_expected_qualified_after_typename : Error< "expected a qualified name after 'typename'">; @@ -859,6 +864,12 @@ def err_availability_query_repeated_platform: Error< def err_availability_query_repeated_star : Error< "'*' query has already been specified">; +// External source symbol attribute +def err_external_source_symbol_expected_keyword : Error< + "expected 'language', 'defined_in', or 'generated_declaration'">; +def err_external_source_symbol_duplicate_clause : Error< + "duplicate %0 clause in an 'external_source_symbol' attribute">; + // Type safety attributes def err_type_safety_unknown_flag : Error< "invalid comparison flag %0; use 'layout_compatible' or 'must_be_null'">; @@ -1036,6 +1047,16 @@ def err_pragma_loop_missing_argument : Error< def err_pragma_loop_invalid_option : Error< "%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, " "vectorize_width, interleave, interleave_count, unroll, unroll_count, or distribute">; + +def err_pragma_fp_invalid_option : Error< + "%select{invalid|missing}0 option%select{ %1|}0; expected contract">; +def err_pragma_fp_invalid_argument : Error< + "unexpected argument '%0' to '#pragma clang fp %1'; " + "expected 'on', 'fast' or 'off'">; +def err_pragma_fp_scope : Error< + "'#pragma clang fp' can only appear at file scope or at the start of a " + "compound statement">; + def err_pragma_invalid_keyword : Error< "invalid argument; expected 'enable'%select{|, 'full'}0%select{|, 'assume_safety'}1 or 'disable'">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index c9343519e38b..9b2cfe495ce2 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -259,6 +259,9 @@ def err_anyx86_interrupt_attribute : Error< "a pointer as the first parameter|a %2 type as the second parameter}1">; def err_anyx86_interrupt_called : Error< "interrupt service routine cannot be called directly">; +def warn_arm_interrupt_calling_convention : Warning< + "call to function without interrupt attribute could clobber interruptee's VFP registers">, + InGroup<Extra>; def warn_mips_interrupt_attribute : Warning< "MIPS 'interrupt' attribute only applies to functions that have " "%select{no parameters|a 'void' return type}0">, @@ -316,6 +319,9 @@ def warn_unneeded_member_function : Warning< InGroup<UnneededMemberFunction>, DefaultIgnore; def warn_unused_private_field: Warning<"private field %0 is not used">, InGroup<UnusedPrivateField>, DefaultIgnore; +def warn_unused_lambda_capture: Warning<"lambda capture %0 is not " + "%select{used|required to be captured for this use}1">, + InGroup<UnusedLambdaCapture>, DefaultIgnore; def warn_parameter_size: Warning< "%0 is a large (%1 bytes) pass-by-value argument; " @@ -363,7 +369,9 @@ def warn_decl_shadow : "local variable|" "variable in %2|" "static data member of %2|" - "field of %2}1">, + "field of %2|" + "typedef in %2|" + "type alias in %2}1">, InGroup<Shadow>, DefaultIgnore; def warn_decl_shadow_uncaptured_local : Warning<warn_decl_shadow.Text>, @@ -1201,8 +1209,9 @@ def warn_cxx98_compat_unelaborated_friend_type : Warning< def err_qualified_friend_not_found : Error< "no function named %0 with type %1 was found in the specified scope">; def err_introducing_special_friend : Error< - "must use a qualified name when declaring a %select{constructor|" - "destructor|conversion operator}0 as a friend">; + "%plural{[0,2]:must use a qualified name when declaring|3:cannot declare}0" + " a %select{constructor|destructor|conversion operator|deduction guide}0 " + "as a friend">; def err_tagless_friend_type_template : Error< "friend type templates must use an elaborated type">; def err_no_matching_local_friend : Error< @@ -1447,6 +1456,15 @@ def err_nested_name_spec_is_not_class : Error< def ext_nested_name_spec_is_enum : ExtWarn< "use of enumeration in a nested name specifier is a C++11 extension">, InGroup<CXX11>; +def err_out_of_line_qualified_id_type_names_constructor : Error< + "qualified reference to %0 is a constructor name rather than a " + "%select{template name|type}1 in this context">; +def ext_out_of_line_qualified_id_type_names_constructor : ExtWarn< + "ISO C++ specifies that " + "qualified reference to %0 is a constructor name rather than a " + "%select{template name|type}1 in this context, despite preceding " + "%select{'typename'|'template'}2 keyword">, SFINAEFailure, + InGroup<DiagGroup<"injected-class-name">>; // C++ class members def err_storageclass_invalid_for_member : Error< @@ -1608,7 +1626,14 @@ def err_covariant_return_type_class_type_more_qualified : Error< "return type of virtual function %0 is not covariant with the return type of " "the function it overrides (class type %1 is more qualified than class " "type %2">; - + +// C++ implicit special member functions +def note_in_declaration_of_implicit_special_member : Note< + "while declaring the implicit " + "%select{default constructor|copy constructor|move constructor|" + "copy assignment operator|move assignment operator|destructor}1" + " for %0">; + // C++ constructors def err_constructor_cannot_be : Error<"constructor cannot be declared '%0'">; def err_invalid_qualified_constructor : Error< @@ -1664,8 +1689,8 @@ def err_init_conversion_failed : Error< "cannot initialize %select{a variable|a parameter|return object|an " "exception object|a member subobject|an array element|a new value|a value|a " "base class|a constructor delegation|a vector element|a block element|a " - "complex element|a lambda capture|a compound literal initializer|a " - "related result|a parameter of CF audited function}0 " + "block element|a complex element|a lambda capture|a compound literal " + "initializer|a related result|a parameter of CF audited function}0 " "%diff{of type $ with an %select{rvalue|lvalue}2 of type $|" "with an %select{rvalue|lvalue}2 of incompatible type}1,3" "%select{|: different classes%diff{ ($ vs $)|}5,6" @@ -1791,8 +1816,9 @@ def note_uninit_fixit_remove_cond : Note< "remove the %select{'%1' if its condition|condition if it}0 " "is always %select{false|true}2">; def err_init_incomplete_type : Error<"initialization of incomplete type %0">; -def err_list_init_in_parens : Error<"list-initializer for non-class type %0 " - "must not be parenthesized">; +def err_list_init_in_parens : Error< + "cannot initialize %select{non-class|reference}0 type %1 with a " + "parenthesized initializer list">; def warn_unsequenced_mod_mod : Warning< "multiple unsequenced modifications to %0">, InGroup<Unsequenced>; @@ -1833,8 +1859,8 @@ def warn_cxx98_compat_temp_copy : Warning< InGroup<CXX98CompatBindToTemporaryCopy>, DefaultIgnore; def err_selected_explicit_constructor : Error< "chosen constructor is explicit in copy-initialization">; -def note_constructor_declared_here : Note< - "constructor declared here">; +def note_explicit_ctor_deduction_guide_here : Note< + "explicit %select{constructor|deduction guide}0 declared here">; // C++11 decltype def err_decltype_in_declarator : Error< @@ -1845,8 +1871,8 @@ def warn_cxx98_compat_auto_type_specifier : Warning< "'auto' type specifier is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def err_auto_variable_cannot_appear_in_own_initializer : Error< - "variable %0 declared with %select{'auto'|'decltype(auto)'|'__auto_type'}1 " - "type cannot appear in its own initializer">; + "variable %0 declared with deduced type %1 " + "cannot appear in its own initializer">; def err_binding_cannot_appear_in_own_initializer : Error< "binding %0 cannot appear in the initializer of its own " "decomposition declaration">; @@ -1855,20 +1881,29 @@ def err_illegal_decl_array_of_auto : Error< def err_new_array_of_auto : Error< "cannot allocate array of 'auto'">; def err_auto_not_allowed : Error< - "%select{'auto'|'decltype(auto)'|'__auto_type'}0 not allowed " + "%select{'auto'|'decltype(auto)'|'__auto_type'|" + "use of " + "%select{class template|function template|variable template|alias template|" + "template template parameter|template}2 %3 requires template arguments; " + "argument deduction}0 not allowed " "%select{in function prototype" "|in non-static struct member|in struct member" "|in non-static union member|in union member" "|in non-static class member|in interface member" - "|in exception declaration|in template parameter|in block literal" + "|in exception declaration|in template parameter until C++1z|in block literal" "|in template argument|in typedef|in type alias|in function return type" "|in conversion function type|here|in lambda parameter" - "|in type allocated by 'new'|in K&R-style function parameter}1" - "%select{|||||||| until C++1z||||||||||}1">; + "|in type allocated by 'new'|in K&R-style function parameter" + "|in template parameter|in friend declaration}1">; +def err_dependent_deduced_tst : Error< + "typename specifier refers to " + "%select{class template|function template|variable template|alias template|" + "template template parameter|template}0 member in %1; " + "argument deduction not allowed here">; def err_auto_not_allowed_var_inst : Error< "'auto' variable template instantiation is not allowed">; def err_auto_var_requires_init : Error< - "declaration of variable %0 with type %1 requires an initializer">; + "declaration of variable %0 with deduced type %1 requires an initializer">; def err_auto_new_requires_ctor_arg : Error< "new expression for type %0 requires a constructor argument">; def err_auto_new_list_init : Error< @@ -1898,8 +1933,13 @@ def err_auto_var_deduction_failure_from_init_list : Error< def err_auto_new_deduction_failure : Error< "new expression for type %0 has incompatible constructor argument of type %1">; def err_auto_different_deductions : Error< - "'%select{auto|decltype(auto)|__auto_type}0' deduced as %1 in declaration " - "of %2 and deduced as %3 in declaration of %4">; + "%select{'auto'|'decltype(auto)'|'__auto_type'|template arguments}0 " + "deduced as %1 in declaration of %2 and " + "deduced as %3 in declaration of %4">; +def err_auto_non_deduced_not_alone : Error< + "%select{function with deduced return type|" + "declaration with trailing return type}0 " + "must be the only declaration in its group">; def err_implied_std_initializer_list_not_found : Error< "cannot deduce type of initializer list because std::initializer_list was " "not found; include <initializer_list>">; @@ -1915,6 +1955,8 @@ def err_auto_bitfield : Error< "cannot pass bit-field as __auto_type initializer in C">; // C++1y decltype(auto) type +def err_decltype_auto_invalid : Error< + "'decltype(auto)' not allowed here">; def err_decltype_auto_cannot_be_combined : Error< "'decltype(auto)' cannot be combined with other type specifiers">; def err_decltype_auto_function_declarator_not_declaration : Error< @@ -1925,6 +1967,56 @@ def err_decltype_auto_compound_type : Error< def err_decltype_auto_initializer_list : Error< "cannot deduce 'decltype(auto)' from initializer list">; +// C++1z deduced class template specialization types +def err_deduced_class_template_compound_type : Error< + "cannot %select{form pointer to|form reference to|form array of|" + "form function returning|use parentheses when declaring variable with}0 " + "deduced class template specialization type">; +def err_deduced_non_class_template_specialization_type : Error< + "%select{<error>|function template|variable template|alias template|" + "template template parameter|template}0 %1 requires template arguments; " + "argument deduction only allowed for class templates">; +def err_deduced_class_template_ctor_ambiguous : Error< + "ambiguous deduction for template arguments of %0">; +def err_deduced_class_template_ctor_no_viable : Error< + "no viable constructor or deduction guide for deduction of " + "template arguments of %0">; +def err_deduced_class_template_incomplete : Error< + "template %0 has no definition and no %select{|viable }1deduction guides " + "for deduction of template arguments">; +def err_deduced_class_template_deleted : Error< + "class template argument deduction for %0 selected a deleted constructor">; +def err_deduced_class_template_explicit : Error< + "class template argument deduction for %0 selected an explicit " + "%select{constructor|deduction guide}1 for copy-list-initialization">; +def err_deduction_guide_no_trailing_return_type : Error< + "deduction guide declaration without trailing return type">; +def err_deduction_guide_bad_trailing_return_type : Error< + "deduced type %1 of deduction guide is not %select{|written as }2" + "a specialization of template %0">; +def err_deduction_guide_with_complex_decl : Error< + "cannot specify any part of a return type in the " + "declaration of a deduction guide">; +def err_deduction_guide_invalid_specifier : Error< + "deduction guide cannot be declared '%0'">; +def err_deduction_guide_name_not_class_template : Error< + "cannot specify deduction guide for " + "%select{<error>|function template|variable template|alias template|" + "template template parameter|dependent template name}0 %1">; +def err_deduction_guide_wrong_scope : Error< + "deduction guide must be declared in the same scope as template %q0">; +def err_deduction_guide_defines_function : Error< + "deduction guide cannot have a function definition">; +def err_deduction_guide_explicit_mismatch : Error< + "deduction guide is %select{not |}0declared 'explicit' but " + "previous declaration was%select{ not|}0">; +def err_deduction_guide_specialized : Error<"deduction guide cannot be " + "%select{explicitly instantiated|explicitly specialized}0">; +def err_deduction_guide_template_not_deducible : Error< + "deduction guide template contains " + "%select{a template parameter|template parameters}0 that cannot be " + "deduced">; + // C++1y deduced return types def err_auto_fn_deduction_failure : Error< "cannot deduce return type %0 from returned value of type %1">; @@ -1950,6 +2042,9 @@ def override_keyword_hides_virtual_member_function : Error< "%select{function|functions}1">; def err_function_marked_override_not_overriding : Error< "%0 marked 'override' but does not override any member functions">; +def warn_destructor_marked_not_override_overriding : Warning < + "%0 overrides a destructor but is not marked 'override'">, + InGroup<CXX11WarnOverrideDestructor>, DefaultIgnore; def warn_function_marked_not_override_overriding : Warning < "%0 overrides a member function but is not marked 'override'">, InGroup<CXX11WarnOverrideMethod>; @@ -2215,6 +2310,9 @@ def err_concept_specialized : Error< "%select{function|variable}0 concept cannot be " "%select{explicitly instantiated|explicitly specialized|partially specialized}1">; +def err_template_different_associated_constraints : Error< + "associated constraints differ in template redeclaration">; + // C++11 char16_t/char32_t def warn_cxx98_compat_unicode_type : Warning< "'%0' type specifier is incompatible with C++98">, @@ -2261,7 +2359,7 @@ def warn_unsupported_target_attribute InGroup<IgnoredAttributes>; def err_attribute_unsupported : Error<"%0 attribute is not supported for this target">; -// The err_*_attribute_argument_not_int are seperate because they're used by +// The err_*_attribute_argument_not_int are separate because they're used by // VerifyIntegerConstantExpression. def err_aligned_attribute_argument_not_int : Error< "'aligned' attribute requires integer constant">; @@ -2659,7 +2757,8 @@ def warn_attribute_wrong_decl_type : Warning< "|functions, methods, enums, and classes" "|structs, classes, variables, functions, and inline namespaces" "|variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members" - "|classes and enumerations}1">, + "|classes and enumerations" + "|named declarations}1">, InGroup<IgnoredAttributes>; def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>; def warn_type_attribute_wrong_type : Warning< @@ -3132,7 +3231,8 @@ def err_attribute_regparm_invalid_number : Error< "'regparm' parameter must be between 0 and %0 inclusive">; def err_attribute_not_supported_in_lang : Error< "%0 attribute is not supported in %select{C|C++|Objective-C}1">; - +def err_attribute_not_supported_on_arch + : Error<"%0 attribute is not supported on '%1'">; // Clang-Specific Attributes def warn_attribute_iboutlet : Warning< @@ -3380,7 +3480,7 @@ def note_ovl_candidate_disabled_by_function_cond_attr : Note< def note_ovl_candidate_disabled_by_extension : Note< "candidate disabled due to OpenCL extension">; def err_addrof_function_disabled_by_enable_if_attr : Error< - "cannot take address of function %0 becuase it has one or more " + "cannot take address of function %0 because it has one or more " "non-tautological enable_if conditions">; def note_addrof_ovl_candidate_disabled_by_enable_if_attr : Note< "candidate function made ineligible by enable_if">; @@ -3789,11 +3889,13 @@ def err_template_decl_ref : Error< // C++ Template Argument Lists def err_template_missing_args : Error< - "use of class template %0 requires template arguments">; + "use of " + "%select{class template|function template|variable template|alias template|" + "template template parameter|template}0 %1 requires template arguments">; def err_template_arg_list_different_arity : Error< "%select{too few|too many}0 template arguments for " - "%select{class template|function template|template template parameter" - "|template}1 %2">; + "%select{class template|function template|variable template|alias template|" + "template template parameter|template}1 %2">; def note_template_decl_here : Note<"template is declared here">; def err_template_arg_must_be_type : Error< "template argument for template type parameter must be a type">; @@ -4063,7 +4165,7 @@ def ext_partial_specs_not_deducible : ExtWarn< "%select{a template parameter|template parameters}1 that cannot be " "deduced; this partial specialization will never be used">, DefaultError, InGroup<DiagGroup<"unusable-partial-specialization">>; -def note_partial_spec_unused_parameter : Note< +def note_non_deducible_parameter : Note< "non-deducible template parameter %0">; def err_partial_spec_ordering_ambiguous : Error< "ambiguous partial specializations of %0">; @@ -4286,6 +4388,8 @@ def note_typename_refers_here : Note< "referenced member %0 is declared here">; def err_typename_missing : Error< "missing 'typename' prior to dependent type name '%0%1'">; +def err_typename_missing_template : Error< + "missing 'typename' prior to dependent type template name '%0%1'">; def ext_typename_missing : ExtWarn< "missing 'typename' prior to dependent type name '%0%1'">, InGroup<DiagGroup<"typename-missing">>; @@ -4304,7 +4408,7 @@ def err_template_kw_refers_to_non_template : Error< "%0 following the 'template' keyword does not refer to a template">; def err_template_kw_refers_to_class_template : Error< "'%0%1' instantiated to a class template, not a function template">; -def note_referenced_class_template : Error< +def note_referenced_class_template : Note< "class template declared here">; def err_template_kw_missing : Error< "missing 'template' keyword prior to dependent template name '%0%1'">; @@ -4808,6 +4912,21 @@ def warn_bitfield_width_exceeds_type_width: Warning< def warn_anon_bitfield_width_exceeds_type_width : Warning< "width of anonymous bit-field (%0 bits) exceeds width of its type; value " "will be truncated to %1 bit%s1">, InGroup<BitFieldWidth>; +def warn_bitfield_too_small_for_enum : Warning< + "bit-field %0 is not wide enough to store all enumerators of %1">, + InGroup<BitFieldEnumConversion>, DefaultIgnore; +def note_widen_bitfield : Note< + "widen this field to %0 bits to store all values of %1">; +def warn_unsigned_bitfield_assigned_signed_enum : Warning< + "assigning value of signed enum type %1 to unsigned bit-field %0; " + "negative enumerators of enum %1 will be converted to positive values">, + InGroup<BitFieldEnumConversion>, DefaultIgnore; +def warn_signed_bitfield_enum_conversion : Warning< + "signed bit-field %0 needs an extra bit to represent the largest positive " + "enumerators of %1">, + InGroup<BitFieldEnumConversion>, DefaultIgnore; +def note_change_bitfield_sign : Note< + "consider making the bitfield type %select{unsigned|signed}0">; def warn_missing_braces : Warning< "suggest braces around initialization of subobject">, @@ -5164,7 +5283,7 @@ def err_arc_inconsistent_property_ownership : Error< def warn_block_capture_autoreleasing : Warning< "block captures an autoreleasing out-parameter, which may result in " "use-after-free bugs">, - InGroup<BlockCaptureAutoReleasing>, DefaultIgnore; + InGroup<BlockCaptureAutoReleasing>; def note_declare_parameter_autoreleasing : Note< "declare the parameter __autoreleasing explicitly to suppress this warning">; def note_declare_parameter_strong : Note< @@ -5725,8 +5844,8 @@ def err_this_static_member_func : Error< def err_invalid_member_use_in_static_method : Error< "invalid use of member %0 in static member function">; def err_invalid_qualified_function_type : Error< - "%select{static |non-}0member function %select{of type %2 |}1" - "cannot have '%3' qualifier">; + "%select{non-member function|static member function|deduction guide}0 " + "%select{of type %2 |}1cannot have '%3' qualifier">; def err_compound_qualified_function_type : Error< "%select{block pointer|pointer|reference}0 to function type %select{%2 |}1" "cannot have '%3' qualifier">; @@ -5750,8 +5869,8 @@ def err_builtin_func_cast_more_than_one_arg : Error< "function-style cast to a builtin type can only take one argument">; def err_value_init_for_array_type : Error< "array types cannot be value-initialized">; -def err_value_init_for_function_type : Error< - "function types cannot be value-initialized">; +def err_init_for_function_type : Error< + "cannot create object of function type %0">; def warn_format_nonliteral_noargs : Warning< "format string is not a string literal (potentially insecure)">, InGroup<FormatSecurity>; @@ -5916,6 +6035,12 @@ def warn_objc_circular_container : Warning< "adding '%0' to '%1' might cause circular dependency in container">, InGroup<DiagGroup<"objc-circular-container">>; def note_objc_circular_container_declared_here : Note<"'%0' declared here">; +def warn_objc_unsafe_perform_selector : Warning< + "%0 is incompatible with selectors that return a " + "%select{struct|union|vector}1 type">, + InGroup<DiagGroup<"objc-unsafe-perform-selector">>; +def note_objc_unsafe_perform_selector_method_declared_here : Note< + "method %0 that returns %1 declared here">; def warn_setter_getter_impl_required : Warning< "property %0 requires method %1 to be defined - " @@ -7001,7 +7126,7 @@ def err_incomplete_type_used_in_type_trait_expr : Error< def err_require_constant_init_failed : Error< "variable does not have a constant initializer">; def note_declared_required_constant_init_here : Note< - "required by 'require_constant_initializer' attribute here">; + "required by 'require_constant_initialization' attribute here">; def err_dimension_expr_not_constant_integer : Error< "dimension expression does not evaluate to a constant unsigned int">; @@ -7899,6 +8024,8 @@ def err_x86_builtin_32_bit_tgt : Error< "this builtin is only available on x86-64 targets">; def err_x86_builtin_invalid_rounding : Error< "invalid rounding argument">; +def err_x86_builtin_invalid_scale : Error< + "scale argument must be 1, 2, 4, or 8">; def err_builtin_longjmp_unsupported : Error< "__builtin_longjmp is not supported for the current target">; @@ -8113,6 +8240,8 @@ def err_opencl_ptrptr_kernel_param : Error< def err_kernel_arg_address_space : Error< "pointer arguments to kernel functions must reside in '__global', " "'__constant' or '__local' address space">; +def err_opencl_ext_vector_component_invalid_length : Error< + "vector component access has invalid length %0. Supported: 1,2,3,4,8,16.">; def err_opencl_function_variable : Error< "%select{non-kernel function|function scope}0 variable cannot be declared in %1 address space">; def err_static_function_scope : Error< @@ -8158,9 +8287,9 @@ def err_opencl_return_value_with_address_space : Error< "return value cannot be qualified with address space">; def err_opencl_constant_no_init : Error< "variable in constant address space must be initialized">; -def err_atomic_init_constant : Error< - "atomic variable can only be assigned to a compile time constant" - " in the declaration statement in the program scope">; +def err_opencl_atomic_init: Error< + "atomic variable can be %select{assigned|initialized}0 to a variable only " + "in global address space">; def err_opencl_implicit_vector_conversion : Error< "implicit conversions between vector types (%0 and %1) are not permitted">; def err_opencl_invalid_type_array : Error< @@ -8210,6 +8339,8 @@ def err_opencl_invalid_block_declaration : Error< "invalid block variable declaration - must be %select{const qualified|initialized}0">; def err_opencl_extern_block_declaration : Error< "invalid block variable declaration - using 'extern' storage class is disallowed">; +def err_opencl_block_ref_block : Error< + "cannot refer to a block inside block">; // OpenCL v2.0 s6.13.9 - Address space qualifier functions. def err_opencl_builtin_to_addr_arg_num : Error< @@ -8227,9 +8358,9 @@ def err_opencl_enqueue_kernel_local_size_args : Error< def err_opencl_enqueue_kernel_invalid_local_size_type : Error< "illegal call to enqueue_kernel, parameter needs to be specified as integer type">; def err_opencl_enqueue_kernel_blocks_non_local_void_args : Error< - "blocks used in device side enqueue are expected to have parameters of type 'local void*'">; + "blocks used in enqueue_kernel call are expected to have parameters of type 'local void*'">; def err_opencl_enqueue_kernel_blocks_no_args : Error< - "blocks in this form of device side enqueue call are expected to have have no parameters">; + "blocks with parameters are not accepted in this prototype of enqueue_kernel call">; // OpenCL v2.2 s2.1.2.3 - Vector Component Access def ext_opencl_ext_vector_type_rgba_selector: ExtWarn< @@ -8708,8 +8839,7 @@ let CategoryName = "Coroutines Issue" in { def err_return_in_coroutine : Error< "return statement not allowed in coroutine; did you mean 'co_return'?">; def note_declared_coroutine_here : Note< - "function is a coroutine due to use of " - "'%select{co_await|co_yield|co_return}0' here">; + "function is a coroutine due to use of '%0' here">; def err_coroutine_objc_method : Error< "Objective-C methods as coroutines are not yet supported">; def err_coroutine_unevaluated_context : Error< @@ -8721,24 +8851,38 @@ def err_coroutine_invalid_func_context : Error< "|a copy assignment operator|a move assignment operator|the 'main' function" "|a constexpr function|a function with a deduced return type" "|a varargs function}0">; -def err_implied_std_coroutine_traits_not_found : Error< - "you need to include <experimental/coroutine> before defining a coroutine">; +def err_implied_coroutine_type_not_found : Error< + "%0 type was not found; include <experimental/coroutine> before defining " + "a coroutine">; +def err_malformed_std_coroutine_handle : Error< + "std::experimental::coroutine_handle must be a class template">; +def err_coroutine_handle_missing_member : Error< + "std::experimental::coroutine_handle missing a member named '%0'">; def err_malformed_std_coroutine_traits : Error< "'std::experimental::coroutine_traits' must be a class template">; def err_implied_std_coroutine_traits_promise_type_not_found : Error< "this function cannot be a coroutine: %q0 has no member named 'promise_type'">; def err_implied_std_coroutine_traits_promise_type_not_class : Error< "this function cannot be a coroutine: %0 is not a class">; -def err_coroutine_traits_missing_specialization : Error< +def err_coroutine_promise_type_incomplete : Error< + "this function cannot be a coroutine: %0 is an incomplete type">; +def err_coroutine_type_missing_specialization : Error< "this function cannot be a coroutine: missing definition of " "specialization %q0">; -def err_implied_std_current_exception_not_found : Error< - "you need to include <exception> before defining a coroutine that implicitly " - "uses 'set_exception'">; -def err_malformed_std_current_exception : Error< - "'std::current_exception' must be a function">; def err_coroutine_promise_return_ill_formed : Error< "%0 declares both 'return_value' and 'return_void'">; +def note_coroutine_promise_implicit_await_transform_required_here : Note< + "call to 'await_transform' implicitly required by 'co_await' here">; +def note_coroutine_promise_call_implicitly_required : Note< + "call to '%select{initial_suspend|final_suspend}0' implicitly " + "required by the %select{initial suspend point|final suspend point}0">; +def err_coroutine_promise_unhandled_exception_required : Error< + "%0 is required to declare the member 'unhandled_exception()'">; +def warn_coroutine_promise_unhandled_exception_required_with_exceptions : Warning< + "%0 is required to declare the member 'unhandled_exception()' when exceptions are enabled">, + InGroup<Coroutine>; +def err_coroutine_promise_get_return_object_on_allocation_failure : Error< + "%0: 'get_return_object_on_allocation_failure()' must be a static member function">; } let CategoryName = "Documentation Issue" in { @@ -8905,4 +9049,9 @@ def ext_warn_gnu_final : ExtWarn< "__final is a GNU extension, consider using C++11 final">, InGroup<GccCompat>; +def warn_shadow_field : + Warning<"non-static data member '%0' of '%1' shadows member inherited from type '%2'">, + InGroup<ShadowField>, DefaultIgnore; +def note_shadow_field : Note<"declared here">; + } // end of sema component. diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td index 066a1f5fa68f..4af4c18ced33 100644 --- a/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/include/clang/Basic/DiagnosticSerializationKinds.td @@ -117,6 +117,57 @@ def note_module_odr_violation_different_definitions : Note< def err_module_odr_violation_different_instantiations : Error< "instantiation of %q0 is different in different modules">; +def err_module_odr_violation_mismatch_decl : Error< + "%q0 has different definitions in different modules; first difference is " + "%select{definition in module '%2'|defined here}1 found " + "%select{end of class|public access specifier|private access specifier|" + "protected access specifier|static assert|field|method}3">; +def note_module_odr_violation_mismatch_decl : Note<"but in '%0' found " + "%select{end of class|public access specifier|private access specifier|" + "protected access specifier|static assert|field|method}1">; + +def err_module_odr_violation_mismatch_decl_diff : Error< + "%q0 has different definitions in different modules; first difference is " + "%select{definition in module '%2'|defined here}1 found " + "%select{" + "static assert with condition|" + "static assert with message|" + "static assert with %select{|no }4message|" + "field %4|" + "field %4 with type %5|" + "%select{non-|}5bitfield %4|" + "bitfield %4 with one width expression|" + "%select{non-|}5mutable field %4|" + "field %4 with %select{no|an}5 initalizer|" + "field %4 with an initializer|" + "method %4|" + "method %4 is %select{not deleted|deleted}5|" + "method %4 is %select{|pure }5%select{not virtual|virtual}6|" + "method %4 is %select{not static|static}5|" + "method %4 is %select{not volatile|volatile}5|" + "method %4 is %select{not const|const}5|" + "method %4 is %select{not inline|inline}5}3">; + +def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " + "%select{" + "static assert with different condition|" + "static assert with different message|" + "static assert with %select{|no }2message|" + "field %2|" + "field %2 with type %3|" + "%select{non-|}3bitfield %2|" + "bitfield %2 with different width expression|" + "%select{non-|}3mutable field %2|" + "field %2 with %select{no|an}3 initializer|" + "field %2 with a different initializer|" + "method %2|" + "method %2 is %select{not deleted|deleted}3|" + "method %2 is %select{|pure }3%select{not virtual|virtual}4|" + "method %2 is %select{not static|static}3|" + "method %2 is %select{not volatile|volatile}3|" + "method %2 is %select{not const|const}3|" + "method %2 is %select{not inline|inline}3}1">; + def warn_module_uses_date_time : Warning< "%select{precompiled header|module}0 uses __DATE__ or __TIME__">, InGroup<DiagGroup<"pch-date-time">>; @@ -125,6 +176,11 @@ def warn_duplicate_module_file_extension : Warning< "duplicate module file extension block name '%0'">, InGroup<ModuleFileExtension>; +def warn_module_system_bit_conflict : Warning< + "module file '%0' was validated as a system module and is now being imported " + "as a non-system module; any difference in diagnostic options will be ignored">, + InGroup<ModuleConflict>; + } // let CategoryName } // let Component diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index 3001d0b1b0c7..a5fd14104d3c 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -280,7 +280,11 @@ public: bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; } /// \brief Return true if this token is a keyword in the specified language. - bool isKeyword(const LangOptions &LangOpts); + bool isKeyword(const LangOptions &LangOpts) const; + + /// \brief Return true if this token is a C++ keyword in the specified + /// language. + bool isCPlusPlusKeyword(const LangOptions &LangOpts) const; /// getFETokenInfo/setFETokenInfo - The language front-end is allowed to /// associate arbitrary metadata with this token. @@ -818,6 +822,7 @@ public: #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ CXXOperator##Name, #include "clang/Basic/OperatorKinds.def" + CXXDeductionGuide, CXXLiteralOperator, CXXUsingDirective, NUM_EXTRA_KINDS diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index d944a9d78ab9..c8e197299754 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -107,7 +107,7 @@ LANGOPT(WChar , 1, CPlusPlus, "wchar_t keyword") LANGOPT(DeclSpecKeyword , 1, 0, "__declspec keyword") BENIGN_LANGOPT(DollarIdents , 1, 1, "'$' in identifiers") BENIGN_LANGOPT(AsmPreprocessor, 1, 0, "preprocessor in asm mode") -BENIGN_LANGOPT(GNUMode , 1, 1, "GNU extensions") +LANGOPT(GNUMode , 1, 1, "GNU extensions") LANGOPT(GNUKeywords , 1, 1, "GNU keywords") BENIGN_LANGOPT(ImplicitInt, 1, !C99 && !CPlusPlus, "C89 implicit 'int'") LANGOPT(Digraphs , 1, 0, "digraphs") @@ -201,6 +201,8 @@ LANGOPT(SizedDeallocation , 1, 0, "sized deallocation") LANGOPT(AlignedAllocation , 1, 0, "aligned allocation") LANGOPT(NewAlignOverride , 32, 0, "maximum alignment guaranteed by '::operator new(size_t)'") LANGOPT(ConceptsTS , 1, 0, "enable C++ Extensions for Concepts") +BENIGN_LANGOPT(ModulesCodegen , 1, 0, "Modules code generation") +BENIGN_LANGOPT(ModulesDebugInfo , 1, 0, "Modules debug info") BENIGN_LANGOPT(ElideConstructors , 1, 1, "C++ copy constructor elision") BENIGN_LANGOPT(DumpRecordLayouts , 1, 0, "dumping the layout of IRgen'd records") BENIGN_LANGOPT(DumpRecordLayoutsSimple , 1, 0, "dumping the layout of IRgen'd records in a simple form") @@ -215,7 +217,8 @@ BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger Objective-C literals and su BENIGN_LANGOPT(SpellChecking , 1, 1, "spell-checking") LANGOPT(SinglePrecisionConstants , 1, 0, "treating double-precision floating point constants as single precision constants") LANGOPT(FastRelaxedMath , 1, 0, "OpenCL fast relaxed math") -LANGOPT(DefaultFPContract , 1, 0, "FP_CONTRACT") +/// \brief FP_CONTRACT mode (on/off/fast). +ENUM_LANGOPT(DefaultFPContractMode, FPContractModeKind, 2, FPC_Off, "FP contraction type") LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment") LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility") LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting") @@ -261,6 +264,8 @@ LANGOPT(SanitizeAddressFieldPadding, 2, 0, "controls how aggressive is ASan " "field padding (0: none, 1:least " "aggressive, 2: more aggressive)") +LANGOPT(XRayInstrument, 1, 0, "controls whether to do XRay instrumentation") + #undef LANGOPT #undef COMPATIBLE_LANGOPT #undef BENIGN_LANGOPT diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 10635b11225e..20a0e5845602 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -88,6 +88,12 @@ public: MSVC2015 = 19 }; + 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: /// \brief Set of enabled sanitizers. SanitizerSet Sanitize; @@ -96,6 +102,16 @@ public: /// (files, functions, variables) should not be instrumented. std::vector<std::string> SanitizerBlacklistFiles; + /// \brief Paths to the XRay "always instrument" files specifying which + /// objects (files, functions, variables) should be imbued with the XRay + /// "always instrument" attribute. + std::vector<std::string> XRayAlwaysInstrumentFiles; + + /// \brief Paths to the XRay "never instrument" files specifying which + /// objects (files, functions, variables) should be imbued with the XRay + /// "never instrument" attribute. + std::vector<std::string> XRayNeverInstrumentFiles; + clang::ObjCRuntime ObjCRuntime; std::string ObjCConstantStringClass; @@ -170,17 +186,45 @@ public: /// \brief Is this a libc/libm function that is no longer recognized as a /// builtin because a -fno-builtin-* option has been specified? bool isNoBuiltinFunc(StringRef Name) const; + + /// \brief True if any ObjC types may have non-trivial lifetime qualifiers. + bool allowsNonTrivialObjCLifetimeQualifiers() const { + return ObjCAutoRefCount || ObjCWeak; + } }; /// \brief Floating point control options class FPOptions { public: - unsigned fp_contract : 1; + FPOptions() : fp_contract(LangOptions::FPC_Off) {} + + // Used for serializing. + explicit FPOptions(unsigned I) + : fp_contract(static_cast<LangOptions::FPContractModeKind>(I)) {} + + explicit FPOptions(const LangOptions &LangOpts) + : fp_contract(LangOpts.getDefaultFPContractMode()) {} + + bool allowFPContractWithinStatement() const { + return fp_contract == LangOptions::FPC_On; + } + bool allowFPContractAcrossStatement() const { + return fp_contract == LangOptions::FPC_Fast; + } + void setAllowFPContractWithinStatement() { + fp_contract = LangOptions::FPC_On; + } + void setAllowFPContractAcrossStatement() { + fp_contract = LangOptions::FPC_Fast; + } + void setDisallowFPContract() { fp_contract = LangOptions::FPC_Off; } - FPOptions() : fp_contract(0) {} + /// Used to serialize this. + unsigned getInt() const { return fp_contract; } - FPOptions(const LangOptions &LangOpts) : - fp_contract(LangOpts.DefaultFPContract) {} +private: + /// Adjust BinaryOperator::FPFeatures to match the bit-field size of this. + unsigned fp_contract : 2; }; /// \brief Describes the kind of translation unit being processed. diff --git a/include/clang/Basic/MemoryBufferCache.h b/include/clang/Basic/MemoryBufferCache.h new file mode 100644 index 000000000000..c79c3c40e4eb --- /dev/null +++ b/include/clang/Basic/MemoryBufferCache.h @@ -0,0 +1,80 @@ +//===- MemoryBufferCache.h - Cache for loaded memory buffers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_MEMORYBUFFERCACHE_H +#define LLVM_CLANG_BASIC_MEMORYBUFFERCACHE_H + +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/StringMap.h" +#include <memory> + +namespace llvm { +class MemoryBuffer; +} // end namespace llvm + +namespace clang { + +/// Manage memory buffers across multiple users. +/// +/// Ensures that multiple users have a consistent view of each buffer. This is +/// used by \a CompilerInstance when building PCMs to ensure that each \a +/// ModuleManager sees the same files. +/// +/// \a finalizeCurrentBuffers() should be called before creating a new user. +/// This locks in the current buffers, ensuring that no buffer that has already +/// been accessed can be purged, preventing use-after-frees. +class MemoryBufferCache : public llvm::RefCountedBase<MemoryBufferCache> { + struct BufferEntry { + std::unique_ptr<llvm::MemoryBuffer> Buffer; + + /// Track the timeline of when this was added to the cache. + unsigned Index; + }; + + /// Cache of buffers. + llvm::StringMap<BufferEntry> Buffers; + + /// Monotonically increasing index. + unsigned NextIndex = 0; + + /// Bumped to prevent "older" buffers from being removed. + unsigned FirstRemovableIndex = 0; + +public: + /// Store the Buffer under the Filename. + /// + /// \pre There is not already buffer is not already in the cache. + /// \return a reference to the buffer as a convenience. + llvm::MemoryBuffer &addBuffer(llvm::StringRef Filename, + std::unique_ptr<llvm::MemoryBuffer> Buffer); + + /// Try to remove a buffer from the cache. + /// + /// \return false on success, iff \c !isBufferFinal(). + bool tryToRemoveBuffer(llvm::StringRef Filename); + + /// Get a pointer to the buffer if it exists; else nullptr. + llvm::MemoryBuffer *lookupBuffer(llvm::StringRef Filename); + + /// Check whether the buffer is final. + /// + /// \return true iff \a finalizeCurrentBuffers() has been called since the + /// buffer was added. This prevents buffers from being removed. + bool isBufferFinal(llvm::StringRef Filename); + + /// Finalize the current buffers in the cache. + /// + /// Should be called when creating a new user to ensure previous uses aren't + /// invalidated. + void finalizeCurrentBuffers(); +}; + +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_MEMORYBUFFERCACHE_H diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index 31c5c7ec9ca8..8fcb0e8b056a 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -42,7 +42,17 @@ class IdentifierInfo; /// \brief Describes the name of a module. typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId; - + +/// The signature of a module, which is a hash of the AST content. +struct ASTFileSignature : std::array<uint32_t, 5> { + ASTFileSignature(std::array<uint32_t, 5> S = {{0}}) + : std::array<uint32_t, 5>(std::move(S)) {} + + explicit operator bool() const { + return *this != std::array<uint32_t, 5>({{0}}); + } +}; + /// \brief Describes a module or submodule. class Module { public: @@ -65,7 +75,7 @@ public: llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella; /// \brief The module signature. - uint64_t Signature; + ASTFileSignature Signature; /// \brief The name of the umbrella entry, as written in the module map. std::string UmbrellaAsWritten; diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h index 78fc89988245..8dc259c7ab66 100644 --- a/include/clang/Basic/ObjCRuntime.h +++ b/include/clang/Basic/ObjCRuntime.h @@ -326,6 +326,20 @@ public: } } + /// Are the empty collection symbols available? + bool hasEmptyCollections() const { + switch (getKind()) { + default: + return false; + case MacOSX: + return getVersion() >= VersionTuple(10, 11); + case iOS: + return getVersion() >= VersionTuple(9); + case WatchOS: + return getVersion() >= VersionTuple(2); + } + } + /// \brief Try to parse an Objective-C runtime specification from the given /// string. /// diff --git a/include/clang/Basic/OpenCLImageTypes.def b/include/clang/Basic/OpenCLImageTypes.def index 1ca12f683beb..0efed996ab96 100644 --- a/include/clang/Basic/OpenCLImageTypes.def +++ b/include/clang/Basic/OpenCLImageTypes.def @@ -66,7 +66,7 @@ IMAGE_WRITE_TYPE(image2d_msaa, OCLImage2dMSAA, "cl_khr_gl_msaa_sharing") IMAGE_WRITE_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA, "cl_khr_gl_msaa_sharing") IMAGE_WRITE_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth, "cl_khr_gl_msaa_sharing") IMAGE_WRITE_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth, "cl_khr_gl_msaa_sharing") -IMAGE_WRITE_TYPE(image3d, OCLImage3d, "") +IMAGE_WRITE_TYPE(image3d, OCLImage3d, "cl_khr_3d_image_writes") IMAGE_READ_WRITE_TYPE(image1d, OCLImage1d, "") IMAGE_READ_WRITE_TYPE(image1d_array, OCLImage1dArray, "") diff --git a/include/clang/Basic/OpenMPKinds.h b/include/clang/Basic/OpenMPKinds.h index 60b9fcef9219..e00333153f9b 100644 --- a/include/clang/Basic/OpenMPKinds.h +++ b/include/clang/Basic/OpenMPKinds.h @@ -234,6 +234,11 @@ bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind); /// directives that need loop bound sharing across loops outlined in nested /// functions bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind); + +/// Return the captured regions of an OpenMP directive. +void getOpenMPCaptureRegions( + llvm::SmallVectorImpl<OpenMPDirectiveKind> &CaptureRegions, + OpenMPDirectiveKind DKind); } #endif diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def index c81273ea5fd4..c574045e139a 100644 --- a/include/clang/Basic/Sanitizers.def +++ b/include/clang/Basic/Sanitizers.def @@ -64,6 +64,11 @@ SANITIZER("function", Function) SANITIZER("integer-divide-by-zero", IntegerDivideByZero) SANITIZER("nonnull-attribute", NonnullAttribute) SANITIZER("null", Null) +SANITIZER("nullability-arg", NullabilityArg) +SANITIZER("nullability-assign", NullabilityAssign) +SANITIZER("nullability-return", NullabilityReturn) +SANITIZER_GROUP("nullability", Nullability, + NullabilityArg | NullabilityAssign | NullabilityReturn) SANITIZER("object-size", ObjectSize) SANITIZER("return", Return) SANITIZER("returns-nonnull-attribute", ReturnsNonnullAttribute) diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h index 006cf3dc950c..f0fe4c27062e 100644 --- a/include/clang/Basic/SourceLocation.h +++ b/include/clang/Basic/SourceLocation.h @@ -321,8 +321,7 @@ public: } /// \brief Comparison function class, useful for sorting FullSourceLocs. - struct BeforeThanCompare : public std::binary_function<FullSourceLoc, - FullSourceLoc, bool> { + struct BeforeThanCompare { bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const { return lhs.isBeforeInTranslationUnitThan(rhs); } diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index 369a36f3dca6..33952f83ff23 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -82,11 +82,12 @@ namespace clang { /// \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; + static_assert(TST_error < 1 << 6, "Type bitfield not wide enough for TST"); + /*DeclSpec::TST*/ unsigned Type : 6; /*DeclSpec::TSS*/ unsigned Sign : 2; /*DeclSpec::TSW*/ unsigned Width : 2; unsigned ModeAttr : 1; - }; + }; /// \brief A C++ access specifier (public, private, protected), plus the /// special value "none" which means different things in different contexts. diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index 67a5ab773aa6..0d21845fbf8b 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -43,7 +43,7 @@ def ObjCAtSynchronizedStmt : Stmt; def ObjCForCollectionStmt : Stmt; def ObjCAutoreleasePoolStmt : Stmt; -// C++ statments +// C++ statements def CXXCatchStmt : Stmt; def CXXTryStmt : Stmt; def CXXForRangeStmt : Stmt; @@ -150,6 +150,7 @@ def CXXFoldExpr : DStmt<Expr>; // C++ Coroutines TS expressions def CoroutineSuspendExpr : DStmt<Expr, 1>; def CoawaitExpr : DStmt<CoroutineSuspendExpr>; +def DependentCoawaitExpr : DStmt<Expr>; def CoyieldExpr : DStmt<CoroutineSuspendExpr>; // Obj-C Expressions. diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 208f8e8c7137..9bdb288eef4f 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -154,7 +154,7 @@ public: /// typedef void* __builtin_va_list; VoidPtrBuiltinVaList, - /// __builtin_va_list as defind by the AArch64 ABI + /// __builtin_va_list as defined by the AArch64 ABI /// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055a/IHI0055A_aapcs64.pdf AArch64ABIBuiltinVaList, @@ -168,7 +168,7 @@ public: PowerABIBuiltinVaList, /// __builtin_va_list as defined by the x86-64 ABI: - /// http://www.x86-64.org/documentation/abi.pdf + /// http://refspecs.linuxbase.org/elf/x86_64-abi-0.21.pdf X86_64ABIBuiltinVaList, /// __builtin_va_list as defined by ARM AAPCS ABI @@ -823,8 +823,9 @@ public: /// \brief Set forced language options. /// /// Apply changes to the target information with respect to certain - /// language options which change the target configuration. - virtual void adjust(const LangOptions &Opts); + /// language options which change the target configuration and adjust + /// the language based on the target options where applicable. + virtual void adjust(LangOptions &Opts); /// \brief Adjust target options based on codegen options. virtual void adjustTargetOptions(const CodeGenOptions &CGOpts, @@ -1032,6 +1033,21 @@ public: return LangAS::opencl_global; } + /// \returns Target specific vtbl ptr address space. + virtual unsigned getVtblPtrAddressSpace() const { + return 0; + } + + /// \returns If a target requires an address within a target specific address + /// space \p AddressSpace to be converted in order to be used, then return the + /// corresponding target specific DWARF address space. + /// + /// \returns Otherwise return None and no conversion will be emitted in the + /// DWARF. + virtual Optional<unsigned> getDWARFAddressSpace(unsigned AddressSpace) const { + return None; + } + /// \brief Check the target is valid after it is fully initialized. virtual bool validateTarget(DiagnosticsEngine &Diags) const { return true; diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 104b053a14af..48e0c33f0e86 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -432,6 +432,7 @@ TYPE_TRAIT_1(__has_trivial_move_constructor, HasTrivialMoveConstructor, KEYCXX) TYPE_TRAIT_1(__has_trivial_destructor, HasTrivialDestructor, KEYCXX) TYPE_TRAIT_1(__has_virtual_destructor, HasVirtualDestructor, KEYCXX) TYPE_TRAIT_1(__is_abstract, IsAbstract, KEYCXX) +TYPE_TRAIT_1(__is_aggregate, IsAggregate, KEYCXX) TYPE_TRAIT_2(__is_base_of, IsBaseOf, KEYCXX) TYPE_TRAIT_1(__is_class, IsClass, KEYCXX) TYPE_TRAIT_2(__is_convertible_to, IsConvertibleTo, KEYCXX) @@ -787,6 +788,8 @@ ANNOTATION(pragma_openmp_end) // handles #pragma loop ... directives. ANNOTATION(pragma_loop_hint) +ANNOTATION(pragma_fp) + // Annotations for module import translated from #include etc. ANNOTATION(module_include) ANNOTATION(module_begin) diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h index 730ecba3d4fa..ffe62559002e 100644 --- a/include/clang/Basic/TypeTraits.h +++ b/include/clang/Basic/TypeTraits.h @@ -31,6 +31,7 @@ namespace clang { UTT_HasTrivialDestructor, UTT_HasVirtualDestructor, UTT_IsAbstract, + UTT_IsAggregate, UTT_IsArithmetic, UTT_IsArray, UTT_IsClass, diff --git a/include/clang/Basic/VirtualFileSystem.h b/include/clang/Basic/VirtualFileSystem.h index 39dab6cbf045..e52b345e286c 100644 --- a/include/clang/Basic/VirtualFileSystem.h +++ b/include/clang/Basic/VirtualFileSystem.h @@ -161,7 +161,7 @@ public: directory_iterator &increment(std::error_code &EC) { assert(Impl && "attempting to increment past end"); EC = Impl->increment(); - if (EC || !Impl->CurrentEntry.isStatusKnown()) + if (!Impl->CurrentEntry.isStatusKnown()) Impl.reset(); // Normalize the end iterator to Impl == nullptr. return *this; } diff --git a/include/clang/Basic/XRayLists.h b/include/clang/Basic/XRayLists.h new file mode 100644 index 000000000000..fe538289c3a6 --- /dev/null +++ b/include/clang/Basic/XRayLists.h @@ -0,0 +1,54 @@ +//===--- XRayLists.h - XRay automatic attribution ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// User-provided filters for always/never XRay instrumenting certain functions. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_BASIC_XRAYLISTS_H +#define LLVM_CLANG_BASIC_XRAYLISTS_H + +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SpecialCaseList.h" +#include <memory> + +namespace clang { + +class XRayFunctionFilter { + std::unique_ptr<llvm::SpecialCaseList> AlwaysInstrument; + std::unique_ptr<llvm::SpecialCaseList> NeverInstrument; + SourceManager &SM; + +public: + XRayFunctionFilter(ArrayRef<std::string> AlwaysInstrumentPaths, + ArrayRef<std::string> NeverInstrumentPaths, + SourceManager &SM); + + enum class ImbueAttribute { + NONE, + ALWAYS, + NEVER, + }; + + ImbueAttribute shouldImbueFunction(StringRef FunctionName) const; + + ImbueAttribute + shouldImbueFunctionsInFile(StringRef Filename, + StringRef Category = StringRef()) const; + + ImbueAttribute shouldImbueLocation(SourceLocation Loc, + StringRef Category = StringRef()) const; +}; + +} // namespace clang + +#endif diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index 5605fc6de2b6..ad8d679a1664 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -1362,7 +1362,7 @@ def SCALAR_SHL: SInst<"vshl", "sss", "SlSUl">; def SCALAR_QSHL: SInst<"vqshl", "sss", "ScSsSiSlSUcSUsSUiSUl">; // Scalar Saturating Rounding Shift Left def SCALAR_QRSHL: SInst<"vqrshl", "sss", "ScSsSiSlSUcSUsSUiSUl">; -// Scalar Shift Rouding Left +// Scalar Shift Rounding Left def SCALAR_RSHL: SInst<"vrshl", "sss", "SlSUl">; //////////////////////////////////////////////////////////////////////////////// diff --git a/include/clang/CodeGen/BackendUtil.h b/include/clang/CodeGen/BackendUtil.h index c6abc6e3f574..bb105cb533a4 100644 --- a/include/clang/CodeGen/BackendUtil.h +++ b/include/clang/CodeGen/BackendUtil.h @@ -15,6 +15,8 @@ #include <memory> namespace llvm { + class BitcodeModule; + template <typename T> class Expected; class Module; class MemoryBufferRef; } @@ -44,6 +46,9 @@ namespace clang { void EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts, llvm::MemoryBufferRef Buf); + + llvm::Expected<llvm::BitcodeModule> + FindThinLTOModule(llvm::MemoryBufferRef MBRef); } #endif diff --git a/include/clang/CodeGen/CodeGenABITypes.h b/include/clang/CodeGen/CodeGenABITypes.h index e7b7435968fb..8ba769dfc3af 100644 --- a/include/clang/CodeGen/CodeGenABITypes.h +++ b/include/clang/CodeGen/CodeGenABITypes.h @@ -16,7 +16,7 @@ // // It allows other clients, like LLDB, to determine the LLVM types that are // actually used in function calls, which makes it possible to then determine -// the acutal ABI locations (e.g. registers, stack locations, etc.) that +// the actual ABI locations (e.g. registers, stack locations, etc.) that // these parameters are stored in. // //===----------------------------------------------------------------------===// diff --git a/include/clang/CodeGen/CodeGenAction.h b/include/clang/CodeGen/CodeGenAction.h index cc38e243420b..5a18a9de030b 100644 --- a/include/clang/CodeGen/CodeGenAction.h +++ b/include/clang/CodeGen/CodeGenAction.h @@ -23,14 +23,36 @@ class BackendConsumer; class CodeGenAction : public ASTFrontendAction { private: + // Let BackendConsumer access LinkModule. + friend class BackendConsumer; + + /// Info about module to link into a module we're generating. + struct LinkModule { + /// The module to link in. + std::unique_ptr<llvm::Module> Module; + + /// If true, we set attributes on Module's functions according to our + /// CodeGenOptions and LangOptions, as though we were generating the + /// function ourselves. + bool PropagateAttrs; + + /// If true, we use LLVM module internalizer. + bool Internalize; + + /// Bitwise combination of llvm::LinkerFlags used when we link the module. + unsigned LinkFlags; + }; + unsigned Act; std::unique_ptr<llvm::Module> TheModule; - // Vector of {Linker::Flags, Module*} pairs to specify bitcode - // modules to link in using corresponding linker flags. - SmallVector<std::pair<unsigned, llvm::Module *>, 4> LinkModules; + + /// Bitcode modules to link in to our module. + SmallVector<LinkModule, 4> LinkModules; llvm::LLVMContext *VMContext; bool OwnsVMContext; + std::unique_ptr<llvm::Module> loadModule(llvm::MemoryBufferRef MBRef); + protected: /// Create a new code generation action. If the optional \p _VMContext /// parameter is supplied, the action uses it without taking ownership, @@ -49,13 +71,6 @@ protected: public: ~CodeGenAction() override; - /// setLinkModule - Set the link module to be used by this action. If a link - /// module is not provided, and CodeGenOptions::LinkBitcodeFile is non-empty, - /// the action will load it from the specified file. - void addLinkModule(llvm::Module *Mod, unsigned LinkFlags) { - LinkModules.push_back(std::make_pair(LinkFlags, Mod)); - } - /// Take the generated LLVM module, for use after the action has been run. /// The result may be null on failure. std::unique_ptr<llvm::Module> takeModule(); diff --git a/include/clang/CodeGen/ConstantInitBuilder.h b/include/clang/CodeGen/ConstantInitBuilder.h new file mode 100644 index 000000000000..113d86d82c10 --- /dev/null +++ b/include/clang/CodeGen/ConstantInitBuilder.h @@ -0,0 +1,561 @@ +//===- ConstantInitBuilder.h - Builder for LLVM IR constants ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class provides a convenient interface for building complex +// global initializers of the sort that are frequently required for +// language ABIs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H +#define LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/GlobalValue.h" +#include "clang/AST/CharUnits.h" +#include "clang/CodeGen/ConstantInitFuture.h" + +#include <vector> + +namespace clang { +namespace CodeGen { + +class CodeGenModule; + +/// A convenience builder class for complex constant initializers, +/// especially for anonymous global structures used by various language +/// runtimes. +/// +/// The basic usage pattern is expected to be something like: +/// ConstantInitBuilder builder(CGM); +/// auto toplevel = builder.beginStruct(); +/// toplevel.addInt(CGM.SizeTy, widgets.size()); +/// auto widgetArray = builder.beginArray(); +/// for (auto &widget : widgets) { +/// auto widgetDesc = widgetArray.beginStruct(); +/// widgetDesc.addInt(CGM.SizeTy, widget.getPower()); +/// widgetDesc.add(CGM.GetAddrOfConstantString(widget.getName())); +/// widgetDesc.add(CGM.GetAddrOfGlobal(widget.getInitializerDecl())); +/// widgetDesc.finishAndAddTo(widgetArray); +/// } +/// widgetArray.finishAndAddTo(toplevel); +/// auto global = toplevel.finishAndCreateGlobal("WIDGET_LIST", Align, +/// /*constant*/ true); +class ConstantInitBuilderBase { + struct SelfReference { + llvm::GlobalVariable *Dummy; + llvm::SmallVector<llvm::Constant*, 4> Indices; + + SelfReference(llvm::GlobalVariable *dummy) : Dummy(dummy) {} + }; + CodeGenModule &CGM; + llvm::SmallVector<llvm::Constant*, 16> Buffer; + std::vector<SelfReference> SelfReferences; + bool Frozen = false; + + friend class ConstantInitFuture; + friend class ConstantAggregateBuilderBase; + template <class, class> + friend class ConstantAggregateBuilderTemplateBase; + +protected: + explicit ConstantInitBuilderBase(CodeGenModule &CGM) : CGM(CGM) {} + + ~ConstantInitBuilderBase() { + assert(Buffer.empty() && "didn't claim all values out of buffer"); + assert(SelfReferences.empty() && "didn't apply all self-references"); + } + +private: + llvm::GlobalVariable *createGlobal(llvm::Constant *initializer, + const llvm::Twine &name, + CharUnits alignment, + bool constant = false, + llvm::GlobalValue::LinkageTypes linkage + = llvm::GlobalValue::InternalLinkage, + unsigned addressSpace = 0); + + ConstantInitFuture createFuture(llvm::Constant *initializer); + + void setGlobalInitializer(llvm::GlobalVariable *GV, + llvm::Constant *initializer); + + void resolveSelfReferences(llvm::GlobalVariable *GV); + + void abandon(size_t newEnd); +}; + +/// A concrete base class for struct and array aggregate +/// initializer builders. +class ConstantAggregateBuilderBase { +protected: + ConstantInitBuilderBase &Builder; + ConstantAggregateBuilderBase *Parent; + size_t Begin; + mutable size_t CachedOffsetEnd = 0; + bool Finished = false; + bool Frozen = false; + bool Packed = false; + mutable CharUnits CachedOffsetFromGlobal; + + llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() { + return Builder.Buffer; + } + + const llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() const { + return Builder.Buffer; + } + + ConstantAggregateBuilderBase(ConstantInitBuilderBase &builder, + ConstantAggregateBuilderBase *parent) + : Builder(builder), Parent(parent), Begin(builder.Buffer.size()) { + if (parent) { + assert(!parent->Frozen && "parent already has child builder active"); + parent->Frozen = true; + } else { + assert(!builder.Frozen && "builder already has child builder active"); + builder.Frozen = true; + } + } + + ~ConstantAggregateBuilderBase() { + assert(Finished && "didn't finish aggregate builder"); + } + + void markFinished() { + assert(!Frozen && "child builder still active"); + assert(!Finished && "builder already finished"); + Finished = true; + if (Parent) { + assert(Parent->Frozen && + "parent not frozen while child builder active"); + Parent->Frozen = false; + } else { + assert(Builder.Frozen && + "builder not frozen while child builder active"); + Builder.Frozen = false; + } + } + +public: + // Not copyable. + ConstantAggregateBuilderBase(const ConstantAggregateBuilderBase &) = delete; + ConstantAggregateBuilderBase &operator=(const ConstantAggregateBuilderBase &) + = delete; + + // Movable, mostly to allow returning. But we have to write this out + // properly to satisfy the assert in the destructor. + ConstantAggregateBuilderBase(ConstantAggregateBuilderBase &&other) + : Builder(other.Builder), Parent(other.Parent), Begin(other.Begin), + CachedOffsetEnd(other.CachedOffsetEnd), + Finished(other.Finished), Frozen(other.Frozen), Packed(other.Packed), + CachedOffsetFromGlobal(other.CachedOffsetFromGlobal) { + other.Finished = true; + } + ConstantAggregateBuilderBase &operator=(ConstantAggregateBuilderBase &&other) + = delete; + + /// Return the number of elements that have been added to + /// this struct or array. + size_t size() const { + assert(!this->Finished && "cannot query after finishing builder"); + assert(!this->Frozen && "cannot query while sub-builder is active"); + assert(this->Begin <= this->getBuffer().size()); + return this->getBuffer().size() - this->Begin; + } + + /// Return true if no elements have yet been added to this struct or array. + bool empty() const { + return size() == 0; + } + + /// Abandon this builder completely. + void abandon() { + markFinished(); + Builder.abandon(Begin); + } + + /// Add a new value to this initializer. + void add(llvm::Constant *value) { + assert(value && "adding null value to constant initializer"); + assert(!Finished && "cannot add more values after finishing builder"); + assert(!Frozen && "cannot add values while subbuilder is active"); + Builder.Buffer.push_back(value); + } + + /// Add an integer value of type size_t. + void addSize(CharUnits size); + + /// Add an integer value of a specific type. + void addInt(llvm::IntegerType *intTy, uint64_t value, + bool isSigned = false) { + add(llvm::ConstantInt::get(intTy, value, isSigned)); + } + + /// Add a null pointer of a specific type. + void addNullPointer(llvm::PointerType *ptrTy) { + add(llvm::ConstantPointerNull::get(ptrTy)); + } + + /// Add a bitcast of a value to a specific type. + void addBitCast(llvm::Constant *value, llvm::Type *type) { + add(llvm::ConstantExpr::getBitCast(value, type)); + } + + /// Add a bunch of new values to this initializer. + void addAll(llvm::ArrayRef<llvm::Constant *> values) { + assert(!Finished && "cannot add more values after finishing builder"); + assert(!Frozen && "cannot add values while subbuilder is active"); + Builder.Buffer.append(values.begin(), values.end()); + } + + /// Add a relative offset to the given target address, i.e. the + /// static difference between the target address and the address + /// of the relative offset. The target must be known to be defined + /// in the current linkage unit. The offset will have the given + /// integer type, which must be no wider than intptr_t. Some + /// targets may not fully support this operation. + void addRelativeOffset(llvm::IntegerType *type, llvm::Constant *target) { + add(getRelativeOffset(type, target)); + } + + /// Add a relative offset to the target address, plus a small + /// constant offset. This is primarily useful when the relative + /// offset is known to be a multiple of (say) four and therefore + /// the tag can be used to express an extra two bits of information. + void addTaggedRelativeOffset(llvm::IntegerType *type, + llvm::Constant *address, + unsigned tag) { + llvm::Constant *offset = getRelativeOffset(type, address); + if (tag) { + offset = llvm::ConstantExpr::getAdd(offset, + llvm::ConstantInt::get(type, tag)); + } + add(offset); + } + + /// Return the offset from the start of the initializer to the + /// next position, assuming no padding is required prior to it. + /// + /// This operation will not succeed if any unsized placeholders are + /// currently in place in the initializer. + CharUnits getNextOffsetFromGlobal() const { + assert(!Finished && "cannot add more values after finishing builder"); + assert(!Frozen && "cannot add values while subbuilder is active"); + return getOffsetFromGlobalTo(Builder.Buffer.size()); + } + + /// An opaque class to hold the abstract position of a placeholder. + class PlaceholderPosition { + size_t Index; + friend class ConstantAggregateBuilderBase; + PlaceholderPosition(size_t index) : Index(index) {} + }; + + /// Add a placeholder value to the structure. The returned position + /// can be used to set the value later; it will not be invalidated by + /// any intermediate operations except (1) filling the same position or + /// (2) finishing the entire builder. + /// + /// This is useful for emitting certain kinds of structure which + /// contain some sort of summary field, generaly a count, before any + /// of the data. By emitting a placeholder first, the structure can + /// be emitted eagerly. + PlaceholderPosition addPlaceholder() { + assert(!Finished && "cannot add more values after finishing builder"); + assert(!Frozen && "cannot add values while subbuilder is active"); + Builder.Buffer.push_back(nullptr); + return Builder.Buffer.size() - 1; + } + + /// Add a placeholder, giving the expected type that will be filled in. + PlaceholderPosition addPlaceholderWithSize(llvm::Type *expectedType); + + /// Fill a previously-added placeholder. + void fillPlaceholderWithInt(PlaceholderPosition position, + llvm::IntegerType *type, uint64_t value, + bool isSigned = false) { + fillPlaceholder(position, llvm::ConstantInt::get(type, value, isSigned)); + } + + /// Fill a previously-added placeholder. + void fillPlaceholder(PlaceholderPosition position, llvm::Constant *value) { + assert(!Finished && "cannot change values after finishing builder"); + assert(!Frozen && "cannot add values while subbuilder is active"); + llvm::Constant *&slot = Builder.Buffer[position.Index]; + assert(slot == nullptr && "placeholder already filled"); + slot = value; + } + + /// Produce an address which will eventually point to the the next + /// position to be filled. This is computed with an indexed + /// getelementptr rather than by computing offsets. + /// + /// The returned pointer will have type T*, where T is the given + /// position. + llvm::Constant *getAddrOfCurrentPosition(llvm::Type *type); + + llvm::ArrayRef<llvm::Constant*> getGEPIndicesToCurrentPosition( + llvm::SmallVectorImpl<llvm::Constant*> &indices) { + getGEPIndicesTo(indices, Builder.Buffer.size()); + return indices; + } + +protected: + llvm::Constant *finishArray(llvm::Type *eltTy); + llvm::Constant *finishStruct(llvm::StructType *structTy); + +private: + void getGEPIndicesTo(llvm::SmallVectorImpl<llvm::Constant*> &indices, + size_t position) const; + + llvm::Constant *getRelativeOffset(llvm::IntegerType *offsetType, + llvm::Constant *target); + + CharUnits getOffsetFromGlobalTo(size_t index) const; +}; + +template <class Impl, class Traits> +class ConstantAggregateBuilderTemplateBase + : public Traits::AggregateBuilderBase { + using super = typename Traits::AggregateBuilderBase; +public: + using InitBuilder = typename Traits::InitBuilder; + using ArrayBuilder = typename Traits::ArrayBuilder; + using StructBuilder = typename Traits::StructBuilder; + using AggregateBuilderBase = typename Traits::AggregateBuilderBase; + +protected: + ConstantAggregateBuilderTemplateBase(InitBuilder &builder, + AggregateBuilderBase *parent) + : super(builder, parent) {} + + Impl &asImpl() { return *static_cast<Impl*>(this); } + +public: + ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) { + return ArrayBuilder(static_cast<InitBuilder&>(this->Builder), this, eltTy); + } + + StructBuilder beginStruct(llvm::StructType *ty = nullptr) { + return StructBuilder(static_cast<InitBuilder&>(this->Builder), this, ty); + } + + /// Given that this builder was created by beginning an array or struct + /// component on the given parent builder, finish the array/struct + /// component and add it to the parent. + /// + /// It is an intentional choice that the parent is passed in explicitly + /// despite it being redundant with information already kept in the + /// builder. This aids in readability by making it easier to find the + /// places that add components to a builder, as well as "bookending" + /// the sub-builder more explicitly. + void finishAndAddTo(AggregateBuilderBase &parent) { + assert(this->Parent == &parent && "adding to non-parent builder"); + parent.add(asImpl().finishImpl()); + } + + /// Given that this builder was created by beginning an array or struct + /// directly on a ConstantInitBuilder, finish the array/struct and + /// create a global variable with it as the initializer. + template <class... As> + llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { + assert(!this->Parent && "finishing non-root builder"); + return this->Builder.createGlobal(asImpl().finishImpl(), + std::forward<As>(args)...); + } + + /// Given that this builder was created by beginning an array or struct + /// directly on a ConstantInitBuilder, finish the array/struct and + /// set it as the initializer of the given global variable. + void finishAndSetAsInitializer(llvm::GlobalVariable *global) { + assert(!this->Parent && "finishing non-root builder"); + return this->Builder.setGlobalInitializer(global, asImpl().finishImpl()); + } + + /// Given that this builder was created by beginning an array or struct + /// directly on a ConstantInitBuilder, finish the array/struct and + /// return a future which can be used to install the initializer in + /// a global later. + /// + /// This is useful for allowing a finished initializer to passed to + /// an API which will build the global. However, the "future" preserves + /// a dependency on the original builder; it is an error to pass it aside. + ConstantInitFuture finishAndCreateFuture() { + assert(!this->Parent && "finishing non-root builder"); + return this->Builder.createFuture(asImpl().finishImpl()); + } +}; + +template <class Traits> +class ConstantArrayBuilderTemplateBase + : public ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder, + Traits> { + using super = + ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder, Traits>; + +public: + using InitBuilder = typename Traits::InitBuilder; + using AggregateBuilderBase = typename Traits::AggregateBuilderBase; + +private: + llvm::Type *EltTy; + + template <class, class> + friend class ConstantAggregateBuilderTemplateBase; + +protected: + ConstantArrayBuilderTemplateBase(InitBuilder &builder, + AggregateBuilderBase *parent, + llvm::Type *eltTy) + : super(builder, parent), EltTy(eltTy) {} + +private: + /// Form an array constant from the values that have been added to this + /// builder. + llvm::Constant *finishImpl() { + return AggregateBuilderBase::finishArray(EltTy); + } +}; + +/// A template class designed to allow other frontends to +/// easily customize the builder classes used by ConstantInitBuilder, +/// and thus to extend the API to work with the abstractions they +/// prefer. This would probably not be necessary if C++ just +/// supported extension methods. +template <class Traits> +class ConstantStructBuilderTemplateBase + : public ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder, + Traits> { + using super = + ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder,Traits>; + +public: + using InitBuilder = typename Traits::InitBuilder; + using AggregateBuilderBase = typename Traits::AggregateBuilderBase; + +private: + llvm::StructType *StructTy; + + template <class, class> + friend class ConstantAggregateBuilderTemplateBase; + +protected: + ConstantStructBuilderTemplateBase(InitBuilder &builder, + AggregateBuilderBase *parent, + llvm::StructType *structTy) + : super(builder, parent), StructTy(structTy) { + if (structTy) this->Packed = structTy->isPacked(); + } + +public: + void setPacked(bool packed) { + this->Packed = packed; + } + + /// Use the given type for the struct if its element count is correct. + /// Don't add more elements after calling this. + void suggestType(llvm::StructType *structTy) { + if (this->size() == structTy->getNumElements()) { + StructTy = structTy; + } + } + +private: + /// Form an array constant from the values that have been added to this + /// builder. + llvm::Constant *finishImpl() { + return AggregateBuilderBase::finishStruct(StructTy); + } +}; + +/// A template class designed to allow other frontends to +/// easily customize the builder classes used by ConstantInitBuilder, +/// and thus to extend the API to work with the abstractions they +/// prefer. This would probably not be necessary if C++ just +/// supported extension methods. +template <class Traits> +class ConstantInitBuilderTemplateBase : public ConstantInitBuilderBase { +protected: + ConstantInitBuilderTemplateBase(CodeGenModule &CGM) + : ConstantInitBuilderBase(CGM) {} + +public: + using InitBuilder = typename Traits::InitBuilder; + using ArrayBuilder = typename Traits::ArrayBuilder; + using StructBuilder = typename Traits::StructBuilder; + + ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) { + return ArrayBuilder(static_cast<InitBuilder&>(*this), nullptr, eltTy); + } + + StructBuilder beginStruct(llvm::StructType *structTy = nullptr) { + return StructBuilder(static_cast<InitBuilder&>(*this), nullptr, structTy); + } +}; + +class ConstantInitBuilder; +class ConstantStructBuilder; +class ConstantArrayBuilder; + +struct ConstantInitBuilderTraits { + using InitBuilder = ConstantInitBuilder; + using AggregateBuilderBase = ConstantAggregateBuilderBase; + using ArrayBuilder = ConstantArrayBuilder; + using StructBuilder = ConstantStructBuilder; +}; + +/// The standard implementation of ConstantInitBuilder used in Clang. +class ConstantInitBuilder + : public ConstantInitBuilderTemplateBase<ConstantInitBuilderTraits> { +public: + explicit ConstantInitBuilder(CodeGenModule &CGM) : + ConstantInitBuilderTemplateBase(CGM) {} +}; + +/// A helper class of ConstantInitBuilder, used for building constant +/// array initializers. +class ConstantArrayBuilder + : public ConstantArrayBuilderTemplateBase<ConstantInitBuilderTraits> { + template <class Traits> + friend class ConstantInitBuilderTemplateBase; + + // The use of explicit qualification is a GCC workaround. + template <class Impl, class Traits> + friend class CodeGen::ConstantAggregateBuilderTemplateBase; + + ConstantArrayBuilder(ConstantInitBuilder &builder, + ConstantAggregateBuilderBase *parent, + llvm::Type *eltTy) + : ConstantArrayBuilderTemplateBase(builder, parent, eltTy) {} +}; + +/// A helper class of ConstantInitBuilder, used for building constant +/// struct initializers. +class ConstantStructBuilder + : public ConstantStructBuilderTemplateBase<ConstantInitBuilderTraits> { + template <class Traits> + friend class ConstantInitBuilderTemplateBase; + + // The use of explicit qualification is a GCC workaround. + template <class Impl, class Traits> + friend class CodeGen::ConstantAggregateBuilderTemplateBase; + + ConstantStructBuilder(ConstantInitBuilder &builder, + ConstantAggregateBuilderBase *parent, + llvm::StructType *structTy) + : ConstantStructBuilderTemplateBase(builder, parent, structTy) {} +}; + +} // end namespace CodeGen +} // end namespace clang + +#endif diff --git a/include/clang/CodeGen/ConstantInitFuture.h b/include/clang/CodeGen/ConstantInitFuture.h new file mode 100644 index 000000000000..ef1a5d2f49af --- /dev/null +++ b/include/clang/CodeGen/ConstantInitFuture.h @@ -0,0 +1,111 @@ +//===- ConstantInitFuture.h - "Future" constant initializers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class defines the ConstantInitFuture class. This is split out +// from ConstantInitBuilder.h in order to allow APIs to work with it +// without having to include that entire header. This is particularly +// important because it is often useful to be able to default-construct +// a future in, say, a default argument. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_CONSTANTINITFUTURE_H +#define LLVM_CLANG_CODEGEN_CONSTANTINITFUTURE_H + +#include "llvm/ADT/PointerUnion.h" +#include "llvm/IR/Constant.h" + +// Forward-declare ConstantInitBuilderBase and give it a +// PointerLikeTypeTraits specialization so that we can safely use it +// in a PointerUnion below. +namespace clang { +namespace CodeGen { +class ConstantInitBuilderBase; +} +} +namespace llvm { +template <> +class PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitBuilderBase*> { +public: + using T = ::clang::CodeGen::ConstantInitBuilderBase*; + + static inline void *getAsVoidPointer(T p) { return p; } + static inline T getFromVoidPointer(void *p) {return static_cast<T>(p);} + enum { NumLowBitsAvailable = 2 }; +}; +} + +namespace clang { +namespace CodeGen { + +/// A "future" for a completed constant initializer, which can be passed +/// around independently of any sub-builders (but not the original parent). +class ConstantInitFuture { + using PairTy = llvm::PointerUnion<ConstantInitBuilderBase*, llvm::Constant*>; + + PairTy Data; + + friend class ConstantInitBuilderBase; + explicit ConstantInitFuture(ConstantInitBuilderBase *builder); + +public: + ConstantInitFuture() {} + + /// A future can be explicitly created from a fixed initializer. + explicit ConstantInitFuture(llvm::Constant *initializer) : Data(initializer) { + assert(initializer && "creating null future"); + } + + /// Is this future non-null? + explicit operator bool() const { return bool(Data); } + + /// Return the type of the initializer. + llvm::Type *getType() const; + + /// Abandon this initializer. + void abandon(); + + /// Install the initializer into a global variable. This cannot + /// be called multiple times. + void installInGlobal(llvm::GlobalVariable *global); + + void *getOpaqueValue() const { return Data.getOpaqueValue(); } + static ConstantInitFuture getFromOpaqueValue(void *value) { + ConstantInitFuture result; + result.Data = PairTy::getFromOpaqueValue(value); + return result; + } + enum { + NumLowBitsAvailable = + llvm::PointerLikeTypeTraits<PairTy>::NumLowBitsAvailable + }; +}; + +} // end namespace CodeGen +} // end namespace clang + +namespace llvm { + +template <> +class PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitFuture> { +public: + using T = ::clang::CodeGen::ConstantInitFuture; + + static inline void *getAsVoidPointer(T future) { + return future.getOpaqueValue(); + } + static inline T getFromVoidPointer(void *p) { + return T::getFromOpaqueValue(p); + } + enum { NumLowBitsAvailable = T::NumLowBitsAvailable }; +}; + +} // end namespace llvm + +#endif diff --git a/include/clang/CodeGen/ModuleBuilder.h b/include/clang/CodeGen/ModuleBuilder.h index 58638348653f..6f81ea9d6370 100644 --- a/include/clang/CodeGen/ModuleBuilder.h +++ b/include/clang/CodeGen/ModuleBuilder.h @@ -35,6 +35,7 @@ namespace clang { namespace CodeGen { class CodeGenModule; + class CGDebugInfo; } /// The primary public interface to the Clang code generator. @@ -65,6 +66,9 @@ public: /// CodeGenerator after releasing its module. llvm::Module *ReleaseModule(); + /// Return debug info code generator. + CodeGen::CGDebugInfo *getCGDebugInfo(); + /// Given a mangled name, return a declaration which mangles that way /// which has been added to this code generator via a Handle method. /// diff --git a/include/clang/Config/config.h.cmake b/include/clang/Config/config.h.cmake index 55f0ca94dedc..6971b4e9f06d 100644 --- a/include/clang/Config/config.h.cmake +++ b/include/clang/Config/config.h.cmake @@ -38,6 +38,9 @@ /* Define if we have libxml2 */ #cmakedefine CLANG_HAVE_LIBXML ${CLANG_HAVE_LIBXML} +/* Define if we have z3 and want to build it */ +#cmakedefine CLANG_ANALYZER_WITH_Z3 ${CLANG_ANALYZER_WITH_Z3} + /* Define if we have sys/resource.h (rlimits) */ #cmakedefine CLANG_HAVE_RLIMITS ${CLANG_HAVE_RLIMITS} diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index ab296ebb9f6a..ba09bccfe1c5 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -136,6 +136,8 @@ def migrator_no_finalize_removal : Flag<["-"], "no-finalize-removal">, let Flags = [CC1Option, CC1AsOption, NoDriverOption] in { def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">; +def debug_info_macro : Flag<["-"], "debug-info-macro">, + HelpText<"Emit macro debug information">; def dwarf_version_EQ : Joined<["-"], "dwarf-version=">; def debugger_tuning_EQ : Joined<["-"], "debugger-tuning=">; def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">, @@ -307,6 +309,11 @@ def fprofile_instrument_use_path_EQ : def flto_visibility_public_std: Flag<["-"], "flto-visibility-public-std">, HelpText<"Use public LTO visibility for classes in std and stdext namespaces">; +def flto_unit: Flag<["-"], "flto-unit">, + HelpText<"Emit IR to support LTO unit features (CFI, whole program vtable opt)">; +def fno_lto_unit: Flag<["-"], "fno-lto-unit">; +def fthin_link_bitcode_EQ : Joined<["-"], "fthin-link-bitcode=">, + HelpText<"Write minimized bitcode to <file> for the ThinLTO thin link only">; //===----------------------------------------------------------------------===// // Dependency Output Options @@ -429,6 +436,14 @@ def fmodules_local_submodule_visibility : Flag<["-"], "fmodules-local-submodule-visibility">, HelpText<"Enforce name visibility rules across submodules of the same " "top-level module.">; +def fmodules_codegen : + Flag<["-"], "fmodules-codegen">, + HelpText<"Generate code for uses of this module that assumes an explicit " + "object file will be built for the module">; +def fmodules_debuginfo : + Flag<["-"], "fmodules-debuginfo">, + HelpText<"Generate debug info for types in an object file built from this " + "module and do not generate them elsewhere">; def fmodule_format_EQ : Joined<["-"], "fmodule-format=">, HelpText<"Select the container format for clang modules and PCH. " "Supported options are 'raw' and 'obj'.">; @@ -466,6 +481,8 @@ def ast_list : Flag<["-"], "ast-list">, HelpText<"Build ASTs and print the list of declaration node qualified names">; def ast_dump : Flag<["-"], "ast-dump">, HelpText<"Build ASTs and then debug dump them">; +def ast_dump_all : Flag<["-"], "ast-dump-all">, + HelpText<"Build ASTs and then debug dump them, forcing deserialization">; def ast_dump_lookups : Flag<["-"], "ast-dump-lookups">, HelpText<"Build ASTs and then debug dump their name lookup tables">; def ast_view : Flag<["-"], "ast-view">, @@ -579,6 +596,8 @@ def pic_is_pie : Flag<["-"], "pic-is-pie">, HelpText<"File is for a position independent executable">; def fno_validate_pch : Flag<["-"], "fno-validate-pch">, HelpText<"Disable validation of precompiled headers">; +def fallow_pch_with_errors : Flag<["-"], "fallow-pch-with-compiler-errors">, + HelpText<"Accept a PCH file that was created with compiler errors">; def dump_deserialized_pch_decls : Flag<["-"], "dump-deserialized-decls">, HelpText<"Dump declarations that are deserialized from PCH, for testing">; def error_on_deserialized_pch_decl : Separate<["-"], "error-on-deserialized-decl">, @@ -643,6 +662,8 @@ def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">, HelpText<"Set default MS calling convention">; def finclude_default_header : Flag<["-"], "finclude-default-header">, HelpText<"Include the default header file for OpenCL">; +def fpreserve_vec3_type : Flag<["-"], "fpreserve-vec3-type">, + HelpText<"Preserve 3-component vector type">; // FIXME: Remove these entirely once functionality/tests have been excised. def fobjc_gc_only : Flag<["-"], "fobjc-gc-only">, Group<f_Group>, @@ -658,6 +679,8 @@ def nostdsysteminc : Flag<["-"], "nostdsysteminc">, HelpText<"Disable standard system #include directories">; def fdisable_module_hash : Flag<["-"], "fdisable-module-hash">, HelpText<"Disable the module hash">; +def fmodules_hash_content : Flag<["-"], "fmodules-hash-content">, + HelpText<"Enable hashing the content of a module file">; def c_isystem : JoinedOrSeparate<["-"], "c-isystem">, MetaVarName<"<directory>">, HelpText<"Add directory to the C SYSTEM include search path">; def objc_isystem : JoinedOrSeparate<["-"], "objc-isystem">, diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td index 60048c49c0f7..9b6ab3a5ef2b 100644 --- a/include/clang/Driver/CLCompatOptions.td +++ b/include/clang/Driver/CLCompatOptions.td @@ -11,7 +11,7 @@ // //===----------------------------------------------------------------------===// -def cl_Group : OptionGroup<"<clang-cl options>">, +def cl_Group : OptionGroup<"<clang-cl options>">, Flags<[CLOption]>, HelpText<"CL.EXE COMPATIBILITY OPTIONS">; def cl_compile_Group : OptionGroup<"<clang-cl compile-only options>">, diff --git a/include/clang/Driver/ClangOptionDocs.td b/include/clang/Driver/ClangOptionDocs.td new file mode 100644 index 000000000000..97c44692d257 --- /dev/null +++ b/include/clang/Driver/ClangOptionDocs.td @@ -0,0 +1,36 @@ +//==--- ClangOptionDocs.td - Option documentation -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +def GlobalDocumentation { + code Intro =[{.. + ------------------------------------------------------------------- + NOTE: This file is automatically generated by running clang-tblgen + -gen-opt-docs. Do not edit this file by hand!! + ------------------------------------------------------------------- + +===================================== +Clang command line argument reference +===================================== +.. contents:: + :local: + +Introduction +============ + +This page lists the command line arguments currently supported by the +GCC-compatible ``clang`` and ``clang++`` drivers. + +}]; + + string Program = "clang"; + list<string> ExcludedFlags = ["HelpHidden", "NoDriverOption", + "CLOption", "Unsupported", "Ignored"]; +} + +include "Options.td" diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index 0ce461ca61e1..1009754a15d5 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -14,6 +14,7 @@ #include "clang/Basic/LLVM.h" #include "clang/Driver/Action.h" #include "clang/Driver/Phases.h" +#include "clang/Driver/ToolChain.h" #include "clang/Driver/Types.h" #include "clang/Driver/Util.h" #include "llvm/ADT/StringMap.h" @@ -62,7 +63,7 @@ enum LTOKind { /// Driver - Encapsulate logic for constructing compilation processes /// from a set of gcc-driver-like command line arguments. class Driver { - llvm::opt::OptTable *Opts; + std::unique_ptr<llvm::opt::OptTable> Opts; DiagnosticsEngine &Diags; @@ -215,6 +216,11 @@ public: /// Use lazy precompiled headers for PCH support. unsigned CCCUsePCH : 1; + /// Force clang to emit reproducer for driver invocation. This is enabled + /// indirectly by setting FORCE_CLANG_DIAGNOSTICS_CRASH environment variable + /// or when using the -gen-reproducer driver flag. + unsigned GenReproducer : 1; + private: /// Certain options suppress the 'no input files' warning. unsigned SuppressMissingInputWarning : 1; @@ -227,7 +233,7 @@ private: /// This maps from the string representation of a triple to a ToolChain /// created targeting that triple. The driver owns all the ToolChain objects /// stored in it, and will clean them up when torn down. - mutable llvm::StringMap<ToolChain *> ToolChains; + mutable llvm::StringMap<std::unique_ptr<ToolChain>> ToolChains; private: /// TranslateInputArgs - Create a new derived argument list from the input @@ -264,7 +270,6 @@ public: Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple, DiagnosticsEngine &Diags, IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr); - ~Driver(); /// @name Accessors /// @{ @@ -304,13 +309,8 @@ public: bool isSaveTempsObj() const { return SaveTemps == SaveTempsObj; } bool embedBitcodeEnabled() const { return BitcodeEmbed != EmbedNone; } - bool embedBitcodeInObject() const { - // LTO has no object file output so ignore embed bitcode option in LTO. - return (BitcodeEmbed == EmbedBitcode) && !isUsingLTO(); - } - bool embedBitcodeMarkerOnly() const { - return (BitcodeEmbed == EmbedMarker) && !isUsingLTO(); - } + bool embedBitcodeInObject() const { return (BitcodeEmbed == EmbedBitcode); } + bool embedBitcodeMarkerOnly() const { return (BitcodeEmbed == EmbedMarker); } /// Compute the desired OpenMP runtime from the flags provided. OpenMPRuntimeKind getOpenMPRuntime(const llvm::opt::ArgList &Args) const; diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h index 54bed09e0adf..ff88256b8c0d 100644 --- a/include/clang/Driver/Job.h +++ b/include/clang/Driver/Job.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_DRIVER_JOB_H #include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator.h" #include "llvm/Option/Option.h" @@ -69,6 +70,9 @@ class Command { /// file std::string ResponseFileFlag; + /// See Command::setEnvironment + std::vector<const char *> Environment; + /// When a response file is needed, we try to put most arguments in an /// exclusive file, while others remains as regular command line arguments. /// This functions fills a vector with the regular command line arguments, @@ -111,6 +115,12 @@ public: InputFileList = std::move(List); } + /// \brief Sets the environment to be used by the new process. + /// \param NewEnvironment An array of environment variables. + /// \remark If the environment remains unset, then the environment + /// from the parent process will be used. + void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment); + const char *getExecutable() const { return Executable; } const llvm::opt::ArgStringList &getArguments() const { return Arguments; } diff --git a/include/clang/Driver/Options.h b/include/clang/Driver/Options.h index 2716fa9ae85e..57e4452f3e8c 100644 --- a/include/clang/Driver/Options.h +++ b/include/clang/Driver/Options.h @@ -10,6 +10,8 @@ #ifndef LLVM_CLANG_DRIVER_OPTIONS_H #define LLVM_CLANG_DRIVER_OPTIONS_H +#include <memory> + namespace llvm { namespace opt { class OptTable; @@ -31,7 +33,8 @@ enum ClangFlags { CLOption = (1 << 9), CC1Option = (1 << 10), CC1AsOption = (1 << 11), - NoDriverOption = (1 << 12) + NoDriverOption = (1 << 12), + Ignored = (1 << 13) }; enum ID { @@ -44,7 +47,7 @@ enum ID { }; } -llvm::opt::OptTable *createDriverOptTable(); +std::unique_ptr<llvm::opt::OptTable> createDriverOptTable(); } } diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 6be159fad694..36b24a02b2fe 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -33,6 +33,9 @@ def NoArgumentUnused : OptionFlag; // lines that use it. def Unsupported : OptionFlag; +// Ignored - The option is unsupported, and the driver will silently ignore it. +def Ignored : OptionFlag; + // CoreOption - This is considered a "core" Clang option, available in both // clang and clang-cl modes. def CoreOption : OptionFlag; @@ -50,72 +53,150 @@ def CC1AsOption : OptionFlag; // NoDriverOption - This option should not be accepted by the driver. def NoDriverOption : OptionFlag; +// A short name to show in documentation. The name will be interpreted as rST. +class DocName<string name> { string DocName = name; } + +// A brief description to show in documentation, interpreted as rST. +class DocBrief<code descr> { code DocBrief = descr; } + +// Indicates that this group should be flattened into its parent when generating +// documentation. +class DocFlatten { bit DocFlatten = 1; } + +// Indicates that this warning is ignored, but accepted with a warning for +// GCC compatibility. +class IgnoredGCCCompat : Flags<[HelpHidden]> {} + ///////// // Groups +def Action_Group : OptionGroup<"<action group>">, DocName<"Actions">, + DocBrief<[{The action to perform on the input.}]>; + // Meta-group for options which are only used for compilation, // and not linking etc. -def CompileOnly_Group : OptionGroup<"<CompileOnly group>">; - -def Action_Group : OptionGroup<"<action group>">; - -def I_Group : OptionGroup<"<I group>">, Group<CompileOnly_Group>; -def M_Group : OptionGroup<"<M group>">, Group<CompileOnly_Group>; -def T_Group : OptionGroup<"<T group>">; -def O_Group : OptionGroup<"<O group>">, Group<CompileOnly_Group>; -def R_Group : OptionGroup<"<R group>">, Group<CompileOnly_Group>; -def R_value_Group : OptionGroup<"<R (with value) group>">, Group<R_Group>; -def W_Group : OptionGroup<"<W group>">, Group<CompileOnly_Group>; -def W_value_Group : OptionGroup<"<W (with value) group>">, Group<W_Group>; -def d_Group : OptionGroup<"<d group>">; -def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>; -def f_clang_Group : OptionGroup<"<f (clang-only) group>">, Group<CompileOnly_Group>; -def g_Group : OptionGroup<"<g group>">; -def gN_Group : OptionGroup<"<gN group>">, Group<g_Group>; -def ggdbN_Group : OptionGroup<"<ggdbN group>">, Group<gN_Group>; -def gTune_Group : OptionGroup<"<gTune group>">, Group<g_Group>; -def g_flags_Group : OptionGroup<"<g flags group>">; -def i_Group : OptionGroup<"<i group>">, Group<CompileOnly_Group>; -def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>; -def m_Group : OptionGroup<"<m group>">, Group<CompileOnly_Group>; -def opencl_Group : OptionGroup<"<opencl group>">, Group<CompileOnly_Group>; +def CompileOnly_Group : OptionGroup<"<CompileOnly group>">, + DocName<"Compilation flags">, DocBrief<[{ +Flags controlling the behavior of Clang during compilation. These flags have +no effect during actions that do not perform compilation.}]>; + +def Preprocessor_Group : OptionGroup<"<Preprocessor group>">, + Group<CompileOnly_Group>, + DocName<"Preprocessor flags">, DocBrief<[{ +Flags controlling the behavior of the Clang preprocessor.}]>; + +def IncludePath_Group : OptionGroup<"<I/i group>">, Group<Preprocessor_Group>, + DocName<"Include path management">, + DocBrief<[{ +Flags controlling how ``#include``\s are resolved to files.}]>; + +def I_Group : OptionGroup<"<I group>">, Group<IncludePath_Group>, DocFlatten; +def i_Group : OptionGroup<"<i group>">, Group<IncludePath_Group>, DocFlatten; +def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>, DocFlatten; + +def M_Group : OptionGroup<"<M group>">, Group<Preprocessor_Group>, + DocName<"Dependency file generation">, DocBrief<[{ +Flags controlling generation of a dependency file for ``make``-like build +systems.}]>; + +def d_Group : OptionGroup<"<d group>">, Group<Preprocessor_Group>, + DocName<"Dumping preprocessor state">, DocBrief<[{ +Flags allowing the state of the preprocessor to be dumped in various ways.}]>; + +def Diag_Group : OptionGroup<"<W/R group>">, Group<CompileOnly_Group>, + DocName<"Diagnostic flags">, DocBrief<[{ +Flags controlling which warnings, errors, and remarks Clang will generate. +See the :doc:`full list of warning and remark flags <DiagnosticsReference>`.}]>; + +def R_Group : OptionGroup<"<R group>">, Group<Diag_Group>, DocFlatten; +def R_value_Group : OptionGroup<"<R (with value) group>">, Group<R_Group>, + DocFlatten; +def W_Group : OptionGroup<"<W group>">, Group<Diag_Group>, DocFlatten; +def W_value_Group : OptionGroup<"<W (with value) group>">, Group<W_Group>, + DocFlatten; + +def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>, + DocName<"Target-independent compilation options">; + +def f_clang_Group : OptionGroup<"<f (clang-only) group>">, + Group<CompileOnly_Group>, DocFlatten; +def pedantic_Group : OptionGroup<"<pedantic group>">, Group<f_Group>, + DocFlatten; +def opencl_Group : OptionGroup<"<opencl group>">, Group<f_Group>, + DocName<"OpenCL flags">; + +def m_Group : OptionGroup<"<m group>">, Group<CompileOnly_Group>, + DocName<"Target-dependent compilation options">; // Feature groups - these take command line options that correspond directly to // target specific features and can be translated directly from command line // options. -def m_x86_Features_Group : OptionGroup<"<x86 features group>">, - Group<m_Group>, - Flags<[CoreOption]>; -def m_hexagon_Features_Group : OptionGroup<"<hexagon features group>">, - Group<m_Group>; -def m_arm_Features_Group : OptionGroup<"<arm features group>">, - Group<m_Group>; def m_aarch64_Features_Group : OptionGroup<"<aarch64 features group>">, - Group<m_Group>; + Group<m_Group>, DocName<"AARCH64">; +def m_amdgpu_Features_Group : OptionGroup<"<amdgpu features group>">, + Group<m_Group>, DocName<"AMDGPU">; +def m_arm_Features_Group : OptionGroup<"<arm features group>">, + Group<m_Group>, DocName<"ARM">; +def m_hexagon_Features_Group : OptionGroup<"<hexagon features group>">, + Group<m_Group>, DocName<"Hexagon">; def m_ppc_Features_Group : OptionGroup<"<ppc features group>">, - Group<m_Group>; + Group<m_Group>, DocName<"PowerPC">; def m_wasm_Features_Group : OptionGroup<"<wasm features group>">, - Group<m_Group>; -def m_amdgpu_Features_Group : OptionGroup<"<amdgpu features group>">, - Group<m_Group>; + Group<m_Group>, DocName<"WebAssembly">; +def m_x86_Features_Group : OptionGroup<"<x86 features group>">, + Group<m_Group>, Flags<[CoreOption]>, DocName<"X86">; + +def m_libc_Group : OptionGroup<"<m libc group>">, Group<m_Group>, + Flags<[HelpHidden]>; + +def O_Group : OptionGroup<"<O group>">, Group<CompileOnly_Group>, + DocName<"Optimization level">, DocBrief<[{ +Flags controlling how much optimization should be performed.}]>; + +def DebugInfo_Group : OptionGroup<"<g group>">, Group<CompileOnly_Group>, + DocName<"Debug information generation">, DocBrief<[{ +Flags controlling how much and what kind of debug information should be +generated.}]>; + +def g_Group : OptionGroup<"<g group>">, Group<DebugInfo_Group>, + DocName<"Kind and level of debug information">; +def gN_Group : OptionGroup<"<gN group>">, Group<g_Group>, + DocName<"Debug level">; +def ggdbN_Group : OptionGroup<"<ggdbN group>">, Group<gN_Group>, DocFlatten; +def gTune_Group : OptionGroup<"<gTune group>">, Group<g_Group>, + DocName<"Debugger to tune debug information for">; +def g_flags_Group : OptionGroup<"<g flags group>">, Group<DebugInfo_Group>, + DocName<"Debug information flags">; + +def StaticAnalyzer_Group : OptionGroup<"<Static analyzer group>">, + DocName<"Static analyzer flags">, DocBrief<[{ +Flags controlling the behavior of the Clang Static Analyzer.}]>; -def m_libc_Group : OptionGroup<"<m libc group>">, Group<m_Group>; -def u_Group : OptionGroup<"<u group>">; +// gfortran options that we recognize in the driver and pass along when +// invoking GCC to compile Fortran code. +def gfortran_Group : OptionGroup<"<gfortran group>">, + DocName<"Fortran compilation flags">, DocBrief<[{ +Flags that will be passed onto the ``gfortran`` compiler when Clang is given +a Fortran input.}]>; -def pedantic_Group : OptionGroup<"<pedantic group>">, - Group<CompileOnly_Group>; -def reserved_lib_Group : OptionGroup<"<reserved libs group>">; +def Link_Group : OptionGroup<"<T/e/s/t/u group>">, DocName<"Linker flags">, + DocBrief<[{Flags that are passed on to the linker}]>; +def T_Group : OptionGroup<"<T group>">, Group<Link_Group>, DocFlatten; +def u_Group : OptionGroup<"<u group>">, Group<Link_Group>, DocFlatten; + +def reserved_lib_Group : OptionGroup<"<reserved libs group>">, + Flags<[Unsupported]>; // Temporary groups for clang options which we know we don't support, // but don't want to verbosely warn the user about. def clang_ignored_f_Group : OptionGroup<"<clang ignored f group>">, - Group<f_Group>; + Group<f_Group>, Flags<[Ignored]>; def clang_ignored_m_Group : OptionGroup<"<clang ignored m group>">, - Group<m_Group>; + Group<m_Group>, Flags<[Ignored]>; // Group that ignores all gcc optimizations that won't be implemented def clang_ignored_gcc_optimization_f_Group : OptionGroup< - "<clang_ignored_gcc_optimization_f_Group>">, Group<f_Group>; + "<clang_ignored_gcc_optimization_f_Group>">, Group<f_Group>, Flags<[Ignored]>; ///////// // Options @@ -141,7 +222,7 @@ def clang_ignored_gcc_optimization_f_Group : OptionGroup< // Developer Driver Options -def internal_Group : OptionGroup<"<clang internal options>">; +def internal_Group : OptionGroup<"<clang internal options>">, Flags<[HelpHidden]>; def internal_driver_Group : OptionGroup<"<clang driver internal options>">, Group<internal_Group>, HelpText<"DRIVER OPTIONS">; def internal_debug_Group : @@ -184,6 +265,8 @@ def arcmt_migrate_report_output : Separate<["-"], "arcmt-migrate-report-output"> def arcmt_migrate_emit_arc_errors : Flag<["-"], "arcmt-migrate-emit-errors">, HelpText<"Emit ARC errors even if the migrator can fix them">, Flags<[CC1Option]>; +def gen_reproducer: Flag<["-"], "gen-reproducer">, InternalDebugOpt, + HelpText<"Auto-generates preprocessed source files and a reproduction script">; def _migrate : Flag<["--"], "migrate">, Flags<[DriverOption]>, HelpText<"Run the migrator">; @@ -236,23 +319,34 @@ def _HASH_HASH_HASH : Flag<["-"], "###">, Flags<[DriverOption, CoreOption]>, HelpText<"Print (but do not run) the commands to run for this compilation">; def _DASH_DASH : Option<["--"], "", KIND_REMAINING_ARGS>, Flags<[DriverOption, CoreOption]>; -def A : JoinedOrSeparate<["-"], "A">, Flags<[RenderJoined]>; -def B : JoinedOrSeparate<["-"], "B">; -def CC : Flag<["-"], "CC">, Flags<[CC1Option]>; -def C : Flag<["-"], "C">, Flags<[CC1Option]>; -def D : JoinedOrSeparate<["-"], "D">, Group<CompileOnly_Group>, Flags<[CC1Option]>; +def A : JoinedOrSeparate<["-"], "A">, Flags<[RenderJoined]>, Group<gfortran_Group>; +def B : JoinedOrSeparate<["-"], "B">, MetaVarName<"<dir>">, + HelpText<"Add <dir> to search path for binaries and object files used implicitly">; +def CC : Flag<["-"], "CC">, Flags<[CC1Option]>, Group<Preprocessor_Group>, + HelpText<"Include comments from within macros in preprocessed output">; +def C : Flag<["-"], "C">, Flags<[CC1Option]>, Group<Preprocessor_Group>, + HelpText<"Include comments in preprocessed output">; +def D : JoinedOrSeparate<["-"], "D">, Group<Preprocessor_Group>, + Flags<[CC1Option]>, MetaVarName<"<macro>=<value>">, + HelpText<"Define <macro> to <value> (or 1 if <value> omitted)">; def E : Flag<["-"], "E">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>, - HelpText<"Only run the preprocessor">; + HelpText<"Only run the preprocessor">; def F : JoinedOrSeparate<["-"], "F">, Flags<[RenderJoined,CC1Option]>, HelpText<"Add directory to framework include search path">; -def G : JoinedOrSeparate<["-"], "G">, Flags<[DriverOption]>; -def G_EQ : Joined<["-"], "G=">, Flags<[DriverOption]>; -def H : Flag<["-"], "H">, Flags<[CC1Option]>, +def G : JoinedOrSeparate<["-"], "G">, Flags<[DriverOption]>, Group<m_Group>, + MetaVarName<"<size>">, HelpText<"Put objects of at most <size> bytes " + "into small data section (MIPS / Hexagon)">; +def G_EQ : Joined<["-"], "G=">, Flags<[DriverOption]>, Group<m_Group>, Alias<G>; +def H : Flag<["-"], "H">, Flags<[CC1Option]>, Group<Preprocessor_Group>, HelpText<"Show header includes and nesting depth">; -def I_ : Flag<["-"], "I-">, Group<I_Group>; -def I : JoinedOrSeparate<["-"], "I">, Group<I_Group>, Flags<[CC1Option,CC1AsOption]>, +def I_ : Flag<["-"], "I-">, Group<I_Group>, + HelpText<"Restrict all prior -I flags to double-quoted inclusion and " + "remove current directory from include path">; +def I : JoinedOrSeparate<["-"], "I">, Group<I_Group>, + Flags<[CC1Option,CC1AsOption]>, MetaVarName<"<dir>">, HelpText<"Add directory to include search path">; -def L : JoinedOrSeparate<["-"], "L">, Flags<[RenderJoined]>; +def L : JoinedOrSeparate<["-"], "L">, Flags<[RenderJoined]>, Group<Link_Group>, + MetaVarName<"<dir>">, HelpText<"Add directory to library search path">; def MD : Flag<["-"], "MD">, Group<M_Group>, HelpText<"Write a depfile containing user and system headers">; def MMD : Flag<["-"], "MMD">, Group<M_Group>, @@ -276,9 +370,9 @@ def MT : JoinedOrSeparate<["-"], "MT">, Group<M_Group>, Flags<[CC1Option]>, HelpText<"Specify name of main file output in depfile">; def MV : Flag<["-"], "MV">, Group<M_Group>, Flags<[CC1Option]>, HelpText<"Use NMake/Jom format for the depfile">; -def Mach : Flag<["-"], "Mach">; -def O0 : Flag<["-"], "O0">, Group<O_Group>, Flags<[CC1Option]>; -def O4 : Flag<["-"], "O4">, Group<O_Group>, Flags<[CC1Option]>; +def Mach : Flag<["-"], "Mach">, Group<Link_Group>; +def O0 : Flag<["-"], "O0">, Group<O_Group>, Flags<[CC1Option, HelpHidden]>; +def O4 : Flag<["-"], "O4">, Group<O_Group>, Flags<[CC1Option, HelpHidden]>; def ObjCXX : Flag<["-"], "ObjC++">, Flags<[DriverOption]>, HelpText<"Treat source input files as Objective-C++ inputs">; def ObjC : Flag<["-"], "ObjC">, Flags<[DriverOption]>, @@ -286,12 +380,12 @@ def ObjC : Flag<["-"], "ObjC">, Flags<[DriverOption]>, def O : Joined<["-"], "O">, Group<O_Group>, Flags<[CC1Option]>; def O_flag : Flag<["-"], "O">, Flags<[CC1Option]>, Alias<O>, AliasArgs<["2"]>; def Ofast : Joined<["-"], "Ofast">, Group<O_Group>, Flags<[CC1Option]>; -def P : Flag<["-"], "P">, Flags<[CC1Option]>, +def P : Flag<["-"], "P">, Flags<[CC1Option]>, Group<Preprocessor_Group>, HelpText<"Disable linemarker output in -E mode">; -def Qn : Flag<["-"], "Qn">; +def Qn : Flag<["-"], "Qn">, IgnoredGCCCompat; def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Flags<[DriverOption, CoreOption]>, HelpText<"Don't emit warning for unused driver arguments">; -def Q : Flag<["-"], "Q">; +def Q : Flag<["-"], "Q">, IgnoredGCCCompat; def Rpass_EQ : Joined<["-"], "Rpass=">, Group<R_value_Group>, Flags<[CC1Option]>, HelpText<"Report transformations performed by optimization passes whose " "name matches the given POSIX regular expression">; @@ -307,23 +401,28 @@ def R_Joined : Joined<["-"], "R">, Group<R_Group>, Flags<[CC1Option, CoreOption] MetaVarName<"<remark>">, HelpText<"Enable the specified remark">; def S : Flag<["-"], "S">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>, HelpText<"Only run preprocess and compilation steps">; -def Tbss : JoinedOrSeparate<["-"], "Tbss">, Group<T_Group>; -def Tdata : JoinedOrSeparate<["-"], "Tdata">, Group<T_Group>; -def Ttext : JoinedOrSeparate<["-"], "Ttext">, Group<T_Group>; -def T : JoinedOrSeparate<["-"], "T">, Group<T_Group>; -def U : JoinedOrSeparate<["-"], "U">, Group<CompileOnly_Group>, Flags<[CC1Option]>; +def Tbss : JoinedOrSeparate<["-"], "Tbss">, Group<T_Group>, + MetaVarName<"<addr>">, HelpText<"Set starting address of BSS to <addr>">; +def Tdata : JoinedOrSeparate<["-"], "Tdata">, Group<T_Group>, + MetaVarName<"<addr>">, HelpText<"Set starting address of BSS to <addr>">; +def Ttext : JoinedOrSeparate<["-"], "Ttext">, Group<T_Group>, + MetaVarName<"<addr>">, HelpText<"Set starting address of BSS to <addr>">; +def T : JoinedOrSeparate<["-"], "T">, Group<T_Group>, + MetaVarName<"<script>">, HelpText<"Specify <script> as linker script">; +def U : JoinedOrSeparate<["-"], "U">, Group<Preprocessor_Group>, + Flags<[CC1Option]>, MetaVarName<"<macro>">, HelpText<"Undefine macro <macro>">; def V : JoinedOrSeparate<["-"], "V">, Flags<[DriverOption, Unsupported]>; def Wa_COMMA : CommaJoined<["-"], "Wa,">, HelpText<"Pass the comma separated arguments in <arg> to the assembler">, MetaVarName<"<arg>">; -def Wall : Flag<["-"], "Wall">, Group<W_Group>, Flags<[CC1Option]>; -def WCL4 : Flag<["-"], "WCL4">, Group<W_Group>, Flags<[CC1Option]>; -def Wdeprecated : Flag<["-"], "Wdeprecated">, Group<W_Group>, Flags<[CC1Option]>; +def Wall : Flag<["-"], "Wall">, Group<W_Group>, Flags<[CC1Option, HelpHidden]>; +def WCL4 : Flag<["-"], "WCL4">, Group<W_Group>, Flags<[CC1Option, HelpHidden]>; +def Wdeprecated : Flag<["-"], "Wdeprecated">, Group<W_Group>, Flags<[CC1Option]>, + HelpText<"Enable warnings for deprecated constructs and define __DEPRECATED">; def Wno_deprecated : Flag<["-"], "Wno-deprecated">, Group<W_Group>, Flags<[CC1Option]>; -def Wextra : Flag<["-"], "Wextra">, Group<W_Group>, Flags<[CC1Option]>; def Wl_COMMA : CommaJoined<["-"], "Wl,">, Flags<[LinkerInput, RenderAsInput]>, HelpText<"Pass the comma separated arguments in <arg> to the linker">, - MetaVarName<"<arg>">; + MetaVarName<"<arg>">, Group<Link_Group>; // FIXME: This is broken; these should not be Joined arguments. def Wno_nonportable_cfstrings : Joined<["-"], "Wno-nonportable-cfstrings">, Group<W_Group>, Flags<[CC1Option]>; @@ -331,16 +430,18 @@ def Wnonportable_cfstrings : Joined<["-"], "Wnonportable-cfstrings">, Group<W_Gr Flags<[CC1Option]>; def Wp_COMMA : CommaJoined<["-"], "Wp,">, HelpText<"Pass the comma separated arguments in <arg> to the preprocessor">, - MetaVarName<"<arg>">; -def Wwrite_strings : Flag<["-"], "Wwrite-strings">, Group<W_Group>, Flags<[CC1Option]>; -def Wno_write_strings : Flag<["-"], "Wno-write-strings">, Group<W_Group>, Flags<[CC1Option]>; + MetaVarName<"<arg>">, Group<Preprocessor_Group>; +def Wwrite_strings : Flag<["-"], "Wwrite-strings">, Group<W_Group>, Flags<[CC1Option, HelpHidden]>; +def Wno_write_strings : Flag<["-"], "Wno-write-strings">, Group<W_Group>, Flags<[CC1Option, HelpHidden]>; def W_Joined : Joined<["-"], "W">, Group<W_Group>, Flags<[CC1Option, CoreOption]>, MetaVarName<"<warning>">, HelpText<"Enable the specified warning">; def Xanalyzer : Separate<["-"], "Xanalyzer">, - HelpText<"Pass <arg> to the static analyzer">, MetaVarName<"<arg>">; + HelpText<"Pass <arg> to the static analyzer">, MetaVarName<"<arg>">, + Group<StaticAnalyzer_Group>; def Xarch__ : JoinedAndSeparate<["-"], "Xarch_">, Flags<[DriverOption]>; def Xassembler : Separate<["-"], "Xassembler">, - HelpText<"Pass <arg> to the assembler">, MetaVarName<"<arg>">; + HelpText<"Pass <arg> to the assembler">, MetaVarName<"<arg>">, + Group<CompileOnly_Group>; def Xclang : Separate<["-"], "Xclang">, HelpText<"Pass <arg> to the clang compiler">, MetaVarName<"<arg>">, Flags<[DriverOption, CoreOption]>, Group<CompileOnly_Group>; @@ -349,14 +450,17 @@ def Xcuda_fatbinary : Separate<["-"], "Xcuda-fatbinary">, def Xcuda_ptxas : Separate<["-"], "Xcuda-ptxas">, HelpText<"Pass <arg> to the ptxas assembler">, MetaVarName<"<arg>">; def z : Separate<["-"], "z">, Flags<[LinkerInput, RenderAsInput]>, - HelpText<"Pass -z <arg> to the linker">, MetaVarName<"<arg>">; + HelpText<"Pass -z <arg> to the linker">, MetaVarName<"<arg>">, + Group<Link_Group>; def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>, - HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">; -def Xpreprocessor : Separate<["-"], "Xpreprocessor">, + HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">, + Group<Link_Group>; +def Xpreprocessor : Separate<["-"], "Xpreprocessor">, Group<Preprocessor_Group>, HelpText<"Pass <arg> to the preprocessor">, MetaVarName<"<arg>">; -def X_Flag : Flag<["-"], "X">; -def X_Joined : Joined<["-"], "X">; -def Z_Flag : Flag<["-"], "Z">; +def X_Flag : Flag<["-"], "X">, Group<Link_Group>; +def X_Joined : Joined<["-"], "X">, IgnoredGCCCompat; +def Z_Flag : Flag<["-"], "Z">, Group<Link_Group>; +// FIXME: All we do with this is reject it. Remove. def Z_Joined : Joined<["-"], "Z">; def all__load : Flag<["-"], "all_load">; def allowable__client : Separate<["-"], "allowable_client">; @@ -402,7 +506,7 @@ def current__version : JoinedOrSeparate<["-"], "current_version">; def cxx_isystem : JoinedOrSeparate<["-"], "cxx-isystem">, Group<clang_i_Group>, HelpText<"Add directory to the C++ SYSTEM include search path">, Flags<[CC1Option]>, MetaVarName<"<directory>">; -def c : Flag<["-"], "c">, Flags<[DriverOption]>, +def c : Flag<["-"], "c">, Flags<[DriverOption]>, Group<Action_Group>, HelpText<"Only run preprocess, compile, and assemble steps">; def cuda_device_only : Flag<["--"], "cuda-device-only">, HelpText<"Compile CUDA code for device only">; @@ -462,7 +566,7 @@ def emit_ast : Flag<["-"], "emit-ast">, def emit_llvm : Flag<["-"], "emit-llvm">, Flags<[CC1Option]>, Group<Action_Group>, HelpText<"Use the LLVM representation for assembler and object files">; def exported__symbols__list : Separate<["-"], "exported_symbols_list">; -def e : JoinedOrSeparate<["-"], "e">; +def e : JoinedOrSeparate<["-"], "e">, Group<Link_Group>; def fPIC : Flag<["-"], "fPIC">, Group<f_Group>; def fno_PIC : Flag<["-"], "fno-PIC">, Group<f_Group>; def fPIE : Flag<["-"], "fPIE">, Group<f_Group>; @@ -511,14 +615,28 @@ def fno_gnu_inline_asm : Flag<["-"], "fno-gnu-inline-asm">, Group<f_Group>, Flags<[DriverOption, CC1Option]>, HelpText<"Disable GNU style inline asm">; +def fprofile_sample_use : Flag<["-"], "fprofile-sample-use">, Group<f_Group>, + Flags<[CoreOption]>; +def fno_profile_sample_use : Flag<["-"], "fno-profile-sample-use">, Group<f_Group>, + Flags<[CoreOption]>; def fprofile_sample_use_EQ : Joined<["-"], "fprofile-sample-use=">, Group<f_Group>, Flags<[DriverOption, CC1Option]>, HelpText<"Enable sample-based profile guided optimizations">; +def fauto_profile : Flag<["-"], "fauto-profile">, Group<f_Group>, + Alias<fprofile_sample_use>; +def fno_auto_profile : Flag<["-"], "fno-auto-profile">, Group<f_Group>, + Alias<fno_profile_sample_use>; def fauto_profile_EQ : Joined<["-"], "fauto-profile=">, Alias<fprofile_sample_use_EQ>; +def fdebug_info_for_profiling : Flag<["-"], "fdebug-info-for-profiling">, Group<f_Group>, + Flags<[CC1Option]>, + HelpText<"Emit extra debug info to make sample profile more accurate.">; +def fno_debug_info_for_profiling : Flag<["-"], "fno-debug-info-for-profiling">, Group<f_Group>, + Flags<[DriverOption]>, + HelpText<"Do not emit extra debug info for sample profiler.">; def fprofile_instr_generate : Flag<["-"], "fprofile-instr-generate">, Group<f_Group>, Flags<[CoreOption]>, - HelpText<"Generate instrumented code to collect execution counts into default.profraw file (overriden by '=' form of option or LLVM_PROFILE_FILE env var)">; + HelpText<"Generate instrumented code to collect execution counts into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var)">; def fprofile_instr_generate_EQ : Joined<["-"], "fprofile-instr-generate=">, Group<f_Group>, Flags<[CoreOption]>, MetaVarName<"<file>">, HelpText<"Generate instrumented code to collect execution counts into <file> (overridden by LLVM_PROFILE_FILE env var)">; @@ -585,7 +703,8 @@ def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group<f_Group>; def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group<f_Group>; def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit=">, Group<f_Group>; -def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group<f_clang_Group>, Flags<[NoArgumentUnused]>; +def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group<f_clang_Group>, Flags<[NoArgumentUnused]>, + HelpText<"Disable auto-generation of preprocessed source files and a script for reproduction during a clang crash">; def fcreate_profile : Flag<["-"], "fcreate-profile">, Group<f_Group>; def fcxx_exceptions: Flag<["-"], "fcxx-exceptions">, Group<f_Group>, HelpText<"Enable C++ exceptions">, Flags<[CC1Option]>; @@ -659,65 +778,71 @@ def fno_signaling_math : Flag<["-"], "fno-signaling-math">, Group<f_Group>; def fjump_tables : Flag<["-"], "fjump-tables">, Group<f_Group>; def fno_jump_tables : Flag<["-"], "fno-jump-tables">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Do not use jump tables for lowering switches">; + +// Begin sanitizer flags. These should all be core options exposed in all driver +// modes. +let Flags = [CC1Option, CoreOption] in { + def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>, - Flags<[CC1Option, CoreOption]>, MetaVarName<"<check>">, + MetaVarName<"<check>">, HelpText<"Turn on runtime checks for various forms of undefined " "or suspicious behavior. See user manual for available checks">; def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>, - Flags<[CoreOption]>; + Flags<[CoreOption, DriverOption]>; def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">, - Group<f_clang_Group>, Flags<[CC1Option, CoreOption]>, + Group<f_clang_Group>, 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_coverage : CommaJoined<["-"], "fsanitize-coverage=">, - Group<f_clang_Group>, Flags<[CoreOption]>, + Group<f_clang_Group>, HelpText<"Specify the type of coverage instrumentation for Sanitizers">; def fno_sanitize_coverage : CommaJoined<["-"], "fno-sanitize-coverage=">, - Group<f_clang_Group>, Flags<[CoreOption]>, + Group<f_clang_Group>, Flags<[CoreOption, DriverOption]>, HelpText<"Disable specified features of coverage instrumentation for " "Sanitizers">; def fsanitize_memory_track_origins_EQ : Joined<["-"], "fsanitize-memory-track-origins=">, - Group<f_clang_Group>, Flags<[CC1Option]>, + Group<f_clang_Group>, HelpText<"Enable origins tracking in MemorySanitizer">; def fsanitize_memory_track_origins : Flag<["-"], "fsanitize-memory-track-origins">, - Group<f_clang_Group>, Flags<[CC1Option]>, + Group<f_clang_Group>, HelpText<"Enable origins tracking in MemorySanitizer">; def fno_sanitize_memory_track_origins : Flag<["-"], "fno-sanitize-memory-track-origins">, - Group<f_clang_Group>, Flags<[CC1Option]>, + Group<f_clang_Group>, + Flags<[CoreOption, DriverOption]>, HelpText<"Disable origins tracking in MemorySanitizer">; def fsanitize_memory_use_after_dtor : Flag<["-"], "fsanitize-memory-use-after-dtor">, - Group<f_clang_Group>, Flags<[CC1Option]>, + Group<f_clang_Group>, HelpText<"Enable use-after-destroy detection in MemorySanitizer">; def fsanitize_address_field_padding : Joined<["-"], "fsanitize-address-field-padding=">, - Group<f_clang_Group>, Flags<[CC1Option]>, + Group<f_clang_Group>, HelpText<"Level of field padding for AddressSanitizer">; def fsanitize_address_use_after_scope : Flag<["-"], "fsanitize-address-use-after-scope">, - Group<f_clang_Group>, Flags<[CC1Option]>, + Group<f_clang_Group>, HelpText<"Enable use-after-scope detection in AddressSanitizer">; def fno_sanitize_address_use_after_scope : Flag<["-"], "fno-sanitize-address-use-after-scope">, - Group<f_clang_Group>, Flags<[CC1Option]>, + Group<f_clang_Group>, + Flags<[CoreOption, DriverOption]>, HelpText<"Disable use-after-scope detection in AddressSanitizer">; -def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group<f_clang_Group>, - Flags<[CoreOption]>; +def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group<f_clang_Group>; def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">, - Group<f_clang_Group>, Flags<[CoreOption]>; + Flags<[CoreOption, DriverOption]>, + Group<f_clang_Group>; def fsanitize_recover_EQ : CommaJoined<["-"], "fsanitize-recover=">, Group<f_clang_Group>, - Flags<[CC1Option, CoreOption]>, HelpText<"Enable recovery for specified sanitizers">; def fno_sanitize_recover_EQ : CommaJoined<["-"], "fno-sanitize-recover=">, - Group<f_clang_Group>, Flags<[CoreOption]>, + Group<f_clang_Group>, + Flags<[CoreOption, DriverOption]>, HelpText<"Disable recovery for specified sanitizers">; def fsanitize_trap_EQ : CommaJoined<["-"], "fsanitize-trap=">, Group<f_clang_Group>, - Flags<[CC1Option, CoreOption]>, HelpText<"Enable trapping for specified sanitizers">; def fno_sanitize_trap_EQ : CommaJoined<["-"], "fno-sanitize-trap=">, Group<f_clang_Group>, - Flags<[CoreOption]>, + Flags<[CoreOption, DriverOption]>, HelpText<"Disable trapping for specified sanitizers">; def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on-error">, Group<f_clang_Group>; @@ -726,39 +851,47 @@ def fno_sanitize_undefined_trap_on_error : Flag<["-"], "fno-sanitize-undefined-t def fsanitize_link_cxx_runtime : Flag<["-"], "fsanitize-link-c++-runtime">, Group<f_clang_Group>; def fsanitize_cfi_cross_dso : Flag<["-"], "fsanitize-cfi-cross-dso">, - Group<f_clang_Group>, Flags<[CC1Option]>, + Group<f_clang_Group>, HelpText<"Enable control flow integrity (CFI) checks for cross-DSO calls.">; def fno_sanitize_cfi_cross_dso : Flag<["-"], "fno-sanitize-cfi-cross-dso">, - Group<f_clang_Group>, Flags<[CC1Option]>, + Flags<[CoreOption, DriverOption]>, + Group<f_clang_Group>, HelpText<"Disable control flow integrity (CFI) checks for cross-DSO calls.">; def fsanitize_stats : Flag<["-"], "fsanitize-stats">, - Group<f_clang_Group>, Flags<[CC1Option]>, + Group<f_clang_Group>, HelpText<"Enable sanitizer statistics gathering.">; def fno_sanitize_stats : Flag<["-"], "fno-sanitize-stats">, - Group<f_clang_Group>, Flags<[CC1Option]>, + Group<f_clang_Group>, + Flags<[CoreOption, DriverOption]>, HelpText<"Disable sanitizer statistics gathering.">; def fsanitize_thread_memory_access : Flag<["-"], "fsanitize-thread-memory-access">, Group<f_clang_Group>, HelpText<"Enable memory access instrumentation in ThreadSanitizer (default)">; def fno_sanitize_thread_memory_access : Flag<["-"], "fno-sanitize-thread-memory-access">, Group<f_clang_Group>, + Flags<[CoreOption, DriverOption]>, HelpText<"Disable memory access instrumentation in ThreadSanitizer">; def fsanitize_thread_func_entry_exit : Flag<["-"], "fsanitize-thread-func-entry-exit">, Group<f_clang_Group>, HelpText<"Enable function entry/exit instrumentation in ThreadSanitizer (default)">; def fno_sanitize_thread_func_entry_exit : Flag<["-"], "fno-sanitize-thread-func-entry-exit">, Group<f_clang_Group>, + Flags<[CoreOption, DriverOption]>, HelpText<"Disable function entry/exit instrumentation in ThreadSanitizer">; def fsanitize_thread_atomics : Flag<["-"], "fsanitize-thread-atomics">, Group<f_clang_Group>, HelpText<"Enable atomic operations instrumentation in ThreadSanitizer (default)">; def fno_sanitize_thread_atomics : Flag<["-"], "fno-sanitize-thread-atomics">, Group<f_clang_Group>, + Flags<[CoreOption, DriverOption]>, HelpText<"Disable atomic operations instrumentation in ThreadSanitizer">; def fsanitize_undefined_strip_path_components_EQ : Joined<["-"], "fsanitize-undefined-strip-path-components=">, - Group<f_clang_Group>, Flags<[CC1Option]>, MetaVarName<"<number>">, + Group<f_clang_Group>, MetaVarName<"<number>">, HelpText<"Strip (or keep only, if negative) a given number of path components " "when emitting check metadata.">; + +} // end -f[no-]sanitize* flags + def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">, Group<f_Group>; def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">, @@ -816,12 +949,13 @@ def fno_gnu89_inline : Flag<["-"], "fno-gnu89-inline">, Group<f_Group>; def fgnu_runtime : Flag<["-"], "fgnu-runtime">, Group<f_Group>, HelpText<"Generate output compatible with the standard GNU Objective-C runtime">; def fheinous_gnu_extensions : Flag<["-"], "fheinous-gnu-extensions">, Flags<[CC1Option]>; -def filelist : Separate<["-"], "filelist">, Flags<[LinkerInput]>; +def filelist : Separate<["-"], "filelist">, Flags<[LinkerInput]>, + Group<Link_Group>; def : Flag<["-"], "findirect-virtual-calls">, Alias<fapple_kext>; def finline_functions : Flag<["-"], "finline-functions">, Group<f_clang_Group>, Flags<[CC1Option]>, HelpText<"Inline suitable functions">; def finline_hint_functions: Flag<["-"], "finline-hint-functions">, Group<f_clang_Group>, Flags<[CC1Option]>, - HelpText<"Inline functions wich are (explicitly or implicitly) marked inline">; + HelpText<"Inline functions which are (explicitly or implicitly) marked inline">; def finline : Flag<["-"], "finline">, Group<clang_ignored_f_Group>; def fexperimental_new_pass_manager : Flag<["-"], "fexperimental-new-pass-manager">, Group<f_clang_Group>, Flags<[CC1Option]>, @@ -845,10 +979,19 @@ def fxray_instruction_threshold_ : JoinedOrSeparate<["-"], "fxray-instruction-threshold">, Group<f_Group>, Flags<[CC1Option]>; +def fxray_always_instrument : + JoinedOrSeparate<["-"], "fxray-always-instrument=">, + Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Filename defining the whitelist for imbuing the 'always instrument' XRay attribute.">; +def fxray_never_instrument : + JoinedOrSeparate<["-"], "fxray-never-instrument=">, + Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Filename defining the whitelist for imbuing the 'never instrument' XRay attribute.">; + def flat__namespace : Flag<["-"], "flat_namespace">; def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>; def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>; -def flto_EQ : Joined<["-"], "flto=">, Flags<[CC1Option]>, Group<f_Group>, +def flto_EQ : Joined<["-"], "flto=">, Flags<[CoreOption, CC1Option]>, Group<f_Group>, HelpText<"Set LTO mode to either 'full' or 'thin'">; def flto : Flag<["-"], "flto">, Flags<[CoreOption, CC1Option]>, Group<f_Group>, HelpText<"Enable LTO in 'full' mode">; @@ -1213,6 +1356,10 @@ def fno_standalone_debug : Flag<["-"], "fno-standalone-debug">, Group<f_Group>, HelpText<"Limit debug information produced to reduce size of debug binary">; def flimit_debug_info : Flag<["-"], "flimit-debug-info">, Flags<[CoreOption]>, Alias<fno_standalone_debug>; def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Flags<[CoreOption]>, Alias<fstandalone_debug>; +def fdebug_macro : Flag<["-"], "fdebug-macro">, Group<f_Group>, Flags<[CoreOption]>, + HelpText<"Emit macro debug information">; +def fno_debug_macro : Flag<["-"], "fno-debug-macro">, Group<f_Group>, Flags<[CoreOption]>, + HelpText<"Do not emit macro debug information">; def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group<f_Group>, Flags<[DriverOption, CoreOption]>; def fstrict_enums : Flag<["-"], "fstrict-enums">, Group<f_Group>, Flags<[CC1Option]>, @@ -1335,8 +1482,8 @@ def fno_unique_section_names : Flag <["-"], "fno-unique-section-names">, def fstrict_return : Flag<["-"], "fstrict-return">, Group<f_Group>, Flags<[CC1Option]>, - HelpText<"Always treat control flow paths that fall off the end of a non-void" - "function as unreachable">; + HelpText<"Always treat control flow paths that fall off the end of a " + "non-void function as unreachable">; def fno_strict_return : Flag<["-"], "fno-strict-return">, Group<f_Group>, Flags<[CC1Option]>; @@ -1411,6 +1558,11 @@ def idirafter : JoinedOrSeparate<["-"], "idirafter">, Group<clang_i_Group>, Flag HelpText<"Add directory to AFTER include search path">; def iframework : JoinedOrSeparate<["-"], "iframework">, Group<clang_i_Group>, Flags<[CC1Option]>, HelpText<"Add directory to SYSTEM framework search path">; +def iframeworkwithsysroot : JoinedOrSeparate<["-"], "iframeworkwithsysroot">, + Group<clang_i_Group>, + HelpText<"Add directory to SYSTEM framework search path, " + "absolute paths are relative to -isysroot">, + MetaVarName<"<directory>">, Flags<[CC1Option]>; def imacros : JoinedOrSeparate<["-", "--"], "imacros">, Group<clang_i_Group>, Flags<[CC1Option]>, HelpText<"Include macros from file before parsing">, MetaVarName<"<file>">; def image__base : Separate<["-"], "image_base">; @@ -1449,7 +1601,8 @@ def ivfsoverlay : JoinedOrSeparate<["-"], "ivfsoverlay">, Group<clang_i_Group>, HelpText<"Overlay the virtual filesystem described by file over the real file system">; def i : Joined<["-"], "i">, Group<i_Group>; def keep__private__externs : Flag<["-"], "keep_private_externs">; -def l : JoinedOrSeparate<["-"], "l">, Flags<[LinkerInput, RenderJoined]>; +def l : JoinedOrSeparate<["-"], "l">, Flags<[LinkerInput, RenderJoined]>, + Group<Link_Group>; def lazy__framework : Separate<["-"], "lazy_framework">, Flags<[LinkerInput]>; def lazy__library : Separate<["-"], "lazy_library">, Flags<[LinkerInput]>; def mlittle_endian : Flag<["-"], "mlittle-endian">, Flags<[DriverOption]>; @@ -1484,11 +1637,11 @@ def mpure_code : Flag<["-"], "mpure-code">, Alias<mexecute_only>; // Alias for G def mno_pure_code : Flag<["-"], "mno-pure-code">, Alias<mno_execute_only>; def mtvos_version_min_EQ : Joined<["-"], "mtvos-version-min=">, Group<m_Group>; def mappletvos_version_min_EQ : Joined<["-"], "mappletvos-version-min=">, Alias<mtvos_version_min_EQ>; -def mtvos_simulator_version_min_EQ : Joined<["-"], "mtvos-simulator-version-min=">, Alias<mtvos_version_min_EQ>; -def mappletvsimulator_version_min_EQ : Joined<["-"], "mappletvsimulator-version-min=">, Alias<mtvos_version_min_EQ>; +def mtvos_simulator_version_min_EQ : Joined<["-"], "mtvos-simulator-version-min=">; +def mappletvsimulator_version_min_EQ : Joined<["-"], "mappletvsimulator-version-min=">, Alias<mtvos_simulator_version_min_EQ>; def mwatchos_version_min_EQ : Joined<["-"], "mwatchos-version-min=">, Group<m_Group>; -def mwatchos_simulator_version_min_EQ : Joined<["-"], "mwatchos-simulator-version-min=">, Alias<mwatchos_version_min_EQ>; -def mwatchsimulator_version_min_EQ : Joined<["-"], "mwatchsimulator-version-min=">, Alias<mwatchos_version_min_EQ>; +def mwatchos_simulator_version_min_EQ : Joined<["-"], "mwatchos-simulator-version-min=">; +def mwatchsimulator_version_min_EQ : Joined<["-"], "mwatchsimulator-version-min=">, Alias<mwatchos_simulator_version_min_EQ>; def march_EQ : Joined<["-"], "march=">, Group<m_Group>; def masm_EQ : Joined<["-"], "masm=">, Group<m_Group>, Flags<[DriverOption]>; def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>; @@ -1517,8 +1670,8 @@ def mhard_float : Flag<["-"], "mhard-float">, Group<m_Group>; def miphoneos_version_min_EQ : Joined<["-"], "miphoneos-version-min=">, Group<m_Group>; def mios_version_min_EQ : Joined<["-"], "mios-version-min=">, Alias<miphoneos_version_min_EQ>, HelpText<"Set iOS deployment target">; -def mios_simulator_version_min_EQ : Joined<["-"], "mios-simulator-version-min=">, Alias<miphoneos_version_min_EQ>; -def miphonesimulator_version_min_EQ : Joined<["-"], "miphonesimulator-version-min=">, Alias<miphoneos_version_min_EQ>; +def mios_simulator_version_min_EQ : Joined<["-"], "mios-simulator-version-min=">; +def miphonesimulator_version_min_EQ : Joined<["-"], "miphonesimulator-version-min=">, Alias<mios_simulator_version_min_EQ>; def mkernel : Flag<["-"], "mkernel">, Group<m_Group>; def mlinker_version_EQ : Joined<["-"], "mlinker-version=">, Flags<[DriverOption]>; @@ -1604,7 +1757,14 @@ def mno_xsaveopt : Flag<["-"], "mno-xsaveopt">, Group<m_x86_Features_Group>; def mno_xsavec : Flag<["-"], "mno-xsavec">, Group<m_x86_Features_Group>; def mno_xsaves : Flag<["-"], "mno-xsaves">, Group<m_x86_Features_Group>; def mno_mwaitx : Flag<["-"], "mno-mwaitx">, Group<m_x86_Features_Group>; +def mno_clzero : Flag<["-"], "mno-clzero">, Group<m_x86_Features_Group>; def mno_pku : Flag<["-"], "mno-pku">, Group<m_x86_Features_Group>; +def mno_clflushopt : Flag<["-"], "mno-clflushopt">, Group<m_x86_Features_Group>; +def mno_clwb : Flag<["-"], "mno-clwb">, Group<m_x86_Features_Group>; +def mno_movbe : Flag<["-"], "mno-movbe">, Group<m_x86_Features_Group>; +def mno_mpx : Flag<["-"], "mno-mpx">, Group<m_x86_Features_Group>; +def mno_sgx : Flag<["-"], "mno-sgx">, Group<m_x86_Features_Group>; +def mno_prefetchwt1 : Flag<["-"], "mno-prefetchwt1">, Group<m_x86_Features_Group>; def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>, HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">; @@ -1626,6 +1786,8 @@ def mcrc : Flag<["-"], "mcrc">, Group<m_arm_Features_Group>, HelpText<"Allow use of CRC instructions (ARM only)">; def mnocrc : Flag<["-"], "mnocrc">, Group<m_arm_Features_Group>, HelpText<"Disallow use of CRC instructions (ARM only)">; +def mno_neg_immediates: Flag<["-"], "mno-neg-immediates">, Group<m_arm_Features_Group>, + HelpText<"Disallow converting instructions with negative immediates to their negation or inversion.">; def mgeneral_regs_only : Flag<["-"], "mgeneral-regs-only">, Group<m_aarch64_Features_Group>, HelpText<"Generate code which only uses the general purpose registers (AArch64 only)">; @@ -1648,6 +1810,10 @@ def mamdgpu_debugger_abi : Joined<["-"], "mamdgpu-debugger-abi=">, HelpText<"Generate additional code for specified <version> of debugger ABI (AMDGPU only)">, MetaVarName<"<version>">; +def faltivec : Flag<["-"], "faltivec">, Group<f_Group>, Flags<[DriverOption]>; +def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>, Flags<[DriverOption]>; +def maltivec : Flag<["-"], "maltivec">, Group<m_ppc_Features_Group>; +def mno_altivec : Flag<["-"], "mno-altivec">, Group<m_ppc_Features_Group>; def mvsx : Flag<["-"], "mvsx">, Group<m_ppc_Features_Group>; def mno_vsx : Flag<["-"], "mno-vsx">, Group<m_ppc_Features_Group>; def mpower8_vector : Flag<["-"], "mpower8-vector">, @@ -1698,12 +1864,6 @@ def mlongcall: Flag<["-"], "mlongcall">, def mno_longcall : Flag<["-"], "mno-longcall">, Group<m_ppc_Features_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 maltivec : Flag<["-"], "maltivec">, Alias<faltivec>; -def mno_altivec : Flag<["-"], "mno-altivec">, Alias<fno_altivec>; - def mvx : Flag<["-"], "mvx">, Group<m_Group>; def mno_vx : Flag<["-"], "mno-vx">, Group<m_Group>; @@ -1735,7 +1895,8 @@ def mno_incremental_linker_compatible : Flag<["-"], "mno-incremental-linker-comp HelpText<"(integrated-as) Emit an object file which cannot be used with an incremental linker">; def mrtd : Flag<["-"], "mrtd">, Group<m_Group>, Flags<[CC1Option]>, HelpText<"Make StdCall calling convention the default">; -def msmall_data_threshold_EQ : Joined <["-"], "msmall-data-threshold=">, Group<m_Group>; +def msmall_data_threshold_EQ : Joined <["-"], "msmall-data-threshold=">, + Group<m_Group>, Alias<G>; def msoft_float : Flag<["-"], "msoft-float">, Group<m_Group>, Flags<[CC1Option]>, HelpText<"Use software floating point">; def mno_implicit_float : Flag<["-"], "mno-implicit-float">, Group<m_Group>, @@ -1747,6 +1908,8 @@ def mpie_copy_relocations : Flag<["-"], "mpie-copy-relocations">, Group<m_Group> Flags<[CC1Option]>, HelpText<"Use copy relocations support for PIE builds">; def mno_pie_copy_relocations : Flag<["-"], "mno-pie-copy-relocations">, Group<m_Group>; +def mfentry : Flag<["-"], "mfentry">, HelpText<"Insert calls to fentry at function entry (x86 only)">, + Flags<[CC1Option]>, Group<m_Group>; def mx87 : Flag<["-"], "mx87">, Group<m_x86_Features_Group>; def m80387 : Flag<["-"], "m80387">, Alias<mx87>; def msse2 : Flag<["-"], "msse2">, Group<m_x86_Features_Group>; @@ -1794,6 +1957,13 @@ def mxsaveopt : Flag<["-"], "mxsaveopt">, Group<m_x86_Features_Group>; def mxsavec : Flag<["-"], "mxsavec">, Group<m_x86_Features_Group>; def mxsaves : Flag<["-"], "mxsaves">, Group<m_x86_Features_Group>; def mmwaitx : Flag<["-"], "mmwaitx">, Group<m_x86_Features_Group>; +def mclzero : Flag<["-"], "mclzero">, Group<m_x86_Features_Group>; +def mclflushopt : Flag<["-"], "mclflushopt">, Group<m_x86_Features_Group>; +def mclwb : Flag<["-"], "mclwb">, Group<m_x86_Features_Group>; +def mmovbe : Flag<["-"], "mmovbe">, Group<m_x86_Features_Group>; +def mmpx : Flag<["-"], "mmpx">, Group<m_x86_Features_Group>; +def msgx : Flag<["-"], "msgx">, Group<m_x86_Features_Group>; +def mprefetchwt1 : Flag<["-"], "mprefetchwt1">, Group<m_x86_Features_Group>; def mips16 : Flag<["-"], "mips16">, Group<m_Group>; def mno_mips16 : Flag<["-"], "mno-mips16">, Group<m_Group>; def mmicromips : Flag<["-"], "mmicromips">, Group<m_Group>; @@ -1938,6 +2108,8 @@ def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">, Flags<[Unsupported]>; def print_prog_name_EQ : Joined<["-", "--"], "print-prog-name=">, HelpText<"Print the full program path of <name>">, MetaVarName<"<name>">; +def print_resource_dir : Flag<["-", "--"], "print-resource-dir">, + HelpText<"Print the resource directory pathname">; def print_search_dirs : Flag<["-", "--"], "print-search-dirs">, HelpText<"Print the paths used for finding libraries and programs">; def private__bundle : Flag<["-"], "private_bundle">; @@ -1959,10 +2131,15 @@ def resource_dir : Separate<["-"], "resource-dir">, HelpText<"The directory which holds the compiler resource files">; def resource_dir_EQ : Joined<["-"], "resource-dir=">, Flags<[DriverOption, CoreOption]>, Alias<resource_dir>; -def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>; +def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>, Group<Link_Group>; def rtlib_EQ : Joined<["-", "--"], "rtlib=">, HelpText<"Compiler runtime library to use">; -def r : Flag<["-"], "r">, Flags<[LinkerInput,NoArgumentUnused]>; +def frtlib_add_rpath: Flag<["-"], "frtlib-add-rpath">, Flags<[NoArgumentUnused]>, + HelpText<"Add -rpath with architecture-specific resource directory to the linker flags">; +def fno_rtlib_add_rpath: Flag<["-"], "fno-rtlib-add-rpath">, Flags<[NoArgumentUnused]>, + HelpText<"Do not add -rpath with architecture-specific resource directory to the linker flags">; +def r : Flag<["-"], "r">, Flags<[LinkerInput,NoArgumentUnused]>, + Group<Link_Group>; def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[DriverOption]>, HelpText<"Save intermediate compilation results.">; def save_temps : Flag<["-", "--"], "save-temps">, Flags<[DriverOption]>, @@ -2014,7 +2191,7 @@ def no_system_header_prefix : Joined<["--"], "no-system-header-prefix=">, HelpText<"Treat all #include paths starting with <prefix> as not including a " "system header.">; def : Separate<["--"], "no-system-header-prefix">, Alias<no_system_header_prefix>; -def s : Flag<["-"], "s">; +def s : Flag<["-"], "s">, Group<Link_Group>; def target : Joined<["--"], "target=">, Flags<[DriverOption, CoreOption]>, HelpText<"Generate code for the given target">; def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[DriverOption]>, @@ -2028,7 +2205,7 @@ def trigraphs : Flag<["-", "--"], "trigraphs">, Alias<ftrigraphs>, HelpText<"Process trigraph sequences">; def twolevel__namespace__hints : Flag<["-"], "twolevel_namespace_hints">; def twolevel__namespace : Flag<["-"], "twolevel_namespace">; -def t : Flag<["-"], "t">; +def t : Flag<["-"], "t">, Group<Link_Group>; def umbrella : Separate<["-"], "umbrella">; def undefined : JoinedOrSeparate<["-"], "undefined">, Group<u_Group>; def undef : Flag<["-"], "undef">, Group<u_Group>, Flags<[CC1Option]>, @@ -2185,6 +2362,8 @@ def mv55 : Flag<["-"], "mv55">, Group<m_hexagon_Features_Group>, Alias<mcpu_EQ>, AliasArgs<["hexagonv55"]>; def mv60 : Flag<["-"], "mv60">, Group<m_hexagon_Features_Group>, Alias<mcpu_EQ>, AliasArgs<["hexagonv60"]>; +def mv62 : Flag<["-"], "mv62">, Group<m_hexagon_Features_Group>, + Alias<mcpu_EQ>, AliasArgs<["hexagonv62"]>; def mhexagon_hvx : Flag<["-"], "mhvx">, Group<m_hexagon_Features_Group>, Flags<[CC1Option]>, HelpText<"Enable Hexagon Vector eXtensions">; def mno_hexagon_hvx : Flag<["-"], "mno-hvx">, Group<m_hexagon_Features_Group>, @@ -2322,10 +2501,6 @@ defm devirtualize : BooleanFFlag<"devirtualize">, Group<clang_ignored_gcc_optimi defm devirtualize_speculatively : BooleanFFlag<"devirtualize-speculatively">, Group<clang_ignored_gcc_optimization_f_Group>; -// gfortran options that we recognize in the driver and pass along when -// invoking GCC to compile Fortran code. -def gfortran_Group : OptionGroup<"gfortran Group">; - // Generic gfortran options. def A_DASH : Joined<["-"], "A-">, Group<gfortran_Group>; def J : JoinedOrSeparate<["-"], "J">, Flags<[RenderJoined]>, Group<gfortran_Group>; diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h index 6206680118d5..2df8077d6da6 100644 --- a/include/clang/Driver/SanitizerArgs.h +++ b/include/clang/Driver/SanitizerArgs.h @@ -34,7 +34,7 @@ class SanitizerArgs { bool CfiCrossDso = false; int AsanFieldPadding = 0; bool AsanSharedRuntime = false; - bool AsanUseAfterScope = false; + bool AsanUseAfterScope = true; bool LinkCXXRuntimes = false; bool NeedPIE = false; bool Stats = false; diff --git a/include/clang/Driver/Tool.h b/include/clang/Driver/Tool.h index 5012cc896683..8f76e17c48ba 100644 --- a/include/clang/Driver/Tool.h +++ b/include/clang/Driver/Tool.h @@ -35,7 +35,7 @@ class Tool { public: // Documents the level of support for response files in this tool. // Response files are necessary if the command line gets too large, - // requiring the arguments to be transfered to a file. + // requiring the arguments to be transferred to a file. enum ResponseFileSupport { // Provides full support for response files, which means we can transfer // all tool input arguments to a file. E.g.: clang, gcc, binutils and MSVC diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index ffb0d60a6398..105d0f338ac6 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -44,6 +44,7 @@ namespace driver { class RegisterEffectiveTriple; class SanitizerArgs; class Tool; + class XRayArgs; /// ToolChain - Access to tools for a single platform. class ToolChain { @@ -94,12 +95,15 @@ private: Tool *getOffloadBundler() const; mutable std::unique_ptr<SanitizerArgs> SanitizerArguments; + mutable std::unique_ptr<XRayArgs> XRayArguments; /// The effective clang triple for the current Job. mutable llvm::Triple EffectiveTriple; /// Set the toolchain's effective clang triple. - void setEffectiveTriple(llvm::Triple ET) const { EffectiveTriple = ET; } + void setEffectiveTriple(llvm::Triple ET) const { + EffectiveTriple = std::move(ET); + } friend class RegisterEffectiveTriple; @@ -175,6 +179,8 @@ public: const SanitizerArgs& getSanitizerArgs() const; + const XRayArgs& getXRayArgs() const; + // Returns the Arg * that explicitly turned on/off rtti, or nullptr. const llvm::opt::Arg *getRTTIArg() const { return CachedRTTIArg; } @@ -299,6 +305,11 @@ public: const char *getCompilerRTArgString(const llvm::opt::ArgList &Args, StringRef Component, bool Shared = false) const; + + // Returns <ResourceDir>/lib/<OSName>/<arch>. This is used by runtimes (such + // as OpenMP) to find arch-specific libraries. + std::string getArchSpecificLibPath() const; + /// needsProfileRT - returns true if instrumentation profile is on. static bool needsProfileRT(const llvm::opt::ArgList &Args); @@ -471,7 +482,7 @@ class RegisterEffectiveTriple { public: RegisterEffectiveTriple(const ToolChain &TC, llvm::Triple T) : TC(TC) { - TC.setEffectiveTriple(T); + TC.setEffectiveTriple(std::move(T)); } ~RegisterEffectiveTriple() { TC.setEffectiveTriple(llvm::Triple()); } diff --git a/include/clang/Driver/XRayArgs.h b/include/clang/Driver/XRayArgs.h new file mode 100644 index 000000000000..83210d100a12 --- /dev/null +++ b/include/clang/Driver/XRayArgs.h @@ -0,0 +1,38 @@ +//===--- XRayArgs.h - Arguments for XRay ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_DRIVER_XRAYARGS_H +#define LLVM_CLANG_DRIVER_XRAYARGS_H + +#include "clang/Driver/Types.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" + +namespace clang { +namespace driver { + +class ToolChain; + +class XRayArgs { + std::vector<std::string> AlwaysInstrumentFiles; + std::vector<std::string> NeverInstrumentFiles; + std::vector<std::string> ExtraDeps; + bool XRayInstrument = false; + int InstructionThreshold = 200; + +public: + /// Parses the XRay arguments from an argument list. + XRayArgs(const ToolChain &TC, const llvm::opt::ArgList &Args); + void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const; +}; + +} // namespace driver +} // namespace clang + +#endif // LLVM_CLANG_DRIVER_XRAYARGS_H diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index 6c6458b33d85..05daf4f897f4 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -100,6 +100,19 @@ struct FormatStyle { /// \brief If ``true``, aligns escaped newlines as far left as possible. /// Otherwise puts them into the right-most column. + /// \code + /// true: + /// #define A \ + /// int aaaa; \ + /// int b; \ + /// int dddddddddd; + /// + /// false: + /// #define A \ + /// int aaaa; \ + /// int b; \ + /// int dddddddddd; + /// \endcode bool AlignEscapedNewlinesLeft; /// \brief If ``true``, horizontally align operands of binary and ternary @@ -114,10 +127,21 @@ struct FormatStyle { bool AlignOperands; /// \brief If ``true``, aligns trailing comments. + /// \code + /// true: false: + /// int a; // My comment a vs. int a; // My comment a + /// int b = 2; // comment b int b = 2; // comment about b + /// \endcode bool AlignTrailingComments; /// \brief Allow putting all parameters of a function declaration onto /// the next line even if ``BinPackParameters`` is ``false``. + /// \code + /// true: false: + /// myFunction(foo, vs. myFunction(foo, bar, plop); + /// bar, + /// plop); + /// \endcode bool AllowAllParametersOfDeclarationOnNextLine; /// \brief Allows contracting simple braced statements to a single line. @@ -126,6 +150,16 @@ struct FormatStyle { bool AllowShortBlocksOnASingleLine; /// \brief If ``true``, short case labels will be contracted to a single line. + /// \code + /// true: false: + /// switch (a) { vs. switch (a) { + /// case 1: x = 1; break; case 1: + /// case 2: return; x = 1; + /// } break; + /// case 2: + /// return; + /// } + /// \endcode bool AllowShortCaseLabelsOnASingleLine; /// \brief Different styles for merging short functions containing at most one @@ -134,10 +168,27 @@ struct FormatStyle { /// \brief Never merge functions into a single line. SFS_None, /// \brief Only merge empty functions. + /// \code + /// void f() { bar(); } + /// void f2() { + /// bar2(); + /// } + /// \endcode SFS_Empty, /// \brief Only merge functions defined inside a class. Implies "empty". + /// \code + /// class Foo { + /// void f() { foo(); } + /// }; + /// \endcode SFS_Inline, /// \brief Merge all functions fitting on a single line. + /// \code + /// class Foo { + /// void f() { foo(); } + /// }; + /// void f() { bar(); } + /// \endcode SFS_All, }; @@ -153,6 +204,7 @@ struct FormatStyle { bool AllowShortLoopsOnASingleLine; /// \brief Different ways to break after the function definition return type. + /// This option is **deprecated** and is retained for backwards compatibility. enum DefinitionReturnTypeBreakingStyle { /// Break after return type automatically. /// ``PenaltyReturnTypeOnItsOwnLine`` is taken into account. @@ -168,19 +220,74 @@ struct FormatStyle { enum ReturnTypeBreakingStyle { /// Break after return type automatically. /// ``PenaltyReturnTypeOnItsOwnLine`` is taken into account. + /// \code + /// class A { + /// int f() { return 0; }; + /// }; + /// int f(); + /// int f() { return 1; } + /// \endcode RTBS_None, /// Always break after the return type. + /// \code + /// class A { + /// int + /// f() { + /// return 0; + /// }; + /// }; + /// int + /// f(); + /// int + /// f() { + /// return 1; + /// } + /// \endcode RTBS_All, /// Always break after the return types of top-level functions. + /// \code + /// class A { + /// int f() { return 0; }; + /// }; + /// int + /// f(); + /// int + /// f() { + /// return 1; + /// } + /// \endcode RTBS_TopLevel, /// Always break after the return type of function definitions. + /// \code + /// class A { + /// int + /// f() { + /// return 0; + /// }; + /// }; + /// int f(); + /// int + /// f() { + /// return 1; + /// } + /// \endcode RTBS_AllDefinitions, /// Always break after the return type of top-level definitions. + /// \code + /// class A { + /// int f() { return 0; }; + /// }; + /// int f(); + /// int + /// f() { + /// return 1; + /// } + /// \endcode RTBS_TopLevelDefinitions, }; /// \brief The function definition return type breaking style to use. This - /// option is deprecated and is retained for backwards compatibility. + /// option is **deprecated** and is retained for backwards compatibility. DefinitionReturnTypeBreakingStyle AlwaysBreakAfterDefinitionReturnType; /// \brief The function declaration return type breaking style to use. @@ -192,27 +299,92 @@ struct FormatStyle { /// in a file look more consistent. Thus, it will only take effect if wrapping /// the string at that point leads to it being indented /// ``ContinuationIndentWidth`` spaces from the start of the line. + /// \code + /// true: false: + /// aaaa = vs. aaaa = "bbbb" + /// "bbbb" "cccc"; + /// "cccc"; + /// \endcode bool AlwaysBreakBeforeMultilineStrings; /// \brief If ``true``, always break after the ``template<...>`` of a template /// declaration. + /// \code + /// true: false: + /// template <typename T> vs. template <typename T> class C {}; + /// class C {}; + /// \endcode bool AlwaysBreakTemplateDeclarations; /// \brief If ``false``, a function call's arguments will either be all on the /// same line or will have one line each. + /// \code + /// true: + /// void f() { + /// f(aaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaa, + /// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa); + /// } + /// + /// false: + /// void f() { + /// f(aaaaaaaaaaaaaaaaaaaa, + /// aaaaaaaaaaaaaaaaaaaa, + /// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa); + /// } + /// \endcode bool BinPackArguments; /// \brief If ``false``, a function declaration's or function definition's /// parameters will either all be on the same line or will have one line each. + /// \code + /// true: + /// void f(int aaaaaaaaaaaaaaaaaaaa, int aaaaaaaaaaaaaaaaaaaa, + /// int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {} + /// + /// false: + /// void f(int aaaaaaaaaaaaaaaaaaaa, + /// int aaaaaaaaaaaaaaaaaaaa, + /// int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {} + /// \endcode bool BinPackParameters; /// \brief The style of breaking before or after binary operators. enum BinaryOperatorStyle { /// Break after operators. + /// \code + /// LooooooooooongType loooooooooooooooooooooongVariable = + /// someLooooooooooooooooongFunction(); + /// + /// bool value = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + /// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa == + /// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && + /// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > + /// ccccccccccccccccccccccccccccccccccccccccc; + /// \endcode BOS_None, /// Break before operators that aren't assignments. + /// \code + /// LooooooooooongType loooooooooooooooooooooongVariable = + /// someLooooooooooooooooongFunction(); + /// + /// bool value = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + /// + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + /// == aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + /// && aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + /// > ccccccccccccccccccccccccccccccccccccccccc; + /// \endcode BOS_NonAssignment, /// Break before operators. + /// \code + /// LooooooooooongType loooooooooooooooooooooongVariable + /// = someLooooooooooooooooongFunction(); + /// + /// bool value = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + /// + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + /// == aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + /// && aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + /// > ccccccccccccccccccccccccccccccccccccccccc; + /// \endcode BOS_All, }; @@ -222,23 +394,133 @@ struct FormatStyle { /// \brief Different ways to attach braces to their surrounding context. enum BraceBreakingStyle { /// Always attach braces to surrounding context. + /// \code + /// try { + /// foo(); + /// } catch () { + /// } + /// void foo() { bar(); } + /// class foo {}; + /// if (foo()) { + /// } else { + /// } + /// enum X : int { A, B }; + /// \endcode BS_Attach, /// Like ``Attach``, but break before braces on function, namespace and /// class definitions. + /// \code + /// try { + /// foo(); + /// } catch () { + /// } + /// void foo() { bar(); } + /// class foo + /// { + /// }; + /// if (foo()) { + /// } else { + /// } + /// enum X : int { A, B }; + /// \endcode BS_Linux, /// Like ``Attach``, but break before braces on enum, function, and record /// definitions. + /// \code + /// try { + /// foo(); + /// } catch () { + /// } + /// void foo() { bar(); } + /// class foo + /// { + /// }; + /// if (foo()) { + /// } else { + /// } + /// enum X : int { A, B }; + /// \endcode BS_Mozilla, /// Like ``Attach``, but break before function definitions, ``catch``, and /// ``else``. + /// \code + /// try { + /// foo(); + /// } catch () { + /// } + /// void foo() { bar(); } + /// class foo + /// { + /// }; + /// if (foo()) { + /// } else { + /// } + /// enum X : int + /// { + /// A, + /// B + /// }; + /// \endcode BS_Stroustrup, /// Always break before braces. + /// \code + /// try { + /// foo(); + /// } + /// catch () { + /// } + /// void foo() { bar(); } + /// class foo { + /// }; + /// if (foo()) { + /// } + /// else { + /// } + /// enum X : int { A, B }; + /// \endcode BS_Allman, /// Always break before braces and add an extra level of indentation to /// braces of control statements, not to those of class, function /// or other definitions. + /// \code + /// try + /// { + /// foo(); + /// } + /// catch () + /// { + /// } + /// void foo() { bar(); } + /// class foo + /// { + /// }; + /// if (foo()) + /// { + /// } + /// else + /// { + /// } + /// enum X : int + /// { + /// A, + /// B + /// }; + /// \endcode BS_GNU, /// Like ``Attach``, but break before functions. + /// \code + /// try { + /// foo(); + /// } catch () { + /// } + /// void foo() { bar(); } + /// class foo { + /// }; + /// if (foo()) { + /// } else { + /// } + /// enum X : int { A, B }; + /// \endcode BS_WebKit, /// Configure each individual brace in `BraceWrapping`. BS_Custom @@ -248,26 +530,144 @@ struct FormatStyle { BraceBreakingStyle BreakBeforeBraces; /// \brief Precise control over the wrapping of braces. + /// \code + /// # Should be declared this way: + /// BreakBeforeBraces: Custom + /// BraceWrapping: + /// AfterClass: true + /// \endcode struct BraceWrappingFlags { /// \brief Wrap class definitions. + /// \code + /// true: + /// class foo {}; + /// + /// false: + /// class foo + /// {}; + /// \endcode bool AfterClass; /// \brief Wrap control statements (``if``/``for``/``while``/``switch``/..). + /// \code + /// true: + /// if (foo()) + /// { + /// } else + /// {} + /// for (int i = 0; i < 10; ++i) + /// {} + /// + /// false: + /// if (foo()) { + /// } else { + /// } + /// for (int i = 0; i < 10; ++i) { + /// } + /// \endcode bool AfterControlStatement; /// \brief Wrap enum definitions. + /// \code + /// true: + /// enum X : int + /// { + /// B + /// }; + /// + /// false: + /// enum X : int { B }; + /// \endcode bool AfterEnum; /// \brief Wrap function definitions. + /// \code + /// true: + /// void foo() + /// { + /// bar(); + /// bar2(); + /// } + /// + /// false: + /// void foo() { + /// bar(); + /// bar2(); + /// } + /// \endcode bool AfterFunction; /// \brief Wrap namespace definitions. + /// \code + /// true: + /// namespace + /// { + /// int foo(); + /// int bar(); + /// } + /// + /// false: + /// namespace { + /// int foo(); + /// int bar(); + /// } + /// \endcode bool AfterNamespace; /// \brief Wrap ObjC definitions (``@autoreleasepool``, interfaces, ..). bool AfterObjCDeclaration; /// \brief Wrap struct definitions. + /// \code + /// true: + /// struct foo + /// { + /// int x; + /// } + /// + /// false: + /// struct foo { + /// int x; + /// } + /// \endcode bool AfterStruct; /// \brief Wrap union definitions. + /// \code + /// true: + /// union foo + /// { + /// int x; + /// } + /// + /// false: + /// union foo { + /// int x; + /// } + /// \endcode bool AfterUnion; /// \brief Wrap before ``catch``. + /// \code + /// true: + /// try { + /// foo(); + /// } + /// catch () { + /// } + /// + /// false: + /// try { + /// foo(); + /// } catch () { + /// } + /// \endcode bool BeforeCatch; /// \brief Wrap before ``else``. + /// \code + /// true: + /// if (foo()) { + /// } + /// else { + /// } + /// + /// false: + /// if (foo()) { + /// } else { + /// } + /// \endcode bool BeforeElse; /// \brief Indent the wrapped braces themselves. bool IndentBraces; @@ -280,13 +680,37 @@ struct FormatStyle { BraceWrappingFlags BraceWrapping; /// \brief If ``true``, ternary operators will be placed after line breaks. + /// \code + /// true: + /// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongDescription + /// ? firstValue + /// : SecondValueVeryVeryVeryVeryLong; + /// + /// true: + /// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongDescription ? + /// firstValue : + /// SecondValueVeryVeryVeryVeryLong; + /// \endcode bool BreakBeforeTernaryOperators; /// \brief Always break constructor initializers before commas and align /// the commas with the colon. + /// \code + /// true: false: + /// SomeClass::Constructor() vs. SomeClass::Constructor() : a(a), + /// : a(a) b(b), + /// , b(b) c(c) {} + /// , c(c) {} + /// \endcode bool BreakConstructorInitializersBeforeComma; /// \brief Break after each annotation on a field in Java files. + /// \code{.java} + /// true: false: + /// @Partial vs. @Partial @Mock DataLoad loader; + /// @Mock + /// DataLoad loader; + /// \endcode bool BreakAfterJavaFieldAnnotations; /// \brief Allow breaking string literals when formatting. @@ -301,10 +725,40 @@ struct FormatStyle { /// \brief A regular expression that describes comments with special meaning, /// which should not be split into lines or otherwise changed. + /// \code + /// // CommentPragmas: '^ FOOBAR pragma:' + /// // Will leave the following line unaffected + /// #include <vector> // FOOBAR pragma: keep + /// \endcode std::string CommentPragmas; + /// \brief If ``true``, in the class inheritance expression clang-format will + /// break before ``:`` and ``,`` if there is multiple inheritance. + /// \code + /// true: false: + /// class MyClass vs. class MyClass : public X, public Y { + /// : public X }; + /// , public Y { + /// }; + /// \endcode + bool BreakBeforeInheritanceComma; + /// \brief If the constructor initializers don't fit on a line, put each /// initializer on its own line. + /// \code + /// true: + /// SomeClass::Constructor() + /// : aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaa) { + /// return 0; + /// } + /// + /// false: + /// SomeClass::Constructor() + /// : aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaa), + /// aaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaa) { + /// return 0; + /// } + /// \endcode bool ConstructorInitializerAllOnOneLineOrOnePerLine; /// \brief The number of characters to use for indentation of constructor @@ -312,6 +766,13 @@ struct FormatStyle { unsigned ConstructorInitializerIndentWidth; /// \brief Indent width for line continuations. + /// \code + /// ContinuationIndentWidth: 2 + /// + /// int i = // VeryVeryVeryVeryVeryLongComment + /// longFunction( // Again a long comment + /// arg); + /// \endcode unsigned ContinuationIndentWidth; /// \brief If ``true``, format braced lists as best suited for C++11 braced @@ -327,11 +788,20 @@ struct FormatStyle { /// (e.g. a type or variable name), clang-format formats as if the ``{}`` were /// the parentheses of a function call with that name. If there is no name, /// a zero-length name is assumed. + /// \code + /// true: false: + /// vector<int> x{1, 2, 3, 4}; vs. vector<int> x{ 1, 2, 3, 4 }; + /// vector<T> x{{}, {}, {}, {}}; vector<T> x{ {}, {}, {}, {} }; + /// f(MyMap[{composite, key}]); f(MyMap[{ composite, key }]); + /// new int[3]{1, 2, 3}; new int[3]{ 1, 2, 3 }; + /// \endcode bool Cpp11BracedListStyle; /// \brief If ``true``, analyze the formatted file for the most common - /// alignment of ``&`` and ``*``. ``PointerAlignment`` is then used only as - /// fallback. + /// alignment of ``&`` and ``*``. + /// Pointer and reference alignment styles are going to be updated according + /// to the preferences found in the file. + /// ``PointerAlignment`` is then used only as fallback. bool DerivePointerAlignment; /// \brief Disables formatting completely. @@ -349,6 +819,16 @@ struct FormatStyle { /// not use this in config files, etc. Use at your own risk. bool ExperimentalAutoDetectBinPacking; + /// \brief If ``true``, clang-format adds missing namespace end comments and + /// fixes invalid existing ones. + /// \code + /// true: false: + /// namespace a { vs. namespace a { + /// foo(); foo(); + /// } // namespace a; } + /// \endcode + bool FixNamespaceComments; + /// \brief A vector of macros that should be interpreted as foreach loops /// instead of as function calls. /// @@ -422,23 +902,64 @@ struct FormatStyle { /// /// When ``false``, use the same indentation level as for the switch statement. /// Switch statement body is always indented one level more than case labels. + /// \code + /// false: true: + /// switch (fool) { vs. switch (fool) { + /// case 1: case 1: + /// bar(); bar(); + /// break; break; + /// default: default: + /// plop(); plop(); + /// } } + /// \endcode bool IndentCaseLabels; /// \brief The number of columns to use for indentation. + /// \code + /// IndentWidth: 3 + /// + /// void f() { + /// someFunction(); + /// if (true, false) { + /// f(); + /// } + /// } + /// \endcode unsigned IndentWidth; /// \brief Indent if a function definition or declaration is wrapped after the /// type. + /// \code + /// true: + /// LoooooooooooooooooooooooooooooooooooooooongReturnType + /// LoooooooooooooooooooooooooooooooongFunctionDeclaration(); + /// + /// false: + /// LoooooooooooooooooooooooooooooooooooooooongReturnType + /// LoooooooooooooooooooooooooooooooongFunctionDeclaration(); + /// \endcode bool IndentWrappedFunctionNames; /// \brief Quotation styles for JavaScript strings. Does not affect template /// strings. enum JavaScriptQuoteStyle { /// Leave string quotes as they are. + /// \code{.js} + /// string1 = "foo"; + /// string2 = 'bar'; + /// \endcode JSQS_Leave, /// Always use single quotes. + /// \code{.js} + /// string1 = 'foo'; + /// string2 = 'bar'; + /// \endcode JSQS_Single, /// Always use double quotes. + /// \code{.js} + /// string1 = "foo"; + /// string2 = "bar"; + /// \endcode JSQS_Double }; @@ -446,9 +967,27 @@ struct FormatStyle { JavaScriptQuoteStyle JavaScriptQuotes; /// \brief Whether to wrap JavaScript import/export statements. + /// \code{.js} + /// true: + /// import { + /// VeryLongImportsAreAnnoying, + /// VeryLongImportsAreAnnoying, + /// VeryLongImportsAreAnnoying, + /// } from 'some/module.js' + /// + /// false: + /// import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,} from "some/module.js" + /// \endcode bool JavaScriptWrapImports; - /// \brief If true, empty lines at the start of blocks are kept. + /// \brief If true, the empty line at the start of blocks is kept. + /// \code + /// true: false: + /// if (foo) { vs. if (foo) { + /// bar(); + /// bar(); } + /// } + /// \endcode bool KeepEmptyLinesAtTheStartOfBlocks; /// \brief Supported languages. @@ -459,13 +998,13 @@ struct FormatStyle { enum LanguageKind { /// Do not use. LK_None, - /// Should be used for C, C++, ObjectiveC, ObjectiveC++. + /// Should be used for C, C++. LK_Cpp, /// Should be used for Java. LK_Java, /// Should be used for JavaScript. LK_JavaScript, - /// Should be used for ObjC code. + /// Should be used for Objective-C, Objective-C++. LK_ObjC, /// Should be used for Protocol Buffers /// (https://developers.google.com/protocol-buffers/). @@ -473,26 +1012,86 @@ struct FormatStyle { /// Should be used for TableGen code. LK_TableGen }; + bool isCpp() const { return Language == LK_Cpp || Language == LK_ObjC; } /// \brief Language, this format style is targeted at. LanguageKind Language; /// \brief A regular expression matching macros that start a block. + /// \code + /// # With: + /// MacroBlockBegin: "^NS_MAP_BEGIN|\ + /// NS_TABLE_HEAD$" + /// MacroBlockEnd: "^\ + /// NS_MAP_END|\ + /// NS_TABLE_.*_END$" + /// + /// NS_MAP_BEGIN + /// foo(); + /// NS_MAP_END + /// + /// NS_TABLE_HEAD + /// bar(); + /// NS_TABLE_FOO_END + /// + /// # Without: + /// NS_MAP_BEGIN + /// foo(); + /// NS_MAP_END + /// + /// NS_TABLE_HEAD + /// bar(); + /// NS_TABLE_FOO_END + /// \endcode std::string MacroBlockBegin; /// \brief A regular expression matching macros that end a block. std::string MacroBlockEnd; /// \brief The maximum number of consecutive empty lines to keep. + /// \code + /// MaxEmptyLinesToKeep: 1 vs. MaxEmptyLinesToKeep: 0 + /// int f() { int f() { + /// int = 1; int i = 1; + /// i = foo(); + /// i = foo(); return i; + /// } + /// return i; + /// } + /// \endcode unsigned MaxEmptyLinesToKeep; /// \brief Different ways to indent namespace contents. enum NamespaceIndentationKind { /// Don't indent in namespaces. + /// \code + /// namespace out { + /// int i; + /// namespace in { + /// int i; + /// } + /// } + /// \endcode NI_None, /// Indent only in inner namespaces (nested in other namespaces). + /// \code + /// namespace out { + /// int i; + /// namespace in { + /// int i; + /// } + /// } + /// \endcode NI_Inner, /// Indent in all namespaces. + /// \code + /// namespace out { + /// int i; + /// namespace in { + /// int i; + /// } + /// } + /// \endcode NI_All }; @@ -500,6 +1099,13 @@ struct FormatStyle { NamespaceIndentationKind NamespaceIndentation; /// \brief The number of characters to use for indentation of ObjC blocks. + /// \code{.objc} + /// ObjCBlockIndentWidth: 4 + /// + /// [operation setCompletionBlock:^{ + /// [self onOperationDone]; + /// }]; + /// \endcode unsigned ObjCBlockIndentWidth; /// \brief Add a space after ``@property`` in Objective-C, i.e. use @@ -532,10 +1138,19 @@ struct FormatStyle { /// \brief The ``&`` and ``*`` alignment style. enum PointerAlignmentStyle { /// Align pointer to the left. + /// \code + /// int* a; + /// \endcode PAS_Left, /// Align pointer to the right. + /// \code + /// int *a; + /// \endcode PAS_Right, /// Align pointer in the middle. + /// \code + /// int * a; + /// \endcode PAS_Middle }; @@ -543,31 +1158,81 @@ struct FormatStyle { PointerAlignmentStyle PointerAlignment; /// \brief If ``true``, clang-format will attempt to re-flow comments. + /// \code + /// false: + /// // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information + /// /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */ + /// + /// true: + /// // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of + /// // information + /// /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of + /// * information */ + /// \endcode bool ReflowComments; /// \brief If ``true``, clang-format will sort ``#includes``. + /// \code + /// false: true: + /// #include "b.h" vs. #include "a.h" + /// #include "a.h" #include "b.h" + /// \endcode bool SortIncludes; - /// \brief If ``true``, a space may be inserted after C style casts. + /// \brief If ``true``, a space is inserted after C style casts. + /// \code + /// true: false: + /// (int)i; vs. (int) i; + /// \endcode bool SpaceAfterCStyleCast; /// \brief If \c true, a space will be inserted after the 'template' keyword. + /// \code + /// true: false: + /// template <int> void foo(); vs. template<int> void foo(); + /// \endcode bool SpaceAfterTemplateKeyword; /// \brief If ``false``, spaces will be removed before assignment operators. + /// \code + /// true: false: + /// int a = 5; vs. int a=5; + /// a += 42 a+=42; + /// \endcode bool SpaceBeforeAssignmentOperators; /// \brief Different ways to put a space before opening parentheses. enum SpaceBeforeParensOptions { /// Never put a space before opening parentheses. + /// \code + /// void f() { + /// if(true) { + /// f(); + /// } + /// } + /// \endcode SBPO_Never, /// Put a space before opening parentheses only after control statement /// keywords (``for/if/while...``). + /// \code + /// void f() { + /// if (true) { + /// f(); + /// } + /// } + /// \endcode SBPO_ControlStatements, /// Always put a space before opening parentheses, except when it's /// prohibited by the syntax rules (in function-like macro definitions) or /// when determined by other style rules (after unary operators, opening /// parentheses, etc.) + /// \code + /// void f () { + /// if (true) { + /// f (); + /// } + /// } + /// \endcode SBPO_Always }; @@ -575,6 +1240,15 @@ struct FormatStyle { SpaceBeforeParensOptions SpaceBeforeParens; /// \brief If ``true``, spaces may be inserted into ``()``. + /// \code + /// true: false: + /// void f( ) { vs. void f() { + /// int x[] = {foo( ), bar( )}; int x[] = {foo(), bar()}; + /// if (true) { if (true) { + /// f( ); f(); + /// } } + /// } } + /// \endcode bool SpaceInEmptyParentheses; /// \brief The number of spaces before trailing line comments @@ -583,30 +1257,63 @@ struct FormatStyle { /// This does not affect trailing block comments (``/*`` - comments) as /// those commonly have different usage patterns and a number of special /// cases. + /// \code + /// SpacesBeforeTrailingComments: 3 + /// void f() { + /// if (true) { // foo1 + /// f(); // bar + /// } // foo + /// } + /// \endcode unsigned SpacesBeforeTrailingComments; /// \brief If ``true``, spaces will be inserted after ``<`` and before ``>`` /// in template argument lists. + /// \code + /// true: false: + /// static_cast< int >(arg); vs. static_cast<int>(arg); + /// std::function< void(int) > fct; std::function<void(int)> fct; + /// \endcode bool SpacesInAngles; /// \brief If ``true``, spaces are inserted inside container literals (e.g. /// ObjC and Javascript array and dict literals). + /// \code{.js} + /// true: false: + /// var arr = [ 1, 2, 3 ]; vs. var arr = [1, 2, 3]; + /// f({a : 1, b : 2, c : 3}); f({a: 1, b: 2, c: 3}); + /// \endcode bool SpacesInContainerLiterals; /// \brief If ``true``, spaces may be inserted into C style casts. + /// \code + /// true: false: + /// x = ( int32 )y vs. x = (int32)y + /// \endcode bool SpacesInCStyleCastParentheses; /// \brief If ``true``, spaces will be inserted after ``(`` and before ``)``. + /// \code + /// true: false: + /// t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete; + /// \endcode bool SpacesInParentheses; /// \brief If ``true``, spaces will be inserted after ``[`` and before ``]``. + /// Lambdas or unspecified size array declarations will not be affected. + /// \code + /// true: false: + /// int a[ 5 ]; vs. int a[5]; + /// std::unique_ptr<int[]> foo() {} // Won't be affected + /// \endcode bool SpacesInSquareBrackets; /// \brief Supported language standards. enum LanguageStandard { /// Use C++03-compatible syntax. LS_Cpp03, - /// Use features of C++11 (e.g. ``A<A<int>>`` instead of ``A<A<int> >``). + /// Use features of C++11, C++14 and C++1z (e.g. ``A<A<int>>`` instead of + /// ``A<A<int> >``). LS_Cpp11, /// Automatic detection based on the input. LS_Auto @@ -668,6 +1375,7 @@ struct FormatStyle { BreakAfterJavaFieldAnnotations == R.BreakAfterJavaFieldAnnotations && BreakStringLiterals == R.BreakStringLiterals && ColumnLimit == R.ColumnLimit && CommentPragmas == R.CommentPragmas && + BreakBeforeInheritanceComma == R.BreakBeforeInheritanceComma && ConstructorInitializerAllOnOneLineOrOnePerLine == R.ConstructorInitializerAllOnOneLineOrOnePerLine && ConstructorInitializerIndentWidth == @@ -678,6 +1386,7 @@ struct FormatStyle { DisableFormat == R.DisableFormat && ExperimentalAutoDetectBinPacking == R.ExperimentalAutoDetectBinPacking && + FixNamespaceComments == R.FixNamespaceComments && ForEachMacros == R.ForEachMacros && IncludeCategories == R.IncludeCategories && IndentCaseLabels == R.IndentCaseLabels && @@ -828,6 +1537,15 @@ tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, ArrayRef<tooling::Range> Ranges, StringRef FileName = "<stdin>"); +/// \brief Fix namespace end comments in the given \p Ranges in \p Code. +/// +/// Returns the ``Replacements`` that fix the namespace comments in all +/// \p Ranges in \p Code. +tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, + StringRef Code, + ArrayRef<tooling::Range> Ranges, + StringRef FileName = "<stdin>"); + /// \brief Returns the ``LangOpts`` that the formatter expects you to set. /// /// \param Style determines specific settings for lexing mode. @@ -853,23 +1571,27 @@ extern const char *StyleOptionHelpDescription; /// \param[in] FileName Path to start search for .clang-format if ``StyleName`` /// == "file". /// \param[in] FallbackStyle The name of a predefined style used to fallback to -/// in case the style can't be determined from \p StyleName. +/// in case \p StyleName is "file" and no file can be found. /// \param[in] Code The actual code to be formatted. Used to determine the /// language if the filename isn't sufficient. /// \param[in] FS The underlying file system, in which the file resides. By /// default, the file system is the real file system. /// -/// \returns FormatStyle as specified by ``StyleName``. If no style could be -/// determined, the default is LLVM Style (see ``getLLVMStyle()``). -FormatStyle getStyle(StringRef StyleName, StringRef FileName, - StringRef FallbackStyle, StringRef Code = "", - vfs::FileSystem *FS = nullptr); +/// \returns FormatStyle as specified by ``StyleName``. If ``StyleName`` is +/// "file" and no file is found, returns ``FallbackStyle``. If no style could be +/// determined, returns an Error. +llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, + StringRef FallbackStyle, + StringRef Code = "", + vfs::FileSystem *FS = nullptr); // \brief Returns a string representation of ``Language``. inline StringRef getLanguageName(FormatStyle::LanguageKind Language) { switch (Language) { case FormatStyle::LK_Cpp: return "C++"; + case FormatStyle::LK_ObjC: + return "Objective-C"; case FormatStyle::LK_Java: return "Java"; case FormatStyle::LK_JavaScript: diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index b76bfcbe4663..53975a07ea94 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -37,7 +37,7 @@ std::unique_ptr<ASTConsumer> CreateASTPrinter(std::unique_ptr<raw_ostream> OS, // AST dumper: dumps the raw AST in human-readable form to stderr; this is // intended for debugging. std::unique_ptr<ASTConsumer> CreateASTDumper(StringRef FilterString, - bool DumpDecls, + bool DumpDecls, bool Deserialize, bool DumpLookups); // AST Decl node lister: prints qualified names of all filterable AST Decl diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index b1cdb46d505b..2a8df1b7b9ae 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -51,6 +51,7 @@ class DiagnosticsEngine; class FileEntry; class FileManager; class HeaderSearch; +class MemoryBufferCache; class Preprocessor; class PCHContainerOperations; class PCHContainerReader; @@ -84,6 +85,7 @@ private: IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics; IntrusiveRefCntPtr<FileManager> FileMgr; IntrusiveRefCntPtr<SourceManager> SourceMgr; + IntrusiveRefCntPtr<MemoryBufferCache> PCMCache; std::unique_ptr<HeaderSearch> HeaderInfo; IntrusiveRefCntPtr<TargetInfo> Target; std::shared_ptr<Preprocessor> PP; @@ -519,6 +521,8 @@ public: const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; } + IntrusiveRefCntPtr<ASTReader> getASTReader() const; + StringRef getOriginalSourceFileName() { return OriginalSourceFile; } diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 964a6cc2a007..9565b22e7059 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -65,8 +65,6 @@ 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. CODEGENOPT(EmulatedTLS , 1, 0) ///< Set when -femulated-tls is enabled. -/// \brief FP_CONTRACT mode (on/off/fast). -ENUM_CODEGENOPT(FPContractMode, FPContractModeKind, 2, FPC_On) /// \brief Embed Bitcode mode (off/all/bitcode/marker). ENUM_CODEGENOPT(EmbedBitcode, EmbedBitcodeKind, 2, Embed_Off) CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables @@ -83,12 +81,15 @@ CODEGENOPT(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is VALUE_CODEGENOPT(XRayInstructionThreshold , 32, 200) CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled. +CODEGENOPT(CallFEntry , 1, 0) ///< Set when -mfentry is enabled. CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions to ///< be generated. CODEGENOPT(PrepareForLTO , 1, 0) ///< Set when -flto is enabled on the ///< compile step. CODEGENOPT(EmitSummaryIndex, 1, 0) ///< Set when -flto=thin is enabled on the ///< compile step. +CODEGENOPT(LTOUnit, 1, 0) ///< Emit IR to support LTO unit features (CFI, whole + ///< program vtable opt). CODEGENOPT(IncrementalLinkerCompatible, 1, 0) ///< Emit an object file which can ///< be used with an incremental ///< linker. @@ -221,6 +222,9 @@ VALUE_CODEGENOPT(SSPBufferSize, 32, 0) /// The kind of generated debug info. ENUM_CODEGENOPT(DebugInfo, codegenoptions::DebugInfoKind, 3, codegenoptions::NoDebugInfo) +/// Whether to generate macro debug info. +CODEGENOPT(MacroDebugInfo, 1, 0) + /// Tune the debug info for this debugger. ENUM_CODEGENOPT(DebuggerTuning, llvm::DebuggerKind, 2, llvm::DebuggerKind::Default) @@ -256,6 +260,12 @@ CODEGENOPT(PIECopyRelocations, 1, 0) /// paths that reach the end of a function without executing a required return. CODEGENOPT(StrictReturn, 1, 1) +/// Whether emit extra debug info for sample pgo profile collection. +CODEGENOPT(DebugInfoForProfiling, 1, 0) + +/// Whether 3-component vector type is preserved. +CODEGENOPT(PreserveVec3Type, 1, 0) + #undef CODEGENOPT #undef ENUM_CODEGENOPT #undef VALUE_CODEGENOPT diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index 52bd1c5aff79..22d5d3d16ee2 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -69,12 +69,6 @@ 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). - }; - enum StructReturnConventionKind { SRCK_Default, // No special option was passed. SRCK_OnStack, // Small structs on the stack (-fpcc-struct-return). @@ -130,8 +124,21 @@ public: /// The float precision limit to use, if non-empty. std::string LimitFloatPrecision; - /// The name of the bitcode file to link before optzns. - std::vector<std::pair<unsigned, std::string>> LinkBitcodeFiles; + struct BitcodeFileToLink { + /// The filename of the bitcode file to link in. + std::string Filename; + /// If true, we set attributes functions in the bitcode library according to + /// our CodeGenOptions, much as we set attrs on functions that we generate + /// ourselves. + bool PropagateAttrs = false; + /// If true, we use LLVM module internalizer. + bool Internalize = false; + /// Bitwise combination of llvm::Linker::Flags, passed to the LLVM linker. + unsigned LinkFlags = 0; + }; + + /// The files specified here are linked in to the module before optimizations. + std::vector<BitcodeFileToLink> LinkBitcodeFiles; /// The user provided name for the "main file", if non-empty. This is useful /// in situations where the input file name does not match the original input @@ -175,6 +182,11 @@ public: /// importing. std::string ThinLTOIndexFile; + /// Name of a file that can optionally be written with minimized bitcode + /// to be used as input for the ThinLTO thin link step, which only needs + /// the summary and module symbol table (and not, e.g. any debug metadata). + std::string ThinLinkBitcodeFile; + /// A list of file names passed with -fcuda-include-gpubinary options to /// forward to CUDA runtime back-end for incorporating them into host-side /// object file. @@ -206,7 +218,7 @@ public: /// flag. std::shared_ptr<llvm::Regex> OptimizationRemarkAnalysisPattern; - /// Set of files definining the rules for the symbol rewriting. + /// Set of files defining the rules for the symbol rewriting. std::vector<std::string> RewriteMapFiles; /// Set of sanitizer checks that are non-fatal (i.e. execution should be diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 3ebbc61515c6..4f7149fcb8b3 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -44,6 +44,7 @@ class ExternalASTSource; class FileEntry; class FileManager; class FrontendAction; +class MemoryBufferCache; class Module; class Preprocessor; class Sema; @@ -90,6 +91,9 @@ class CompilerInstance : public ModuleLoader { /// The source manager. IntrusiveRefCntPtr<SourceManager> SourceMgr; + /// The cache of PCM files. + IntrusiveRefCntPtr<MemoryBufferCache> PCMCache; + /// The preprocessor. std::shared_ptr<Preprocessor> PP; @@ -142,13 +146,13 @@ class CompilerInstance : public ModuleLoader { /// \brief Whether we should (re)build the global module index once we /// have finished with this translation unit. - bool BuildGlobalModuleIndex; + bool BuildGlobalModuleIndex = false; /// \brief We have a full global module index, with all modules. - bool HaveFullGlobalModuleIndex; + bool HaveFullGlobalModuleIndex = false; /// \brief One or more modules failed to build. - bool ModuleBuildFailed; + bool ModuleBuildFailed = false; /// \brief Holds information about the output file. /// @@ -178,7 +182,7 @@ public: explicit CompilerInstance( std::shared_ptr<PCHContainerOperations> PCHContainerOps = std::make_shared<PCHContainerOperations>(), - bool BuildingModule = false); + MemoryBufferCache *SharedPCMCache = nullptr); ~CompilerInstance() override; /// @name High-Level Operations @@ -658,6 +662,8 @@ public: bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context, const PCHContainerReader &PCHContainerRdr, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, + DependencyFileGenerator *DependencyFile, + ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors, void *DeserializationListener, bool OwnDeserializationListener, bool Preamble, bool UseGlobalModuleIndex); @@ -783,6 +789,8 @@ public: } void setExternalSemaSource(IntrusiveRefCntPtr<ExternalSemaSource> ESS); + + MemoryBufferCache &getPCMCache() const { return *PCMCache; } }; } // end namespace clang diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index 20fddc4d5a52..778b40b15df7 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -80,6 +80,8 @@ protected: bool hasASTFileSupport() const override { return false; } + bool shouldEraseOutputFiles() override; + public: /// \brief Compute the AST consumer arguments that will be used to /// create the PCHGenerator instance returned by CreateASTConsumer. diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index 9c960bb0c305..4fd0f82a3ad2 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -81,7 +81,7 @@ enum InputKind { IK_LLVM_IR }; - + /// \brief An input file for the front end. class FrontendInputFile { /// \brief The file name, or "-" to read from standard input. @@ -109,6 +109,13 @@ public: bool isEmpty() const { return File.empty() && Buffer == nullptr; } bool isFile() const { return !isBuffer(); } bool isBuffer() const { return Buffer != nullptr; } + bool isPreprocessed() const { + return Kind == IK_PreprocessedC || + Kind == IK_PreprocessedCXX || + Kind == IK_PreprocessedObjC || + Kind == IK_PreprocessedObjCXX || + Kind == IK_PreprocessedCuda; + } StringRef getFile() const { assert(isFile()); @@ -150,6 +157,8 @@ public: ///< global module index if needed. unsigned ASTDumpDecls : 1; ///< Whether we include declaration ///< dumps in AST dumps. + unsigned ASTDumpAll : 1; ///< Whether we deserialize all decls + ///< when forming AST dumps. unsigned ASTDumpLookups : 1; ///< Whether we include lookup table ///< dumps in AST dumps. unsigned BuildingImplicitModule : 1; ///< Whether we are performing an diff --git a/include/clang/Frontend/LangStandard.h b/include/clang/Frontend/LangStandard.h index 8021d08942e5..5ead90f00721 100644 --- a/include/clang/Frontend/LangStandard.h +++ b/include/clang/Frontend/LangStandard.h @@ -29,7 +29,8 @@ enum LangFeatures { Digraphs = (1 << 8), GNUMode = (1 << 9), HexFloat = (1 << 10), - ImplicitInt = (1 << 11) + ImplicitInt = (1 << 11), + OpenCL = (1 << 12) }; } @@ -91,6 +92,9 @@ public: /// hasImplicitInt - Language allows variables to be typed as int implicitly. bool hasImplicitInt() const { return Flags & frontend::ImplicitInt; } + /// isOpenCL - Language is a OpenCL variant. + bool isOpenCL() const { return Flags & frontend::OpenCL; } + static const LangStandard &getLangStandardForKind(Kind K); static const LangStandard *getLangStandardForName(StringRef Name); }; diff --git a/include/clang/Frontend/LangStandards.def b/include/clang/Frontend/LangStandards.def index 06fe1a3350ce..425ac84bf6ff 100644 --- a/include/clang/Frontend/LangStandards.def +++ b/include/clang/Frontend/LangStandards.def @@ -142,16 +142,16 @@ LANGSTANDARD(gnucxx1z, "gnu++1z", // OpenCL LANGSTANDARD(opencl, "cl", "OpenCL 1.0", - LineComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat | OpenCL) LANGSTANDARD(opencl11, "cl1.1", "OpenCL 1.1", - LineComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat | OpenCL) LANGSTANDARD(opencl12, "cl1.2", "OpenCL 1.2", - LineComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat | OpenCL) LANGSTANDARD(opencl20, "cl2.0", "OpenCL 2.0", - LineComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat | OpenCL) LANGSTANDARD_ALIAS(opencl, "CL") LANGSTANDARD_ALIAS(opencl11, "CL1.1") diff --git a/include/clang/Frontend/PCHContainerOperations.h b/include/clang/Frontend/PCHContainerOperations.h index d323fb3e8b94..f9a73508d700 100644 --- a/include/clang/Frontend/PCHContainerOperations.h +++ b/include/clang/Frontend/PCHContainerOperations.h @@ -10,6 +10,7 @@ #ifndef LLVM_CLANG_PCH_CONTAINER_OPERATIONS_H #define LLVM_CLANG_PCH_CONTAINER_OPERATIONS_H +#include "clang/Basic/Module.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/MemoryBuffer.h" @@ -29,7 +30,7 @@ class DiagnosticsEngine; class CompilerInstance; struct PCHBuffer { - uint64_t Signature; + ASTFileSignature Signature; llvm::SmallVector<char, 0> Data; bool IsComplete; }; diff --git a/include/clang/Index/IndexSymbol.h b/include/clang/Index/IndexSymbol.h index d19e5ebef2f0..217d6b1fb1cc 100644 --- a/include/clang/Index/IndexSymbol.h +++ b/include/clang/Index/IndexSymbol.h @@ -51,6 +51,8 @@ enum class SymbolKind : uint8_t { Constructor, Destructor, ConversionFunction, + + Parameter, }; enum class SymbolLanguage { @@ -77,8 +79,9 @@ enum class SymbolProperty : uint8_t { IBAnnotated = 1 << 4, IBOutletCollection = 1 << 5, GKInspectable = 1 << 6, + Local = 1 << 7, }; -static const unsigned SymbolPropertyBitNum = 7; +static const unsigned SymbolPropertyBitNum = 8; typedef unsigned SymbolPropertySet; /// Set of roles that are attributed to symbol occurrences. @@ -125,8 +128,12 @@ struct SymbolInfo { SymbolInfo getSymbolInfo(const Decl *D); +bool isFunctionLocalSymbol(const Decl *D); + void applyForEachSymbolRole(SymbolRoleSet Roles, llvm::function_ref<void(SymbolRole)> Fn); +bool applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles, + llvm::function_ref<bool(SymbolRole)> Fn); void printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS); /// \returns true if no name was printed, false otherwise. diff --git a/include/clang/Index/IndexingAction.h b/include/clang/Index/IndexingAction.h index e2e63dc6357d..8eed33c61227 100644 --- a/include/clang/Index/IndexingAction.h +++ b/include/clang/Index/IndexingAction.h @@ -14,9 +14,14 @@ #include <memory> namespace clang { + class ASTReader; class ASTUnit; class FrontendAction; +namespace serialization { + class ModuleFile; +} + namespace index { class IndexDataConsumer; @@ -42,6 +47,11 @@ void indexASTUnit(ASTUnit &Unit, std::shared_ptr<IndexDataConsumer> DataConsumer, IndexingOptions Opts); +void indexModuleFile(serialization::ModuleFile &Mod, + ASTReader &Reader, + std::shared_ptr<IndexDataConsumer> DataConsumer, + IndexingOptions Opts); + } // namespace index } // namespace clang diff --git a/include/clang/Index/USRGeneration.h b/include/clang/Index/USRGeneration.h index be89068469c4..61f2c9d1ff13 100644 --- a/include/clang/Index/USRGeneration.h +++ b/include/clang/Index/USRGeneration.h @@ -16,6 +16,7 @@ namespace clang { class Decl; class MacroDefinitionRecord; +class SourceLocation; class SourceManager; namespace index { @@ -54,6 +55,8 @@ void generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS); /// \returns true on error, false on success. bool generateUSRForMacro(const MacroDefinitionRecord *MD, const SourceManager &SM, SmallVectorImpl<char> &Buf); +bool generateUSRForMacro(StringRef MacroName, SourceLocation Loc, + const SourceManager &SM, SmallVectorImpl<char> &Buf); } // namespace index } // namespace clang diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h index e99980537348..ca3a84e75e18 100644 --- a/include/clang/Lex/HeaderSearchOptions.h +++ b/include/clang/Lex/HeaderSearchOptions.h @@ -178,6 +178,8 @@ public: unsigned ModulesValidateDiagnosticOptions : 1; + unsigned ModulesHashContent : 1; + HeaderSearchOptions(StringRef _Sysroot = "/") : Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(0), ImplicitModuleMaps(0), ModuleMapFileHomeIsCwd(0), @@ -186,8 +188,8 @@ public: UseBuiltinIncludes(true), UseStandardSystemIncludes(true), UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false), ModulesValidateOncePerBuildSession(false), - ModulesValidateSystemHeaders(false), - UseDebugInfo(false), ModulesValidateDiagnosticOptions(true) {} + ModulesValidateSystemHeaders(false), UseDebugInfo(false), + ModulesValidateDiagnosticOptions(true), ModulesHashContent(false) {} /// AddPath - Add the \p Path path to the specified \p Group list. void AddPath(StringRef Path, frontend::IncludeDirGroup Group, diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 7ce1aad36d12..3efe914daaee 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -47,6 +47,7 @@ class ExternalPreprocessorSource; class FileManager; class FileEntry; class HeaderSearch; +class MemoryBufferCache; class PragmaNamespace; class PragmaHandler; class CommentHandler; @@ -102,6 +103,7 @@ class Preprocessor { const TargetInfo *AuxTarget; FileManager &FileMgr; SourceManager &SourceMgr; + MemoryBufferCache &PCMCache; std::unique_ptr<ScratchBuffer> ScratchBuf; HeaderSearch &HeaderInfo; ModuleLoader &TheModuleLoader; @@ -652,6 +654,7 @@ class Preprocessor { public: Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, DiagnosticsEngine &diags, LangOptions &opts, SourceManager &SM, + MemoryBufferCache &PCMCache, HeaderSearch &Headers, ModuleLoader &TheModuleLoader, IdentifierInfoLookup *IILookup = nullptr, bool OwnsHeaderSearch = false, @@ -691,6 +694,7 @@ public: const TargetInfo *getAuxTargetInfo() const { return AuxTarget; } FileManager &getFileManager() const { return FileMgr; } SourceManager &getSourceManager() const { return SourceMgr; } + MemoryBufferCache &getPCMCache() const { return PCMCache; } HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; } IdentifierTable &getIdentifierTable() { return Identifiers; } @@ -1077,6 +1081,24 @@ public: /// \brief Disable the last EnableBacktrackAtThisPos call. void CommitBacktrackedTokens(); + struct CachedTokensRange { + CachedTokensTy::size_type Begin, End; + }; + +private: + /// \brief A range of cached tokens that should be erased after lexing + /// when backtracking requires the erasure of such cached tokens. + Optional<CachedTokensRange> CachedTokenRangeToErase; + +public: + /// \brief Returns the range of cached tokens that were lexed since + /// EnableBacktrackAtThisPos() was previously called. + CachedTokensRange LastCachedTokenRange(); + + /// \brief Erase the range of cached tokens that were lexed since + /// EnableBacktrackAtThisPos() was previously called. + void EraseCachedTokens(CachedTokensRange TokenRange); + /// \brief Make Preprocessor re-lex the tokens that were lexed since /// EnableBacktrackAtThisPos() was previously called. void Backtrack(); diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index fe159022c223..5f4e5fb4b215 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -142,6 +142,10 @@ class Parser : public CodeCompletionHandler { /// \brief Identifier for "replacement". IdentifierInfo *Ident_replacement; + /// Identifiers used by the 'external_source_symbol' attribute. + IdentifierInfo *Ident_language, *Ident_defined_in, + *Ident_generated_declaration; + /// C++0x contextual keywords. mutable IdentifierInfo *Ident_final; mutable IdentifierInfo *Ident_GNU_final; @@ -179,6 +183,7 @@ class Parser : public CodeCompletionHandler { std::unique_ptr<PragmaHandler> LoopHintHandler; std::unique_ptr<PragmaHandler> UnrollHintHandler; std::unique_ptr<PragmaHandler> NoUnrollHintHandler; + std::unique_ptr<PragmaHandler> FPHandler; std::unique_ptr<CommentHandler> CommentSemaHandler; @@ -545,6 +550,10 @@ private: void HandlePragmaFPContract(); /// \brief Handle the annotation token produced for + /// #pragma clang fp ... + void HandlePragmaFP(); + + /// \brief Handle the annotation token produced for /// #pragma OPENCL EXTENSION... void HandlePragmaOpenCLExtension(); @@ -791,6 +800,14 @@ private: /// \brief Consume any extra semi-colons until the end of the line. void ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST = TST_unspecified); + /// Return false if the next token is an identifier. An 'expected identifier' + /// error is emitted otherwise. + /// + /// The parser tries to recover from the error by checking if the next token + /// is a C++ keyword when parsing Objective-C++. Return false if the recovery + /// was successful. + bool expectIdentifier(); + public: //===--------------------------------------------------------------------===// // Scope manipulation @@ -1445,10 +1462,12 @@ private: ExprResult ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, bool &NotCastExpr, - TypeCastState isTypeCast); + TypeCastState isTypeCast, + bool isVectorLiteral = false); ExprResult ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand = false, - TypeCastState isTypeCast = NotTypeCast); + TypeCastState isTypeCast = NotTypeCast, + bool isVectorLiteral = false); /// Returns true if the next token cannot start an expression. bool isNotExpressionStart(); @@ -1530,7 +1549,8 @@ private: bool EnteringContext, bool *MayBePseudoDestructor = nullptr, bool IsTypename = false, - IdentifierInfo **LastII = nullptr); + IdentifierInfo **LastII = nullptr, + bool OnlyNamespace = false); //===--------------------------------------------------------------------===// // C++0x 5.1.2: Lambda expressions @@ -1682,7 +1702,7 @@ private: StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr, bool AllowOpenMPStandalone = false); - enum AllowedContsructsKind { + enum AllowedConstructsKind { /// \brief Allow any declarations, statements, OpenMP directives. ACK_Any, /// \brief Allow only statements and non-standalone OpenMP directives. @@ -1691,11 +1711,11 @@ private: ACK_StatementsOpenMPAnyExecutable }; StmtResult - ParseStatementOrDeclaration(StmtVector &Stmts, AllowedContsructsKind Allowed, + ParseStatementOrDeclaration(StmtVector &Stmts, AllowedConstructsKind Allowed, SourceLocation *TrailingElseLoc = nullptr); StmtResult ParseStatementOrDeclarationAfterAttributes( StmtVector &Stmts, - AllowedContsructsKind Allowed, + AllowedConstructsKind Allowed, SourceLocation *TrailingElseLoc, ParsedAttributesWithRange &Attrs); StmtResult ParseExprStatement(); @@ -1724,7 +1744,7 @@ private: StmtResult ParseAsmStatement(bool &msAsm); StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc); StmtResult ParsePragmaLoopHint(StmtVector &Stmts, - AllowedContsructsKind Allowed, + AllowedConstructsKind Allowed, SourceLocation *TrailingElseLoc, ParsedAttributesWithRange &Attrs); @@ -1834,6 +1854,26 @@ private: llvm_unreachable("Missing DeclSpecContext case"); } + /// Is this a context in which we can perform class template argument + /// deduction? + static bool isClassTemplateDeductionContext(DeclSpecContext DSC) { + switch (DSC) { + case DSC_normal: + case DSC_class: + case DSC_top_level: + case DSC_condition: + case DSC_type_specifier: + return true; + + case DSC_objc_method_result: + case DSC_template_type_arg: + case DSC_trailing: + case DSC_alias_declaration: + return false; + } + llvm_unreachable("Missing DeclSpecContext case"); + } + /// Information on a C++0x for-range-initializer found while parsing a /// declaration which turns out to be a for-range-declaration. struct ForRangeInit { @@ -1947,7 +1987,7 @@ private: /// \brief Starting with a scope specifier, identifier, or /// template-id that refers to the current class, determine whether /// this is a constructor declarator. - bool isConstructorDeclarator(bool Unqualified); + bool isConstructorDeclarator(bool Unqualified, bool DeductionGuide = false); /// \brief Specifies the context in which type-id/expression /// disambiguation will occur. @@ -2177,6 +2217,12 @@ private: Declarator *D); IdentifierLoc *ParseIdentifierLoc(); + unsigned + ParseClangAttributeArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, + ParsedAttributes &Attrs, SourceLocation *EndLoc, + IdentifierInfo *ScopeName, SourceLocation ScopeLoc, + AttributeList::Syntax Syntax); + void MaybeParseCXX11Attributes(Declarator &D) { if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrs(AttrFactory); @@ -2266,6 +2312,14 @@ private: Optional<AvailabilitySpec> ParseAvailabilitySpec(); ExprResult ParseAvailabilityCheckExpr(SourceLocation StartLoc); + void ParseExternalSourceSymbolAttribute(IdentifierInfo &ExternalSourceSymbol, + SourceLocation Loc, + ParsedAttributes &Attrs, + SourceLocation *EndLoc, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, + AttributeList::Syntax Syntax); + void ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated, SourceLocation ObjCBridgeRelatedLoc, ParsedAttributes &attrs, @@ -2365,10 +2419,10 @@ private: AR_DeclspecAttributesParsed }; - void ParseTypeQualifierListOpt(DeclSpec &DS, - unsigned AttrReqs = AR_AllAttributesParsed, - bool AtomicAllowed = true, - bool IdentifierRequired = false); + void ParseTypeQualifierListOpt( + DeclSpec &DS, unsigned AttrReqs = AR_AllAttributesParsed, + bool AtomicAllowed = true, bool IdentifierRequired = false, + Optional<llvm::function_ref<void()>> CodeCompletionHandler = None); void ParseDirectDeclarator(Declarator &D); void ParseDecompositionDeclarator(Declarator &D); void ParseParenDeclarator(Declarator &D); @@ -2549,7 +2603,7 @@ private: /// executable directives are allowed. /// StmtResult - ParseOpenMPDeclarativeOrExecutableDirective(AllowedContsructsKind Allowed); + ParseOpenMPDeclarativeOrExecutableDirective(AllowedConstructsKind Allowed); /// \brief Parses clause of kind \a CKind for directive of a kind \a Kind. /// /// \param DKind Kind of current directive. @@ -2614,6 +2668,7 @@ public: bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, + bool AllowDeductionGuide, ParsedType ObjectType, SourceLocation& TemplateKWLoc, UnqualifiedId &Result); @@ -2674,7 +2729,7 @@ private: SourceLocation TemplateKWLoc, UnqualifiedId &TemplateName, bool AllowTypeAnnotation = true); - void AnnotateTemplateIdTokenAsType(); + void AnnotateTemplateIdTokenAsType(bool IsClassName = false); bool IsTemplateArgumentList(unsigned Skip = 0); bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs); ParsedTemplateArgument ParseTemplateTemplateArgument(); diff --git a/include/clang/Parse/RAIIObjectsForParser.h b/include/clang/Parse/RAIIObjectsForParser.h new file mode 100644 index 000000000000..0422b038da65 --- /dev/null +++ b/include/clang/Parse/RAIIObjectsForParser.h @@ -0,0 +1,467 @@ +//===--- RAIIObjectsForParser.h - RAII helpers for the parser ---*- 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 and implements the some simple RAII objects that are used +// by the parser to manage bits in recursion. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H +#define LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H + +#include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/Parser.h" +#include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/Sema.h" + +namespace clang { + // TODO: move ParsingClassDefinition here. + // TODO: move TentativeParsingAction here. + + /// \brief A RAII object used to temporarily suppress access-like + /// checking. Access-like checks are those associated with + /// controlling the use of a declaration, like C++ access control + /// errors and deprecation warnings. They are contextually + /// dependent, in that they can only be resolved with full + /// information about what's being declared. They are also + /// suppressed in certain contexts, like the template arguments of + /// an explicit instantiation. However, those suppression contexts + /// cannot necessarily be fully determined in advance; for + /// example, something starting like this: + /// template <> class std::vector<A::PrivateType> + /// might be the entirety of an explicit instantiation: + /// template <> class std::vector<A::PrivateType>; + /// or just an elaborated type specifier: + /// template <> class std::vector<A::PrivateType> make_vector<>(); + /// Therefore this class collects all the diagnostics and permits + /// them to be re-delayed in a new context. + class SuppressAccessChecks { + Sema &S; + sema::DelayedDiagnosticPool DiagnosticPool; + Sema::ParsingDeclState State; + bool Active; + + public: + /// Begin suppressing access-like checks + SuppressAccessChecks(Parser &P, bool activate = true) + : S(P.getActions()), DiagnosticPool(nullptr) { + if (activate) { + State = S.PushParsingDeclaration(DiagnosticPool); + Active = true; + } else { + Active = false; + } + } + SuppressAccessChecks(SuppressAccessChecks &&Other) + : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)), + State(Other.State), Active(Other.Active) { + Other.Active = false; + } + void operator=(SuppressAccessChecks &&Other) = delete; + + void done() { + assert(Active && "trying to end an inactive suppression"); + S.PopParsingDeclaration(State, nullptr); + Active = false; + } + + void redelay() { + assert(!Active && "redelaying without having ended first"); + if (!DiagnosticPool.pool_empty()) + S.redelayDiagnostics(DiagnosticPool); + assert(DiagnosticPool.pool_empty()); + } + + ~SuppressAccessChecks() { + if (Active) done(); + } + }; + + /// \brief RAII object used to inform the actions that we're + /// currently parsing a declaration. This is active when parsing a + /// variable's initializer, but not when parsing the body of a + /// class or function definition. + class ParsingDeclRAIIObject { + Sema &Actions; + sema::DelayedDiagnosticPool DiagnosticPool; + Sema::ParsingDeclState State; + bool Popped; + + ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) = delete; + void operator=(const ParsingDeclRAIIObject &) = delete; + + public: + enum NoParent_t { NoParent }; + ParsingDeclRAIIObject(Parser &P, NoParent_t _) + : Actions(P.getActions()), DiagnosticPool(nullptr) { + push(); + } + + /// Creates a RAII object whose pool is optionally parented by another. + ParsingDeclRAIIObject(Parser &P, + const sema::DelayedDiagnosticPool *parentPool) + : Actions(P.getActions()), DiagnosticPool(parentPool) { + push(); + } + + /// Creates a RAII object and, optionally, initialize its + /// diagnostics pool by stealing the diagnostics from another + /// RAII object (which is assumed to be the current top pool). + ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other) + : Actions(P.getActions()), + DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) { + if (other) { + DiagnosticPool.steal(other->DiagnosticPool); + other->abort(); + } + push(); + } + + ~ParsingDeclRAIIObject() { + abort(); + } + + sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() { + return DiagnosticPool; + } + const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const { + return DiagnosticPool; + } + + /// Resets the RAII object for a new declaration. + void reset() { + abort(); + push(); + } + + /// Signals that the context was completed without an appropriate + /// declaration being parsed. + void abort() { + pop(nullptr); + } + + void complete(Decl *D) { + assert(!Popped && "ParsingDeclaration has already been popped!"); + pop(D); + } + + /// Unregister this object from Sema, but remember all the + /// diagnostics that were emitted into it. + void abortAndRemember() { + pop(nullptr); + } + + private: + void push() { + State = Actions.PushParsingDeclaration(DiagnosticPool); + Popped = false; + } + + void pop(Decl *D) { + if (!Popped) { + Actions.PopParsingDeclaration(State, D); + Popped = true; + } + } + }; + + /// A class for parsing a DeclSpec. + class ParsingDeclSpec : public DeclSpec { + ParsingDeclRAIIObject ParsingRAII; + + public: + ParsingDeclSpec(Parser &P) + : DeclSpec(P.getAttrFactory()), + ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {} + ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII) + : DeclSpec(P.getAttrFactory()), + ParsingRAII(P, RAII) {} + + const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const { + return ParsingRAII.getDelayedDiagnosticPool(); + } + + void complete(Decl *D) { + ParsingRAII.complete(D); + } + + void abort() { + ParsingRAII.abort(); + } + }; + + /// A class for parsing a declarator. + class ParsingDeclarator : public Declarator { + ParsingDeclRAIIObject ParsingRAII; + + public: + ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C) + : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) { + } + + const ParsingDeclSpec &getDeclSpec() const { + return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec()); + } + + ParsingDeclSpec &getMutableDeclSpec() const { + return const_cast<ParsingDeclSpec&>(getDeclSpec()); + } + + void clear() { + Declarator::clear(); + ParsingRAII.reset(); + } + + void complete(Decl *D) { + ParsingRAII.complete(D); + } + }; + + /// A class for parsing a field declarator. + class ParsingFieldDeclarator : public FieldDeclarator { + ParsingDeclRAIIObject ParsingRAII; + + public: + ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS) + : FieldDeclarator(DS), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) { + } + + const ParsingDeclSpec &getDeclSpec() const { + return static_cast<const ParsingDeclSpec&>(D.getDeclSpec()); + } + + ParsingDeclSpec &getMutableDeclSpec() const { + return const_cast<ParsingDeclSpec&>(getDeclSpec()); + } + + void complete(Decl *D) { + ParsingRAII.complete(D); + } + }; + + /// ExtensionRAIIObject - This saves the state of extension warnings when + /// constructed and disables them. When destructed, it restores them back to + /// the way they used to be. This is used to handle __extension__ in the + /// parser. + class ExtensionRAIIObject { + ExtensionRAIIObject(const ExtensionRAIIObject &) = delete; + void operator=(const ExtensionRAIIObject &) = delete; + + DiagnosticsEngine &Diags; + public: + ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) { + Diags.IncrementAllExtensionsSilenced(); + } + + ~ExtensionRAIIObject() { + Diags.DecrementAllExtensionsSilenced(); + } + }; + + /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and + /// restores it when destroyed. This says that "foo:" should not be + /// considered a possible typo for "foo::" for error recovery purposes. + class ColonProtectionRAIIObject { + Parser &P; + bool OldVal; + public: + ColonProtectionRAIIObject(Parser &p, bool Value = true) + : P(p), OldVal(P.ColonIsSacred) { + P.ColonIsSacred = Value; + } + + /// restore - This can be used to restore the state early, before the dtor + /// is run. + void restore() { + P.ColonIsSacred = OldVal; + } + + ~ColonProtectionRAIIObject() { + restore(); + } + }; + + /// \brief RAII object that makes '>' behave either as an operator + /// or as the closing angle bracket for a template argument list. + class GreaterThanIsOperatorScope { + bool &GreaterThanIsOperator; + bool OldGreaterThanIsOperator; + public: + GreaterThanIsOperatorScope(bool >IO, bool Val) + : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) { + GreaterThanIsOperator = Val; + } + + ~GreaterThanIsOperatorScope() { + GreaterThanIsOperator = OldGreaterThanIsOperator; + } + }; + + class InMessageExpressionRAIIObject { + bool &InMessageExpression; + bool OldValue; + + public: + InMessageExpressionRAIIObject(Parser &P, bool Value) + : InMessageExpression(P.InMessageExpression), + OldValue(P.InMessageExpression) { + InMessageExpression = Value; + } + + ~InMessageExpressionRAIIObject() { + InMessageExpression = OldValue; + } + }; + + /// \brief RAII object that makes sure paren/bracket/brace count is correct + /// after declaration/statement parsing, even when there's a parsing error. + class ParenBraceBracketBalancer { + Parser &P; + unsigned short ParenCount, BracketCount, BraceCount; + public: + ParenBraceBracketBalancer(Parser &p) + : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount), + BraceCount(p.BraceCount) { } + + ~ParenBraceBracketBalancer() { + P.ParenCount = ParenCount; + P.BracketCount = BracketCount; + P.BraceCount = BraceCount; + } + }; + + class PoisonSEHIdentifiersRAIIObject { + PoisonIdentifierRAIIObject Ident_AbnormalTermination; + PoisonIdentifierRAIIObject Ident_GetExceptionCode; + PoisonIdentifierRAIIObject Ident_GetExceptionInfo; + PoisonIdentifierRAIIObject Ident__abnormal_termination; + PoisonIdentifierRAIIObject Ident__exception_code; + PoisonIdentifierRAIIObject Ident__exception_info; + PoisonIdentifierRAIIObject Ident___abnormal_termination; + PoisonIdentifierRAIIObject Ident___exception_code; + PoisonIdentifierRAIIObject Ident___exception_info; + public: + PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue) + : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue), + Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue), + Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue), + Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue), + Ident__exception_code(Self.Ident__exception_code, NewValue), + Ident__exception_info(Self.Ident__exception_info, NewValue), + Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue), + Ident___exception_code(Self.Ident___exception_code, NewValue), + Ident___exception_info(Self.Ident___exception_info, NewValue) { + } + }; + + /// \brief RAII class that helps handle the parsing of an open/close delimiter + /// pair, such as braces { ... } or parentheses ( ... ). + class BalancedDelimiterTracker : public GreaterThanIsOperatorScope { + Parser& P; + tok::TokenKind Kind, Close, FinalToken; + SourceLocation (Parser::*Consumer)(); + SourceLocation LOpen, LClose; + + unsigned short &getDepth() { + switch (Kind) { + case tok::l_brace: return P.BraceCount; + case tok::l_square: return P.BracketCount; + case tok::l_paren: return P.ParenCount; + default: llvm_unreachable("Wrong token kind"); + } + } + + enum { MaxDepth = 256 }; + + bool diagnoseOverflow(); + bool diagnoseMissingClose(); + + public: + BalancedDelimiterTracker(Parser& p, tok::TokenKind k, + tok::TokenKind FinalToken = tok::semi) + : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true), + P(p), Kind(k), FinalToken(FinalToken) + { + switch (Kind) { + default: llvm_unreachable("Unexpected balanced token"); + case tok::l_brace: + Close = tok::r_brace; + Consumer = &Parser::ConsumeBrace; + break; + case tok::l_paren: + Close = tok::r_paren; + Consumer = &Parser::ConsumeParen; + break; + + case tok::l_square: + Close = tok::r_square; + Consumer = &Parser::ConsumeBracket; + break; + } + } + + SourceLocation getOpenLocation() const { return LOpen; } + SourceLocation getCloseLocation() const { return LClose; } + SourceRange getRange() const { return SourceRange(LOpen, LClose); } + + bool consumeOpen() { + if (!P.Tok.is(Kind)) + return true; + + if (getDepth() < P.getLangOpts().BracketDepth) { + LOpen = (P.*Consumer)(); + return false; + } + + return diagnoseOverflow(); + } + + bool expectAndConsume(unsigned DiagID = diag::err_expected, + const char *Msg = "", + tok::TokenKind SkipToTok = tok::unknown); + bool consumeClose() { + if (P.Tok.is(Close)) { + LClose = (P.*Consumer)(); + return false; + } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) { + SourceLocation SemiLoc = P.ConsumeToken(); + P.Diag(SemiLoc, diag::err_unexpected_semi) + << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc)); + LClose = (P.*Consumer)(); + return false; + } + + return diagnoseMissingClose(); + } + void skipToEnd(); + }; + + /// \brief RAIIObject to destroy the contents of a SmallVector of + /// TemplateIdAnnotation pointers and clear the vector. + class DestroyTemplateIdAnnotationsRAIIObj { + SmallVectorImpl<TemplateIdAnnotation *> &Container; + + public: + DestroyTemplateIdAnnotationsRAIIObj( + SmallVectorImpl<TemplateIdAnnotation *> &Container) + : Container(Container) {} + + ~DestroyTemplateIdAnnotationsRAIIObj() { + for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I = + Container.begin(), + E = Container.end(); + I != E; ++I) + (*I)->Destroy(); + Container.clear(); + } + }; +} // end namespace clang + +#endif diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index e74bf6a7cc86..7c1678086c2f 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -927,6 +927,7 @@ enum AttributeDeclKind { ExpectedStructClassVariableFunctionOrInlineNamespace, ExpectedForMaybeUnused, ExpectedEnumOrClass, + ExpectedNamedDecl, }; } // end namespace clang diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 331fd0db6724..df5e1050367e 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -519,7 +519,7 @@ public: SourceRange getTypeofParensRange() const { return TypeofParensRange; } void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; } - bool containsPlaceholderType() const { + bool hasAutoTypeSpec() const { return (TypeSpecType == TST_auto || TypeSpecType == TST_auto_type || TypeSpecType == TST_decltype_auto); } @@ -819,7 +819,9 @@ public: : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr), Nullability(0), GetterName(nullptr), SetterName(nullptr) { } - ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; } + ObjCDeclQualifier getObjCDeclQualifier() const { + return (ObjCDeclQualifier)objcDeclQualifier; + } void setObjCDeclQualifier(ObjCDeclQualifier DQVal) { objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); } @@ -859,17 +861,25 @@ public: const IdentifierInfo *getGetterName() const { return GetterName; } IdentifierInfo *getGetterName() { return GetterName; } - void setGetterName(IdentifierInfo *name) { GetterName = name; } + SourceLocation getGetterNameLoc() const { return GetterNameLoc; } + void setGetterName(IdentifierInfo *name, SourceLocation loc) { + GetterName = name; + GetterNameLoc = loc; + } const IdentifierInfo *getSetterName() const { return SetterName; } IdentifierInfo *getSetterName() { return SetterName; } - void setSetterName(IdentifierInfo *name) { SetterName = name; } + SourceLocation getSetterNameLoc() const { return SetterNameLoc; } + void setSetterName(IdentifierInfo *name, SourceLocation loc) { + SetterName = name; + SetterNameLoc = loc; + } private: // FIXME: These two are unrelated and mutually exclusive. So perhaps // we can put them in a union to reflect their mutual exclusivity // (space saving is negligible). - ObjCDeclQualifier objcDeclQualifier : 7; + unsigned objcDeclQualifier : 7; // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind unsigned PropertyAttributes : 15; @@ -880,6 +890,9 @@ private: IdentifierInfo *GetterName; // getter name or NULL if no getter IdentifierInfo *SetterName; // setter name or NULL if no setter + SourceLocation GetterNameLoc; // location of the getter attribute's value + SourceLocation SetterNameLoc; // location of the setter attribute's value + }; /// \brief Represents a C++ unqualified-id that has been parsed. @@ -908,7 +921,9 @@ public: /// \brief A template-id, e.g., f<int>. IK_TemplateId, /// \brief An implicit 'self' parameter - IK_ImplicitSelfParam + IK_ImplicitSelfParam, + /// \brief A deduction-guide name (a template-name) + IK_DeductionGuideName } Kind; struct OFI { @@ -928,8 +943,8 @@ public: /// \brief Anonymous union that holds extra data associated with the /// parsed unqualified-id. union { - /// \brief When Kind == IK_Identifier, the parsed identifier, or when Kind - /// == IK_UserLiteralId, the identifier suffix. + /// \brief When Kind == IK_Identifier, the parsed identifier, or when + /// Kind == IK_UserLiteralId, the identifier suffix. IdentifierInfo *Identifier; /// \brief When Kind == IK_OperatorFunctionId, the overloaded operator @@ -947,6 +962,9 @@ public: /// \brief When Kind == IK_DestructorName, the type referred to by the /// class-name. UnionParsedType DestructorName; + + /// \brief When Kind == IK_DeductionGuideName, the parsed template-name. + UnionParsedTemplateTy TemplateName; /// \brief When Kind == IK_TemplateId or IK_ConstructorTemplateId, /// the template-id annotation that contains the template name and @@ -1085,6 +1103,18 @@ public: /// \p TemplateId and will free it on destruction. void setTemplateId(TemplateIdAnnotation *TemplateId); + /// \brief Specify that this unqualified-id was parsed as a template-name for + /// a deduction-guide. + /// + /// \param Template The parsed template-name. + /// \param TemplateLoc The location of the parsed template-name. + void setDeductionGuideName(ParsedTemplateTy Template, + SourceLocation TemplateLoc) { + Kind = IK_DeductionGuideName; + TemplateName = Template; + StartLocation = EndLocation = TemplateLoc; + } + /// \brief Return the source range that covers this unqualified-id. SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(StartLocation, EndLocation); @@ -1709,6 +1739,7 @@ public: ObjCParameterContext,// An ObjC method parameter type. KNRTypeListContext, // K&R type definition list for formals. TypeNameContext, // Abstract declarator for types. + FunctionalCastContext, // Type in a C++ functional cast expression. MemberContext, // Struct/Union field. BlockContext, // Declaration within a block in a function. ForContext, // Declaration within first part of a for loop. @@ -1911,6 +1942,7 @@ public: return false; case TypeNameContext: + case FunctionalCastContext: case AliasDeclContext: case AliasTemplateContext: case PrototypeContext: @@ -1951,6 +1983,7 @@ public: return true; case TypeNameContext: + case FunctionalCastContext: case CXXNewContext: case AliasDeclContext: case AliasTemplateContext: @@ -1983,6 +2016,7 @@ public: case CXXCatchContext: case ObjCCatchContext: case TypeNameContext: + case FunctionalCastContext: case ConversionIdContext: case ObjCParameterContext: case ObjCResultContext: @@ -2021,6 +2055,7 @@ public: // These contexts don't allow any kind of non-abstract declarator. case KNRTypeListContext: case TypeNameContext: + case FunctionalCastContext: case AliasDeclContext: case AliasTemplateContext: case LambdaExprParameterContext: @@ -2078,6 +2113,7 @@ public: case CXXCatchContext: case ObjCCatchContext: case TypeNameContext: + case FunctionalCastContext: // FIXME case CXXNewContext: case AliasDeclContext: case AliasTemplateContext: @@ -2279,6 +2315,7 @@ public: case ConditionContext: case KNRTypeListContext: case TypeNameContext: + case FunctionalCastContext: case AliasDeclContext: case AliasTemplateContext: case PrototypeContext: @@ -2312,6 +2349,16 @@ public: return true; } + /// \brief Determine whether a trailing return type was written (at any + /// level) within this declarator. + bool hasTrailingReturnType() const { + for (const auto &Chunk : type_objects()) + if (Chunk.Kind == DeclaratorChunk::Function && + Chunk.Fun.hasTrailingReturnType()) + return true; + return false; + } + /// takeAttributes - Takes attributes from the given parsed-attributes /// set and add them to this declarator. /// diff --git a/include/clang/Sema/IdentifierResolver.h b/include/clang/Sema/IdentifierResolver.h index a07834f95629..382fe80bea7d 100644 --- a/include/clang/Sema/IdentifierResolver.h +++ b/include/clang/Sema/IdentifierResolver.h @@ -73,12 +73,10 @@ public: typedef std::input_iterator_tag iterator_category; typedef std::ptrdiff_t difference_type; - /// Ptr - There are 3 forms that 'Ptr' represents: + /// Ptr - There are 2 forms that 'Ptr' represents: /// 1) A single NamedDecl. (Ptr & 0x1 == 0) /// 2) A IdDeclInfo::DeclsTy::iterator that traverses only the decls of the - /// same declaration context. (Ptr & 0x3 == 0x1) - /// 3) A IdDeclInfo::DeclsTy::iterator that traverses the decls of parent - /// declaration contexts too. (Ptr & 0x3 == 0x3) + /// same declaration context. (Ptr & 0x1 == 0x1) uintptr_t Ptr; typedef IdDeclInfo::DeclsTy::iterator BaseIter; @@ -97,7 +95,7 @@ public: BaseIter getIterator() const { assert(isIterator() && "Ptr not an iterator!"); - return reinterpret_cast<BaseIter>(Ptr & ~0x3); + return reinterpret_cast<BaseIter>(Ptr & ~0x1); } friend class IdentifierResolver; @@ -128,14 +126,6 @@ public: incrementSlowCase(); return *this; } - - uintptr_t getAsOpaqueValue() const { return Ptr; } - - static iterator getFromOpaqueValue(uintptr_t P) { - iterator Result; - Result.Ptr = P; - return Result; - } }; /// begin - Returns an iterator for decls with the name 'Name'. diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index 94be58ac8aeb..bd07b9ea9aee 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -70,6 +70,9 @@ public: /// \brief The entity being initialized is a field of block descriptor for /// the copied-in c++ object. EK_BlockElement, + /// The entity being initialized is a field of block descriptor for the + /// copied-in lambda object that's used in the lambda to block conversion. + EK_LambdaToBlockConversionBlockElement, /// \brief The entity being initialized is the real or imaginary part of a /// complex number. EK_ComplexElement, @@ -260,7 +263,13 @@ public: QualType Type, bool NRVO) { return InitializedEntity(EK_BlockElement, BlockVarLoc, Type, NRVO); } - + + static InitializedEntity InitializeLambdaToBlock(SourceLocation BlockVarLoc, + QualType Type, bool NRVO) { + return InitializedEntity(EK_LambdaToBlockConversionBlockElement, + BlockVarLoc, Type, NRVO); + } + /// \brief Create the initialization entity for an exception object. static InitializedEntity InitializeException(SourceLocation ThrowLoc, QualType Type, bool NRVO) { @@ -274,15 +283,18 @@ public: /// \brief Create the initialization entity for a temporary. static InitializedEntity InitializeTemporary(QualType Type) { - InitializedEntity Result(EK_Temporary, SourceLocation(), Type); - Result.TypeInfo = nullptr; - return Result; + return InitializeTemporary(nullptr, Type); } /// \brief Create the initialization entity for a temporary. static InitializedEntity InitializeTemporary(TypeSourceInfo *TypeInfo) { - InitializedEntity Result(EK_Temporary, SourceLocation(), - TypeInfo->getType()); + return InitializeTemporary(TypeInfo, TypeInfo->getType()); + } + + /// \brief Create the initialization entity for a temporary. + static InitializedEntity InitializeTemporary(TypeSourceInfo *TypeInfo, + QualType Type) { + InitializedEntity Result(EK_Temporary, SourceLocation(), Type); Result.TypeInfo = TypeInfo; return Result; } @@ -579,6 +591,16 @@ public: return InitializationKind(IK_Value, isImplicit ? IC_Implicit : IC_Normal, InitLoc, LParenLoc, RParenLoc); } + + /// \brief Create an initialization from an initializer (which, for direct + /// initialization from a parenthesized list, will be a ParenListExpr). + static InitializationKind CreateForInit(SourceLocation Loc, bool DirectInit, + Expr *Init) { + if (!Init) return CreateDefault(Loc); + if (!DirectInit) return CreateCopy(Loc, Init->getLocStart()); + if (isa<InitListExpr>(Init)) return CreateDirectList(Loc); + return CreateDirect(Loc, Init->getLocStart(), Init->getLocEnd()); + } /// \brief Determine the initialization kind. InitKind getKind() const { @@ -809,6 +831,8 @@ public: enum FailureKind { /// \brief Too many initializers provided for a reference. FK_TooManyInitsForReference, + /// \brief Reference initialized from a parenthesized initializer list. + FK_ParenthesizedListInitForReference, /// \brief Array must be initialized with an initializer list. FK_ArrayNeedsInitList, /// \brief Array must be initialized with an initializer list or a @@ -853,6 +877,8 @@ public: FK_ConversionFromPropertyFailed, /// \brief Too many initializers for scalar FK_TooManyInitsForScalar, + /// \brief Scalar initialized from a parenthesized initializer list. + FK_ParenthesizedListInitForScalar, /// \brief Reference initialization from an initializer list FK_ReferenceBindingToInitList, /// \brief Initialization of some unused destination type with an @@ -879,7 +905,7 @@ public: /// having its address taken. FK_AddressOfUnaddressableFunction, /// \brief List-copy-initialization chose an explicit constructor. - FK_ExplicitConstructor + FK_ExplicitConstructor, }; private: diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h index 2ed9548b5936..9134ddf9198c 100644 --- a/include/clang/Sema/Lookup.h +++ b/include/clang/Sema/Lookup.h @@ -146,7 +146,7 @@ public: } // TODO: consider whether this constructor should be restricted to take - // as input a const IndentifierInfo* (instead of Name), + // as input a const IdentifierInfo* (instead of Name), // forcing other cases towards the constructor taking a DNInfo. LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc, Sema::LookupNameKind LookupKind, diff --git a/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h index 37157204ea10..1d681a00552f 100644 --- a/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/include/clang/Sema/MultiplexExternalSemaSource.h @@ -90,6 +90,8 @@ public: /// initializers themselves. CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override; + ExtKind hasExternalDefinitions(const Decl *D) override; + /// \brief Find all declarations with the given name in the /// given context. bool FindExternalVisibleDeclsByName(const DeclContext *DC, diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index 5220d9873022..941b772b7880 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -98,6 +98,7 @@ namespace clang { ICR_Exact_Match = 0, ///< Exact Match ICR_Promotion, ///< Promotion ICR_Conversion, ///< Conversion + ICR_OCL_Scalar_Widening, ///< OpenCL Scalar Widening ICR_Complex_Real_Conversion, ///< Complex <-> Real conversion ICR_Writeback_Conversion, ///< ObjC ARC writeback conversion ICR_C_Conversion, ///< Conversion only allowed in the C standard. diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h index fd46de870fb4..848837a1decc 100644 --- a/include/clang/Sema/Ownership.h +++ b/include/clang/Sema/Ownership.h @@ -257,6 +257,7 @@ namespace clang { typedef ActionResult<Decl*> DeclResult; typedef OpaquePtr<TemplateName> ParsedTemplateTy; + typedef UnionOpaquePtr<TemplateName> UnionParsedTemplateTy; typedef MutableArrayRef<Expr*> MultiExprArg; typedef MutableArrayRef<Stmt*> MultiStmtArg; diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index 4b54807ab660..4487c7c2ccb6 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -24,6 +24,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" #include <algorithm> namespace clang { @@ -135,6 +136,18 @@ public: /// false if there is an invocation of an initializer on 'self'. bool ObjCWarnForNoInitDelegation : 1; + /// \brief True only when this function has not already built, or attempted + /// to build, the initial and final coroutine suspend points + bool NeedsCoroutineSuspends : 1; + + /// \brief An enumeration represeting the kind of the first coroutine statement + /// in the function. One of co_return, co_await, or co_yield. + unsigned char FirstCoroutineStmtKind : 2; + + /// First coroutine statement in the current function. + /// (ex co_return, co_await, co_yield) + SourceLocation FirstCoroutineStmtLoc; + /// First 'return' statement in the current function. SourceLocation FirstReturnLoc; @@ -157,12 +170,10 @@ public: SmallVector<ReturnStmt*, 4> Returns; /// \brief The promise object for this coroutine, if any. - VarDecl *CoroutinePromise; + VarDecl *CoroutinePromise = nullptr; - /// \brief The list of coroutine control flow constructs (co_await, co_yield, - /// co_return) that occur within the function or block. Empty if and only if - /// this function or block is not (yet known to be) a coroutine. - SmallVector<Stmt*, 4> CoroutineStmts; + /// \brief The initial and final coroutine suspend points. + std::pair<Stmt *, Stmt *> CoroutineSuspends; /// \brief The stack of currently active compound stamement scopes in the /// function. @@ -376,7 +387,47 @@ public: (HasIndirectGoto || (HasBranchProtectedScope && HasBranchIntoScope)); } - + + void setFirstCoroutineStmt(SourceLocation Loc, StringRef Keyword) { + assert(FirstCoroutineStmtLoc.isInvalid() && + "first coroutine statement location already set"); + FirstCoroutineStmtLoc = Loc; + FirstCoroutineStmtKind = llvm::StringSwitch<unsigned char>(Keyword) + .Case("co_return", 0) + .Case("co_await", 1) + .Case("co_yield", 2); + } + + StringRef getFirstCoroutineStmtKeyword() const { + assert(FirstCoroutineStmtLoc.isValid() + && "no coroutine statement available"); + switch (FirstCoroutineStmtKind) { + case 0: return "co_return"; + case 1: return "co_await"; + case 2: return "co_yield"; + default: + llvm_unreachable("FirstCoroutineStmtKind has an invalid value"); + }; + } + + void setNeedsCoroutineSuspends(bool value = true) { + assert((!value || CoroutineSuspends.first == nullptr) && + "we already have valid suspend points"); + NeedsCoroutineSuspends = value; + } + + bool hasInvalidCoroutineSuspends() const { + return !NeedsCoroutineSuspends && CoroutineSuspends.first == nullptr; + } + + void setCoroutineSuspends(Stmt *Initial, Stmt *Final) { + assert(Initial && Final && "suspend points cannot be null"); + assert(CoroutineSuspends.first == nullptr && "suspend points already set"); + NeedsCoroutineSuspends = false; + CoroutineSuspends.first = Initial; + CoroutineSuspends.second = Final; + } + FunctionScopeInfo(DiagnosticsEngine &Diag) : Kind(SK_Function), HasBranchProtectedScope(false), @@ -391,6 +442,7 @@ public: ObjCWarnForNoDesignatedInitChain(false), ObjCIsSecondaryInit(false), ObjCWarnForNoInitDelegation(false), + NeedsCoroutineSuspends(true), ErrorTrap(Diag) { } virtual ~FunctionScopeInfo(); @@ -452,6 +504,14 @@ public: /// non-static data member that would hold the capture. QualType CaptureType; + /// \brief Whether an explicit capture has been odr-used in the body of the + /// lambda. + bool ODRUsed; + + /// \brief Whether an explicit capture has been non-odr-used in the body of + /// the lambda. + bool NonODRUsed; + public: Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested, SourceLocation Loc, SourceLocation EllipsisLoc, @@ -460,7 +520,8 @@ public: InitExprAndCaptureKind( Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef : Cap_ByCopy), - Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {} + Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType), + ODRUsed(false), NonODRUsed(false) {} enum IsThisCapture { ThisCapture }; Capture(IsThisCapture, bool IsNested, SourceLocation Loc, @@ -468,7 +529,8 @@ public: : VarAndNestedAndThis( nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture : 0))), InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef), - Loc(Loc), EllipsisLoc(), CaptureType(CaptureType) {} + Loc(Loc), EllipsisLoc(), CaptureType(CaptureType), ODRUsed(false), + NonODRUsed(false) {} bool isThisCapture() const { return VarAndNestedAndThis.getInt() & IsThisCaptured; @@ -491,6 +553,9 @@ public: bool isNested() const { return VarAndNestedAndThis.getInt() & IsNestedCapture; } + bool isODRUsed() const { return ODRUsed; } + bool isNonODRUsed() const { return NonODRUsed; } + void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; } VarDecl *getVariable() const { return VarAndNestedAndThis.getPointer(); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 63d078498fe4..5a3cdfb77c9c 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -26,6 +26,7 @@ #include "clang/AST/MangleNumberingContext.h" #include "clang/AST/NSAPI.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/AST/StmtCXX.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" #include "clang/Basic/ExpressionTraits.h" @@ -101,6 +102,7 @@ namespace clang { class CodeCompletionAllocator; class CodeCompletionTUInfo; class CodeCompletionResult; + class CoroutineBodyStmt; class Decl; class DeclAccessPair; class DeclContext; @@ -679,7 +681,8 @@ public: : S(S), SavedContext(S, DC) { S.PushFunctionScope(); - S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); + S.PushExpressionEvaluationContext( + Sema::ExpressionEvaluationContext::PotentiallyEvaluated); } ~SynthesizedFunctionScope() { @@ -800,7 +803,7 @@ public: /// \brief Describes how the expressions currently being parsed are /// evaluated at run-time, if at all. - enum ExpressionEvaluationContext { + enum class ExpressionEvaluationContext { /// \brief The current expression and its subexpressions occur within an /// unevaluated operand (C++11 [expr]p7), such as the subexpression of /// \c sizeof, where the type of the expression may be significant but @@ -906,8 +909,12 @@ public: MangleNumberingContext &getMangleNumberingContext(ASTContext &Ctx); bool isUnevaluated() const { - return Context == Unevaluated || Context == UnevaluatedAbstract || - Context == UnevaluatedList; + return Context == ExpressionEvaluationContext::Unevaluated || + Context == ExpressionEvaluationContext::UnevaluatedAbstract || + Context == ExpressionEvaluationContext::UnevaluatedList; + } + bool isConstantEvaluated() const { + return Context == ExpressionEvaluationContext::ConstantEvaluated; } }; @@ -931,7 +938,7 @@ public: /// /// This is basically a wrapper around PointerIntPair. The lowest bits of the /// integer are used to determine whether overload resolution succeeded. - class SpecialMemberOverloadResult : public llvm::FastFoldingSetNode { + class SpecialMemberOverloadResult { public: enum Kind { NoMemberOrDeleted, @@ -943,9 +950,9 @@ public: llvm::PointerIntPair<CXXMethodDecl*, 2> Pair; public: - SpecialMemberOverloadResult(const llvm::FoldingSetNodeID &ID) - : FastFoldingSetNode(ID) - {} + SpecialMemberOverloadResult() : Pair() {} + SpecialMemberOverloadResult(CXXMethodDecl *MD) + : Pair(MD, MD->isDeleted() ? NoMemberOrDeleted : Success) {} CXXMethodDecl *getMethod() const { return Pair.getPointer(); } void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); } @@ -954,9 +961,18 @@ public: void setKind(Kind K) { Pair.setInt(K); } }; + class SpecialMemberOverloadResultEntry + : public llvm::FastFoldingSetNode, + public SpecialMemberOverloadResult { + public: + SpecialMemberOverloadResultEntry(const llvm::FoldingSetNodeID &ID) + : FastFoldingSetNode(ID) + {} + }; + /// \brief A cache of special member function overload resolution results /// for C++ records. - llvm::FoldingSet<SpecialMemberOverloadResult> SpecialMemberCache; + llvm::FoldingSet<SpecialMemberOverloadResultEntry> SpecialMemberCache; /// \brief A cache of the flags available in enumerations with the flag_bits /// attribute. @@ -1054,14 +1070,12 @@ public: /// statements. class FPContractStateRAII { public: - FPContractStateRAII(Sema& S) - : S(S), OldFPContractState(S.FPFeatures.fp_contract) {} - ~FPContractStateRAII() { - S.FPFeatures.fp_contract = OldFPContractState; - } + FPContractStateRAII(Sema &S) : S(S), OldFPFeaturesState(S.FPFeatures) {} + ~FPContractStateRAII() { S.FPFeatures = OldFPFeaturesState; } + private: Sema& S; - bool OldFPContractState : 1; + FPOptions OldFPFeaturesState; }; void addImplicitTypedef(StringRef Name, QualType T); @@ -1235,9 +1249,11 @@ public: sema::BlockScopeInfo *getCurBlock(); /// Retrieve the current lambda scope info, if any. - /// \param IgnoreCapturedRegions true if should find the top-most lambda scope - /// info ignoring all inner captured regions scope infos. - sema::LambdaScopeInfo *getCurLambda(bool IgnoreCapturedRegions = false); + /// \param IgnoreNonLambdaCapturingScope true if should find the top-most + /// lambda scope info ignoring all inner capturing scopes that are not + /// lambda scopes. + sema::LambdaScopeInfo * + getCurLambda(bool IgnoreNonLambdaCapturingScope = false); /// \brief Retrieve the current generic lambda info, if any. sema::LambdaScopeInfo *getCurGenericLambda(); @@ -1548,6 +1564,7 @@ public: ParsedType ObjectType = nullptr, bool IsCtorOrDtorName = false, bool WantNontrivialTypeSourceInfo = false, + bool IsClassTemplateDeductionContext = true, IdentifierInfo **CorrectedII = nullptr); TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S); bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S); @@ -1689,6 +1706,18 @@ public: bool IsAddressOfOperand, std::unique_ptr<CorrectionCandidateCallback> CCC = nullptr); + /// Describes the detailed kind of a template name. Used in diagnostics. + enum class TemplateNameKindForDiagnostics { + ClassTemplate, + FunctionTemplate, + VarTemplate, + AliasTemplate, + TemplateTemplateParam, + DependentTemplate + }; + TemplateNameKindForDiagnostics + getTemplateNameKindForDiagnostics(TemplateName Name); + Decl *ActOnDeclarator(Scope *S, Declarator &D); NamedDecl *HandleDeclarator(Scope *S, Declarator &D, @@ -1709,8 +1738,11 @@ public: static bool adjustContextForLocalExternDecl(DeclContext *&DC); void DiagnoseFunctionSpecifiers(const DeclSpec &DS); + NamedDecl *getShadowedDeclaration(const TypedefNameDecl *D, + const LookupResult &R); NamedDecl *getShadowedDeclaration(const VarDecl *D, const LookupResult &R); - void CheckShadow(VarDecl *D, NamedDecl *ShadowedDecl, const LookupResult &R); + void CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, + const LookupResult &R); void CheckShadow(Scope *S, VarDecl *D); /// Warn if 'E', which is an expression that is about to be modified, refers @@ -1747,6 +1779,8 @@ public: // Returns true if the variable declaration is a redeclaration bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous); void CheckVariableDeclarationType(VarDecl *NewVD); + bool DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit, + Expr *Init); void CheckCompleteVariableDeclaration(VarDecl *VD); void CheckCompleteDecompositionDeclaration(DecompositionDecl *DD); void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D); @@ -1769,7 +1803,7 @@ public: // Returns true if the function declaration is a redeclaration bool CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, LookupResult &Previous, - bool IsExplicitSpecialization); + bool IsMemberSpecialization); bool shouldLinkDependentDeclWithPrevious(Decl *D, Decl *OldDecl); void CheckMain(FunctionDecl *FD, const DeclSpec &D); void CheckMSVCRTEntryPoint(FunctionDecl *FD); @@ -1794,7 +1828,6 @@ public: void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit); void ActOnUninitializedDecl(Decl *dcl); void ActOnInitializerError(Decl *Dcl); - bool canInitializeWithParenthesizedList(QualType TargetType); void ActOnPureSpecifier(Decl *D, SourceLocation PureSpecLoc); void ActOnCXXForRangeDecl(Decl *D); @@ -2876,13 +2909,13 @@ public: LOLR_StringTemplate }; - SpecialMemberOverloadResult *LookupSpecialMember(CXXRecordDecl *D, - CXXSpecialMember SM, - bool ConstArg, - bool VolatileArg, - bool RValueThis, - bool ConstThis, - bool VolatileThis); + SpecialMemberOverloadResult LookupSpecialMember(CXXRecordDecl *D, + CXXSpecialMember SM, + bool ConstArg, + bool VolatileArg, + bool RValueThis, + bool ConstThis, + bool VolatileThis); typedef std::function<void(const TypoCorrection &)> TypoDiagnosticGenerator; typedef std::function<ExprResult(Sema &, TypoExpr *, TypoCorrection)> @@ -2963,9 +2996,6 @@ public: void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, QualType T1, QualType T2, UnresolvedSetImpl &Functions); - void addOverloadedOperatorToUnresolvedSet(UnresolvedSetImpl &Functions, - DeclAccessPair Operator, - QualType T1, QualType T2); LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc, SourceLocation GnuLabelLoc = SourceLocation()); @@ -3098,6 +3128,8 @@ public: void ProcessPragmaWeak(Scope *S, Decl *D); // Decl attributes - this routine is the top level dispatcher. void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD); + // Helper for delayed proccessing of attributes. + void ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList); void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL, bool IncludeCXX11Attributes = true); bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, @@ -3184,7 +3216,6 @@ public: bool IsProtocolMethodDecl); typedef llvm::SmallPtrSet<Selector, 8> SelectorSet; - typedef llvm::DenseMap<Selector, ObjCMethodDecl*> ProtocolsMethodsMap; /// CheckImplementationIvars - This routine checks if the instance variables /// listed in the implelementation match those listed in the interface. @@ -3237,7 +3268,9 @@ public: SourceLocation LParenLoc, FieldDeclarator &FD, Selector GetterSel, + SourceLocation GetterNameLoc, Selector SetterSel, + SourceLocation SetterNameLoc, const bool isReadWrite, unsigned &Attributes, const unsigned AttributesAsWritten, @@ -3253,7 +3286,9 @@ public: SourceLocation LParenLoc, FieldDeclarator &FD, Selector GetterSel, + SourceLocation GetterNameLoc, Selector SetterSel, + SourceLocation SetterNameLoc, const bool isReadWrite, const unsigned Attributes, const unsigned AttributesAsWritten, @@ -4328,7 +4363,7 @@ public: /// \brief Determine whether Ctor is an initializer-list constructor, as /// defined in [dcl.init.list]p2. - bool isInitListConstructor(const CXXConstructorDecl *Ctor); + bool isInitListConstructor(const FunctionDecl *Ctor); Decl *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc, @@ -4737,7 +4772,8 @@ public: ParsedType ObjectType, bool EnteringContext); - ParsedType getDestructorType(const DeclSpec& DS, ParsedType ObjectType); + ParsedType getDestructorTypeForDecltype(const DeclSpec &DS, + ParsedType ObjectType); // Checks that reinterpret casts don't have undefined behavior. void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType, @@ -4953,7 +4989,7 @@ public: ArrayRef<TypeSourceInfo *> Args, SourceLocation RParenLoc); - /// ActOnArrayTypeTrait - Parsed one of the bianry type trait support + /// ActOnArrayTypeTrait - Parsed one of the binary type trait support /// pseudo-functions. ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc, @@ -5106,7 +5142,8 @@ public: CXXScopeSpec &SS, NamedDecl *ScopeLookupResult, bool ErrorRecoveryLookup, - bool *IsCorrectedToColon = nullptr); + bool *IsCorrectedToColon = nullptr, + bool OnlyNamespace = false); /// \brief The parser has parsed a nested-name-specifier 'identifier::'. /// @@ -5130,13 +5167,16 @@ public: /// are allowed. The bool value pointed by this parameter is set to 'true' /// if the identifier is treated as if it was followed by ':', not '::'. /// + /// \param OnlyNamespace If true, only considers namespaces in lookup. + /// /// \returns true if an error occurred, false otherwise. bool ActOnCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, bool EnteringContext, CXXScopeSpec &SS, bool ErrorRecoveryLookup = false, - bool *IsCorrectedToColon = nullptr); + bool *IsCorrectedToColon = nullptr, + bool OnlyNamespace = false); ExprResult ActOnDecltypeExpression(Expr *E); @@ -5312,6 +5352,12 @@ public: ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, Scope *CurScope); + /// \brief Does copying/destroying the captured variable have side effects? + bool CaptureHasSideEffects(const sema::LambdaScopeInfo::Capture &From); + + /// \brief Diagnose if an explicit lambda capture is unused. + void DiagnoseUnusedLambdaCapture(const sema::LambdaScopeInfo::Capture &From); + /// \brief Complete a lambda-expression having processed and attached the /// lambda body. ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, @@ -5604,6 +5650,9 @@ public: void CheckConversionDeclarator(Declarator &D, QualType &R, StorageClass& SC); Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion); + void CheckDeductionGuideDeclarator(Declarator &D, QualType &R, + StorageClass &SC); + void CheckDeductionGuideTemplate(FunctionTemplateDecl *TD); void CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD); void CheckExplicitlyDefaultedMemberExceptionSpec(CXXMethodDecl *MD, @@ -5807,6 +5856,12 @@ public: TemplateTy &Template, bool &MemberOfUnknownSpecialization); + /// Determine whether a particular identifier might be the name in a C++1z + /// deduction-guide declaration. + bool isDeductionGuideName(Scope *S, const IdentifierInfo &Name, + SourceLocation NameLoc, + ParsedTemplateTy *Template = nullptr); + bool DiagnoseUnknownTemplateName(const IdentifierInfo &II, SourceLocation IILoc, Scope *S, @@ -5882,7 +5937,7 @@ public: SourceLocation DeclStartLoc, SourceLocation DeclLoc, const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId, ArrayRef<TemplateParameterList *> ParamLists, - bool IsFriend, bool &IsExplicitSpecialization, bool &Invalid); + bool IsFriend, bool &IsMemberSpecialization, bool &Invalid); DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, @@ -5911,11 +5966,13 @@ public: TypeResult ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, - TemplateTy Template, SourceLocation TemplateLoc, + TemplateTy Template, IdentifierInfo *TemplateII, + SourceLocation TemplateIILoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc, - bool IsCtorOrDtorName = false); + bool IsCtorOrDtorName = false, + bool IsClassName = false); /// \brief Parsed an elaborated-type-specifier that refers to a template-id, /// such as \c class T::template apply<U>. @@ -5957,13 +6014,10 @@ public: const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs); - TemplateNameKind ActOnDependentTemplateName(Scope *S, - CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - UnqualifiedId &Name, - ParsedType ObjectType, - bool EnteringContext, - TemplateTy &Template); + TemplateNameKind ActOnDependentTemplateName( + Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext, + TemplateTy &Template, bool AllowInjectedClassName = false); DeclResult ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK, @@ -6088,12 +6142,17 @@ public: /// \param Converted Will receive the converted, canonicalized template /// arguments. /// + /// \param UpdateArgsWithConversions If \c true, update \p TemplateArgs to + /// contain the converted forms of the template arguments as written. + /// Otherwise, \p TemplateArgs will not be modified. + /// /// \returns true if an error occurred, false otherwise. bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, - SmallVectorImpl<TemplateArgument> &Converted); + SmallVectorImpl<TemplateArgument> &Converted, + bool UpdateArgsWithConversions = true); bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg, @@ -6182,7 +6241,8 @@ public: /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). /// \param TemplateLoc the location of the 'template' keyword, if any. /// \param TemplateName The template name. - /// \param TemplateNameLoc The location of the template name. + /// \param TemplateII The identifier used to name the template. + /// \param TemplateIILoc The location of the template name. /// \param LAngleLoc The location of the opening angle bracket ('<'). /// \param TemplateArgs The template arguments. /// \param RAngleLoc The location of the closing angle bracket ('>'). @@ -6191,7 +6251,8 @@ public: const CXXScopeSpec &SS, SourceLocation TemplateLoc, TemplateTy TemplateName, - SourceLocation TemplateNameLoc, + IdentifierInfo *TemplateII, + SourceLocation TemplateIILoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc); @@ -6706,6 +6767,9 @@ public: /// \brief Substitute Replacement for auto in TypeWithAuto TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, QualType Replacement); + /// \brief Completely replace the \c auto in \p TypeWithAuto by + /// \p Replacement. This does not retain any \c auto type sugar. + QualType ReplaceAutoType(QualType TypeWithAuto, QualType Replacement); /// \brief Result type of DeduceAutoType. enum DeduceAutoResult { @@ -6724,6 +6788,15 @@ public: bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc, bool Diagnose = true); + /// \brief Declare implicit deduction guides for a class template if we've + /// not already done so. + void DeclareImplicitDeductionGuides(TemplateDecl *Template, + SourceLocation Loc); + + QualType DeduceTemplateSpecializationFromInitializer( + TypeSourceInfo *TInfo, const InitializedEntity &Entity, + const InitializationKind &Kind, MultiExprArg Init); + QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name, QualType Type, TypeSourceInfo *TSI, SourceRange Range, bool DirectInit, @@ -6792,10 +6865,12 @@ public: bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr); - /// \brief A template instantiation that is currently in progress. - struct ActiveTemplateInstantiation { + /// A context in which code is being synthesized (where a source location + /// alone is not sufficient to identify the context). This covers template + /// instantiation and various forms of implicitly-generated functions. + struct CodeSynthesisContext { /// \brief The kind of template instantiation we are performing - enum InstantiationKind { + enum SynthesisKind { /// We are instantiating a template declaration. The entity is /// the declaration we're instantiating (e.g., a CXXRecordDecl). TemplateInstantiation, @@ -6834,28 +6909,42 @@ public: /// We are instantiating the exception specification for a function /// template which was deferred until it was needed. - ExceptionSpecInstantiation + ExceptionSpecInstantiation, + + /// We are declaring an implicit special member function. + DeclaringSpecialMember, } Kind; - /// \brief The point of instantiation within the source code. + /// \brief Was the enclosing context a non-instantiation SFINAE context? + bool SavedInNonInstantiationSFINAEContext; + + /// \brief The point of instantiation or synthesis within the source code. SourceLocation PointOfInstantiation; + /// \brief The entity that is being synthesized. + Decl *Entity; + /// \brief The template (or partial specialization) in which we are /// performing the instantiation, for substitutions of prior template /// arguments. NamedDecl *Template; - /// \brief The entity that is being instantiated. - Decl *Entity; - /// \brief The list of template arguments we are substituting, if they /// are not part of the entity. const TemplateArgument *TemplateArgs; - /// \brief The number of template arguments in TemplateArgs. - unsigned NumTemplateArgs; + // FIXME: Wrap this union around more members, or perhaps store the + // kind-specific members in the RAII object owning the context. + union { + /// \brief The number of template arguments in TemplateArgs. + unsigned NumTemplateArgs; + + /// \brief The special member being declared or defined. + CXXSpecialMember SpecialMember; + }; ArrayRef<TemplateArgument> template_arguments() const { + assert(Kind != DeclaringSpecialMember); return {TemplateArgs, NumTemplateArgs}; } @@ -6868,56 +6957,20 @@ public: /// template instantiation. SourceRange InstantiationRange; - ActiveTemplateInstantiation() - : Kind(TemplateInstantiation), Template(nullptr), Entity(nullptr), + CodeSynthesisContext() + : Kind(TemplateInstantiation), Entity(nullptr), Template(nullptr), TemplateArgs(nullptr), NumTemplateArgs(0), DeductionInfo(nullptr) {} /// \brief Determines whether this template is an actual instantiation /// that should be counted toward the maximum instantiation depth. bool isInstantiationRecord() const; - - friend bool operator==(const ActiveTemplateInstantiation &X, - const ActiveTemplateInstantiation &Y) { - if (X.Kind != Y.Kind) - return false; - - if (X.Entity != Y.Entity) - return false; - - switch (X.Kind) { - case TemplateInstantiation: - case ExceptionSpecInstantiation: - return true; - - case PriorTemplateArgumentSubstitution: - case DefaultTemplateArgumentChecking: - return X.Template == Y.Template && X.TemplateArgs == Y.TemplateArgs; - - case DefaultTemplateArgumentInstantiation: - case ExplicitTemplateArgumentSubstitution: - case DeducedTemplateArgumentSubstitution: - case DefaultFunctionArgumentInstantiation: - return X.TemplateArgs == Y.TemplateArgs; - - } - - llvm_unreachable("Invalid InstantiationKind!"); - } - - friend bool operator!=(const ActiveTemplateInstantiation &X, - const ActiveTemplateInstantiation &Y) { - return !(X == Y); - } }; - /// \brief List of active template instantiations. + /// \brief List of active code synthesis contexts. /// - /// This vector is treated as a stack. As one template instantiation - /// requires another template instantiation, additional - /// instantiations are pushed onto the stack up to a - /// user-configurable limit LangOptions::InstantiationDepth. - SmallVector<ActiveTemplateInstantiation, 16> - ActiveTemplateInstantiations; + /// This vector is treated as a stack. As synthesis of one entity requires + /// synthesis of another, additional contexts are pushed onto the stack. + SmallVector<CodeSynthesisContext, 16> CodeSynthesisContexts; /// Specializations whose definitions are currently being instantiated. llvm::DenseSet<std::pair<Decl *, unsigned>> InstantiatingSpecializations; @@ -6928,7 +6981,7 @@ public: /// \brief Extra modules inspected when performing a lookup during a template /// instantiation. Computed lazily. - SmallVector<Module*, 16> ActiveTemplateInstantiationLookupModules; + SmallVector<Module*, 16> CodeSynthesisContextLookupModules; /// \brief Cache of additional modules that should be used for name lookup /// within the current template instantiation. Computed lazily; use @@ -6951,19 +7004,22 @@ public: /// of a template instantiation or template argument deduction. bool InNonInstantiationSFINAEContext; - /// \brief The number of ActiveTemplateInstantiation entries in - /// \c ActiveTemplateInstantiations that are not actual instantiations and, - /// therefore, should not be counted as part of the instantiation depth. + /// \brief The number of \p CodeSynthesisContexts that are not template + /// instantiations and, therefore, should not be counted as part of the + /// instantiation depth. + /// + /// When the instantiation depth reaches the user-configurable limit + /// \p LangOptions::InstantiationDepth we will abort instantiation. + // FIXME: Should we have a similar limit for other forms of synthesis? unsigned NonInstantiationEntries; - /// \brief The last template from which a template instantiation + /// \brief The depth of the context stack at the point when the most recent /// error or warning was produced. /// - /// This value is used to suppress printing of redundant template - /// instantiation backtraces when there are multiple errors in the - /// same instantiation. FIXME: Does this belong in Sema? It's tough - /// to implement it anywhere else. - ActiveTemplateInstantiation LastTemplateInstantiationErrorContext; + /// This value is used to suppress printing of redundant context stacks + /// when there are multiple errors or warnings in the same instantiation. + // FIXME: Does this belong in Sema? It's tough to implement it anywhere else. + unsigned LastEmittedCodeSynthesisContextDepth = 0; /// \brief The current index into pack expansion arguments that will be /// used for substitution of parameter packs. @@ -7041,7 +7097,7 @@ public: InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionTemplateDecl *FunctionTemplate, ArrayRef<TemplateArgument> TemplateArgs, - ActiveTemplateInstantiation::InstantiationKind Kind, + CodeSynthesisContext::SynthesisKind Kind, sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange = SourceRange()); @@ -7120,12 +7176,11 @@ public: Sema &SemaRef; bool Invalid; bool AlreadyInstantiating; - bool SavedInNonInstantiationSFINAEContext; bool CheckInstantiationDepth(SourceLocation PointOfInstantiation, SourceRange InstantiationRange); InstantiatingTemplate( - Sema &SemaRef, ActiveTemplateInstantiation::InstantiationKind Kind, + Sema &SemaRef, CodeSynthesisContext::SynthesisKind Kind, SourceLocation PointOfInstantiation, SourceRange InstantiationRange, Decl *Entity, NamedDecl *Template = nullptr, ArrayRef<TemplateArgument> TemplateArgs = None, @@ -7137,6 +7192,21 @@ public: operator=(const InstantiatingTemplate&) = delete; }; + void pushCodeSynthesisContext(CodeSynthesisContext Ctx); + void popCodeSynthesisContext(); + + /// Determine whether we are currently performing template instantiation. + bool inTemplateInstantiation() const { + return CodeSynthesisContexts.size() > NonInstantiationEntries; + } + + void PrintContextStack() { + if (!CodeSynthesisContexts.empty() && + CodeSynthesisContexts.size() != LastEmittedCodeSynthesisContextDepth) { + PrintInstantiationStack(); + LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size(); + } + } void PrintInstantiationStack(); /// \brief Determines whether we are currently in a context where @@ -7339,7 +7409,8 @@ public: TypeSourceInfo *SubstType(TypeSourceInfo *T, const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation Loc, DeclarationName Entity); + SourceLocation Loc, DeclarationName Entity, + bool AllowDeducedTST = false); QualType SubstType(QualType T, const MultiLevelTemplateArgumentList &TemplateArgs, @@ -7436,6 +7507,12 @@ public: LateInstantiatedAttrVec *LateAttrs = nullptr, LocalInstantiationScope *OuterMostScope = nullptr); + void + InstantiateAttrsForDecl(const MultiLevelTemplateArgumentList &TemplateArgs, + const Decl *Pattern, Decl *Inst, + LateInstantiatedAttrVec *LateAttrs = nullptr, + LocalInstantiationScope *OuterMostScope = nullptr); + bool InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation, ClassTemplateSpecializationDecl *ClassTemplateSpec, @@ -7597,7 +7674,8 @@ public: Decl * const *ProtoRefs, unsigned NumProtoRefs, const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc); + SourceLocation EndProtoLoc, + AttributeList *AttrList); Decl *ActOnStartClassImplementation( SourceLocation AtClassImplLoc, @@ -8039,8 +8117,9 @@ public: SourceLocation AliasNameLoc); /// ActOnPragmaFPContract - Called on well formed - /// \#pragma {STDC,OPENCL} FP_CONTRACT - void ActOnPragmaFPContract(tok::OnOffSwitch OOS); + /// \#pragma {STDC,OPENCL} FP_CONTRACT and + /// \#pragma clang fp contract + void ActOnPragmaFPContract(LangOptions::FPContractModeKind FPC); /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to /// a the record decl, to handle '\#pragma pack' and '\#pragma options align'. @@ -8103,6 +8182,11 @@ public: void AddAssumeAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, Expr *OE, unsigned SpellingListIndex); + /// AddAllocAlignAttr - Adds an alloc_align attribute to a particular + /// declaration. + void AddAllocAlignAttr(SourceRange AttrRange, Decl *D, Expr *ParamExpr, + unsigned SpellingListIndex); + /// AddAlignValueAttr - Adds an align_value attribute to a particular /// declaration. void AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E, @@ -8129,12 +8213,17 @@ public: // ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E); ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E); - StmtResult ActOnCoreturnStmt(SourceLocation KwLoc, Expr *E); + StmtResult ActOnCoreturnStmt(Scope *S, SourceLocation KwLoc, Expr *E); - ExprResult BuildCoawaitExpr(SourceLocation KwLoc, Expr *E); + ExprResult BuildResolvedCoawaitExpr(SourceLocation KwLoc, Expr *E, + bool IsImplicit = false); + ExprResult BuildUnresolvedCoawaitExpr(SourceLocation KwLoc, Expr *E, + UnresolvedLookupExpr* Lookup); ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E); - StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E); - + StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E, + bool IsImplicit = false); + StmtResult BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs); + VarDecl *buildCoroutinePromise(SourceLocation Loc); void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body); //===--------------------------------------------------------------------===// @@ -8314,6 +8403,9 @@ public: return IsInOpenMPDeclareTargetContext; } + /// Return the number of captured regions created for an OpenMP directive. + static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind); + /// \brief Initialization of captured region for OpenMP region. void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope); /// \brief End of OpenMP region. @@ -9257,7 +9349,7 @@ public: ExprResult CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *CastExpr, CastKind &Kind); - ExprResult BuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo, + ExprResult BuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo, QualType Type, SourceLocation LParenLoc, Expr *CastExpr, SourceLocation RParenLoc); @@ -9265,14 +9357,14 @@ public: enum ARCConversionResult { ACR_okay, ACR_unbridged, ACR_error }; /// \brief Checks for invalid conversions and casts between - /// retainable pointers and other pointer kinds. - ARCConversionResult CheckObjCARCConversion(SourceRange castRange, - QualType castType, Expr *&op, - CheckedConversionKind CCK, - bool Diagnose = true, - bool DiagnoseCFAudited = false, - BinaryOperatorKind Opc = BO_PtrMemD - ); + /// retainable pointers and other pointer kinds for ARC and Weak. + ARCConversionResult CheckObjCConversion(SourceRange castRange, + QualType castType, Expr *&op, + CheckedConversionKind CCK, + bool Diagnose = true, + bool DiagnoseCFAudited = false, + BinaryOperatorKind Opc = BO_PtrMemD + ); Expr *stripARCUnbridgedCast(Expr *e); void diagnoseARCUnbridgedCast(Expr *e); @@ -9777,6 +9869,8 @@ public: void CodeCompletePostfixExpression(Scope *S, ExprResult LHS); void CodeCompleteTag(Scope *S, unsigned TagSpec); void CodeCompleteTypeQualifiers(DeclSpec &DS); + void CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D, + const VirtSpecifiers *VS = nullptr); void CodeCompleteBracketDeclarator(Scope *S); void CodeCompleteCase(Scope *S); void CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args); @@ -9922,6 +10016,7 @@ private: bool CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall); + bool CheckX86BuiltinGatherScatterScale(unsigned BuiltinID, CallExpr *TheCall); bool CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); @@ -10028,6 +10123,11 @@ private: void CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *Field, Expr *Init); + /// Check if there is a field shadowing. + void CheckShadowInheritedFields(const SourceLocation &Loc, + DeclarationName FieldName, + const CXXRecordDecl *RD); + /// \brief Check if the given expression contains 'break' or 'continue' /// statement that produces control flow different from GCC. void CheckBreakContinueBinding(Expr *E); @@ -10221,6 +10321,7 @@ class EnterExpressionEvaluationContext { bool Entered = true; public: + EnterExpressionEvaluationContext(Sema &Actions, Sema::ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl = nullptr, @@ -10251,8 +10352,8 @@ public: // a context. if (ShouldEnter && Actions.isUnevaluatedContext() && Actions.getLangOpts().CPlusPlus11) { - Actions.PushExpressionEvaluationContext(Sema::UnevaluatedList, nullptr, - false); + Actions.PushExpressionEvaluationContext( + Sema::ExpressionEvaluationContext::UnevaluatedList, nullptr, false); Entered = true; } } diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h index 401bbbf1e566..644d55b93f1b 100644 --- a/include/clang/Sema/Template.h +++ b/include/clang/Sema/Template.h @@ -46,6 +46,10 @@ namespace clang { /// \brief The template argument lists, stored from the innermost template /// argument list (first) to the outermost template argument list (last). SmallVector<ArgList, 4> TemplateArgumentLists; + + /// \brief The number of outer levels of template arguments that are not + /// being substituted. + unsigned NumRetainedOuterLevels = 0; public: /// \brief Construct an empty set of template argument lists. @@ -59,11 +63,19 @@ namespace clang { /// \brief Determine the number of levels in this template argument /// list. - unsigned getNumLevels() const { return TemplateArgumentLists.size(); } - + unsigned getNumLevels() const { + return TemplateArgumentLists.size() + NumRetainedOuterLevels; + } + + /// \brief Determine the number of substituted levels in this template + /// argument list. + unsigned getNumSubstitutedLevels() const { + return TemplateArgumentLists.size(); + } + /// \brief Retrieve the template argument at a given depth and index. const TemplateArgument &operator()(unsigned Depth, unsigned Index) const { - assert(Depth < TemplateArgumentLists.size()); + assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size()); return TemplateArgumentLists[getNumLevels() - Depth - 1][Index]; } @@ -73,7 +85,10 @@ namespace clang { /// /// There must exist a template argument list at the given depth. bool hasTemplateArgument(unsigned Depth, unsigned Index) const { - assert(Depth < TemplateArgumentLists.size()); + assert(Depth < getNumLevels()); + + if (Depth < NumRetainedOuterLevels) + return false; if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].size()) return false; @@ -84,7 +99,7 @@ namespace clang { /// \brief Clear out a specific template argument. void setArgument(unsigned Depth, unsigned Index, TemplateArgument Arg) { - assert(Depth < TemplateArgumentLists.size()); + assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size()); const_cast<TemplateArgument&>( TemplateArgumentLists[getNumLevels() - Depth - 1][Index]) @@ -101,9 +116,18 @@ namespace clang { /// \brief Add a new outmost level to the multi-level template argument /// list. void addOuterTemplateArguments(ArgList Args) { + assert(!NumRetainedOuterLevels && + "substituted args outside retained args?"); TemplateArgumentLists.push_back(Args); } + /// \brief Add an outermost level that we are not substituting. We have no + /// arguments at this level, and do not remove it from the depth of inner + /// template parameters that we instantiate. + void addOuterRetainedLevel() { + ++NumRetainedOuterLevels; + } + /// \brief Retrieve the innermost template argument list. const ArgList &getInnermost() const { return TemplateArgumentLists.front(); diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index acbd6d1deb5b..823440b19713 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -226,7 +226,7 @@ namespace clang { /// \brief The block containing the detailed preprocessing record. PREPROCESSOR_DETAIL_BLOCK_ID, - + /// \brief The block containing the submodule structure. SUBMODULE_BLOCK_ID, @@ -253,6 +253,12 @@ namespace clang { /// \brief A block containing a module file extension. EXTENSION_BLOCK_ID, + + /// A block with unhashed content. + /// + /// These records should not change the \a ASTFileSignature. See \a + /// UnhashedControlBlockRecordTypes for the list of records. + UNHASHED_CONTROL_BLOCK_ID, }; /// \brief Record types that occur within the control block. @@ -288,9 +294,6 @@ namespace clang { /// AST file. MODULE_MAP_FILE, - /// \brief Record code for the signature that identifiers this AST file. - SIGNATURE, - /// \brief Record code for the module build directory. MODULE_DIRECTORY, }; @@ -309,9 +312,6 @@ namespace clang { /// \brief Record code for the target options table. TARGET_OPTIONS, - /// \brief Record code for the diagnostic options table. - DIAGNOSTIC_OPTIONS, - /// \brief Record code for the filesystem options table. FILE_SYSTEM_OPTIONS, @@ -322,6 +322,18 @@ namespace clang { PREPROCESSOR_OPTIONS, }; + /// Record codes for the unhashed control block. + enum UnhashedControlBlockRecordTypes { + /// Record code for the signature that identifiers this AST file. + SIGNATURE = 1, + + /// Record code for the diagnostic options table. + DIAGNOSTIC_OPTIONS, + + /// Record code for \#pragma diagnostic mappings. + DIAG_PRAGMA_MAPPINGS, + }; + /// \brief Record code for extension blocks. enum ExtensionBlockRecordTypes { /// Metadata describing this particular extension. @@ -493,8 +505,7 @@ namespace clang { // ID 31 used to be a list of offsets to DECL_CXX_BASE_SPECIFIERS records. - /// \brief Record code for \#pragma diagnostic mappings. - DIAG_PRAGMA_MAPPINGS = 32, + // ID 32 used to be the code for \#pragma diagnostic mappings. /// \brief Record code for special CUDA declarations. CUDA_SPECIAL_DECL_REFS = 33, @@ -591,6 +602,11 @@ namespace clang { /// \brief Record code for declarations associated with OpenCL extensions. OPENCL_EXTENSION_DECLS = 59, + + MODULAR_CODEGEN_DECLS = 60, + + /// \brief Record code for \#pragma pack options. + PACK_PRAGMA_OPTIONS = 61, }; /// \brief Record types used within a source manager block. @@ -801,14 +817,12 @@ namespace clang { PREDEF_TYPE_SAMPLER_ID = 39, /// \brief OpenCL queue type. PREDEF_TYPE_QUEUE_ID = 40, - /// \brief OpenCL ndrange type. - PREDEF_TYPE_NDRANGE_ID = 41, /// \brief OpenCL reserve_id type. - PREDEF_TYPE_RESERVE_ID_ID = 42, + PREDEF_TYPE_RESERVE_ID_ID = 41, /// \brief The placeholder type for OpenMP array section. - PREDEF_TYPE_OMP_ARRAY_SECTION = 43, + PREDEF_TYPE_OMP_ARRAY_SECTION = 42, /// \brief The '__float128' type - PREDEF_TYPE_FLOAT128_ID = 44, + PREDEF_TYPE_FLOAT128_ID = 43, /// \brief OpenCL image types with auto numeration #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ PREDEF_TYPE_##Id##_ID, @@ -914,7 +928,11 @@ namespace clang { /// \brief A PipeType record. TYPE_PIPE = 43, /// \brief An ObjCTypeParamType record. - TYPE_OBJC_TYPE_PARAM = 44 + TYPE_OBJC_TYPE_PARAM = 44, + /// \brief A DeducedTemplateSpecializationType record. + TYPE_DEDUCED_TEMPLATE_SPECIALIZATION = 45, + /// \brief A DependentSizedExtVectorType record. + TYPE_DEPENDENT_SIZED_EXT_VECTOR = 46 }; /// \brief The type IDs for special types constructed by semantic @@ -1121,6 +1139,8 @@ namespace clang { DECL_EXPORT, /// \brief A CXXRecordDecl record. DECL_CXX_RECORD, + /// \brief A CXXDeductionGuideDecl record. + DECL_CXX_DEDUCTION_GUIDE, /// \brief A CXXMethodDecl record. DECL_CXX_METHOD, /// \brief A CXXConstructorDecl record. @@ -1624,7 +1644,8 @@ namespace clang { IdentifierInfo *getIdentifier() const { assert(Kind == DeclarationName::Identifier || - Kind == DeclarationName::CXXLiteralOperatorName); + Kind == DeclarationName::CXXLiteralOperatorName || + Kind == DeclarationName::CXXDeductionGuideName); return (IdentifierInfo *)Data; } Selector getSelector() const { diff --git a/include/clang/Serialization/ASTDeserializationListener.h b/include/clang/Serialization/ASTDeserializationListener.h index 4b10c39d8fb2..c26f3e0b425e 100644 --- a/include/clang/Serialization/ASTDeserializationListener.h +++ b/include/clang/Serialization/ASTDeserializationListener.h @@ -26,6 +26,7 @@ class QualType; class MacroDefinitionRecord; class MacroInfo; class Module; +class SourceLocation; class ASTDeserializationListener { public: @@ -52,6 +53,9 @@ public: MacroDefinitionRecord *MD) {} /// \brief A module definition was read from the AST file. virtual void ModuleRead(serialization::SubmoduleID ID, Module *Mod) {} + /// \brief A module import was read from the AST file. + virtual void ModuleImportRead(serialization::SubmoduleID ID, + SourceLocation ImportLoc) {} }; } diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 93994e2c519c..63ccb2461616 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -408,6 +408,9 @@ private: /// \brief The module manager which manages modules and their dependencies ModuleManager ModuleMgr; + /// The cache that manages memory buffers for PCM files. + MemoryBufferCache &PCMCache; + /// \brief A dummy identifier resolver used to merge TU-scope declarations in /// C, for the cases where we don't have a Sema object to provide a real /// identifier resolver. @@ -700,7 +703,7 @@ private: /// \brief Mapping from global preprocessing entity IDs to the module in /// which the preprocessed entity resides along with the offset that should be - /// added to the global preprocessing entitiy ID to produce a local ID. + /// added to the global preprocessing entity ID to produce a local ID. GlobalPreprocessedEntityMapType GlobalPreprocessedEntityMap; /// \name CodeGen-relevant special data @@ -808,6 +811,17 @@ private: int PragmaMSPointersToMembersState = -1; SourceLocation PointersToMembersPragmaLocation; + /// \brief The pragma pack state. + Optional<unsigned> PragmaPackCurrentValue; + SourceLocation PragmaPackCurrentLocation; + struct PragmaPackStackEntry { + unsigned Value; + SourceLocation Location; + StringRef SlotLabel; + }; + llvm::SmallVector<PragmaPackStackEntry, 2> PragmaPackStack; + llvm::SmallVector<std::string, 2> PragmaPackStrings; + /// \brief The OpenCL extension settings. OpenCLOptions OpenCLExtensions; @@ -970,14 +984,26 @@ private: /// \brief The generation number of each identifier, which keeps track of /// the last time we loaded information about this identifier. llvm::DenseMap<IdentifierInfo *, unsigned> IdentifierGeneration; - - /// \brief Contains declarations and definitions that will be + + class InterestingDecl { + Decl *D; + bool DeclHasPendingBody; + + public: + InterestingDecl(Decl *D, bool HasBody) + : D(D), DeclHasPendingBody(HasBody) {} + Decl *getDecl() { return D; } + /// Whether the declaration has a pending body. + bool hasPendingBody() { return DeclHasPendingBody; } + }; + + /// \brief Contains declarations and definitions that could be /// "interesting" to the ASTConsumer, when we get that AST consumer. /// /// "Interesting" declarations are those that have data that may /// need to be emitted, such as inline function definitions or /// Objective-C protocols. - std::deque<Decl *> InterestingDecls; + std::deque<InterestingDecl> PotentiallyInterestingDecls; /// \brief The list of redeclaration chains that still need to be /// reconstructed, and the local offset to the corresponding list @@ -1101,6 +1127,8 @@ private: /// predefines buffer may contain additional definitions. std::string SuggestedPredefines; + llvm::DenseMap<const Decl *, bool> BodySource; + /// \brief Reads a statement from the specified cursor. Stmt *ReadStmtFromStream(ModuleFile &F); @@ -1174,7 +1202,7 @@ private: SourceLocation ImportLoc, ModuleFile *ImportedBy, SmallVectorImpl<ImportedModule> &Loaded, off_t ExpectedSize, time_t ExpectedModTime, - serialization::ASTFileSignature ExpectedSignature, + ASTFileSignature ExpectedSignature, unsigned ClientLoadCapabilities); ASTReadResult ReadControlBlock(ModuleFile &F, SmallVectorImpl<ImportedModule> &Loaded, @@ -1183,9 +1211,25 @@ private: static ASTReadResult ReadOptionsBlock( llvm::BitstreamCursor &Stream, unsigned ClientLoadCapabilities, bool AllowCompatibleConfigurationMismatch, ASTReaderListener &Listener, - std::string &SuggestedPredefines, bool ValidateDiagnosticOptions); + std::string &SuggestedPredefines); + + /// Read the unhashed control block. + /// + /// This has no effect on \c F.Stream, instead creating a fresh cursor from + /// \c F.Data and reading ahead. + ASTReadResult readUnhashedControlBlock(ModuleFile &F, bool WasImportedBy, + unsigned ClientLoadCapabilities); + + static ASTReadResult + readUnhashedControlBlockImpl(ModuleFile *F, llvm::StringRef StreamData, + unsigned ClientLoadCapabilities, + bool AllowCompatibleConfigurationMismatch, + ASTReaderListener *Listener, + bool ValidateDiagnosticOptions); + ASTReadResult ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities); ASTReadResult ReadExtensionBlock(ModuleFile &F); + void ReadModuleOffsetMap(ModuleFile &F) const; bool ParseLineTable(ModuleFile &F, const RecordData &Record); bool ReadSourceManagerBlock(ModuleFile &F); llvm::BitstreamCursor &SLocCursorForID(int ID); @@ -1268,6 +1312,7 @@ private: llvm::iterator_range<PreprocessingRecord::iterator> getModulePreprocessedEntities(ModuleFile &Mod) const; +public: class ModuleDeclIterator : public llvm::iterator_adaptor_base< ModuleDeclIterator, const serialization::LocalDeclID *, @@ -1298,6 +1343,7 @@ private: llvm::iterator_range<ModuleDeclIterator> getModuleFileLevelDecls(ModuleFile &Mod); +private: void PassInterestingDeclsToConsumer(); void PassInterestingDeclToConsumer(Decl *D); @@ -1318,9 +1364,9 @@ private: /// /// This routine should only be used for fatal errors that have to /// do with non-routine failures (e.g., corrupted AST file). - void Error(StringRef Msg); + void Error(StringRef Msg) const; void Error(unsigned DiagID, StringRef Arg1 = StringRef(), - StringRef Arg2 = StringRef()); + StringRef Arg2 = StringRef()) const; ASTReader(const ASTReader &) = delete; void operator=(const ASTReader &) = delete; @@ -1564,7 +1610,7 @@ public: const LangOptions &LangOpts, const TargetOptions &TargetOpts, const PreprocessorOptions &PPOpts, - std::string ExistingModuleCachePath); + StringRef ExistingModuleCachePath); /// \brief Returns the suggested contents of the predefines buffer, /// which contains a (typically-empty) subset of the predefines @@ -1631,11 +1677,8 @@ public: /// reader. unsigned getTotalNumPreprocessedEntities() const { unsigned Result = 0; - for (ModuleConstIterator I = ModuleMgr.begin(), - E = ModuleMgr.end(); I != E; ++I) { - Result += (*I)->NumPreprocessedEntities; - } - + for (const auto &M : ModuleMgr) + Result += M.NumPreprocessedEntities; return Result; } @@ -1904,10 +1947,10 @@ public: SmallVectorImpl<Decl *> *Decls = nullptr); /// \brief Report a diagnostic. - DiagnosticBuilder Diag(unsigned DiagID); + DiagnosticBuilder Diag(unsigned DiagID) const; /// \brief Report a diagnostic. - DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); + DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const; IdentifierInfo *DecodeIdentifierInfo(serialization::IdentifierID ID); @@ -1968,6 +2011,8 @@ public: /// \brief Return a descriptor for the corresponding module. llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID) override; + ExtKind hasExternalDefinitions(const Decl *D) override; + /// \brief Retrieve a selector from the given module with its local ID /// number. Selector getLocalSelector(ModuleFile &M, unsigned LocalID); @@ -2057,6 +2102,8 @@ public: /// location space into ours. SourceLocation TranslateSourceLocation(ModuleFile &ModuleFile, SourceLocation Loc) const { + if (!ModuleFile.ModuleOffsetMap.empty()) + ReadModuleOffsetMap(ModuleFile); assert(ModuleFile.SLocRemap.find(Loc.getOffset()) != ModuleFile.SLocRemap.end() && "Cannot find offset to remap."); @@ -2098,8 +2145,7 @@ public: unsigned &Idx); /// \brief Reads attributes from the current stream position. - void ReadAttributes(ModuleFile &F, AttrVec &Attrs, - const RecordData &Record, unsigned &Idx); + void ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs); /// \brief Reads a statement. Stmt *ReadStmt(ModuleFile &F); @@ -2189,6 +2235,12 @@ public: /// \brief Loads comments ranges. void ReadComments() override; + /// Visit all the input files of the given module file. + void visitInputFiles(serialization::ModuleFile &MF, + bool IncludeSystem, bool Complain, + llvm::function_ref<void(const serialization::InputFile &IF, + bool isSystem)> Visitor); + bool isProcessingUpdateRecords() { return ProcessingUpdateRecords; } }; @@ -2284,6 +2336,14 @@ public: /// \brief Reads a sub-expression operand during statement reading. Expr *readSubExpr() { return Reader->ReadSubExpr(); } + /// \brief Reads a declaration with the given local ID in the given module. + /// + /// \returns The requested declaration, casted to the given return type. + template<typename T> + T *GetLocalDeclAs(uint32_t LocalID) { + return cast_or_null<T>(Reader->GetLocalDecl(*F, LocalID)); + } + /// \brief Reads a TemplateArgumentLocInfo appropriate for the /// given TemplateArgument kind, advancing Idx. TemplateArgumentLocInfo @@ -2455,7 +2515,7 @@ public: /// \brief Reads attributes from the current stream position, advancing Idx. void readAttributes(AttrVec &Attrs) { - return Reader->ReadAttributes(*F, Attrs, Record, Idx); + return Reader->ReadAttributes(*this, Attrs); } /// \brief Reads a token out of a record, advancing Idx. diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index 0d6b0268109d..17cf726e4d6b 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -54,6 +54,7 @@ class MacroInfo; class OpaqueValueExpr; class OpenCLOptions; class ASTReader; +class MemoryBufferCache; class Module; class ModuleFileExtension; class ModuleFileExtensionWriter; @@ -106,6 +107,12 @@ private: /// \brief The bitstream writer used to emit this precompiled header. llvm::BitstreamWriter &Stream; + /// The buffer associated with the bitstream. + const SmallVectorImpl<char> &Buffer; + + /// \brief The PCM manager which manages memory buffers for pcm files. + MemoryBufferCache &PCMCache; + /// \brief The ASTContext we're writing. ASTContext *Context = nullptr; @@ -365,6 +372,7 @@ private: /// IDs, since they will be written out to an EAGERLY_DESERIALIZED_DECLS /// record. SmallVector<uint64_t, 16> EagerlyDeserializedDecls; + SmallVector<uint64_t, 16> ModularCodegenDecls; /// \brief DeclContexts that have received extensions since their serialized /// form. @@ -424,8 +432,16 @@ private: void WriteSubStmt(Stmt *S); void WriteBlockInfoBlock(); - uint64_t WriteControlBlock(Preprocessor &PP, ASTContext &Context, - StringRef isysroot, const std::string &OutputFile); + void WriteControlBlock(Preprocessor &PP, ASTContext &Context, + StringRef isysroot, const std::string &OutputFile); + + /// Write out the signature and diagnostic options, and return the signature. + ASTFileSignature writeUnhashedControlBlock(Preprocessor &PP, + ASTContext &Context); + + /// Calculate hash of the pcm content. + static ASTFileSignature createSignature(StringRef Bytes); + void WriteInputFiles(SourceManager &SourceMgr, HeaderSearchOptions &HSOpts, bool Modules); void WriteSourceManagerBlock(SourceManager &SourceMgr, @@ -469,6 +485,7 @@ private: void WriteOptimizePragmaOptions(Sema &SemaRef); void WriteMSStructPragmaOptions(Sema &SemaRef); void WriteMSPointersToMembersPragmaOptions(Sema &SemaRef); + void WritePackPragmaOptions(Sema &SemaRef); void WriteModuleFileExtension(Sema &SemaRef, ModuleFileExtensionWriter &Writer); @@ -492,14 +509,15 @@ private: void WriteDeclAbbrevs(); void WriteDecl(ASTContext &Context, Decl *D); - uint64_t WriteASTCore(Sema &SemaRef, - StringRef isysroot, const std::string &OutputFile, - Module *WritingModule); + ASTFileSignature WriteASTCore(Sema &SemaRef, StringRef isysroot, + const std::string &OutputFile, + Module *WritingModule); public: /// \brief Create a new precompiled header writer that outputs to /// the given bitstream. - ASTWriter(llvm::BitstreamWriter &Stream, + ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl<char> &Buffer, + MemoryBufferCache &PCMCache, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, bool IncludeTimestamps = true); ~ASTWriter() override; @@ -525,9 +543,9 @@ public: /// /// \return the module signature, which eventually will be a hash of /// the module but currently is merely a random 32-bit number. - uint64_t WriteAST(Sema &SemaRef, const std::string &OutputFile, - Module *WritingModule, StringRef isysroot, - bool hasErrors = false); + ASTFileSignature WriteAST(Sema &SemaRef, const std::string &OutputFile, + Module *WritingModule, StringRef isysroot, + bool hasErrors = false); /// \brief Emit a token. void AddToken(const Token &Tok, RecordDataImpl &Record); diff --git a/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h index 58b3149d407e..4e4bf44f3492 100644 --- a/include/clang/Serialization/Module.h +++ b/include/clang/Serialization/Module.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_SERIALIZATION_MODULE_H #include "clang/Basic/FileManager.h" +#include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ContinuousRangeMap.h" @@ -89,8 +90,6 @@ public: bool isNotFound() const { return Val.getInt() == NotFound; } }; -typedef unsigned ASTFileSignature; - /// \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 @@ -100,13 +99,14 @@ typedef unsigned ASTFileSignature; /// other modules. class ModuleFile { public: - ModuleFile(ModuleKind Kind, unsigned Generation); + ModuleFile(ModuleKind Kind, unsigned Generation) + : Kind(Kind), Generation(Generation) {} ~ModuleFile(); // === General information === /// \brief The index of this module in the list of modules. - unsigned Index; + unsigned Index = 0; /// \brief The type of this module. ModuleKind Kind; @@ -144,34 +144,34 @@ public: std::string ModuleMapPath; /// \brief Whether this precompiled header is a relocatable PCH file. - bool RelocatablePCH; + bool RelocatablePCH = false; /// \brief Whether timestamps are included in this module file. - bool HasTimestamps; + bool HasTimestamps = false; /// \brief The file entry for the module file. - const FileEntry *File; + const FileEntry *File = nullptr; - /// \brief The signature of the module file, which may be used along with size + /// The signature of the module file, which may be used instead of the size /// and modification time to identify this particular file. ASTFileSignature Signature; /// \brief Whether this module has been directly imported by the /// user. - bool DirectlyImported; + bool DirectlyImported = false; /// \brief The generation of which this module file is a part. unsigned Generation; - /// \brief The memory buffer that stores the data associated with - /// this AST file. - std::unique_ptr<llvm::MemoryBuffer> Buffer; + /// The memory buffer that stores the data associated with + /// this AST file, owned by the PCMCache in the ModuleManager. + llvm::MemoryBuffer *Buffer; /// \brief The size of this file, in bits. - uint64_t SizeInBits; + uint64_t SizeInBits = 0; /// \brief The global bit offset (or base) of this module - uint64_t GlobalBitOffset; + uint64_t GlobalBitOffset = 0; /// \brief The serialized bitstream data for this file. StringRef Data; @@ -200,21 +200,29 @@ public: /// file. std::vector<std::unique_ptr<ModuleFileExtensionReader>> ExtensionReaders; + /// The module offset map data for this file. If non-empty, the various + /// ContinuousRangeMaps described below have not yet been populated. + StringRef ModuleOffsetMap; + // === Input Files === /// \brief The cursor to the start of the input-files block. llvm::BitstreamCursor InputFilesCursor; /// \brief Offsets for all of the input file entries in the AST file. - const llvm::support::unaligned_uint64_t *InputFileOffsets; + const llvm::support::unaligned_uint64_t *InputFileOffsets = nullptr; /// \brief The input files that have been loaded from this AST file. std::vector<InputFile> InputFilesLoaded; + // All user input files reside at the index range [0, NumUserInputFiles), and + // system input files reside at [NumUserInputFiles, InputFilesLoaded.size()). + unsigned NumUserInputFiles = 0; + /// \brief If non-zero, specifies the time when we last validated input /// files. Zero means we never validated them. /// /// The time is specified in seconds since the start of the Epoch. - uint64_t InputFilesValidationTimestamp; + uint64_t InputFilesValidationTimestamp = 0; // === Source Locations === @@ -222,17 +230,17 @@ public: llvm::BitstreamCursor SLocEntryCursor; /// \brief The number of source location entries in this AST file. - unsigned LocalNumSLocEntries; + unsigned LocalNumSLocEntries = 0; /// \brief The base ID in the source manager's view of this module. - int SLocEntryBaseID; + int SLocEntryBaseID = 0; /// \brief The base offset in the source manager's view of this module. - unsigned SLocEntryBaseOffset; + unsigned SLocEntryBaseOffset = 0; /// \brief Offsets for all of the source location entries in the /// AST file. - const uint32_t *SLocEntryOffsets; + const uint32_t *SLocEntryOffsets = nullptr; /// \brief SLocEntries that we're going to preload. SmallVector<uint64_t, 4> PreloadSLocEntries; @@ -243,17 +251,17 @@ public: // === Identifiers === /// \brief The number of identifiers in this AST file. - unsigned LocalNumIdentifiers; + unsigned LocalNumIdentifiers = 0; /// \brief Offsets into the identifier table data. /// /// This array is indexed by the identifier ID (-1), and provides /// the offset into IdentifierTableData where the string data is /// stored. - const uint32_t *IdentifierOffsets; + const uint32_t *IdentifierOffsets = nullptr; /// \brief Base identifier ID for identifiers local to this module. - serialization::IdentID BaseIdentifierID; + serialization::IdentID BaseIdentifierID = 0; /// \brief Remapping table for identifier IDs in this module. ContinuousRangeMap<uint32_t, int, 2> IdentifierRemap; @@ -262,11 +270,11 @@ public: /// /// This pointer points into a memory buffer, where the on-disk hash /// table for identifiers actually lives. - const char *IdentifierTableData; + const char *IdentifierTableData = nullptr; /// \brief A pointer to an on-disk hash table of opaque type /// IdentifierHashTable. - void *IdentifierLookupTable; + void *IdentifierLookupTable = nullptr; /// \brief Offsets of identifiers that we're going to preload within /// IdentifierTableData. @@ -279,23 +287,23 @@ public: llvm::BitstreamCursor MacroCursor; /// \brief The number of macros in this AST file. - unsigned LocalNumMacros; + unsigned LocalNumMacros = 0; /// \brief Offsets of macros in the preprocessor block. /// /// This array is indexed by the macro ID (-1), and provides /// the offset into the preprocessor block where macro definitions are /// stored. - const uint32_t *MacroOffsets; + const uint32_t *MacroOffsets = nullptr; /// \brief Base macro ID for macros local to this module. - serialization::MacroID BaseMacroID; + serialization::MacroID BaseMacroID = 0; /// \brief Remapping table for macro IDs in this module. ContinuousRangeMap<uint32_t, int, 2> MacroRemap; /// \brief The offset of the start of the set of defined macros. - uint64_t MacroStartOffset; + uint64_t MacroStartOffset = 0; // === Detailed PreprocessingRecord === @@ -304,40 +312,40 @@ public: llvm::BitstreamCursor PreprocessorDetailCursor; /// \brief The offset of the start of the preprocessor detail cursor. - uint64_t PreprocessorDetailStartOffset; + uint64_t PreprocessorDetailStartOffset = 0; /// \brief Base preprocessed entity ID for preprocessed entities local to /// this module. - serialization::PreprocessedEntityID BasePreprocessedEntityID; + serialization::PreprocessedEntityID BasePreprocessedEntityID = 0; /// \brief Remapping table for preprocessed entity IDs in this module. ContinuousRangeMap<uint32_t, int, 2> PreprocessedEntityRemap; - const PPEntityOffset *PreprocessedEntityOffsets; - unsigned NumPreprocessedEntities; + const PPEntityOffset *PreprocessedEntityOffsets = nullptr; + unsigned NumPreprocessedEntities = 0; // === Header search information === /// \brief The number of local HeaderFileInfo structures. - unsigned LocalNumHeaderFileInfos; + unsigned LocalNumHeaderFileInfos = 0; /// \brief Actual data for the on-disk hash table of header file /// information. /// /// This pointer points into a memory buffer, where the on-disk hash /// table for header file information actually lives. - const char *HeaderFileInfoTableData; + const char *HeaderFileInfoTableData = nullptr; /// \brief The on-disk hash table that contains information about each of /// the header files. - void *HeaderFileInfoTable; + void *HeaderFileInfoTable = nullptr; // === Submodule information === /// \brief The number of submodules in this module. - unsigned LocalNumSubmodules; + unsigned LocalNumSubmodules = 0; /// \brief Base submodule ID for submodules local to this module. - serialization::SubmoduleID BaseSubmoduleID; + serialization::SubmoduleID BaseSubmoduleID = 0; /// \brief Remapping table for submodule IDs in this module. ContinuousRangeMap<uint32_t, int, 2> SubmoduleRemap; @@ -347,14 +355,14 @@ public: /// \brief The number of selectors new to this file. /// /// This is the number of entries in SelectorOffsets. - unsigned LocalNumSelectors; + unsigned LocalNumSelectors = 0; /// \brief Offsets into the selector lookup table's data array /// where each selector resides. - const uint32_t *SelectorOffsets; + const uint32_t *SelectorOffsets = nullptr; /// \brief Base selector ID for selectors local to this module. - serialization::SelectorID BaseSelectorID; + serialization::SelectorID BaseSelectorID = 0; /// \brief Remapping table for selector IDs in this module. ContinuousRangeMap<uint32_t, int, 2> SelectorRemap; @@ -362,14 +370,14 @@ public: /// \brief A pointer to the character data that comprises the selector table /// /// The SelectorOffsets table refers into this memory. - const unsigned char *SelectorLookupTableData; + const unsigned char *SelectorLookupTableData = nullptr; /// \brief A pointer to an on-disk hash table of opaque type /// ASTSelectorLookupTable. /// /// This hash table provides the IDs of all selectors, and the associated /// instance and factory methods. - void *SelectorLookupTable; + void *SelectorLookupTable = nullptr; // === Declarations === @@ -379,14 +387,14 @@ public: llvm::BitstreamCursor DeclsCursor; /// \brief The number of declarations in this AST file. - unsigned LocalNumDecls; + unsigned LocalNumDecls = 0; /// \brief Offset of each declaration within the bitstream, indexed /// by the declaration ID (-1). - const DeclOffset *DeclOffsets; + const DeclOffset *DeclOffsets = nullptr; /// \brief Base declaration ID for declarations local to this module. - serialization::DeclID BaseDeclID; + serialization::DeclID BaseDeclID = 0; /// \brief Remapping table for declaration IDs in this module. ContinuousRangeMap<uint32_t, int, 2> DeclRemap; @@ -401,15 +409,15 @@ public: llvm::DenseMap<ModuleFile *, serialization::DeclID> GlobalToLocalDeclIDs; /// \brief Array of file-level DeclIDs sorted by file. - const serialization::DeclID *FileSortedDecls; - unsigned NumFileSortedDecls; + const serialization::DeclID *FileSortedDecls = nullptr; + unsigned NumFileSortedDecls = 0; /// \brief Array of category list location information within this /// module file, sorted by the definition ID. - const serialization::ObjCCategoriesInfo *ObjCCategoriesMap; + const serialization::ObjCCategoriesInfo *ObjCCategoriesMap = nullptr; /// \brief The number of redeclaration info entries in ObjCCategoriesMap. - unsigned LocalNumObjCCategoriesInMap; + unsigned LocalNumObjCCategoriesInMap = 0; /// \brief The Objective-C category lists for categories known to this /// module. @@ -418,15 +426,15 @@ public: // === Types === /// \brief The number of types in this AST file. - unsigned LocalNumTypes; + unsigned LocalNumTypes = 0; /// \brief Offset of each type within the bitstream, indexed by the /// type ID, or the representation of a Type*. - const uint32_t *TypeOffsets; + const uint32_t *TypeOffsets = nullptr; /// \brief Base type ID for types local to this module as represented in /// the global type ID space. - serialization::TypeID BaseTypeIndex; + serialization::TypeID BaseTypeIndex = 0; /// \brief Remapping table for type IDs in this module. ContinuousRangeMap<uint32_t, int, 2> TypeRemap; diff --git a/include/clang/Serialization/ModuleManager.h b/include/clang/Serialization/ModuleManager.h index 1c4d88e979e3..fae387cac7e2 100644 --- a/include/clang/Serialization/ModuleManager.h +++ b/include/clang/Serialization/ModuleManager.h @@ -19,10 +19,12 @@ #include "clang/Serialization/Module.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/iterator.h" namespace clang { class GlobalModuleIndex; +class MemoryBufferCache; class ModuleMap; class PCHContainerReader; @@ -32,7 +34,7 @@ namespace serialization { class ModuleManager { /// \brief The chain of AST files, in the order in which we started to load /// them (this order isn't really useful for anything). - SmallVector<ModuleFile *, 2> Chain; + SmallVector<std::unique_ptr<ModuleFile>, 2> Chain; /// \brief The chain of non-module PCH files. The first entry is the one named /// by the user, the last one is the one that doesn't depend on anything @@ -50,6 +52,9 @@ class ModuleManager { /// FileEntry *. FileManager &FileMgr; + /// Cache of PCM files. + IntrusiveRefCntPtr<MemoryBufferCache> PCMCache; + /// \brief Knows how to unwrap module containers. const PCHContainerReader &PCHContainerRdr; @@ -111,12 +116,18 @@ class ModuleManager { void returnVisitState(VisitState *State); public: - typedef SmallVectorImpl<ModuleFile*>::iterator ModuleIterator; - typedef SmallVectorImpl<ModuleFile*>::const_iterator ModuleConstIterator; - typedef SmallVectorImpl<ModuleFile*>::reverse_iterator ModuleReverseIterator; + typedef llvm::pointee_iterator< + SmallVectorImpl<std::unique_ptr<ModuleFile>>::iterator> + ModuleIterator; + typedef llvm::pointee_iterator< + SmallVectorImpl<std::unique_ptr<ModuleFile>>::const_iterator> + ModuleConstIterator; + typedef llvm::pointee_iterator< + SmallVectorImpl<std::unique_ptr<ModuleFile>>::reverse_iterator> + ModuleReverseIterator; typedef std::pair<uint32_t, StringRef> ModuleOffset; - explicit ModuleManager(FileManager &FileMgr, + explicit ModuleManager(FileManager &FileMgr, MemoryBufferCache &PCMCache, const PCHContainerReader &PCHContainerRdr); ~ModuleManager(); @@ -136,7 +147,8 @@ public: ModuleReverseIterator rend() { return Chain.rend(); } /// \brief A range covering the PCH and preamble module files loaded. - llvm::iterator_range<ModuleConstIterator> pch_modules() const { + llvm::iterator_range<SmallVectorImpl<ModuleFile *>::const_iterator> + pch_modules() const { return llvm::make_range(PCHChain.begin(), PCHChain.end()); } @@ -152,10 +164,10 @@ public: ModuleFile &operator[](unsigned Index) const { return *Chain[Index]; } /// \brief Returns the module associated with the given name - ModuleFile *lookup(StringRef Name); + ModuleFile *lookup(StringRef Name) const; /// \brief Returns the module associated with the given module file. - ModuleFile *lookup(const FileEntry *File); + ModuleFile *lookup(const FileEntry *File) const; /// \brief Returns the in-memory (virtual file) buffer with the given name std::unique_ptr<llvm::MemoryBuffer> lookupBuffer(StringRef Name); @@ -220,8 +232,8 @@ public: ModuleFile *&Module, std::string &ErrorStr); - /// \brief Remove the given set of modules. - void removeModules(ModuleIterator first, ModuleIterator last, + /// \brief Remove the modules starting from First (to the end). + void removeModules(ModuleIterator First, llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully, ModuleMap *modMap); @@ -282,6 +294,8 @@ public: /// \brief View the graphviz representation of the module graph. void viewGraph(); + + MemoryBufferCache &getPCMCache() const { return *PCMCache; } }; } } // end namespace clang::serialization diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td index 69578910499f..790ba5c121c9 100644 --- a/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -45,7 +45,6 @@ def CplusplusAlpha : Package<"cplusplus">, InPackage<Alpha>, Hidden; def CplusplusOptIn : Package<"cplusplus">, InPackage<OptIn>; def Valist : Package<"valist">; -def ValistAlpha : Package<"valist">, InPackage<Alpha>, Hidden; def DeadCode : Package<"deadcode">; def DeadCodeAlpha : Package<"deadcode">, InPackage<Alpha>, Hidden; @@ -280,6 +279,11 @@ def VirtualCallChecker : Checker<"VirtualCall">, let ParentPackage = CplusplusAlpha in { +def MisusedMovedObjectChecker: Checker<"MisusedMovedObject">, + HelpText<"Method calls on a moved-from object and copying a moved-from " + "object will be reported">, + DescFile<"MisusedMovedObjectChecker.cpp">; + def IteratorPastEndChecker : Checker<"IteratorPastEnd">, HelpText<"Check iterators used past end">, DescFile<"IteratorPastEndChecker.cpp">; @@ -291,7 +295,7 @@ def IteratorPastEndChecker : Checker<"IteratorPastEnd">, // Valist checkers. //===----------------------------------------------------------------------===// -let ParentPackage = ValistAlpha in { +let ParentPackage = Valist in { def UninitializedChecker : Checker<"Uninitialized">, HelpText<"Check for usages of uninitialized (or already released) va_lists.">, @@ -305,7 +309,7 @@ def CopyToSelfChecker : Checker<"CopyToSelf">, HelpText<"Check for va_lists which are copied onto itself.">, DescFile<"ValistChecker.cpp">; -} // end : "alpha.valist" +} // end : "valist" //===----------------------------------------------------------------------===// // Deadcode checkers. diff --git a/include/clang/StaticAnalyzer/Core/Analyses.def b/include/clang/StaticAnalyzer/Core/Analyses.def index 3355f4b6949c..04bf41bfde4f 100644 --- a/include/clang/StaticAnalyzer/Core/Analyses.def +++ b/include/clang/StaticAnalyzer/Core/Analyses.def @@ -22,6 +22,7 @@ ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store", CreateR #endif ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of concrete value ranges", CreateRangeConstraintManager) +ANALYSIS_CONSTRAINTS(Z3Constraints, "z3", "Use Z3 contraint solver", CreateZ3ConstraintManager) #ifndef ANALYSIS_DIAGNOSTICS #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h index dd7a6c863be0..f9477762c758 100644 --- a/include/clang/StaticAnalyzer/Core/Checker.h +++ b/include/clang/StaticAnalyzer/Core/Checker.h @@ -321,9 +321,11 @@ class RegionChanges { const InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> Explicits, ArrayRef<const MemRegion *> Regions, + const LocationContext *LCtx, const CallEvent *Call) { - return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, - Explicits, Regions, Call); + return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated, + Explicits, Regions, + LCtx, Call); } public: diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index 0316c8fb173b..52ed260346bf 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -338,6 +338,7 @@ public: const InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, + const LocationContext *LCtx, const CallEvent *Call); /// \brief Run checkers when pointers escape. @@ -443,10 +444,11 @@ public: typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc; typedef CheckerFn<ProgramStateRef (ProgramStateRef, - const InvalidatedSymbols *symbols, - ArrayRef<const MemRegion *> ExplicitRegions, - ArrayRef<const MemRegion *> Regions, - const CallEvent *Call)> + const InvalidatedSymbols *symbols, + ArrayRef<const MemRegion *> ExplicitRegions, + ArrayRef<const MemRegion *> Regions, + const LocationContext *LCtx, + const CallEvent *Call)> CheckRegionChangesFunc; typedef CheckerFn<ProgramStateRef (ProgramStateRef, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index 0d1a120c9dd4..fb427f618575 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -20,6 +20,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" namespace clang { namespace ento { @@ -29,8 +30,9 @@ class CompoundValData : public llvm::FoldingSetNode { llvm::ImmutableList<SVal> L; public: - CompoundValData(QualType t, llvm::ImmutableList<SVal> l) - : T(t), L(l) {} + CompoundValData(QualType t, llvm::ImmutableList<SVal> l) : T(t), L(l) { + assert(NonLoc::isCompoundType(t)); + } typedef llvm::ImmutableList<SVal>::iterator iterator; iterator begin() const { return L.begin(); } @@ -47,7 +49,9 @@ class LazyCompoundValData : public llvm::FoldingSetNode { const TypedValueRegion *region; public: LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r) - : store(st), region(r) {} + : store(st), region(r) { + assert(NonLoc::isCompoundType(r->getValueType())); + } const void *getStore() const { return store.getStore(); } const TypedValueRegion *getRegion() const { return region; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index 89610ef5c17d..fa7ee62ab704 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -55,6 +55,7 @@ class CallEventManager; class CallDescription { friend CallEvent; mutable IdentifierInfo *II; + mutable bool IsLookupDone; StringRef FuncName; unsigned RequiredArgs; @@ -68,7 +69,8 @@ public: /// call. Omit this parameter to match every occurance of call with a given /// name regardless the number of arguments. CallDescription(StringRef FuncName, unsigned RequiredArgs = NoArgRequirement) - : II(nullptr), FuncName(FuncName), RequiredArgs(RequiredArgs) {} + : II(nullptr), IsLookupDone(false), FuncName(FuncName), + RequiredArgs(RequiredArgs) {} /// \brief Get the name of the function that this object matches. StringRef getFunctionName() const { return FuncName; } @@ -381,7 +383,9 @@ public: // Iterator access to formal parameters and their types. private: - typedef std::const_mem_fun_t<QualType, ParmVarDecl> get_type_fun; + struct GetTypeFn { + QualType operator()(ParmVarDecl *PD) const { return PD->getType(); } + }; public: /// Return call's formal parameters. @@ -391,7 +395,7 @@ public: /// correspond with the argument value returned by \c getArgSVal(0). virtual ArrayRef<ParmVarDecl*> parameters() const = 0; - typedef llvm::mapped_iterator<ArrayRef<ParmVarDecl*>::iterator, get_type_fun> + typedef llvm::mapped_iterator<ArrayRef<ParmVarDecl*>::iterator, GetTypeFn> param_type_iterator; /// Returns an iterator over the types of the call's formal parameters. @@ -400,13 +404,11 @@ public: /// definition because it represents a public interface, and probably has /// more annotations. param_type_iterator param_type_begin() const { - return llvm::map_iterator(parameters().begin(), - get_type_fun(&ParmVarDecl::getType)); + return llvm::map_iterator(parameters().begin(), GetTypeFn()); } /// \sa param_type_begin() param_type_iterator param_type_end() const { - return llvm::map_iterator(parameters().end(), - get_type_fun(&ParmVarDecl::getType)); + return llvm::map_iterator(parameters().end(), GetTypeFn()); } // For debugging purposes only diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h index 6651382d9e95..c01600d5c969 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h @@ -139,6 +139,8 @@ public: return nullptr; } + /// Scan all symbols referenced by the constraints. If the symbol is not + /// alive, remove it. virtual ProgramStateRef removeDeadBindings(ProgramStateRef state, SymbolReaper& SymReaper) = 0; @@ -182,6 +184,9 @@ std::unique_ptr<ConstraintManager> CreateRangeConstraintManager(ProgramStateManager &statemgr, SubEngine *subengine); +std::unique_ptr<ConstraintManager> +CreateZ3ConstraintManager(ProgramStateManager &statemgr, SubEngine *subengine); + } // end GR namespace } // end clang namespace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 591b112d60ac..067d70610868 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -237,7 +237,7 @@ public: const CFGBlock *DstF) override; /// Called by CoreEngine. Used to processing branching behavior - /// at static initalizers. + /// at static initializers. void processStaticInitializer(const DeclStmt *DS, NodeBuilderContext& BuilderCtx, ExplodedNode *Pred, @@ -293,6 +293,7 @@ public: const InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, + const LocationContext *LCtx, const CallEvent *Call) override; /// printState - Called by ProgramStateManager to print checker-specific data. @@ -522,7 +523,9 @@ protected: /// Call PointerEscape callback when a value escapes as a result of bind. ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, - SVal Loc, SVal Val) override; + SVal Loc, + SVal Val, + const LocationContext *LCtx) override; /// Call PointerEscape callback when a value escapes as a result of /// region invalidation. /// \param[in] ITraits Specifies invalidation traits for regions/symbols. @@ -618,16 +621,16 @@ private: 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 the value of the given expression \p InitWithAdjustments 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. + /// If \p Result is provided, the new region will be bound to this expression + /// instead of \p InitWithAdjustments. ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State, const LocationContext *LC, - const Expr *E, - const Expr *ResultE = nullptr); + const Expr *InitWithAdjustments, + const Expr *Result = nullptr); /// For a DeclStmt or CXXInitCtorInitializer, walk backward in the current CFG /// block to find the constructor expression that directly constructed into diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index da4b964424c3..29b1c4cdca04 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -182,6 +182,7 @@ protected: MemSpaceRegion(MemRegionManager *mgr, Kind k) : MemRegion(k), Mgr(mgr) { assert(classof(this)); + assert(mgr); } MemRegionManager* getMemRegionManager() const override { return Mgr; } @@ -215,9 +216,12 @@ public: class GlobalsSpaceRegion : public MemSpaceRegion { virtual void anchor(); + protected: - GlobalsSpaceRegion(MemRegionManager *mgr, Kind k) - : MemSpaceRegion(mgr, k) {} + GlobalsSpaceRegion(MemRegionManager *mgr, Kind k) : MemSpaceRegion(mgr, k) { + assert(classof(this)); + } + public: static bool classof(const MemRegion *R) { Kind k = R->getKind(); @@ -236,7 +240,9 @@ class StaticGlobalSpaceRegion : public GlobalsSpaceRegion { const CodeTextRegion *CR; StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr) - : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {} + : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) { + assert(cr); + } public: void Profile(llvm::FoldingSetNodeID &ID) const override; @@ -257,9 +263,13 @@ public: /// RegionStoreManager::invalidateRegions (instead of finding all the dependent /// globals, we invalidate the whole parent region). class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion { + virtual void anchor() override; + protected: NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k) - : GlobalsSpaceRegion(mgr, k) {} + : GlobalsSpaceRegion(mgr, k) { + assert(classof(this)); + } public: @@ -326,7 +336,6 @@ public: }; class HeapSpaceRegion : public MemSpaceRegion { - virtual void anchor(); friend class MemRegionManager; HeapSpaceRegion(MemRegionManager *mgr) @@ -341,10 +350,10 @@ public: }; class UnknownSpaceRegion : public MemSpaceRegion { - virtual void anchor(); friend class MemRegionManager; UnknownSpaceRegion(MemRegionManager *mgr) - : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {} + : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {} + public: void dumpToStream(raw_ostream &os) const override; @@ -355,13 +364,15 @@ public: }; class StackSpaceRegion : public MemSpaceRegion { -private: + virtual void anchor(); + const StackFrameContext *SFC; protected: StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc) : MemSpaceRegion(mgr, k), SFC(sfc) { assert(classof(this)); + assert(sfc); } public: @@ -376,7 +387,6 @@ public: }; class StackLocalsSpaceRegion : public StackSpaceRegion { - virtual void anchor(); friend class MemRegionManager; StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {} @@ -391,7 +401,6 @@ public: class StackArgumentsSpaceRegion : public StackSpaceRegion { private: - virtual void anchor(); friend class MemRegionManager; StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {} @@ -408,11 +417,15 @@ public: /// SubRegion - A region that subsets another larger region. Most regions /// are subclasses of SubRegion. class SubRegion : public MemRegion { -private: virtual void anchor(); + protected: const MemRegion* superRegion; - SubRegion(const MemRegion* sReg, Kind k) : MemRegion(k), superRegion(sReg) {} + SubRegion(const MemRegion *sReg, Kind k) : MemRegion(k), superRegion(sReg) { + assert(classof(this)); + assert(sReg); + } + public: const MemRegion* getSuperRegion() const { return superRegion; @@ -440,13 +453,18 @@ public: /// by a call to 'alloca'. class AllocaRegion : public SubRegion { friend class MemRegionManager; -protected: + unsigned Cnt; // Block counter. Used to distinguish different pieces of // memory allocated by alloca at the same call site. const Expr *Ex; - AllocaRegion(const Expr *ex, unsigned cnt, const MemRegion *superRegion) - : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {} + AllocaRegion(const Expr *ex, unsigned cnt, const MemSpaceRegion *superRegion) + : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) { + assert(Ex); + } + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex, + unsigned Cnt, const MemRegion *superRegion); public: @@ -458,9 +476,6 @@ public: void Profile(llvm::FoldingSetNodeID& ID) const override; - static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex, - unsigned Cnt, const MemRegion *superRegion); - void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion* R) { @@ -470,10 +485,12 @@ public: /// TypedRegion - An abstract class representing regions that are typed. class TypedRegion : public SubRegion { -public: - void anchor() override; + virtual void anchor() override; + protected: - TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {} + TypedRegion(const MemRegion *sReg, Kind k) : SubRegion(sReg, k) { + assert(classof(this)); + } public: virtual QualType getLocationType() const = 0; @@ -492,10 +509,12 @@ public: /// TypedValueRegion - An abstract class representing regions having a typed value. class TypedValueRegion : public TypedRegion { -public: - void anchor() override; + virtual void anchor() override; + protected: - TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {} + TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) { + assert(classof(this)); + } public: virtual QualType getValueType() const = 0; @@ -524,10 +543,13 @@ public: class CodeTextRegion : public TypedRegion { -public: - void anchor() override; + virtual void anchor() override; + protected: - CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {} + CodeTextRegion(const MemSpaceRegion *sreg, Kind k) : TypedRegion(sreg, k) { + assert(classof(this)); + } + public: bool isBoundable() const override { return false; } @@ -539,13 +561,19 @@ public: /// FunctionCodeRegion - A region that represents code texts of function. class FunctionCodeRegion : public CodeTextRegion { + friend class MemRegionManager; + const NamedDecl *FD; -public: - FunctionCodeRegion(const NamedDecl *fd, const MemRegion* sreg) + + FunctionCodeRegion(const NamedDecl *fd, const CodeSpaceRegion* sreg) : CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) { assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd)); } + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD, + const MemRegion*); + +public: QualType getLocationType() const override { const ASTContext &Ctx = getContext(); if (const FunctionDecl *D = dyn_cast<FunctionDecl>(FD)) { @@ -568,9 +596,6 @@ public: void Profile(llvm::FoldingSetNodeID& ID) const override; - static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD, - const MemRegion*); - static bool classof(const MemRegion* R) { return R->getKind() == FunctionCodeRegionKind; } @@ -591,8 +616,16 @@ class BlockCodeRegion : public CodeTextRegion { CanQualType locTy; BlockCodeRegion(const BlockDecl *bd, CanQualType lTy, - AnalysisDeclContext *ac, const MemRegion* sreg) - : CodeTextRegion(sreg, BlockCodeRegionKind), BD(bd), AC(ac), locTy(lTy) {} + AnalysisDeclContext *ac, const CodeSpaceRegion* sreg) + : CodeTextRegion(sreg, BlockCodeRegionKind), BD(bd), AC(ac), locTy(lTy) { + assert(bd); + assert(ac); + assert(lTy->getTypePtr()->isBlockPointerType()); + } + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD, + CanQualType, const AnalysisDeclContext*, + const MemRegion*); public: QualType getLocationType() const override { @@ -609,10 +642,6 @@ public: void Profile(llvm::FoldingSetNodeID& ID) const override; - static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD, - CanQualType, const AnalysisDeclContext*, - const MemRegion*); - static bool classof(const MemRegion* R) { return R->getKind() == BlockCodeRegionKind; } @@ -626,6 +655,7 @@ public: /// variables. class BlockDataRegion : public TypedRegion { friend class MemRegionManager; + const BlockCodeRegion *BC; const LocationContext *LC; // Can be null */ unsigned BlockCount; @@ -633,10 +663,19 @@ class BlockDataRegion : public TypedRegion { void *OriginalVars; BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc, - unsigned count, const MemRegion *sreg) - : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), - BlockCount(count), - ReferencedVars(nullptr), OriginalVars(nullptr) {} + unsigned count, const MemSpaceRegion *sreg) + : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), + BlockCount(count), ReferencedVars(nullptr), OriginalVars(nullptr) { + assert(bc); + assert(lc); + assert(isa<GlobalImmutableSpaceRegion>(sreg) || + isa<StackLocalsSpaceRegion>(sreg) || + isa<UnknownSpaceRegion>(sreg)); + } + + static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockCodeRegion *, + const LocationContext *, unsigned, + const MemRegion *); public: const BlockCodeRegion *getCodeRegion() const { return BC; } @@ -686,10 +725,6 @@ public: void Profile(llvm::FoldingSetNodeID& ID) const override; - static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockCodeRegion *, - const LocationContext *, unsigned, - const MemRegion *); - static bool classof(const MemRegion* R) { return R->getKind() == BlockDataRegionKind; } @@ -705,13 +740,20 @@ private: /// map the concept of symbolic values into the domain of regions. Symbolic /// regions do not need to be typed. class SymbolicRegion : public SubRegion { -protected: + friend class MemRegionManager; + const SymbolRef sym; -public: - SymbolicRegion(const SymbolRef s, const MemRegion* sreg) - : SubRegion(sreg, SymbolicRegionKind), sym(s) {} + SymbolicRegion(const SymbolRef s, const MemSpaceRegion *sreg) + : SubRegion(sreg, SymbolicRegionKind), sym(s) { + assert(s); + assert(s->getType()->isAnyPointerType() || + s->getType()->isReferenceType() || + s->getType()->isBlockPointerType()); + assert(isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion>(sreg)); + } +public: SymbolRef getSymbol() const { return sym; } @@ -736,11 +778,13 @@ public: /// StringRegion - Region associated with a StringLiteral. class StringRegion : public TypedValueRegion { friend class MemRegionManager; + const StringLiteral* Str; -protected: - StringRegion(const StringLiteral* str, const MemRegion* sreg) - : TypedValueRegion(sreg, StringRegionKind), Str(str) {} + StringRegion(const StringLiteral *str, const GlobalInternalSpaceRegion *sreg) + : TypedValueRegion(sreg, StringRegionKind), Str(str) { + assert(str); + } static void ProfileRegion(llvm::FoldingSetNodeID& ID, const StringLiteral* Str, @@ -772,12 +816,15 @@ public: /// The region associated with an ObjCStringLiteral. class ObjCStringRegion : public TypedValueRegion { friend class MemRegionManager; + const ObjCStringLiteral* Str; -protected: - - ObjCStringRegion(const ObjCStringLiteral* str, const MemRegion* sreg) - : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) {} - + + ObjCStringRegion(const ObjCStringLiteral *str, + const GlobalInternalSpaceRegion *sreg) + : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) { + assert(str); + } + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCStringLiteral* Str, const MemRegion* superRegion); @@ -807,12 +854,17 @@ public: /// Compound literals are essentially temporaries that are stack allocated /// or in the global constant pool. class CompoundLiteralRegion : public TypedValueRegion { -private: friend class MemRegionManager; + const CompoundLiteralExpr *CL; - CompoundLiteralRegion(const CompoundLiteralExpr *cl, const MemRegion* sReg) - : TypedValueRegion(sReg, CompoundLiteralRegionKind), CL(cl) {} + CompoundLiteralRegion(const CompoundLiteralExpr *cl, + const MemSpaceRegion *sReg) + : TypedValueRegion(sReg, CompoundLiteralRegionKind), CL(cl) { + assert(cl); + assert(isa<GlobalInternalSpaceRegion>(sReg) || + isa<StackLocalsSpaceRegion>(sReg)); + } static void ProfileRegion(llvm::FoldingSetNodeID& ID, const CompoundLiteralExpr *CL, @@ -839,8 +891,11 @@ class DeclRegion : public TypedValueRegion { protected: const Decl *D; - DeclRegion(const Decl *d, const MemRegion* sReg, Kind k) - : TypedValueRegion(sReg, k), D(d) {} + DeclRegion(const Decl *d, const MemRegion *sReg, Kind k) + : TypedValueRegion(sReg, k), D(d) { + assert(classof(this)); + assert(d); + } static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D, const MemRegion* superRegion, Kind k); @@ -859,17 +914,24 @@ class VarRegion : public DeclRegion { friend class MemRegionManager; // Constructors and private methods. - VarRegion(const VarDecl *vd, const MemRegion* sReg) - : DeclRegion(vd, sReg, VarRegionKind) {} + VarRegion(const VarDecl *vd, const MemRegion *sReg) + : DeclRegion(vd, sReg, VarRegionKind) { + // VarRegion appears in unknown space when it's a block variable as seen + // from a block using it, when this block is analyzed at top-level. + // Other block variables appear within block data regions, + // which, unlike everything else on this list, are not memory spaces. + assert(isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion>(sReg) || + isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg)); + } static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl *VD, const MemRegion *superRegion) { DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind); } +public: void Profile(llvm::FoldingSetNodeID& ID) const override; -public: const VarDecl *getDecl() const { return cast<VarDecl>(D); } const StackFrameContext *getStackFrame() const; @@ -895,17 +957,19 @@ public: /// referred to by 'this', but rather 'this' itself. class CXXThisRegion : public TypedValueRegion { friend class MemRegionManager; + CXXThisRegion(const PointerType *thisPointerTy, - const MemRegion *sReg) - : TypedValueRegion(sReg, CXXThisRegionKind), ThisPointerTy(thisPointerTy) {} + const StackArgumentsSpaceRegion *sReg) + : TypedValueRegion(sReg, CXXThisRegionKind), + ThisPointerTy(thisPointerTy) {} static void ProfileRegion(llvm::FoldingSetNodeID &ID, const PointerType *PT, const MemRegion *sReg); +public: void Profile(llvm::FoldingSetNodeID &ID) const override; -public: QualType getValueType() const override { return QualType(ThisPointerTy, 0); } @@ -923,9 +987,14 @@ private: class FieldRegion : public DeclRegion { friend class MemRegionManager; - FieldRegion(const FieldDecl *fd, const MemRegion* sReg) + FieldRegion(const FieldDecl *fd, const SubRegion* sReg) : DeclRegion(fd, sReg, FieldRegionKind) {} + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD, + const MemRegion* superRegion) { + DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind); + } + public: const FieldDecl *getDecl() const { return cast<FieldDecl>(D); } @@ -936,11 +1005,6 @@ public: DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; - static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD, - const MemRegion* superRegion) { - DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind); - } - static bool classof(const MemRegion* R) { return R->getKind() == FieldRegionKind; } @@ -954,10 +1018,9 @@ public: }; class ObjCIvarRegion : public DeclRegion { - friend class MemRegionManager; - ObjCIvarRegion(const ObjCIvarDecl *ivd, const MemRegion* sReg); + ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg); static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl *ivd, const MemRegion* superRegion); @@ -982,7 +1045,6 @@ public: class ElementRegion; class RegionRawOffset { -private: friend class ElementRegion; const MemRegion *Region; @@ -1007,9 +1069,9 @@ class ElementRegion : public TypedValueRegion { QualType ElementType; NonLoc Index; - ElementRegion(QualType elementType, NonLoc Idx, const MemRegion* sReg) - : TypedValueRegion(sReg, ElementRegionKind), - ElementType(elementType), Index(Idx) { + ElementRegion(QualType elementType, NonLoc Idx, const SubRegion *sReg) + : TypedValueRegion(sReg, ElementRegionKind), + ElementType(elementType), Index(Idx) { assert((!Idx.getAs<nonloc::ConcreteInt>() || Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) && "The index must be signed"); @@ -1047,12 +1109,16 @@ class CXXTempObjectRegion : public TypedValueRegion { Expr const *Ex; - CXXTempObjectRegion(Expr const *E, MemRegion const *sReg) - : TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) {} + CXXTempObjectRegion(Expr const *E, MemSpaceRegion const *sReg) + : TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) { + assert(E); + assert(isa<StackLocalsSpaceRegion>(sReg) || + isa<GlobalInternalSpaceRegion>(sReg)); + } static void ProfileRegion(llvm::FoldingSetNodeID &ID, Expr const *E, const MemRegion *sReg); - + public: const Expr *getExpr() const { return Ex; } @@ -1077,8 +1143,10 @@ class CXXBaseObjectRegion : public TypedValueRegion { llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Data; CXXBaseObjectRegion(const CXXRecordDecl *RD, bool IsVirtual, - const MemRegion *SReg) - : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) {} + const SubRegion *SReg) + : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) { + assert(RD); + } static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD, bool IsVirtual, const MemRegion *SReg); @@ -1204,16 +1272,16 @@ public: /// getVarRegion - Retrieve or create the memory region associated with /// a specified VarDecl and super region. - const VarRegion* getVarRegion(const VarDecl *D, const MemRegion *superR); - + const VarRegion *getVarRegion(const VarDecl *D, const MemRegion *superR); + /// getElementRegion - Retrieve the memory region associated with the /// associated element type, index, and super region. const ElementRegion *getElementRegion(QualType elementType, NonLoc Idx, - const MemRegion *superRegion, + const SubRegion *superRegion, ASTContext &Ctx); const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER, - const MemRegion *superRegion) { + const SubRegion *superRegion) { return getElementRegion(ER->getElementType(), ER->getIndex(), superRegion, ER->getContext()); } @@ -1223,10 +1291,10 @@ public: /// memory region (which typically represents the memory representing /// a structure or class). const FieldRegion *getFieldRegion(const FieldDecl *fd, - const MemRegion* superRegion); + const SubRegion* superRegion); const FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR, - const MemRegion *superRegion) { + const SubRegion *superRegion) { return getFieldRegion(FR->getDecl(), superRegion); } @@ -1235,7 +1303,7 @@ public: /// to the containing region (which typically represents the Objective-C /// object). const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl *ivd, - const MemRegion* superRegion); + const SubRegion* superRegion); const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex, LocationContext const *LC); @@ -1245,14 +1313,14 @@ public: /// /// The type of \p Super is assumed be a class deriving from \p BaseClass. const CXXBaseObjectRegion * - getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const MemRegion *Super, + getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const SubRegion *Super, bool IsVirtual); /// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different /// super region. const CXXBaseObjectRegion * getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg, - const MemRegion *superRegion) { + const SubRegion *superRegion) { return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion, baseReg->isVirtual()); } @@ -1276,17 +1344,22 @@ public: const CXXTempObjectRegion *getCXXStaticTempObjectRegion(const Expr *Ex); private: - template <typename RegionTy, typename A1> - RegionTy* getSubRegion(const A1 a1, const MemRegion* superRegion); - - template <typename RegionTy, typename A1, typename A2> - RegionTy* getSubRegion(const A1 a1, const A2 a2, - const MemRegion* superRegion); + template <typename RegionTy, typename SuperTy, + typename Arg1Ty> + RegionTy* getSubRegion(const Arg1Ty arg1, + const SuperTy* superRegion); + + template <typename RegionTy, typename SuperTy, + typename Arg1Ty, typename Arg2Ty> + RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, + const SuperTy* superRegion); + + template <typename RegionTy, typename SuperTy, + typename Arg1Ty, typename Arg2Ty, typename Arg3Ty> + RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, + const Arg3Ty arg3, + const SuperTy* superRegion); - template <typename RegionTy, typename A1, typename A2, typename A3> - RegionTy* getSubRegion(const A1 a1, const A2 a2, const A3 a3, - const MemRegion* superRegion); - template <typename REG> const REG* LazyAllocate(REG*& region); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 463b375fda30..2910ef4212cc 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -229,11 +229,12 @@ public: ProgramStateRef bindLoc(Loc location, SVal V, + const LocationContext *LCtx, bool notifyChanges = true) const; - ProgramStateRef bindLoc(SVal location, SVal V) const; + ProgramStateRef bindLoc(SVal location, SVal V, const LocationContext *LCtx) const; - ProgramStateRef bindDefault(SVal loc, SVal V) const; + ProgramStateRef bindDefault(SVal loc, SVal V, const LocationContext *LCtx) const; ProgramStateRef killBinding(Loc LV) const; @@ -681,9 +682,9 @@ ProgramState::assumeInclusiveRange(DefinedOrUnknownSVal Val, this, Val.castAs<NonLoc>(), From, To); } -inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const { +inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V, const LocationContext *LCtx) const { if (Optional<Loc> L = LV.getAs<Loc>()) - return bindLoc(*L, V); + return bindLoc(*L, V, LCtx); return this; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index a4c01fc45334..14aa3af37620 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -112,6 +112,11 @@ public: /// Evaluates a given SVal. If the SVal has only one possible (integer) value, /// that value is returned. Otherwise, returns NULL. virtual const llvm::APSInt *getKnownValue(ProgramStateRef state, SVal val) = 0; + + /// Simplify symbolic expressions within a given SVal. Return an SVal + /// that represents the same value, but is hopefully easier to work with + /// than the original SVal. + virtual SVal simplifySVal(ProgramStateRef State, SVal Val) = 0; /// Constructs a symbolic expression for two non-location values. SVal makeSymExprValNN(ProgramStateRef state, BinaryOperator::Opcode op, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index cc3c02a02c64..935f0018324a 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -41,6 +41,22 @@ class MemRegionManager; class ProgramStateManager; class SValBuilder; +namespace nonloc { +/// Sub-kinds for NonLoc values. +enum Kind { +#define NONLOC_SVAL(Id, Parent) Id ## Kind, +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" +}; +} + +namespace loc { +/// Sub-kinds for Loc values. +enum Kind { +#define LOC_SVAL(Id, Parent) Id ## Kind, +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" +}; +} + /// SVal - This represents a symbolic expression, which can be either /// an L-value or an R-value. /// @@ -75,10 +91,7 @@ public: template<typename T> T castAs() const { assert(T::isKind(*this)); - T t; - SVal& sv = t; - sv = *this; - return t; + return *static_cast<const T *>(this); } /// \brief Convert to the specified SVal type, returning None if this SVal is @@ -87,10 +100,7 @@ public: Optional<T> getAs() const { if (!T::isKind(*this)) return None; - T t; - SVal& sv = t; - sv = *this; - return t; + return *static_cast<const T *>(this); } /// BufferTy - A temporary buffer to hold a set of SVals. @@ -273,6 +283,11 @@ protected: public: void dumpToStream(raw_ostream &Out) const; + static inline bool isCompoundType(QualType T) { + return T->isArrayType() || T->isRecordType() || + T->isComplexType() || T->isVectorType(); + } + private: friend class SVal; static bool isKind(const SVal& V) { @@ -307,15 +322,11 @@ private: namespace nonloc { -enum Kind { -#define NONLOC_SVAL(Id, Parent) Id ## Kind, -#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" -}; - /// \brief Represents symbolic expression. class SymbolVal : public NonLoc { public: - SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {} + SymbolVal() = delete; + SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) { assert(sym); } SymbolRef getSymbol() const { return (const SymExpr*) Data; @@ -327,7 +338,6 @@ public: private: friend class SVal; - SymbolVal() {} static bool isKind(const SVal& V) { return V.getBaseKind() == NonLocKind && V.getSubKind() == SymbolValKind; @@ -373,7 +383,11 @@ class LocAsInteger : public NonLoc { explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data) : NonLoc(LocAsIntegerKind, &data) { - assert (data.first.getAs<Loc>()); + // We do not need to represent loc::ConcreteInt as LocAsInteger, + // as it'd collapse into a nonloc::ConcreteInt instead. + assert(data.first.getBaseKind() == LocKind && + (data.first.getSubKind() == loc::MemRegionValKind || + data.first.getSubKind() == loc::GotoLabelKind)); } public: @@ -513,14 +527,11 @@ private: namespace loc { -enum Kind { -#define LOC_SVAL(Id, Parent) Id ## Kind, -#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" -}; - class GotoLabel : public Loc { public: - explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {} + explicit GotoLabel(const LabelDecl *Label) : Loc(GotoLabelKind, Label) { + assert(Label); + } const LabelDecl *getLabel() const { return static_cast<const LabelDecl*>(Data); @@ -541,7 +552,9 @@ private: class MemRegionVal : public Loc { public: - explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) {} + explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) { + assert(r); + } /// \brief Get the underlining region. const MemRegion* getRegion() const { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h new file mode 100644 index 000000000000..2c9802bbc536 --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h @@ -0,0 +1,92 @@ +//== SimpleConstraintManager.h ----------------------------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Simplified constraint manager backend. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SIMPLECONSTRAINTMANAGER_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SIMPLECONSTRAINTMANAGER_H + +#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" + +namespace clang { + +namespace ento { + +class SimpleConstraintManager : public ConstraintManager { + SubEngine *SU; + SValBuilder &SVB; + +public: + SimpleConstraintManager(SubEngine *subengine, SValBuilder &SB) + : SU(subengine), SVB(SB) {} + + ~SimpleConstraintManager() override; + + //===------------------------------------------------------------------===// + // Implementation for interface from ConstraintManager. + //===------------------------------------------------------------------===// + + /// Ensures that the DefinedSVal conditional is expressed as a NonLoc by + /// creating boolean casts to handle Loc's. + ProgramStateRef assume(ProgramStateRef State, DefinedSVal Cond, + bool Assumption) override; + + ProgramStateRef assumeInclusiveRange(ProgramStateRef State, NonLoc Value, + const llvm::APSInt &From, + const llvm::APSInt &To, + bool InRange) override; + +protected: + //===------------------------------------------------------------------===// + // Interface that subclasses must implement. + //===------------------------------------------------------------------===// + + /// Given a symbolic expression that can be reasoned about, assume that it is + /// true/false and generate the new program state. + virtual ProgramStateRef assumeSym(ProgramStateRef State, SymbolRef Sym, + bool Assumption) = 0; + + /// Given a symbolic expression within the range [From, To], assume that it is + /// true/false and generate the new program state. + /// This function is used to handle case ranges produced by a language + /// extension for switch case statements. + virtual ProgramStateRef assumeSymInclusiveRange(ProgramStateRef State, + SymbolRef Sym, + const llvm::APSInt &From, + const llvm::APSInt &To, + bool InRange) = 0; + + /// Given a symbolic expression that cannot be reasoned about, assume that + /// it is zero/nonzero and add it directly to the solver state. + virtual ProgramStateRef assumeSymUnsupported(ProgramStateRef State, + SymbolRef Sym, + bool Assumption) = 0; + + //===------------------------------------------------------------------===// + // Internal implementation. + //===------------------------------------------------------------------===// + + BasicValueFactory &getBasicVals() const { return SVB.getBasicValueFactory(); } + SymbolManager &getSymbolManager() const { return SVB.getSymbolManager(); } + +private: + ProgramStateRef assume(ProgramStateRef State, NonLoc Cond, bool Assumption); + + ProgramStateRef assumeAux(ProgramStateRef State, NonLoc Cond, + bool Assumption); +}; + +} // end GR namespace + +} // end clang namespace + +#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index fa7d3f72abf1..7619f22f4013 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -59,6 +59,30 @@ public: /// \return The value bound to the location \c loc. virtual SVal getBinding(Store store, Loc loc, QualType T = QualType()) = 0; + /// Return the default value bound to a region in a given store. The default + /// binding is the value of sub-regions that were not initialized separately + /// from their base region. For example, if the structure is zero-initialized + /// upon construction, this method retrieves the concrete zero value, even if + /// some or all fields were later overwritten manually. Default binding may be + /// an unknown, undefined, concrete, or symbolic value. + /// \param[in] store The store in which to make the lookup. + /// \param[in] R The region to find the default binding for. + /// \return The default value bound to the region in the store, if a default + /// binding exists. + virtual Optional<SVal> getDefaultBinding(Store store, const MemRegion *R) = 0; + + /// Return the default value bound to a LazyCompoundVal. The default binding + /// is used to represent the value of any fields or elements within the + /// structure represented by the LazyCompoundVal which were not initialized + /// explicitly separately from the whole structure. Default binding may be an + /// unknown, undefined, concrete, or symbolic value. + /// \param[in] lcv The lazy compound value. + /// \return The default value bound to the LazyCompoundVal \c lcv, if a + /// default binding exists. + Optional<SVal> getDefaultBinding(nonloc::LazyCompoundVal lcv) { + return getDefaultBinding(lcv.getStore(), lcv.getRegion()); + } + /// Return a state with the specified value bound to the given location. /// \param[in] store The analysis state. /// \param[in] loc The symbolic memory location. @@ -136,7 +160,7 @@ public: /// valid only if Failed flag is set to false. SVal attemptDownCast(SVal Base, QualType DerivedPtrType, bool &Failed); - const ElementRegion *GetElementZeroRegion(const MemRegion *R, QualType T); + const ElementRegion *GetElementZeroRegion(const SubRegion *R, QualType T); /// castRegion - Used by ExprEngine::VisitCast to handle casts from /// a MemRegion* to a specific location type. 'R' is the region being @@ -235,8 +259,9 @@ public: virtual void iterBindings(Store store, BindingsHandler& f) = 0; protected: - const MemRegion *MakeElementRegion(const MemRegion *baseRegion, - QualType pointeeTy, uint64_t index = 0); + const ElementRegion *MakeElementRegion(const SubRegion *baseRegion, + QualType pointeeTy, + uint64_t index = 0); /// CastRetrievedVal - Used by subclasses of StoreManager to implement /// implicit casts that arise from loads from regions that are reinterpreted diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h index 581ef206cff3..8ccd34751bbe 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -83,7 +83,7 @@ public: const CFGBlock *DstF) = 0; /// Called by CoreEngine. Used to processing branching behavior - /// at static initalizers. + /// at static initializers. virtual void processStaticInitializer(const DeclStmt *DS, NodeBuilderContext& BuilderCtx, ExplodedNode *Pred, @@ -131,17 +131,19 @@ public: const InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, + const LocationContext *LCtx, const CallEvent *Call) = 0; inline ProgramStateRef processRegionChange(ProgramStateRef state, - const MemRegion* MR) { - return processRegionChanges(state, nullptr, MR, MR, nullptr); + const MemRegion* MR, + const LocationContext *LCtx) { + return processRegionChanges(state, nullptr, MR, MR, LCtx, nullptr); } virtual ProgramStateRef - processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val) = 0; + processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val, const LocationContext *LCtx) = 0; virtual ProgramStateRef notifyCheckersOfPointerEscape(ProgramStateRef State, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h index 18bc60754b81..f72033955ec3 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h @@ -42,6 +42,12 @@ private: protected: SymExpr(Kind k) : K(k) {} + static bool isValidTypeForSymbol(QualType T) { + // FIXME: Depending on whether we choose to deprecate structural symbols, + // this may become much stricter. + return !T.isNull() && !T->isVoidType(); + } + public: virtual ~SymExpr() {} @@ -103,7 +109,9 @@ class SymbolData : public SymExpr { const SymbolID Sym; protected: - SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {} + SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) { + assert(classof(this)); + } public: ~SymbolData() override {} diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index f00dce568e3a..e9701142cd9e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -44,7 +44,10 @@ class SymbolRegionValue : public SymbolData { public: SymbolRegionValue(SymbolID sym, const TypedValueRegion *r) - : SymbolData(SymbolRegionValueKind, sym), R(r) {} + : SymbolData(SymbolRegionValueKind, sym), R(r) { + assert(r); + assert(isValidTypeForSymbol(r->getValueType())); + } const TypedValueRegion* getRegion() const { return R; } @@ -81,7 +84,15 @@ public: SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx, QualType t, unsigned count, const void *symbolTag) : SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count), - LCtx(lctx), SymbolTag(symbolTag) {} + LCtx(lctx), SymbolTag(symbolTag) { + // FIXME: 's' might be a nullptr if we're conducting invalidation + // that was caused by a destructor call on a temporary object, + // which has no statement associated with it. + // Due to this, we might be creating the same invalidation symbol for + // two different invalidation passes (for two different temporaries). + assert(lctx); + assert(isValidTypeForSymbol(t)); + } const Stmt *getStmt() const { return S; } unsigned getCount() const { return Count; } @@ -120,7 +131,11 @@ class SymbolDerived : public SymbolData { public: SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r) - : SymbolData(SymbolDerivedKind, sym), parentSymbol(parent), R(r) {} + : SymbolData(SymbolDerivedKind, sym), parentSymbol(parent), R(r) { + assert(parent); + assert(r); + assert(isValidTypeForSymbol(r->getValueType())); + } SymbolRef getParentSymbol() const { return parentSymbol; } const TypedValueRegion *getRegion() const { return R; } @@ -155,7 +170,9 @@ class SymbolExtent : public SymbolData { public: SymbolExtent(SymbolID sym, const SubRegion *r) - : SymbolData(SymbolExtentKind, sym), R(r) {} + : SymbolData(SymbolExtentKind, sym), R(r) { + assert(r); + } const SubRegion *getRegion() const { return R; } @@ -193,7 +210,13 @@ public: SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t, const LocationContext *LCtx, unsigned count, const void *tag) : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), LCtx(LCtx), - Count(count), Tag(tag) {} + Count(count), Tag(tag) { + assert(r); + assert(s); + assert(isValidTypeForSymbol(t)); + assert(LCtx); + assert(tag); + } const MemRegion *getRegion() const { return R; } const Stmt *getStmt() const { return S; } @@ -236,8 +259,13 @@ class SymbolCast : public SymExpr { QualType ToTy; public: - SymbolCast(const SymExpr *In, QualType From, QualType To) : - SymExpr(SymbolCastKind), Operand(In), FromTy(From), ToTy(To) { } + SymbolCast(const SymExpr *In, QualType From, QualType To) + : SymExpr(SymbolCastKind), Operand(In), FromTy(From), ToTy(To) { + assert(In); + assert(isValidTypeForSymbol(From)); + // FIXME: GenericTaintChecker creates symbols of void type. + // Otherwise, 'To' should also be a valid type. + } QualType getType() const override { return ToTy; } @@ -270,7 +298,10 @@ class BinarySymExpr : public SymExpr { protected: BinarySymExpr(Kind k, BinaryOperator::Opcode op, QualType t) - : SymExpr(k), Op(op), T(t) {} + : SymExpr(k), Op(op), T(t) { + assert(classof(this)); + assert(isValidTypeForSymbol(t)); + } public: // FIXME: We probably need to make this out-of-line to avoid redundant @@ -293,8 +324,10 @@ class SymIntExpr : public BinarySymExpr { public: SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, - const llvm::APSInt& rhs, QualType t) - : BinarySymExpr(SymIntExprKind, op, t), LHS(lhs), RHS(rhs) {} + const llvm::APSInt &rhs, QualType t) + : BinarySymExpr(SymIntExprKind, op, t), LHS(lhs), RHS(rhs) { + assert(lhs); + } void dumpToStream(raw_ostream &os) const override; @@ -327,9 +360,11 @@ class IntSymExpr : public BinarySymExpr { const SymExpr *RHS; public: - IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op, + IntSymExpr(const llvm::APSInt &lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) - : BinarySymExpr(IntSymExprKind, op, t), LHS(lhs), RHS(rhs) {} + : BinarySymExpr(IntSymExprKind, op, t), LHS(lhs), RHS(rhs) { + assert(rhs); + } void dumpToStream(raw_ostream &os) const override; @@ -364,7 +399,10 @@ class SymSymExpr : public BinarySymExpr { public: SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) - : BinarySymExpr(SymSymExprKind, op, t), LHS(lhs), RHS(rhs) {} + : BinarySymExpr(SymSymExprKind, op, t), LHS(lhs), RHS(rhs) { + assert(lhs); + assert(rhs); + } const SymExpr *getLHS() const { return LHS; } const SymExpr *getRHS() const { return RHS; } diff --git a/include/clang/Tooling/Refactoring/AtomicChange.h b/include/clang/Tooling/Refactoring/AtomicChange.h new file mode 100644 index 000000000000..9cccd78677b1 --- /dev/null +++ b/include/clang/Tooling/Refactoring/AtomicChange.h @@ -0,0 +1,135 @@ +//===--- AtomicChange.h - AtomicChange class --------------------*- 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 AtomicChange which is used to create a set of source +// changes, e.g. replacements and header insertions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTOR_ATOMICCHANGE_H +#define LLVM_CLANG_TOOLING_REFACTOR_ATOMICCHANGE_H + +#include "clang/Basic/SourceManager.h" +#include "clang/Tooling/Core/Replacement.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" + +namespace clang { +namespace tooling { + +/// \brief An atomic change is used to create and group a set of source edits, +/// e.g. replacements or header insertions. Edits in an AtomicChange should be +/// related, e.g. replacements for the same type reference and the corresponding +/// header insertion/deletion. +/// +/// An AtomicChange is uniquely identified by a key and will either be fully +/// applied or not applied at all. +/// +/// Calling setError on an AtomicChange stores the error message and marks it as +/// bad, i.e. none of its source edits will be applied. +class AtomicChange { +public: + /// \brief Creates an atomic change around \p KeyPosition with the key being a + /// concatenation of the file name and the offset of \p KeyPosition. + /// \p KeyPosition should be the location of the key syntactical element that + /// is being changed, e.g. the call to a refactored method. + AtomicChange(const SourceManager &SM, SourceLocation KeyPosition); + + /// \brief Creates an atomic change for \p FilePath with a customized key. + AtomicChange(llvm::StringRef FilePath, llvm::StringRef Key) + : Key(Key), FilePath(FilePath) {} + + /// \brief Returns the atomic change as a YAML string. + std::string toYAMLString(); + + /// \brief Converts a YAML-encoded automic change to AtomicChange. + static AtomicChange convertFromYAML(llvm::StringRef YAMLContent); + + /// \brief Returns the key of this change, which is a concatenation of the + /// file name and offset of the key position. + const std::string &getKey() const { return Key; } + + /// \brief Returns the path of the file containing this atomic change. + const std::string &getFilePath() const { return FilePath; } + + /// \brief If this change could not be created successfully, e.g. because of + /// conflicts among replacements, use this to set an error description. + /// Thereby, places that cannot be fixed automatically can be gathered when + /// applying changes. + void setError(llvm::StringRef Error) { this->Error = Error; } + + /// \brief Returns whether an error has been set on this list. + bool hasError() const { return !Error.empty(); } + + /// \brief Returns the error message or an empty string if it does not exist. + const std::string &getError() const { return Error; } + + /// \brief Adds a replacement that replaces the given Range with + /// ReplacementText. + /// \returns An llvm::Error carrying ReplacementError on error. + llvm::Error replace(const SourceManager &SM, const CharSourceRange &Range, + llvm::StringRef ReplacementText); + + /// \brief Adds a replacement that replaces range [Loc, Loc+Length) with + /// \p Text. + /// \returns An llvm::Error carrying ReplacementError on error. + llvm::Error replace(const SourceManager &SM, SourceLocation Loc, + unsigned Length, llvm::StringRef Text); + + /// \brief Adds a replacement that inserts \p Text at \p Loc. If this + /// insertion conflicts with an existing insertion (at the same position), + /// this will be inserted before/after the existing insertion depending on + /// \p InsertAfter. Users should use `replace` with `Length=0` instead if they + /// do not want conflict resolving by default. If the conflicting replacement + /// is not an insertion, an error is returned. + /// + /// \returns An llvm::Error carrying ReplacementError on error. + llvm::Error insert(const SourceManager &SM, SourceLocation Loc, + llvm::StringRef Text, bool InsertAfter = true); + + /// \brief Adds a header into the file that contains the key position. + /// Header can be in angle brackets or double quotation marks. By default + /// (header is not quoted), header will be surrounded with double quotes. + void addHeader(llvm::StringRef Header); + + /// \brief Removes a header from the file that contains the key position. + void removeHeader(llvm::StringRef Header); + + /// \brief Returns a const reference to existing replacements. + const Replacements &getReplacements() const { return Replaces; } + + llvm::ArrayRef<std::string> getInsertedHeaders() const { + return InsertedHeaders; + } + + llvm::ArrayRef<std::string> getRemovedHeaders() const { + return RemovedHeaders; + } + +private: + AtomicChange() {} + + AtomicChange(std::string Key, std::string FilePath, std::string Error, + std::vector<std::string> InsertedHeaders, + std::vector<std::string> RemovedHeaders, + clang::tooling::Replacements Replaces); + + // This uniquely identifies an AtomicChange. + std::string Key; + std::string FilePath; + std::string Error; + std::vector<std::string> InsertedHeaders; + std::vector<std::string> RemovedHeaders; + tooling::Replacements Replaces; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_ATOMICCHANGE_H |