diff options
Diffstat (limited to 'include/clang/AST')
26 files changed, 1333 insertions, 396 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()); } |
