diff options
Diffstat (limited to 'include')
74 files changed, 1422 insertions, 386 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 3276afc4b960..a2241802078e 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -2225,7 +2225,12 @@ enum CXCursorKind { */ CXCursor_OMPTeamsDirective = 253, - CXCursor_LastStmt = CXCursor_OMPTeamsDirective, + /** \brief OpenMP taskwait directive. + */ + CXCursor_OMPTaskgroupDirective = 254, + + + CXCursor_LastStmt = CXCursor_OMPTaskgroupDirective, /** * \brief Cursor that represents the translation unit itself. @@ -5628,7 +5633,7 @@ typedef enum { * reused after indexing is finished. Set to \c NULL if you do not require it. * * \returns 0 on success or if there were errors from which the compiler could - * recover. If there is a failure from which the there is no recovery, returns + * recover. If there is a failure from which there is no recovery, returns * a non-zero \c CXErrorCode. * * The rest of the parameters are the same as #clang_parseTranslationUnit. @@ -5659,7 +5664,7 @@ CINDEX_LINKAGE int clang_indexSourceFile(CXIndexAction, * * The parameters are the same as #clang_indexSourceFile. * - * \returns If there is a failure from which the there is no recovery, returns + * \returns If there is a failure from which there is no recovery, returns * non-zero, otherwise returns 0. */ CINDEX_LINKAGE int clang_indexTranslationUnit(CXIndexAction, diff --git a/include/clang/ARCMigrate/ARCMT.h b/include/clang/ARCMigrate/ARCMT.h index ad4f23c604b3..74081867eebc 100644 --- a/include/clang/ARCMigrate/ARCMT.h +++ b/include/clang/ARCMigrate/ARCMT.h @@ -17,6 +17,7 @@ namespace clang { class ASTContext; class DiagnosticConsumer; + class PCHContainerOperations; namespace arcmt { class MigrationPass; @@ -37,19 +38,22 @@ namespace arcmt { /// the pre-migration ARC diagnostics. /// /// \returns false if no error is produced, true otherwise. -bool checkForManualIssues(CompilerInvocation &CI, - const FrontendInputFile &Input, - DiagnosticConsumer *DiagClient, - bool emitPremigrationARCErrors = false, - StringRef plistOut = StringRef()); +bool +checkForManualIssues(CompilerInvocation &CI, const FrontendInputFile &Input, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + DiagnosticConsumer *DiagClient, + bool emitPremigrationARCErrors = false, + StringRef plistOut = StringRef()); /// \brief Works similar to checkForManualIssues but instead of checking, it /// applies automatic modifications to source files to conform to ARC. /// /// \returns false if no error is produced, true otherwise. -bool applyTransformations(CompilerInvocation &origCI, - const FrontendInputFile &Input, - DiagnosticConsumer *DiagClient); +bool +applyTransformations(CompilerInvocation &origCI, + const FrontendInputFile &Input, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + DiagnosticConsumer *DiagClient); /// \brief Applies automatic modifications and produces temporary files /// and metadata into the \p outputDir path. @@ -62,12 +66,11 @@ bool applyTransformations(CompilerInvocation &origCI, /// the pre-migration ARC diagnostics. /// /// \returns false if no error is produced, true otherwise. -bool migrateWithTemporaryFiles(CompilerInvocation &origCI, - const FrontendInputFile &Input, - DiagnosticConsumer *DiagClient, - StringRef outputDir, - bool emitPremigrationARCErrors, - StringRef plistOut); +bool migrateWithTemporaryFiles( + CompilerInvocation &origCI, const FrontendInputFile &Input, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + DiagnosticConsumer *DiagClient, StringRef outputDir, + bool emitPremigrationARCErrors, StringRef plistOut); /// \brief Get the set of file remappings from the \p outputDir path that /// migrateWithTemporaryFiles produced. @@ -93,13 +96,16 @@ std::vector<TransformFn> getAllTransformations(LangOptions::GCMode OrigGCMode, class MigrationProcess { CompilerInvocation OrigCI; + std::shared_ptr<PCHContainerOperations> PCHContainerOps; DiagnosticConsumer *DiagClient; FileRemapper Remapper; public: bool HadARCErrors; - MigrationProcess(const CompilerInvocation &CI, DiagnosticConsumer *diagClient, + MigrationProcess(const CompilerInvocation &CI, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + DiagnosticConsumer *diagClient, StringRef outputDir = StringRef()); class RewriteListener { diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 049221ad9144..da288c4fe5ed 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -1854,6 +1854,36 @@ public: getCanonicalType(T2).getTypePtr(); } + bool hasSameNullabilityTypeQualifier(QualType SubT, QualType SuperT, + bool IsParam) const { + auto SubTnullability = SubT->getNullability(*this); + auto SuperTnullability = SuperT->getNullability(*this); + if (SubTnullability.hasValue() == SuperTnullability.hasValue()) { + // Neither has nullability; return true + if (!SubTnullability) + return true; + // Both have nullability qualifier. + if (*SubTnullability == *SuperTnullability || + *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" + return (*SuperTnullability == NullabilityKind::NonNull && + *SubTnullability == NullabilityKind::Nullable); + } + else { + // For the return type, it's okay for the superclass method to specify + // "nullable" and the subclass method specify "nonnull" + return (*SuperTnullability == NullabilityKind::Nullable && + *SubTnullability == NullabilityKind::NonNull); + } + } + return true; + } + bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, const ObjCMethodDecl *MethodImp); diff --git a/include/clang/AST/CommentParser.h b/include/clang/AST/CommentParser.h index 42bf4c989a23..fa8862899c14 100644 --- a/include/clang/AST/CommentParser.h +++ b/include/clang/AST/CommentParser.h @@ -75,11 +75,7 @@ class Parser { return; MoreLATokens.push_back(Tok); - for (const Token *I = &Toks.back(), - *B = &Toks.front(); - I != B; --I) { - MoreLATokens.push_back(*I); - } + MoreLATokens.append(Toks.rbegin(), std::prev(Toks.rend())); Tok = Toks[0]; } diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h index 971841e8fb5d..ef8817659338 100644 --- a/include/clang/AST/DataRecursiveASTVisitor.h +++ b/include/clang/AST/DataRecursiveASTVisitor.h @@ -531,10 +531,7 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) { } } - for (SmallVectorImpl<Stmt *>::reverse_iterator RI = StmtsToEnqueue.rbegin(), - RE = StmtsToEnqueue.rend(); - RI != RE; ++RI) - Queue.push_back(*RI); + Queue.append(StmtsToEnqueue.rbegin(), StmtsToEnqueue.rend()); } return true; @@ -2204,9 +2201,11 @@ DEF_TRAVERSE_STMT(CXXThisExpr, {}) DEF_TRAVERSE_STMT(CXXThrowExpr, {}) DEF_TRAVERSE_STMT(UserDefinedLiteral, {}) DEF_TRAVERSE_STMT(DesignatedInitExpr, {}) +DEF_TRAVERSE_STMT(DesignatedInitUpdateExpr, {}) DEF_TRAVERSE_STMT(ExtVectorElementExpr, {}) DEF_TRAVERSE_STMT(GNUNullExpr, {}) DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {}) +DEF_TRAVERSE_STMT(NoInitExpr, {}) DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {}) DEF_TRAVERSE_STMT(ObjCEncodeExpr, { if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo()) @@ -2356,6 +2355,9 @@ DEF_TRAVERSE_STMT(OMPBarrierDirective, DEF_TRAVERSE_STMT(OMPTaskwaitDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTaskgroupDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPFlushDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index f176e5479e1e..6b6ac3f7d5a5 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -178,7 +178,12 @@ public: OBJC_TQ_Out = 0x4, OBJC_TQ_Bycopy = 0x8, OBJC_TQ_Byref = 0x10, - OBJC_TQ_Oneway = 0x20 + OBJC_TQ_Oneway = 0x20, + + /// The nullability qualifier is set when the nullability of the + /// result or parameter was expressed via a context-sensitive + /// keyword. + OBJC_TQ_CSNullability = 0x40 }; protected: diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 537ad4640c24..08451c051b57 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1440,7 +1440,7 @@ public: /// /// \returns true if this class is derived from \p Base, false otherwise. /// - /// \todo add a separate paramaeter to configure IsDerivedFrom, rather than + /// \todo add a separate parameter to configure IsDerivedFrom, rather than /// tangling input and output in \p Paths bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths) const; diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 4a5b4f3d0756..c3fb57770245 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -141,7 +141,7 @@ private: // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum /// in, inout, etc. - unsigned objcDeclQualifier : 6; + unsigned objcDeclQualifier : 7; /// \brief Indicates whether this method has a related result type. unsigned RelatedResultType : 1; @@ -2203,13 +2203,17 @@ public: OBJC_PR_atomic = 0x100, OBJC_PR_weak = 0x200, OBJC_PR_strong = 0x400, - OBJC_PR_unsafe_unretained = 0x800 + OBJC_PR_unsafe_unretained = 0x800, + /// Indicates that the nullability of the type was spelled with a + /// property attribute rather than a type qualifier. + OBJC_PR_nullability = 0x1000, + OBJC_PR_null_resettable = 0x2000 // Adding a property should change NumPropertyAttrsBits }; enum { /// \brief Number of bits fitting all the property attributes. - NumPropertyAttrsBits = 12 + NumPropertyAttrsBits = 14 }; enum SetterKind { Assign, Retain, Copy, Weak }; @@ -2217,7 +2221,8 @@ public: private: SourceLocation AtLoc; // location of \@property SourceLocation LParenLoc; // location of '(' starting attribute list or null. - TypeSourceInfo *DeclType; + QualType DeclType; + TypeSourceInfo *DeclTypeSourceInfo; unsigned PropertyAttributes : NumPropertyAttrsBits; unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits; // \@required/\@optional @@ -2232,12 +2237,13 @@ private: ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation AtLocation, SourceLocation LParenLocation, - TypeSourceInfo *T) + QualType T, TypeSourceInfo *TSI, + PropertyControl propControl) : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation), - LParenLoc(LParenLocation), DeclType(T), + LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI), PropertyAttributes(OBJC_PR_noattr), PropertyAttributesAsWritten(OBJC_PR_noattr), - PropertyImplementation(None), + PropertyImplementation(propControl), GetterName(Selector()), SetterName(Selector()), GetterMethodDecl(nullptr), SetterMethodDecl(nullptr), @@ -2248,7 +2254,8 @@ public: SourceLocation L, IdentifierInfo *Id, SourceLocation AtLocation, SourceLocation LParenLocation, - TypeSourceInfo *T, + QualType T, + TypeSourceInfo *TSI, PropertyControl propControl = None); static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -2259,9 +2266,14 @@ public: SourceLocation getLParenLoc() const { return LParenLoc; } void setLParenLoc(SourceLocation L) { LParenLoc = L; } - TypeSourceInfo *getTypeSourceInfo() const { return DeclType; } - QualType getType() const { return DeclType->getType(); } - void setType(TypeSourceInfo *T) { DeclType = T; } + TypeSourceInfo *getTypeSourceInfo() const { return DeclTypeSourceInfo; } + + QualType getType() const { return DeclType; } + + void setType(QualType T, TypeSourceInfo *TSI) { + DeclType = T; + DeclTypeSourceInfo = TSI; + } PropertyAttributeKind getPropertyAttributes() const { return PropertyAttributeKind(PropertyAttributes); diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 90cfb2049173..0fc9b4947d49 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -217,6 +217,88 @@ public: } }; +void *allocateDefaultArgStorageChain(const ASTContext &C); + +/// Storage for a default argument. This is conceptually either empty, or an +/// argument value, or a pointer to a previous declaration that had a default +/// argument. +/// +/// However, this is complicated by modules: while we require all the default +/// arguments for a template to be equivalent, there may be more than one, and +/// we need to track all the originating parameters to determine if the default +/// argument is visible. +template<typename ParmDecl, typename ArgType> +class DefaultArgStorage { + /// Storage for both the value *and* another parameter from which we inherit + /// the default argument. This is used when multiple default arguments for a + /// parameter are merged together from different modules. + struct Chain { + ParmDecl *PrevDeclWithDefaultArg; + ArgType Value; + }; + static_assert(sizeof(Chain) == sizeof(void *) * 2, + "non-pointer argument type?"); + + llvm::PointerUnion3<ArgType, ParmDecl*, Chain*> ValueOrInherited; + + static ParmDecl *getParmOwningDefaultArg(ParmDecl *Parm) { + const DefaultArgStorage &Storage = Parm->getDefaultArgStorage(); + if (auto *Prev = Storage.ValueOrInherited.template dyn_cast<ParmDecl*>()) + Parm = Prev; + assert(!Parm->getDefaultArgStorage() + .ValueOrInherited.template is<ParmDecl *>() && + "should only be one level of indirection"); + return Parm; + } + +public: + DefaultArgStorage() : ValueOrInherited(ArgType()) {} + + /// Determine whether there is a default argument for this parameter. + bool isSet() const { return !ValueOrInherited.isNull(); } + /// Determine whether the default argument for this parameter was inherited + /// from a previous declaration of the same entity. + bool isInherited() const { return ValueOrInherited.template is<ParmDecl*>(); } + /// Get the default argument's value. This does not consider whether the + /// default argument is visible. + ArgType get() const { + const DefaultArgStorage *Storage = this; + if (auto *Prev = ValueOrInherited.template dyn_cast<ParmDecl*>()) + Storage = &Prev->getDefaultArgStorage(); + if (auto *C = Storage->ValueOrInherited.template dyn_cast<Chain*>()) + return C->Value; + return Storage->ValueOrInherited.template get<ArgType>(); + } + /// Get the parameter from which we inherit the default argument, if any. + /// This is the parameter on which the default argument was actually written. + const ParmDecl *getInheritedFrom() const { + if (auto *D = ValueOrInherited.template dyn_cast<ParmDecl*>()) + return D; + if (auto *C = ValueOrInherited.template dyn_cast<Chain*>()) + return C->PrevDeclWithDefaultArg; + return nullptr; + } + /// Set the default argument. + void set(ArgType Arg) { + assert(!isSet() && "default argument already set"); + ValueOrInherited = Arg; + } + /// Set that the default argument was inherited from another parameter. + void setInherited(const ASTContext &C, ParmDecl *InheritedFrom) { + assert(!isInherited() && "default argument already inherited"); + InheritedFrom = getParmOwningDefaultArg(InheritedFrom); + if (!isSet()) + ValueOrInherited = InheritedFrom; + else + ValueOrInherited = new (allocateDefaultArgStorageChain(C)) + Chain{InheritedFrom, ValueOrInherited.template get<ArgType>()}; + } + /// Remove the default argument, even if it was inherited. + void clear() { + ValueOrInherited = ArgType(); + } +}; + //===----------------------------------------------------------------------===// // Kinds of Templates //===----------------------------------------------------------------------===// @@ -942,18 +1024,16 @@ class TemplateTypeParmDecl : public TypeDecl { /// If false, it was declared with the 'class' keyword. bool Typename : 1; - /// \brief Whether this template type parameter inherited its - /// default argument. - bool InheritedDefault : 1; - /// \brief The default template argument, if any. - TypeSourceInfo *DefaultArgument; + typedef DefaultArgStorage<TemplateTypeParmDecl, TypeSourceInfo *> + DefArgStorage; + DefArgStorage DefaultArgument; TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc, SourceLocation IdLoc, IdentifierInfo *Id, bool Typename) : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename), - InheritedDefault(false), DefaultArgument() { } + DefaultArgument() { } /// Sema creates these on the stack during auto type deduction. friend class Sema; @@ -974,35 +1054,45 @@ public: /// If not, it was declared with the 'class' keyword. bool wasDeclaredWithTypename() const { return Typename; } + const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } + /// \brief Determine whether this template parameter has a default /// argument. - bool hasDefaultArgument() const { return DefaultArgument != nullptr; } + bool hasDefaultArgument() const { return DefaultArgument.isSet(); } /// \brief Retrieve the default argument, if any. - QualType getDefaultArgument() const { return DefaultArgument->getType(); } + QualType getDefaultArgument() const { + return DefaultArgument.get()->getType(); + } /// \brief Retrieves the default argument's source information, if any. - TypeSourceInfo *getDefaultArgumentInfo() const { return DefaultArgument; } + TypeSourceInfo *getDefaultArgumentInfo() const { + return DefaultArgument.get(); + } /// \brief Retrieves the location of the default argument declaration. SourceLocation getDefaultArgumentLoc() const; /// \brief Determines whether the default argument was inherited /// from a previous declaration of this template. - bool defaultArgumentWasInherited() const { return InheritedDefault; } + bool defaultArgumentWasInherited() const { + return DefaultArgument.isInherited(); + } - /// \brief Set the default argument for this template parameter, and - /// whether that default argument was inherited from another - /// declaration. - void setDefaultArgument(TypeSourceInfo *DefArg, bool Inherited) { - DefaultArgument = DefArg; - InheritedDefault = Inherited; + /// \brief Set the default argument for this template parameter. + void setDefaultArgument(TypeSourceInfo *DefArg) { + DefaultArgument.set(DefArg); + } + /// \brief Set that this default argument was inherited from another + /// parameter. + void setInheritedDefaultArgument(const ASTContext &C, + TemplateTypeParmDecl *Prev) { + DefaultArgument.setInherited(C, Prev); } /// \brief Removes the default argument of this template parameter. void removeDefaultArgument() { - DefaultArgument = nullptr; - InheritedDefault = false; + DefaultArgument.clear(); } /// \brief Set whether this template type parameter was declared with @@ -1034,7 +1124,8 @@ class NonTypeTemplateParmDecl : public DeclaratorDecl, protected TemplateParmPosition { /// \brief The default template argument, if any, and whether or not /// it was inherited. - llvm::PointerIntPair<Expr*, 1, bool> DefaultArgumentAndInherited; + typedef DefaultArgStorage<NonTypeTemplateParmDecl, Expr*> DefArgStorage; + DefArgStorage DefaultArgument; // FIXME: Collapse this into TemplateParamPosition; or, just move depth/index // down here to save memory. @@ -1055,9 +1146,8 @@ class NonTypeTemplateParmDecl IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo) : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc), - TemplateParmPosition(D, P), DefaultArgumentAndInherited(nullptr, false), - ParameterPack(ParameterPack), ExpandedParameterPack(false), - NumExpandedTypes(0) + TemplateParmPosition(D, P), ParameterPack(ParameterPack), + ExpandedParameterPack(false), NumExpandedTypes(0) { } NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc, @@ -1097,16 +1187,14 @@ public: SourceRange getSourceRange() const override LLVM_READONLY; + const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } + /// \brief Determine whether this template parameter has a default /// argument. - bool hasDefaultArgument() const { - return DefaultArgumentAndInherited.getPointer() != nullptr; - } + bool hasDefaultArgument() const { return DefaultArgument.isSet(); } /// \brief Retrieve the default argument, if any. - Expr *getDefaultArgument() const { - return DefaultArgumentAndInherited.getPointer(); - } + Expr *getDefaultArgument() const { return DefaultArgument.get(); } /// \brief Retrieve the location of the default argument, if any. SourceLocation getDefaultArgumentLoc() const; @@ -1114,22 +1202,20 @@ public: /// \brief Determines whether the default argument was inherited /// from a previous declaration of this template. bool defaultArgumentWasInherited() const { - return DefaultArgumentAndInherited.getInt(); + return DefaultArgument.isInherited(); } /// \brief Set the default argument for this template parameter, and /// whether that default argument was inherited from another /// declaration. - void setDefaultArgument(Expr *DefArg, bool Inherited) { - DefaultArgumentAndInherited.setPointer(DefArg); - DefaultArgumentAndInherited.setInt(Inherited); + void setDefaultArgument(Expr *DefArg) { DefaultArgument.set(DefArg); } + void setInheritedDefaultArgument(const ASTContext &C, + NonTypeTemplateParmDecl *Parm) { + DefaultArgument.setInherited(C, Parm); } /// \brief Removes the default argument of this template parameter. - void removeDefaultArgument() { - DefaultArgumentAndInherited.setPointer(nullptr); - DefaultArgumentAndInherited.setInt(false); - } + void removeDefaultArgument() { DefaultArgument.clear(); } /// \brief Whether this parameter is a non-type template parameter pack. /// @@ -1217,10 +1303,10 @@ class TemplateTemplateParmDecl : public TemplateDecl, { void anchor() override; - /// DefaultArgument - The default template argument, if any. - TemplateArgumentLoc DefaultArgument; - /// Whether or not the default argument was inherited. - bool DefaultArgumentWasInherited; + /// \brief The default template argument, if any. + typedef DefaultArgStorage<TemplateTemplateParmDecl, TemplateArgumentLoc *> + DefArgStorage; + DefArgStorage DefaultArgument; /// \brief Whether this parameter is a parameter pack. bool ParameterPack; @@ -1237,8 +1323,7 @@ class TemplateTemplateParmDecl : public TemplateDecl, unsigned D, unsigned P, bool ParameterPack, IdentifierInfo *Id, TemplateParameterList *Params) : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), - TemplateParmPosition(D, P), DefaultArgument(), - DefaultArgumentWasInherited(false), ParameterPack(ParameterPack), + TemplateParmPosition(D, P), ParameterPack(ParameterPack), ExpandedParameterPack(false), NumExpandedParams(0) { } @@ -1322,15 +1407,16 @@ public: return reinterpret_cast<TemplateParameterList *const *>(this + 1)[I]; } + const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } + /// \brief Determine whether this template parameter has a default /// argument. - bool hasDefaultArgument() const { - return !DefaultArgument.getArgument().isNull(); - } + bool hasDefaultArgument() const { return DefaultArgument.isSet(); } /// \brief Retrieve the default argument, if any. const TemplateArgumentLoc &getDefaultArgument() const { - return DefaultArgument; + static const TemplateArgumentLoc None; + return DefaultArgument.isSet() ? *DefaultArgument.get() : None; } /// \brief Retrieve the location of the default argument, if any. @@ -1339,22 +1425,21 @@ public: /// \brief Determines whether the default argument was inherited /// from a previous declaration of this template. bool defaultArgumentWasInherited() const { - return DefaultArgumentWasInherited; + return DefaultArgument.isInherited(); } /// \brief Set the default argument for this template parameter, and /// whether that default argument was inherited from another /// declaration. - void setDefaultArgument(const TemplateArgumentLoc &DefArg, bool Inherited) { - DefaultArgument = DefArg; - DefaultArgumentWasInherited = Inherited; + void setDefaultArgument(const ASTContext &C, + const TemplateArgumentLoc &DefArg); + void setInheritedDefaultArgument(const ASTContext &C, + TemplateTemplateParmDecl *Prev) { + DefaultArgument.setInherited(C, Prev); } /// \brief Removes the default argument of this template parameter. - void removeDefaultArgument() { - DefaultArgument = TemplateArgumentLoc(); - DefaultArgumentWasInherited = false; - } + void removeDefaultArgument() { DefaultArgument.clear(); } SourceRange getSourceRange() const override LLVM_READONLY { SourceLocation End = getLocation(); diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h index 59de104b83f9..5cae5d9eca3f 100644 --- a/include/clang/AST/EvaluatedExprVisitor.h +++ b/include/clang/AST/EvaluatedExprVisitor.h @@ -26,29 +26,32 @@ class ASTContext; /// \brief Given a potentially-evaluated expression, this visitor visits all /// of its potentially-evaluated subexpressions, recursively. -template<typename ImplClass> -class EvaluatedExprVisitor : public StmtVisitor<ImplClass> { - ASTContext &Context; - +template<template <typename> class Ptr, typename ImplClass> +class EvaluatedExprVisitorBase : public StmtVisitorBase<Ptr, ImplClass, void> { +protected: + const ASTContext &Context; + public: - explicit EvaluatedExprVisitor(ASTContext &Context) : Context(Context) { } - +#define PTR(CLASS) typename Ptr<CLASS>::type + + explicit EvaluatedExprVisitorBase(const ASTContext &Context) : Context(Context) { } + // Expressions that have no potentially-evaluated subexpressions (but may have // other sub-expressions). - void VisitDeclRefExpr(DeclRefExpr *E) { } - void VisitOffsetOfExpr(OffsetOfExpr *E) { } - void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { } - void VisitExpressionTraitExpr(ExpressionTraitExpr *E) { } - void VisitBlockExpr(BlockExpr *E) { } - void VisitCXXUuidofExpr(CXXUuidofExpr *E) { } - void VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { } - - void VisitMemberExpr(MemberExpr *E) { + void VisitDeclRefExpr(PTR(DeclRefExpr) E) { } + void VisitOffsetOfExpr(PTR(OffsetOfExpr) E) { } + void VisitUnaryExprOrTypeTraitExpr(PTR(UnaryExprOrTypeTraitExpr) E) { } + void VisitExpressionTraitExpr(PTR(ExpressionTraitExpr) E) { } + void VisitBlockExpr(PTR(BlockExpr) E) { } + void VisitCXXUuidofExpr(PTR(CXXUuidofExpr) E) { } + void VisitCXXNoexceptExpr(PTR(CXXNoexceptExpr) E) { } + + void VisitMemberExpr(PTR(MemberExpr) E) { // Only the base matters. return this->Visit(E->getBase()); } - - void VisitChooseExpr(ChooseExpr *E) { + + void VisitChooseExpr(PTR(ChooseExpr) E) { // Don't visit either child expression if the condition is dependent. if (E->getCond()->isValueDependent()) return; @@ -56,7 +59,7 @@ public: return this->Visit(E->getChosenSubExpr()); } - void VisitGenericSelectionExpr(GenericSelectionExpr *E) { + void VisitGenericSelectionExpr(PTR(GenericSelectionExpr) E) { // The controlling expression of a generic selection is not evaluated. // Don't visit either child expression if the condition is type-dependent. @@ -67,23 +70,23 @@ public: return this->Visit(E->getResultExpr()); } - void VisitDesignatedInitExpr(DesignatedInitExpr *E) { + void VisitDesignatedInitExpr(PTR(DesignatedInitExpr) E) { // Only the actual initializer matters; the designators are all constant // expressions. return this->Visit(E->getInit()); } - void VisitCXXTypeidExpr(CXXTypeidExpr *E) { + void VisitCXXTypeidExpr(PTR(CXXTypeidExpr) E) { if (E->isPotentiallyEvaluated()) return this->Visit(E->getExprOperand()); } - void VisitCallExpr(CallExpr *CE) { + void VisitCallExpr(PTR(CallExpr) CE) { if (!CE->isUnevaluatedBuiltinCall(Context)) return static_cast<ImplClass*>(this)->VisitExpr(CE); } - void VisitLambdaExpr(LambdaExpr *LE) { + void VisitLambdaExpr(PTR(LambdaExpr) LE) { // Only visit the capture initializers, and not the body. for (LambdaExpr::capture_init_iterator I = LE->capture_init_begin(), E = LE->capture_init_end(); @@ -94,11 +97,31 @@ public: /// \brief The basis case walks all of the children of the statement or /// expression, assuming they are all potentially evaluated. - void VisitStmt(Stmt *S) { - for (Stmt::child_range C = S->children(); C; ++C) + void VisitStmt(PTR(Stmt) S) { + for (auto C = S->children(); C; ++C) if (*C) this->Visit(*C); } + +#undef PTR +}; + +/// EvaluatedExprVisitor - This class visits 'Expr *'s +template<typename ImplClass> +class EvaluatedExprVisitor + : public EvaluatedExprVisitorBase<make_ptr, ImplClass> { +public: + explicit EvaluatedExprVisitor(const ASTContext &Context) : + EvaluatedExprVisitorBase<make_ptr, ImplClass>(Context) { } +}; + +/// ConstEvaluatedExprVisitor - This class visits 'const Expr *'s. +template<typename ImplClass> +class ConstEvaluatedExprVisitor + : public EvaluatedExprVisitorBase<make_const_ptr, ImplClass> { +public: + explicit ConstEvaluatedExprVisitor(const ASTContext &Context) : + EvaluatedExprVisitorBase<make_const_ptr, ImplClass>(Context) { } }; } diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index a3be7d06c4b1..2a5b4c0f5ed0 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -598,7 +598,7 @@ public: /// \brief Determine whether this expression involves a call to any function /// that is not trivial. - bool hasNonTrivialCall(ASTContext &Ctx); + bool hasNonTrivialCall(const ASTContext &Ctx) const; /// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded /// integer. This must be called on an expression that constant folds to an @@ -2273,7 +2273,7 @@ public: /// \brief Returns \c true if this is a call to a builtin which does not /// evaluate side-effects within its arguments. - bool isUnevaluatedBuiltinCall(ASTContext &Ctx) const; + bool isUnevaluatedBuiltinCall(const ASTContext &Ctx) const; /// getCallReturnType - Get the return type of the call expr. This is not /// always the type of the expr itself, if the return type is a reference @@ -4267,6 +4267,80 @@ public: } }; +/// \brief Represents a place-holder for an object not to be initialized by +/// anything. +/// +/// This only makes sense when it appears as part of an updater of a +/// DesignatedInitUpdateExpr (see below). The base expression of a DIUE +/// initializes a big object, and the NoInitExpr's mark the spots within the +/// big object not to be overwritten by the updater. +/// +/// \see DesignatedInitUpdateExpr +class NoInitExpr : public Expr { +public: + explicit NoInitExpr(QualType ty) + : Expr(NoInitExprClass, ty, VK_RValue, OK_Ordinary, + false, false, ty->isInstantiationDependentType(), false) { } + + explicit NoInitExpr(EmptyShell Empty) + : Expr(NoInitExprClass, Empty) { } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == NoInitExprClass; + } + + SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } + + // Iterators + child_range children() { return child_range(); } +}; + +// In cases like: +// struct Q { int a, b, c; }; +// Q *getQ(); +// void foo() { +// struct A { Q q; } a = { *getQ(), .q.b = 3 }; +// } +// +// We will have an InitListExpr for a, with type A, and then a +// DesignatedInitUpdateExpr for "a.q" with type Q. The "base" for this DIUE +// is the call expression *getQ(); the "updater" for the DIUE is ".q.b = 3" +// +class DesignatedInitUpdateExpr : public Expr { + // BaseAndUpdaterExprs[0] is the base expression; + // BaseAndUpdaterExprs[1] is an InitListExpr overwriting part of the base. + Stmt *BaseAndUpdaterExprs[2]; + +public: + DesignatedInitUpdateExpr(const ASTContext &C, SourceLocation lBraceLoc, + Expr *baseExprs, SourceLocation rBraceLoc); + + explicit DesignatedInitUpdateExpr(EmptyShell Empty) + : Expr(DesignatedInitUpdateExprClass, Empty) { } + + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == DesignatedInitUpdateExprClass; + } + + Expr *getBase() const { return cast<Expr>(BaseAndUpdaterExprs[0]); } + void setBase(Expr *Base) { BaseAndUpdaterExprs[0] = Base; } + + InitListExpr *getUpdater() const { + return cast<InitListExpr>(BaseAndUpdaterExprs[1]); + } + void setUpdater(Expr *Updater) { BaseAndUpdaterExprs[1] = Updater; } + + // Iterators + // children = the base and the updater + child_range children() { + return child_range(&BaseAndUpdaterExprs[0], &BaseAndUpdaterExprs[0] + 2); + } +}; + /// \brief Represents an implicitly-generated value initialization of /// an object of a given type. /// diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index c8ecef8ce50c..386c8dd3ee94 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -1752,7 +1752,7 @@ public: StmtRange children() { return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(getFinals().end() + 2)); + reinterpret_cast<Stmt **>(varlist_end())); } static bool classof(const OMPClause *T) { @@ -1837,7 +1837,7 @@ public: StmtRange children() { return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end() + 1)); + reinterpret_cast<Stmt **>(varlist_end())); } static bool classof(const OMPClause *T) { diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 95e0df3066b0..95d773073184 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -2234,9 +2234,11 @@ DEF_TRAVERSE_STMT(CXXThisExpr, {}) DEF_TRAVERSE_STMT(CXXThrowExpr, {}) DEF_TRAVERSE_STMT(UserDefinedLiteral, {}) DEF_TRAVERSE_STMT(DesignatedInitExpr, {}) +DEF_TRAVERSE_STMT(DesignatedInitUpdateExpr, {}) DEF_TRAVERSE_STMT(ExtVectorElementExpr, {}) DEF_TRAVERSE_STMT(GNUNullExpr, {}) DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {}) +DEF_TRAVERSE_STMT(NoInitExpr, {}) DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {}) DEF_TRAVERSE_STMT(ObjCEncodeExpr, { if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo()) @@ -2386,6 +2388,9 @@ DEF_TRAVERSE_STMT(OMPBarrierDirective, DEF_TRAVERSE_STMT(OMPTaskwaitDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTaskgroupDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPFlushDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h index 5161eff0993b..63f295ddfec0 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -285,24 +285,23 @@ class OMPLoopDirective : public OMPExecutableDirective { CalcLastIterationOffset = 3, PreConditionOffset = 4, CondOffset = 5, - SeparatedCondOffset = 6, - InitOffset = 7, - IncOffset = 8, + InitOffset = 6, + IncOffset = 7, // The '...End' enumerators do not correspond to child expressions - they // specify the offset to the end (and start of the following counters/ // updates/finals arrays). - DefaultEnd = 9, + DefaultEnd = 8, // The following 7 exprs are used by worksharing loops only. - IsLastIterVariableOffset = 9, - LowerBoundVariableOffset = 10, - UpperBoundVariableOffset = 11, - StrideVariableOffset = 12, - EnsureUpperBoundOffset = 13, - NextLowerBoundOffset = 14, - NextUpperBoundOffset = 15, + IsLastIterVariableOffset = 8, + LowerBoundVariableOffset = 9, + UpperBoundVariableOffset = 10, + StrideVariableOffset = 11, + EnsureUpperBoundOffset = 12, + NextLowerBoundOffset = 13, + NextUpperBoundOffset = 14, // Offset to the end (and start of the following counters/updates/finals // arrays) for worksharing loop directives. - WorksharingEnd = 16, + WorksharingEnd = 15, }; /// \brief Get the counters storage. @@ -374,9 +373,8 @@ protected: void setPreCond(Expr *PC) { *std::next(child_begin(), PreConditionOffset) = PC; } - void setCond(Expr *Cond, Expr *SeparatedCond) { + void setCond(Expr *Cond) { *std::next(child_begin(), CondOffset) = Cond; - *std::next(child_begin(), SeparatedCondOffset) = SeparatedCond; } void setInit(Expr *Init) { *std::next(child_begin(), InitOffset) = Init; } void setInc(Expr *Inc) { *std::next(child_begin(), IncOffset) = Inc; } @@ -435,8 +433,6 @@ public: Expr *PreCond; /// \brief Loop condition. Expr *Cond; - /// \brief A condition with 1 iteration separated. - Expr *SeparatedCond; /// \brief Loop iteration variable init. Expr *Init; /// \brief Loop increment. @@ -467,8 +463,7 @@ public: bool builtAll() { return IterationVarRef != nullptr && LastIteration != nullptr && NumIterations != nullptr && PreCond != nullptr && - Cond != nullptr && SeparatedCond != nullptr && Init != nullptr && - Inc != nullptr; + Cond != nullptr && Init != nullptr && Inc != nullptr; } /// \brief Initialize all the fields to null. @@ -479,7 +474,6 @@ public: CalcLastIteration = nullptr; PreCond = nullptr; Cond = nullptr; - SeparatedCond = nullptr; Init = nullptr; Inc = nullptr; IL = nullptr; @@ -519,10 +513,9 @@ public: return const_cast<Expr *>(reinterpret_cast<const Expr *>( *std::next(child_begin(), PreConditionOffset))); } - Expr *getCond(bool SeparateIter) const { - return const_cast<Expr *>(reinterpret_cast<const Expr *>( - *std::next(child_begin(), - (SeparateIter ? SeparatedCondOffset : CondOffset)))); + Expr *getCond() const { + return const_cast<Expr *>( + reinterpret_cast<const Expr *>(*std::next(child_begin(), CondOffset))); } Expr *getInit() const { return const_cast<Expr *>( @@ -1462,6 +1455,53 @@ public: } }; +/// \brief This represents '#pragma omp taskgroup' directive. +/// +/// \code +/// #pragma omp taskgroup +/// \endcode +/// +class OMPTaskgroupDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPTaskgroupDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPTaskgroupDirectiveClass, OMPD_taskgroup, + StartLoc, EndLoc, 0, 1) {} + + /// \brief Build an empty directive. + /// + explicit OMPTaskgroupDirective() + : OMPExecutableDirective(this, OMPTaskgroupDirectiveClass, OMPD_taskgroup, + SourceLocation(), SourceLocation(), 0, 1) {} + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPTaskgroupDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPTaskgroupDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTaskgroupDirectiveClass; + } +}; + /// \brief This represents '#pragma omp flush' directive. /// /// \code diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 8cd29b7b917e..d903b9d8cbcf 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1818,6 +1818,19 @@ public: /// checking. Should always return true. bool isLinkageValid() const; + /// Determine the nullability of the given type. + /// + /// Note that nullability is only captured as sugar within the type + /// system, not as part of the canonical type, so nullability will + /// be lost by canonicalization and desugaring. + Optional<NullabilityKind> getNullability(const ASTContext &context) const; + + /// Determine whether the given type can have a nullability + /// specifier applied to it, i.e., if it is any kind of pointer type + /// or a dependent type that could instantiate to any kind of + /// pointer type. + bool canHaveNullability() const; + const char *getTypeClassName() const; QualType getCanonicalTypeInternal() const { @@ -3479,7 +3492,10 @@ public: attr_ptr32, attr_ptr64, attr_sptr, - attr_uptr + attr_uptr, + attr_nonnull, + attr_nullable, + attr_null_unspecified, }; private: @@ -3513,6 +3529,35 @@ public: bool isCallingConv() const; + llvm::Optional<NullabilityKind> getImmediateNullability() const; + + /// Retrieve the attribute kind corresponding to the given + /// nullability kind. + static Kind getNullabilityAttrKind(NullabilityKind kind) { + switch (kind) { + case NullabilityKind::NonNull: + return attr_nonnull; + + case NullabilityKind::Nullable: + return attr_nullable; + + case NullabilityKind::Unspecified: + return attr_null_unspecified; + } + llvm_unreachable("Unknown nullability kind."); + } + + /// Strip off the top-level nullability annotation on the given + /// type, if it's there. + /// + /// \param T The type to strip. If the type is exactly an + /// AttributedType specifying nullability (without looking through + /// type sugar), the nullability is returned and this type changed + /// to the underlying modified type. + /// + /// \returns the top-level nullability, if present. + static Optional<NullabilityKind> stripOuterNullability(QualType &T); + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getAttrKind(), ModifiedType, EquivalentType); } diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h index e8eab864b298..8ad0c16ef83a 100644 --- a/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -20,17 +20,30 @@ // to only have the functions (which is all the user cares about) in the // 'ast_matchers' namespace and hide the boilerplate. // -// To define a matcher in user code, always put it into the clang::ast_matchers -// namespace and refer to the internal types via the 'internal::': +// To define a matcher in user code, put it into your own namespace. This would +// help to prevent ODR violations in case a matcher with the same name is +// defined in multiple translation units: +// +// namespace my_matchers { +// AST_MATCHER_P(clang::MemberExpr, Member, +// clang::ast_matchers::internal::Matcher<clang::ValueDecl>, +// InnerMatcher) { +// return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder); +// } +// } // namespace my_matchers +// +// Alternatively, an unnamed namespace may be used: // // namespace clang { // namespace ast_matchers { +// namespace { // AST_MATCHER_P(MemberExpr, Member, // internal::Matcher<ValueDecl>, InnerMatcher) { // return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder); // } -// } // end namespace ast_matchers -// } // end namespace clang +// } // namespace +// } // namespace ast_matchers +// } // namespace clang // //===----------------------------------------------------------------------===// @@ -43,12 +56,13 @@ #define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) \ inline ReturnType DefineMatcher##_getInstance(); \ inline ReturnType DefineMatcher() { \ - return internal::MemoizedMatcher< \ + return ::clang::ast_matchers::internal::MemoizedMatcher< \ ReturnType, DefineMatcher##_getInstance>::getInstance(); \ } \ inline ReturnType DefineMatcher##_getInstance() -/// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) { ... } +/// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) { +/// ... } /// defines a single-parameter function named DefineMatcher() that returns a /// ReturnType object. /// @@ -80,20 +94,24 @@ /// The code should return true if 'Node' matches. #define AST_MATCHER(Type, DefineMatcher) \ namespace internal { \ - class matcher_##DefineMatcher##Matcher : public MatcherInterface<Type> { \ + class matcher_##DefineMatcher##Matcher \ + : public ::clang::ast_matchers::internal::MatcherInterface<Type> { \ public: \ explicit matcher_##DefineMatcher##Matcher() {} \ - bool matches(const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const override; \ + bool matches(const Type &Node, \ + ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ + ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ + *Builder) const override; \ }; \ } \ - inline internal::Matcher<Type> DefineMatcher() { \ - return internal::makeMatcher( \ + inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher() { \ + return ::clang::ast_matchers::internal::makeMatcher( \ new internal::matcher_##DefineMatcher##Matcher()); \ } \ inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ - const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const + const Type &Node, \ + ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ + ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const /// \brief AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... } /// defines a single-parameter function named DefineMatcher() that returns a @@ -115,27 +133,31 @@ OverloadId) \ namespace internal { \ class matcher_##DefineMatcher##OverloadId##Matcher \ - : public MatcherInterface<Type> { \ + : public ::clang::ast_matchers::internal::MatcherInterface<Type> { \ public: \ explicit matcher_##DefineMatcher##OverloadId##Matcher( \ ParamType const &A##Param) \ : Param(A##Param) {} \ - bool matches(const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const override; \ + bool matches(const Type &Node, \ + ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ + ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ + *Builder) const override; \ \ private: \ ParamType const Param; \ }; \ } \ - inline internal::Matcher<Type> DefineMatcher(ParamType const &Param) { \ - return internal::makeMatcher( \ + inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \ + ParamType const &Param) { \ + return ::clang::ast_matchers::internal::makeMatcher( \ new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \ } \ - typedef internal::Matcher<Type>(&DefineMatcher##_Type##OverloadId)( \ - ParamType const &Param); \ + typedef ::clang::ast_matchers::internal::Matcher<Type>( \ + &DefineMatcher##_Type##OverloadId)(ParamType const &Param); \ inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \ - const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const + const Type &Node, \ + ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ + ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const /// \brief AST_MATCHER_P2( /// Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... } @@ -160,30 +182,34 @@ ParamType2, Param2, OverloadId) \ namespace internal { \ class matcher_##DefineMatcher##OverloadId##Matcher \ - : public MatcherInterface<Type> { \ + : public ::clang::ast_matchers::internal::MatcherInterface<Type> { \ public: \ matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \ ParamType2 const &A##Param2) \ : Param1(A##Param1), Param2(A##Param2) {} \ - bool matches(const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const override; \ + bool matches(const Type &Node, \ + ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ + ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ + *Builder) const override; \ \ private: \ ParamType1 const Param1; \ ParamType2 const Param2; \ }; \ } \ - inline internal::Matcher<Type> DefineMatcher(ParamType1 const &Param1, \ - ParamType2 const &Param2) { \ - return internal::makeMatcher( \ + inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \ + ParamType1 const &Param1, ParamType2 const &Param2) { \ + return ::clang::ast_matchers::internal::makeMatcher( \ new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \ Param2)); \ } \ - typedef internal::Matcher<Type>(&DefineMatcher##_Type##OverloadId)( \ - ParamType1 const &Param1, ParamType2 const &Param2); \ + typedef ::clang::ast_matchers::internal::Matcher<Type>( \ + &DefineMatcher##_Type##OverloadId)(ParamType1 const &Param1, \ + ParamType2 const &Param2); \ inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \ - const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const + const Type &Node, \ + ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ + ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const /// \brief Construct a type-list to be passed to the AST_POLYMORPHIC_MATCHER* /// macros. @@ -194,7 +220,7 @@ /// The \c PolymorphicMatcherWithParam* classes will unpack the function type to /// extract the TypeList object. #define AST_POLYMORPHIC_SUPPORTED_TYPES(...) \ - void(internal::TypeList<__VA_ARGS__>) + void(::clang::ast_matchers::internal::TypeList<__VA_ARGS__>) /// \brief AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... } /// defines a single-parameter function named DefineMatcher() that is @@ -205,22 +231,26 @@ #define AST_POLYMORPHIC_MATCHER(DefineMatcher, ReturnTypesF) \ namespace internal { \ template <typename NodeType> \ - class matcher_##DefineMatcher##Matcher : public MatcherInterface<NodeType> { \ + class matcher_##DefineMatcher##Matcher \ + : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \ public: \ - bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const override; \ + bool matches(const NodeType &Node, \ + ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ + ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ + *Builder) const override; \ }; \ } \ - inline internal::PolymorphicMatcherWithParam0< \ + inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam0< \ internal::matcher_##DefineMatcher##Matcher, ReturnTypesF> \ DefineMatcher() { \ - return internal::PolymorphicMatcherWithParam0< \ + return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam0< \ internal::matcher_##DefineMatcher##Matcher, ReturnTypesF>(); \ } \ template <typename NodeType> \ bool internal::matcher_##DefineMatcher##Matcher<NodeType>::matches( \ - const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const + const NodeType &Node, \ + ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ + ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const /// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... } /// defines a single-parameter function named DefineMatcher() that is @@ -241,33 +271,39 @@ namespace internal { \ template <typename NodeType, typename ParamT> \ class matcher_##DefineMatcher##OverloadId##Matcher \ - : public MatcherInterface<NodeType> { \ + : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \ public: \ explicit matcher_##DefineMatcher##OverloadId##Matcher( \ ParamType const &A##Param) \ : Param(A##Param) {} \ - bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const override; \ + bool matches(const NodeType &Node, \ + ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ + ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ + *Builder) const override; \ \ private: \ ParamType const Param; \ }; \ } \ - inline internal::PolymorphicMatcherWithParam1< \ + inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \ - ReturnTypesF> DefineMatcher(ParamType const &Param) { \ - return internal::PolymorphicMatcherWithParam1< \ + ReturnTypesF> \ + DefineMatcher(ParamType const &Param) { \ + return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \ ReturnTypesF>(Param); \ } \ - typedef internal::PolymorphicMatcherWithParam1< \ + typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \ ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \ ParamType const &Param); \ template <typename NodeType, typename ParamT> \ - bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ - NodeType, ParamT>::matches(const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const + bool internal:: \ + matcher_##DefineMatcher##OverloadId##Matcher<NodeType, ParamT>::matches( \ + const NodeType &Node, \ + ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ + ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \ + const /// \brief AST_POLYMORPHIC_MATCHER_P2( /// DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... } @@ -288,41 +324,46 @@ namespace internal { \ template <typename NodeType, typename ParamT1, typename ParamT2> \ class matcher_##DefineMatcher##OverloadId##Matcher \ - : public MatcherInterface<NodeType> { \ + : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \ public: \ matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \ ParamType2 const &A##Param2) \ : Param1(A##Param1), Param2(A##Param2) {} \ - bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const override; \ + bool matches(const NodeType &Node, \ + ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ + ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ + *Builder) const override; \ \ private: \ ParamType1 const Param1; \ ParamType2 const Param2; \ }; \ } \ - inline internal::PolymorphicMatcherWithParam2< \ + inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ - ParamType2, ReturnTypesF> DefineMatcher(ParamType1 const &Param1, \ - ParamType2 const &Param2) { \ - return internal::PolymorphicMatcherWithParam2< \ + ParamType2, ReturnTypesF> \ + DefineMatcher(ParamType1 const &Param1, ParamType2 const &Param2) { \ + return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ ParamType2, ReturnTypesF>(Param1, Param2); \ } \ - typedef internal::PolymorphicMatcherWithParam2< \ + typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ ParamType2, ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \ ParamType1 const &Param1, ParamType2 const &Param2); \ template <typename NodeType, typename ParamT1, typename ParamT2> \ bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ - NodeType, ParamT1, ParamT2>::matches( \ - const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const + NodeType, ParamT1, ParamT2>:: \ + matches(const NodeType &Node, \ + ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ + ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \ + const /// \brief Creates a variadic matcher for both a specific \c Type as well as /// the corresponding \c TypeLoc. #define AST_TYPE_MATCHER(NodeType, MatcherName) \ - const internal::VariadicDynCastAllOfMatcher<Type, NodeType> MatcherName + const ::clang::ast_matchers::internal::VariadicDynCastAllOfMatcher< \ + Type, NodeType> MatcherName // FIXME: add a matcher for TypeLoc derived classes using its custom casting // API (no longer dyn_cast) if/when we need such matching @@ -330,7 +371,7 @@ /// the matcher \c MatcherName that can be used to traverse from one \c Type /// to another. /// -/// For a specific \c SpecificType, the traversal is done using +/// For a specific \c SpecificType, the traversal is done using /// \c SpecificType::FunctionName. The existence of such a function determines /// whether a corresponding matcher can be used on \c SpecificType. #define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \ @@ -339,9 +380,11 @@ static QualType (T::*value())() const { return &T::FunctionName; } \ }; \ } \ - const internal::TypeTraversePolymorphicMatcher< \ - QualType, internal::TypeMatcher##MatcherName##Getter, \ - internal::TypeTraverseMatcher, ReturnTypesF>::Func MatcherName + const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \ + QualType, \ + ::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter, \ + ::clang::ast_matchers::internal::TypeTraverseMatcher, \ + ReturnTypesF>::Func MatcherName /// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works /// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs. @@ -351,9 +394,11 @@ static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; } \ }; \ } \ - const internal::TypeTraversePolymorphicMatcher< \ - TypeLoc, internal::TypeLocMatcher##MatcherName##Getter, \ - internal::TypeLocTraverseMatcher, ReturnTypesF>::Func MatcherName##Loc; \ + const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \ + TypeLoc, \ + ::clang::ast_matchers::internal::TypeLocMatcher##MatcherName##Getter, \ + ::clang::ast_matchers::internal::TypeLocTraverseMatcher, \ + ReturnTypesF>::Func MatcherName##Loc; \ AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF) #endif diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index c310d25a5518..f36f654ff630 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -195,7 +195,8 @@ class CXX11<string namespace, string name, int version = 1> : Spelling<name, "CXX11"> { string Namespace = namespace; int Version = version; -} class Keyword<string name> : Spelling<name, "Keyword">; +} +class Keyword<string name> : Spelling<name, "Keyword">; class Pragma<string namespace, string name> : Spelling<name, "Pragma"> { string Namespace = namespace; } @@ -959,6 +960,22 @@ def ReturnsNonNull : InheritableAttr { let Documentation = [Undocumented]; } +// Nullability type attributes. +def TypeNonNull : TypeAttr { + let Spellings = [Keyword<"__nonnull">]; + let Documentation = [Undocumented]; +} + +def TypeNullable : TypeAttr { + let Spellings = [Keyword<"__nullable">]; + let Documentation = [Undocumented]; +} + +def TypeNullUnspecified : TypeAttr { + let Spellings = [Keyword<"__null_unspecified">]; + let Documentation = [Undocumented]; +} + def AssumeAligned : InheritableAttr { let Spellings = [GCC<"assume_aligned">]; let Subjects = SubjectList<[ObjCMethod, Function]>; @@ -1250,6 +1267,14 @@ def Pascal : InheritableAttr { let Documentation = [Undocumented]; } +def Target : InheritableAttr { + let Spellings = [GCC<"target">]; + let Args = [StringArgument<"features">]; + let Subjects = + SubjectList<[Function], ErrorDiag, "ExpectedFunctionMethodOrClass">; + let Documentation = [Undocumented]; +} + def TransparentUnion : InheritableAttr { let Spellings = [GCC<"transparent_union">]; // let Subjects = SubjectList<[Record, TypedefName]>; @@ -1935,8 +1960,8 @@ def LoopHint : Attr { ["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount", "Unroll", "UnrollCount"]>, EnumArgument<"State", "LoopHintState", - ["default", "enable", "disable"], - ["Default", "Enable", "Disable"]>, + ["default", "enable", "disable", "assume_safety"], + ["Default", "Enable", "Disable", "AssumeSafety"]>, ExprArgument<"Value">]; let AdditionalMembers = [{ @@ -1982,6 +2007,8 @@ def LoopHint : Attr { return ""; else if (state == Enable) OS << (option == Unroll ? "full" : "enable"); + else if (state == AssumeSafety) + OS << "assume_safety"; else OS << "disable"; OS << ")"; diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 192790749be8..bf65b5fa2ea8 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -1240,6 +1240,10 @@ BUILTIN(__builtin_addressof, "v*v&", "nct") BUILTIN(__builtin_operator_new, "v*z", "c") BUILTIN(__builtin_operator_delete, "vv*", "n") +// Safestack builtins +BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn") +BUILTIN(__builtin___get_unsafe_stack_ptr, "v*", "Fn") + #undef BUILTIN #undef LIBBUILTIN #undef LANGBUILTIN diff --git a/include/clang/Basic/BuiltinsAArch64.def b/include/clang/Basic/BuiltinsAArch64.def index 9d223c3e8516..1db4c1471029 100644 --- a/include/clang/Basic/BuiltinsAArch64.def +++ b/include/clang/Basic/BuiltinsAArch64.def @@ -53,4 +53,12 @@ BUILTIN(__builtin_arm_isb, "vUi", "nc") // Prefetch BUILTIN(__builtin_arm_prefetch, "vvC*UiUiUiUi", "nc") +// System Registers +BUILTIN(__builtin_arm_rsr, "UicC*", "nc") +BUILTIN(__builtin_arm_rsr64, "LUicC*", "nc") +BUILTIN(__builtin_arm_rsrp, "v*cC*", "nc") +BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc") +BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc") +BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc") + #undef BUILTIN diff --git a/include/clang/Basic/BuiltinsR600.def b/include/clang/Basic/BuiltinsAMDGPU.def index 84fc4fae4eab..bb9931f7a206 100644 --- a/include/clang/Basic/BuiltinsR600.def +++ b/include/clang/Basic/BuiltinsAMDGPU.def @@ -1,4 +1,4 @@ -//==- BuiltinsR600.def - R600 Builtin function database ----------*- C++ -*-==// +//==- BuiltinsAMDGPU.def - AMDGPU Builtin function database ------*- C++ -*-==// // // The LLVM Compiler Infrastructure // diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def index 98d5ab73aa38..0610d47f8ba1 100644 --- a/include/clang/Basic/BuiltinsARM.def +++ b/include/clang/Basic/BuiltinsARM.def @@ -84,6 +84,14 @@ BUILTIN(__builtin_arm_isb, "vUi", "nc") // Prefetch BUILTIN(__builtin_arm_prefetch, "vvC*UiUi", "nc") +// System registers (ACLE) +BUILTIN(__builtin_arm_rsr, "UicC*", "nc") +BUILTIN(__builtin_arm_rsr64, "LLUicC*", "nc") +BUILTIN(__builtin_arm_rsrp, "v*cC*", "nc") +BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc") +BUILTIN(__builtin_arm_wsr64, "vcC*LLUi", "nc") +BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc") + // MSVC LANGBUILTIN(__emit, "vIUiC", "", ALL_MS_LANGUAGES) diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def index 57ae63e634f4..6f3bea887f59 100644 --- a/include/clang/Basic/BuiltinsPPC.def +++ b/include/clang/Basic/BuiltinsPPC.def @@ -231,6 +231,9 @@ BUILTIN(__builtin_altivec_vcmpgtsd_p, "iiV2LLiV2LLi", "") BUILTIN(__builtin_altivec_vcmpgtud_p, "iiV2ULLiV2ULLi", "") BUILTIN(__builtin_altivec_vcmpgtfp_p, "iiV4fV4f", "") +BUILTIN(__builtin_altivec_vgbbd, "V16UcV16Uc", "") +BUILTIN(__builtin_altivec_vbpermq, "V2ULLiV16UcV16Uc", "") + // P8 Crypto built-ins. BUILTIN(__builtin_altivec_crypto_vsbox, "V2ULLiV2ULLi", "") BUILTIN(__builtin_altivec_crypto_vpermxor, "V16UcV16UcV16UcV16Uc", "") diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 1a597b5c27d4..00c1340ac37f 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -59,6 +59,9 @@ BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc") // All MMX instructions will be generated via builtins. Any MMX vector // types (<1 x i64>, <2 x i32>, etc.) that aren't used by these builtins will be // expanded by the back-end. +// FIXME: _mm_prefetch must be a built-in because it takes a compile-time constant +// argument and our prior approach of using a #define to the current built-in +// doesn't work in the presence of re-declaration of _mm_prefetch for windows. BUILTIN(_mm_prefetch, "vcC*i", "nc") BUILTIN(__builtin_ia32_emms, "v", "") BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "") diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index deb23f3149cb..82718d9255f3 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -99,6 +99,37 @@ def err_enum_template : Error<"enumeration cannot be a template">; } +let CategoryName = "Nullability Issue" in { + +def warn_nullability_duplicate : Warning< + "duplicate nullability specifier " + "'%select{__|}1%select{nonnull|nullable|null_unspecified}0'">, + InGroup<Nullability>; + +def warn_conflicting_nullability_attr_overriding_ret_types : Warning< + "conflicting nullability specifier on return types, " + "'%select{%select{__|}1nonnull|" + "%select{__|}1nullable|%select{__|}1null_unspecified}0' " + "conflicts with existing specifier '%select{%select{__|}3nonnull|" + "%select{__|}3nullable|%select{__|}3null_unspecified}2'">, + InGroup<Nullability>; + +def warn_conflicting_nullability_attr_overriding_param_types : Warning< + "conflicting nullability specifier on parameter types, " + "'%select{%select{__|}1nonnull|" + "%select{__|}1nullable|%select{__|}1null_unspecified}0' " + "conflicts with existing specifier '%select{%select{__|}3nonnull|" + "%select{__|}3nullable|%select{__|}3null_unspecified}2'">, + InGroup<Nullability>; + +def err_nullability_conflicting : Error< + "nullability specifier " + "'%select{__|}1%select{nonnull|nullable|null_unspecified}0' conflicts with " + "existing specifier '%select{__|}3%select{nonnull|nullable|" + "null_unspecified}2'">; + +} + // Sema && Lex def ext_c99_longlong : Extension< "'long long' is an extension when C99 mode is not enabled">, diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 016c2e198e3a..85796cc0d325 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -248,6 +248,10 @@ def MissingFieldInitializers : DiagGroup<"missing-field-initializers">; def ModuleBuild : DiagGroup<"module-build">; def ModuleConflict : DiagGroup<"module-conflict">; def NewlineEOF : DiagGroup<"newline-eof">; +def Nullability : DiagGroup<"nullability">; +def NullabilityDeclSpec : DiagGroup<"nullability-declspec">; +def NullableToNonNullConversion : DiagGroup<"nullable-to-nonnull-conversion">; +def NullabilityCompleteness : DiagGroup<"nullability-completeness">; def NullArithmetic : DiagGroup<"null-arithmetic">; def NullCharacter : DiagGroup<"null-character">; def NullDereference : DiagGroup<"null-dereference">; @@ -598,6 +602,7 @@ def Most : DiagGroup<"most", [ DeleteNonVirtualDtor, Format, Implicit, + InfiniteRecursion, MismatchedTags, MissingBraces, Move, diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 3d568e84a9a6..5dd4ae0ac7fd 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -646,5 +646,20 @@ def warn_header_guard : Warning< "%0 is used as a header guard here, followed by #define of a different macro">, InGroup<DiagGroup<"header-guard">>; def note_header_guard : Note< - "%0 is defined here; did you mean %1?">; + "%0 is defined here; did you mean %1?">; + +let CategoryName = "Nullability Issue" in { + +def err_pp_assume_nonnull_syntax : Error<"expected 'begin' or 'end'">; +def err_pp_double_begin_of_assume_nonnull : Error< + "already inside '#pragma clang assume_nonnull'">; +def err_pp_unmatched_end_of_assume_nonnull : Error< + "not currently inside '#pragma clang assume_nonnull'">; +def err_pp_include_in_assume_nonnull : Error< + "cannot #include files inside '#pragma clang assume_nonnull'">; +def err_pp_eof_in_assume_nonnull : Error< + "'#pragma clang assume_nonnull' was not ended within this file">; + +} + } diff --git a/include/clang/Basic/DiagnosticOptions.def b/include/clang/Basic/DiagnosticOptions.def index fdd325446e27..f4ba6da81fe0 100644 --- a/include/clang/Basic/DiagnosticOptions.def +++ b/include/clang/Basic/DiagnosticOptions.def @@ -69,7 +69,10 @@ ENUM_DIAGOPT(ShowOverloads, OverloadsShown, 1, DIAGOPT(VerifyDiagnostics, 1, 0) /// Check that diagnostics match the expected /// diagnostics, indicated by markers in the /// input source file. - +ENUM_DIAGOPT(VerifyIgnoreUnexpected, DiagnosticLevelMask, 4, + DiagnosticLevelMask::None) /// Ignore unexpected diagnostics of + /// the specified levels when using + /// -verify. DIAGOPT(ElideType, 1, 0) /// Elide identical types in template diffing DIAGOPT(ShowTemplateTree, 1, 0) /// Print a template tree when diffing DIAGOPT(CLFallbackMode, 1, 0) /// Format for clang-cl fallback mode diff --git a/include/clang/Basic/DiagnosticOptions.h b/include/clang/Basic/DiagnosticOptions.h index a16c7747cec3..c9b0c5def992 100644 --- a/include/clang/Basic/DiagnosticOptions.h +++ b/include/clang/Basic/DiagnosticOptions.h @@ -13,6 +13,7 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include <string> +#include <type_traits> #include <vector> namespace clang { @@ -24,6 +25,38 @@ enum OverloadsShown : unsigned { Ovl_Best ///< Show just the "best" overload candidates. }; +/// \brief A bitmask representing the diagnostic levels used by +/// VerifyDiagnosticConsumer. +enum class DiagnosticLevelMask : unsigned { + None = 0, + Note = 1 << 0, + Remark = 1 << 1, + Warning = 1 << 2, + Error = 1 << 3, + All = Note | Remark | Warning | Error +}; + +inline DiagnosticLevelMask operator~(DiagnosticLevelMask M) { + using UT = std::underlying_type<DiagnosticLevelMask>::type; + return static_cast<DiagnosticLevelMask>(~static_cast<UT>(M)); +} + +inline DiagnosticLevelMask operator|(DiagnosticLevelMask LHS, + DiagnosticLevelMask RHS) { + using UT = std::underlying_type<DiagnosticLevelMask>::type; + return static_cast<DiagnosticLevelMask>( + static_cast<UT>(LHS) | static_cast<UT>(RHS)); +} + +inline DiagnosticLevelMask operator&(DiagnosticLevelMask LHS, + DiagnosticLevelMask RHS) { + using UT = std::underlying_type<DiagnosticLevelMask>::type; + return static_cast<DiagnosticLevelMask>( + static_cast<UT>(LHS) & static_cast<UT>(RHS)); +} + +raw_ostream& operator<<(raw_ostream& Out, DiagnosticLevelMask M); + /// \brief Options for controlling the compiler diagnostics engine. class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{ public: diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index f00a3b39d23b..6a11d240c63c 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -65,6 +65,10 @@ def ext_keyword_as_ident : ExtWarn< "%select{here|for the remainder of the translation unit}1">, InGroup<KeywordCompat>; +def ext_nullability : Extension< + "type nullability specifier %0 is a Clang extension">, + InGroup<DiagGroup<"nullability-extension">>; + def error_empty_enum : Error<"use of empty enum">; def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">; def err_invalid_short_spec : Error<"'short %0' is invalid">; @@ -989,17 +993,21 @@ def err_omp_expected_identifier_for_critical : Error< // Pragma loop support. def err_pragma_loop_missing_argument : Error< "missing argument; expected %select{an integer value|" - "'%select{enable|full}1' or 'disable'}0">; + "%select{'enable', 'assume_safety'|'full'}1 or 'disable'}0">; def err_pragma_loop_invalid_option : Error< "%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, " "vectorize_width, interleave, interleave_count, unroll, or unroll_count">; def err_pragma_invalid_keyword : Error< - "invalid argument; expected '%select{enable|full}0' or 'disable'">; + "invalid argument; expected %select{'enable', 'assume_safety'|'full'}0 or 'disable'">; // Pragma unroll support. def warn_pragma_unroll_cuda_value_in_parens : Warning< "argument to '#pragma unroll' should not be in parentheses in CUDA C/C++">, InGroup<CudaCompat>; + +def err_empty_attribute_block : Error< + "Microsoft attribute block cannot be empty">; + } // end of Parse Issue category. let CategoryName = "Modules Issue" in { diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index be1911e7d506..803203cc50be 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -108,6 +108,7 @@ def err_ice_ambiguous_conversion : Error< def err_ice_too_large : Error< "integer constant expression evaluates to value %0 that cannot be " "represented in a %1-bit %select{signed|unsigned}2 integer type">; +def err_expr_not_string_literal : Error<"expression is not a string literal">; // Semantic analysis of constant literals. def ext_predef_outside_function : Warning< @@ -424,6 +425,7 @@ def warn_redecl_library_builtin : Warning< "incompatible redeclaration of library function %0">, InGroup<DiagGroup<"incompatible-library-redeclaration">>; def err_builtin_definition : Error<"definition of builtin function %0">; +def err_arm_invalid_specialreg : Error<"invalid special register for builtin">; def warn_builtin_unknown : Warning<"use of unknown builtin %0">, InGroup<ImplicitFunctionDeclare>, DefaultError; def warn_dyn_class_memaccess : Warning< @@ -1974,8 +1976,11 @@ def err_attribute_too_few_arguments : Error< def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">; def err_attribute_bad_neon_vector_size : Error< "Neon vector size must be 64 or 128 bits">; -def err_attribute_unsupported : Error< - "%0 attribute is not supported for this target">; +def warn_unsupported_target_attribute + : Warning<"Ignoring unsupported '%0' in the target attribute string">, + InGroup<IgnoredAttributes>; +def err_attribute_unsupported + : Error<"%0 attribute is not supported for this target">; // The err_*_attribute_argument_not_int are seperate because they're used by // VerifyIntegerConstantExpression. def err_aligned_attribute_argument_not_int : Error< @@ -2249,7 +2254,7 @@ def warn_attribute_dllimport_static_field_definition : Warning< InGroup<DiagGroup<"dllimport-static-field-def">>; def warn_attribute_dllexport_explicit_instantiation_decl : Warning< "explicit instantiation declaration should not be 'dllexport'">, - InGroup<DiagGroup<"dllexport-explicit-instantation-decl">>; + InGroup<DiagGroup<"dllexport-explicit-instantiation-decl">>; def warn_invalid_initializer_from_system_header : Warning< "invalid constructor form class in system header, should not be explicit">, InGroup<DiagGroup<"invalid-initializer-from-system-header">>; @@ -2680,6 +2685,8 @@ def err_mode_not_primitive : Error< "mode attribute only supported for integer and floating-point types">; def err_mode_wrong_type : Error< "type of machine mode does not match type of base type">; +def err_complex_mode_vector_type : Error< + "type of machine mode does not support base vector types">; def err_attr_wrong_decl : Error< "%0 attribute invalid on this declaration, requires typedef or value">; def warn_attribute_nonnull_no_pointers : Warning< @@ -2744,8 +2751,8 @@ def warn_ns_attribute_wrong_return_type : Warning< "return %select{an Objective-C object|a pointer|a non-retainable pointer}2">, InGroup<IgnoredAttributes>; def warn_ns_attribute_wrong_parameter_type : Warning< - "%0 attribute only applies to %select{Objective-C object|pointer}1 " - "parameters">, + "%0 attribute only applies to " + "%select{Objective-C object|pointer|pointer-to-CF-pointer}1 parameters">, InGroup<IgnoredAttributes>; def warn_objc_requires_super_protocol : Warning< "%0 attribute cannot be applied to %select{methods in protocols|dealloc}1">, @@ -7631,10 +7638,12 @@ def err_module_private_local : Error< def err_module_private_local_class : Error< "local %select{struct|interface|union|class|enum}0 cannot be declared " "__module_private__">; -def err_module_private_declaration : Error< - "declaration of %0 must be imported from module '%1' before it is required">; -def err_module_private_definition : Error< - "definition of %0 must be imported from module '%1' before it is required">; +def err_module_unimported_use : Error< + "%select{declaration|definition|default argument}0 of %1 must be imported " + "from module '%2' before it is required">; +def err_module_unimported_use_multiple : Error< + "%select{declaration|definition|default argument}0 of %1 must be imported " + "from one of the following modules before it is required:%2">; def err_module_import_in_extern_c : Error< "import of C++ module '%0' appears within extern \"C\" language linkage " "specification">; @@ -7665,4 +7674,55 @@ def warn_profile_data_unprofiled : Warning< } // end of instrumentation issue category +let CategoryName = "Nullability Issue" in { + +def warn_mismatched_nullability_attr : Warning< + "nullability specifier " + "'%select{__|}1%select{nonnull|nullable|null_unspecified}0' " + "conflicts with existing specifier " + "'%select{__|}3%select{nonnull|nullable|null_unspecified}2'">, + InGroup<Nullability>; + +def warn_nullability_declspec : Warning< + "nullability specifier " + "'%select{__nonnull|__nullable|__null_unspecified}0' cannot be applied " + "to non-pointer type %1; did you mean to apply the specifier to the " + "%select{pointer|block pointer|member pointer|function pointer|" + "member function pointer}2?">, + InGroup<NullabilityDeclSpec>, + DefaultError; + +def note_nullability_here : Note< + "'%select{__nonnull|__nullable|__null_unspecified}0' specified here">; + +def err_nullability_nonpointer : Error< + "nullability specifier " + "'%select{__|}1%select{nonnull|nullable|null_unspecified}0' cannot be applied " + "to non-pointer type %2">; + +def warn_nullability_lost : Warning< + "implicit conversion from nullable pointer %0 to non-nullable pointer " + "type %1">, + InGroup<NullableToNonNullConversion>, DefaultIgnore; + +def err_nullability_cs_multilevel : Error< + "nullability keyword " + "'%select{nonnull|nullable|null_unspecified}0' cannot be applied to " + "multi-level pointer type %1">; +def note_nullability_type_specifier : Note< + "use nullability type specifier " + "'%select{__nonnull|__nullable|__null_unspecified}0' to affect the innermost " + "pointer type of %1">; + +def warn_null_resettable_setter : Warning< + "synthesized setter %0 for null_resettable property %1 does not handle nil">, + InGroup<Nullability>; + +def warn_nullability_missing : Warning< + "%select{pointer|block pointer|member pointer}0 is missing a nullability " + "type specifier (__nonnull, __nullable, or __null_unspecified)">, + InGroup<NullabilityCompleteness>; + +} + } // end of sema component. diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index 37e19e1e279d..ac0d7a15e568 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -25,16 +25,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include <memory> -// FIXME: Enhance libsystem to support inode and other fields in stat. -#include <sys/types.h> #include <map> -#ifdef _MSC_VER -typedef unsigned short mode_t; -#endif - -struct stat; - namespace llvm { class MemoryBuffer; } diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index 95d3f0682abd..bef122f093c4 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -127,8 +127,7 @@ LANGOPT(Modules , 1, 0, "modules extension to C") COMPATIBLE_LANGOPT(ModulesDeclUse , 1, 0, "require declaration of module uses") LANGOPT(ModulesSearchAll , 1, 1, "search even non-imported modules to find unresolved references") COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "require declaration of module uses and all headers to be in modules") -LANGOPT(ModulesErrorRecovery, 1, 1, "automatically import modules as needed when performing error recovery") -BENIGN_LANGOPT(ModulesImplicitMaps, 1, 1, "use files called module.modulemap implicitly as module maps") +BENIGN_LANGOPT(ModulesErrorRecovery, 1, 1, "automatically import modules as needed when performing error recovery") BENIGN_LANGOPT(ImplicitModules, 1, 1, "build modules that are not specified via -fmodule-file") COMPATIBLE_LANGOPT(ModulesLocalVisibility, 1, 0, "local submodule visibility") COMPATIBLE_LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro") diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def index 0145db059329..b09f012c4317 100644 --- a/include/clang/Basic/OpenMPKinds.def +++ b/include/clang/Basic/OpenMPKinds.def @@ -84,6 +84,7 @@ OPENMP_DIRECTIVE(critical) OPENMP_DIRECTIVE(taskyield) OPENMP_DIRECTIVE(barrier) OPENMP_DIRECTIVE(taskwait) +OPENMP_DIRECTIVE(taskgroup) OPENMP_DIRECTIVE(flush) OPENMP_DIRECTIVE(ordered) OPENMP_DIRECTIVE(atomic) diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def index 65ababd5ac86..1b528c8d6f69 100644 --- a/include/clang/Basic/Sanitizers.def +++ b/include/clang/Basic/Sanitizers.def @@ -41,6 +41,9 @@ // AddressSanitizer SANITIZER("address", Address) +// Kernel AddressSanitizer (KASan) +SANITIZER("kernel-address", KernelAddress) + // MemorySanitizer SANITIZER("memory", Memory) @@ -87,18 +90,20 @@ SANITIZER("cfi-vcall", CFIVCall) SANITIZER_GROUP("cfi", CFI, CFIDerivedCast | CFIUnrelatedCast | CFINVCall | CFIVCall) -// -fsanitize=undefined-trap includes sanitizers from -fsanitize=undefined -// that can be used without runtime support, generally by providing extra -// -fsanitize-undefined-trap-on-error flag. -SANITIZER_GROUP("undefined-trap", UndefinedTrap, +// Safe Stack +SANITIZER("safe-stack", SafeStack) + +// -fsanitize=undefined includes all the sanitizers which have low overhead, no +// ABI or address space layout implications, and only catch undefined behavior. +SANITIZER_GROUP("undefined", Undefined, Alignment | Bool | ArrayBounds | Enum | FloatCastOverflow | FloatDivideByZero | IntegerDivideByZero | NonnullAttribute | Null | ObjectSize | Return | ReturnsNonnullAttribute | - Shift | SignedIntegerOverflow | Unreachable | VLABound) + Shift | SignedIntegerOverflow | Unreachable | VLABound | + Function | Vptr) -// -fsanitize=undefined includes all the sanitizers which have low overhead, no -// ABI or address space layout implications, and only catch undefined behavior. -SANITIZER_GROUP("undefined", Undefined, UndefinedTrap | Function | Vptr) +// -fsanitize=undefined-trap is an alias for -fsanitize=undefined. +SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined) SANITIZER_GROUP("integer", Integer, SignedIntegerOverflow | UnsignedIntegerOverflow | Shift | diff --git a/include/clang/Basic/Sanitizers.h b/include/clang/Basic/Sanitizers.h index 3b1797e9f539..78c1ddb56f9b 100644 --- a/include/clang/Basic/Sanitizers.h +++ b/include/clang/Basic/Sanitizers.h @@ -52,6 +52,9 @@ struct SanitizerSet { /// \brief Check if a certain (single) sanitizer is enabled. bool has(SanitizerMask K) const; + /// \brief Check if one or more sanitizers are enabled. + bool hasOneOf(SanitizerMask K) const; + /// \brief Enable or disable a certain (single) sanitizer. void set(SanitizerMask K, bool Value); diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index 7569c16412b2..5ce56c0ee1f8 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -16,6 +16,9 @@ #ifndef LLVM_CLANG_BASIC_SPECIFIERS_H #define LLVM_CLANG_BASIC_SPECIFIERS_H +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" + namespace clang { /// \brief Specifies the width of a type, e.g., short, long, or long long. enum TypeSpecifierWidth { @@ -239,6 +242,22 @@ namespace clang { SD_Static, ///< Static storage duration. SD_Dynamic ///< Dynamic storage duration. }; + + /// Describes the nullability of a particular type. + enum class NullabilityKind : uint8_t { + /// Values of this type can never be null. + NonNull = 0, + /// Values of this type can be null. + Nullable, + /// Whether values of this type can be null is (explicitly) + /// unspecified. This captures a (fairly rare) case where we + /// can't conclude anything about the nullability of the type even + /// though it has been considered. + Unspecified + }; + + /// Retrieve the spelling of the given nullability kind. + llvm::StringRef getNullabilitySpelling(NullabilityKind kind); } // end namespace clang #endif // LLVM_CLANG_BASIC_SPECIFIERS_H diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index 750108f39f9a..675e91d866d0 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -77,7 +77,9 @@ def CompoundLiteralExpr : DStmt<Expr>; def ExtVectorElementExpr : DStmt<Expr>; def InitListExpr : DStmt<Expr>; def DesignatedInitExpr : DStmt<Expr>; +def DesignatedInitUpdateExpr : DStmt<Expr>; def ImplicitValueInitExpr : DStmt<Expr>; +def NoInitExpr : DStmt<Expr>; def ParenListExpr : DStmt<Expr>; def VAArgExpr : DStmt<Expr>; def GenericSelectionExpr : DStmt<Expr>; @@ -197,6 +199,7 @@ def OMPTaskDirective : DStmt<OMPExecutableDirective>; def OMPTaskyieldDirective : DStmt<OMPExecutableDirective>; def OMPBarrierDirective : DStmt<OMPExecutableDirective>; def OMPTaskwaitDirective : DStmt<OMPExecutableDirective>; +def OMPTaskgroupDirective : DStmt<OMPExecutableDirective>; def OMPFlushDirective : DStmt<OMPExecutableDirective>; def OMPOrderedDirective : DStmt<OMPExecutableDirective>; def OMPAtomicDirective : DStmt<OMPExecutableDirective>; diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h index eece4e8de13c..b4740c595226 100644 --- a/include/clang/Basic/TargetBuiltins.h +++ b/include/clang/Basic/TargetBuiltins.h @@ -73,12 +73,12 @@ namespace clang { }; } - /// \brief R600 builtins - namespace R600 { + /// \brief AMDGPU builtins + namespace AMDGPU { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, #define BUILTIN(ID, TYPE, ATTRS) BI##ID, - #include "clang/Basic/BuiltinsR600.def" + #include "clang/Basic/BuiltinsAMDGPU.def" LastTSBuiltin }; } diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 8406205c7fd9..e415733189ab 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -363,6 +363,10 @@ public: return *LongDoubleFormat; } + /// \brief Return true if the 'long double' type should be mangled like + /// __float128. + virtual bool useFloat128ManglingForLongDouble() const { return false; } + /// \brief Return the value for the C99 FLT_EVAL_METHOD macro. virtual unsigned getFloatEvalMethod() const { return 0; } diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h index 97825394202f..ca0cca78bfc8 100644 --- a/include/clang/Basic/TargetOptions.h +++ b/include/clang/Basic/TargetOptions.h @@ -45,6 +45,8 @@ public: /// The list of target specific features to enable or disable -- this should /// be a list of strings starting with by '+' or '-'. std::vector<std::string> Features; + + std::vector<std::string> Reciprocals; }; } // end namespace clang diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index b6d983b55245..67b9933562eb 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -548,6 +548,11 @@ ALIAS("__typeof__" , typeof , KEYALL) ALIAS("__volatile" , volatile , KEYALL) ALIAS("__volatile__" , volatile , KEYALL) +// Type nullability. +KEYWORD(__nonnull , KEYALL) +KEYWORD(__nullable , KEYALL) +KEYWORD(__null_unspecified , KEYALL) + // Microsoft extensions which should be disabled in strict conformance mode KEYWORD(__ptr64 , KEYMS) KEYWORD(__ptr32 , KEYMS) diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index 933f204bfb52..c6f879513eac 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -803,6 +803,13 @@ def VREINTERPRET def VFMA : SInst<"vfma", "dddd", "fQf">; //////////////////////////////////////////////////////////////////////////////// +// fp16 vector operations +def SCALAR_HALF_GET_LANE : IOpInst<"vget_lane", "sdi", "h", OP_SCALAR_HALF_GET_LN>; +def SCALAR_HALF_SET_LANE : IOpInst<"vset_lane", "dsdi", "h", OP_SCALAR_HALF_SET_LN>; +def SCALAR_HALF_GET_LANEQ : IOpInst<"vget_lane", "sdi", "Qh", OP_SCALAR_HALF_GET_LNQ>; +def SCALAR_HALF_SET_LANEQ : IOpInst<"vset_lane", "dsdi", "Qh", OP_SCALAR_HALF_SET_LNQ>; + +//////////////////////////////////////////////////////////////////////////////// // AArch64 Intrinsics let ArchGuard = "defined(__aarch64__)" in { @@ -1594,10 +1601,4 @@ def SCALAR_SQRDMULH_LANEQ : SOpInst<"vqrdmulh_laneq", "ssji", "SsSi", OP_SCALAR_ def SCALAR_VDUP_LANE : IInst<"vdup_lane", "sdi", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">; def SCALAR_VDUP_LANEQ : IInst<"vdup_laneq", "sji", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">; - -// FIXME: Rename so it is obvious this only applies to halfs. -def SCALAR_HALF_GET_LANE : IOpInst<"vget_lane", "sdi", "h", OP_SCALAR_HALF_GET_LN>; -def SCALAR_HALF_SET_LANE : IOpInst<"vset_lane", "dsdi", "h", OP_SCALAR_HALF_SET_LN>; -def SCALAR_HALF_GET_LANEQ : IOpInst<"vget_lane", "sdi", "Qh", OP_SCALAR_HALF_GET_LNQ>; -def SCALAR_HALF_SET_LANEQ : IOpInst<"vset_lane", "dsdi", "Qh", OP_SCALAR_HALF_SET_LNQ>; } diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 1622c41fe13a..f2ef71e2f919 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -301,6 +301,10 @@ def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"<N>">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; def verify : Flag<["-"], "verify">, HelpText<"Verify diagnostic output using comment directives">; +def verify_ignore_unexpected : Flag<["-"], "verify-ignore-unexpected">, + HelpText<"Ignore unexpected diagnostic messages">; +def verify_ignore_unexpected_EQ : CommaJoined<["-"], "verify-ignore-unexpected=">, + HelpText<"Ignore unexpected diagnostic messages">; def Wno_rewrite_macros : Flag<["-"], "Wno-rewrite-macros">, HelpText<"Silence ObjC rewriting warnings">; diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td index e217cb755f6e..01913be93d56 100644 --- a/include/clang/Driver/CLCompatOptions.td +++ b/include/clang/Driver/CLCompatOptions.td @@ -139,6 +139,8 @@ def _SLASH_wd4005 : CLFlag<"wd4005">, Alias<W_Joined>, AliasArgs<["no-macro-redefined"]>; def _SLASH_wd4996 : CLFlag<"wd4996">, Alias<W_Joined>, AliasArgs<["no-deprecated-declarations"]>; +def _SLASH_wd4910 : CLFlag<"wd4910">, Alias<W_Joined>, + AliasArgs<["no-dllexport-explicit-instantiation-decl"]>; def _SLASH_vd : CLJoined<"vd">, HelpText<"Control vtordisp placement">, Alias<vtordisp_mode_EQ>; def _SLASH_Zc_sizedDealloc : CLFlag<"Zc:sizedDealloc">, @@ -202,7 +204,6 @@ def _SLASH_Fi : CLCompileJoined<"Fi">, def _SLASH_Fo : CLCompileJoined<"Fo">, HelpText<"Set output object file, or directory (ends in / or \\)">, MetaVarName<"<file or directory>">; -def _SLASH_GL : CLFlag<"GL">, Alias<flto>; def _SLASH_LD : CLFlag<"LD">, HelpText<"Create DLL">; def _SLASH_LDd : CLFlag<"LDd">, HelpText<"Create debug DLL">; def _SLASH_link : CLRemainingArgs<"link">, @@ -287,6 +288,7 @@ def _SLASH_G2 : CLFlag<"G2">; def _SLASH_Ge : CLFlag<"Ge">; def _SLASH_Gh : CLFlag<"Gh">; def _SLASH_GH : CLFlag<"GH">; +def _SLASH_GL : CLFlag<"GL">; def _SLASH_GL_ : CLFlag<"GL-">; def _SLASH_Gm : CLFlag<"Gm">; def _SLASH_Gm_ : CLFlag<"Gm-">; diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index 09521c2bae3f..d7bb1d2283fb 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -91,7 +91,7 @@ public: /// The path to the compiler resource directory. std::string ResourceDir; - /// A prefix directory used to emulated a limited subset of GCC's '-Bprefix' + /// A prefix directory used to emulate a limited subset of GCC's '-Bprefix' /// functionality. /// FIXME: This type of customization should be removed in favor of the /// universal driver when it is ready. @@ -402,7 +402,7 @@ public: /// handle this action. bool ShouldUseClangCompiler(const JobAction &JA) const; - bool IsUsingLTO(const ToolChain &TC, const llvm::opt::ArgList &Args) const; + bool IsUsingLTO(const llvm::opt::ArgList &Args) const; private: /// \brief Retrieves a ToolChain for a particular target triple. diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 7e39a9ae5b22..aae377693551 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -561,8 +561,13 @@ def fno_sanitize_recover_EQ : CommaJoined<["-"], "fno-sanitize-recover=">, Group<f_clang_Group>, HelpText<"Disable recovery for specified sanitizers">; +def fsanitize_trap_EQ : CommaJoined<["-"], "fsanitize-trap=">, Group<f_clang_Group>, + Flags<[CC1Option, CoreOption]>, + HelpText<"Enable trapping for specified sanitizers">; +def fno_sanitize_trap_EQ : CommaJoined<["-"], "fno-sanitize-trap=">, Group<f_clang_Group>, + HelpText<"Disable trapping for specified sanitizers">; def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on-error">, - Group<f_clang_Group>, Flags<[CC1Option]>; + Group<f_clang_Group>; def fno_sanitize_undefined_trap_on_error : Flag<["-"], "fno-sanitize-undefined-trap-on-error">, Group<f_clang_Group>; def fsanitize_link_cxx_runtime : Flag<["-"], "fsanitize-link-c++-runtime">, @@ -691,9 +696,10 @@ def fmodules_validate_system_headers : Flag<["-"], "fmodules-validate-system-hea def fmodules : Flag <["-"], "fmodules">, Group<f_Group>, Flags<[DriverOption, CC1Option]>, HelpText<"Enable the 'modules' language feature">; -def fmodule_maps : Flag <["-"], "fmodule-maps">, Group<f_Group>, - Flags<[DriverOption,CC1Option]>, - HelpText<"Read module maps to understand the structure of library headers">; +def fimplicit_module_maps : Flag <["-"], "fimplicit-module-maps">, Group<f_Group>, + Flags<[DriverOption, CC1Option]>, + HelpText<"Implicitly search the file system for module map files.">; +def fmodule_maps : Flag <["-"], "fmodule-maps">, Alias<fimplicit_module_maps>; def fmodule_name : JoinedOrSeparate<["-"], "fmodule-name=">, Group<f_Group>, Flags<[DriverOption,CC1Option]>, MetaVarName<"<name>">, HelpText<"Specify the name of the module to build">; @@ -713,12 +719,6 @@ def fmodules_strict_decluse : Flag <["-"], "fmodules-strict-decluse">, Group<f_G HelpText<"Like -fmodules-decluse but requires all headers to be in modules">; def fno_modules_search_all : Flag <["-"], "fno-modules-search-all">, Group<f_Group>, Flags<[DriverOption, CC1Option]>; -def fmodules_implicit_maps : - Flag <["-"], "fmodules-implicit-maps">, - Group<f_Group>, Flags<[DriverOption, CC1Option]>; -def fno_modules_implicit_maps : - Flag <["-"], "fno-modules-implicit-maps">, - Group<f_Group>, Flags<[DriverOption, CC1Option]>; def fno_implicit_modules : Flag <["-"], "fno-implicit-modules">, Group<f_Group>, Flags<[DriverOption, CC1Option]>; @@ -780,8 +780,9 @@ def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group<f_Gr Flags<[CC1Option]>, HelpText<"Disallow merging of constants">; def fno_modules : Flag <["-"], "fno-modules">, Group<f_Group>, Flags<[DriverOption]>; -def fno_module_maps : Flag <["-"], "fno-module-maps">, Group<f_Group>, +def fno_implicit_module_maps : Flag <["-"], "fno-implicit-module-maps">, Group<f_Group>, Flags<[DriverOption]>; +def fno_module_maps : Flag <["-"], "fno-module-maps">, Alias<fno_implicit_module_maps>; def fno_modules_decluse : Flag <["-"], "fno-modules-decluse">, Group<f_Group>, Flags<[DriverOption]>; def fno_modules_strict_decluse : Flag <["-"], "fno-strict-modules-decluse">, Group<f_Group>, @@ -1338,6 +1339,8 @@ def msoft_float : Flag<["-"], "msoft-float">, Group<m_Group>, Flags<[CC1Option]> def mno_implicit_float : Flag<["-"], "mno-implicit-float">, Group<m_Group>, HelpText<"Don't generate implicit floating point instructions">; def mimplicit_float : Flag<["-"], "mimplicit-float">, Group<m_Group>; +def mrecip : Flag<["-"], "mrecip">, Group<m_Group>; +def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group<m_Group>, Flags<[CC1Option]>; def msse2 : Flag<["-"], "msse2">, Group<m_x86_Features_Group>; def msse3 : Flag<["-"], "msse3">, Group<m_x86_Features_Group>; def msse4a : Flag<["-"], "msse4a">, Group<m_x86_Features_Group>; diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h index bfa63e7734fb..ceba912dad13 100644 --- a/include/clang/Driver/SanitizerArgs.h +++ b/include/clang/Driver/SanitizerArgs.h @@ -23,13 +23,13 @@ class ToolChain; class SanitizerArgs { SanitizerSet Sanitizers; SanitizerSet RecoverableSanitizers; + SanitizerSet TrapSanitizers; std::vector<std::string> BlacklistFiles; int CoverageFeatures; int MsanTrackOrigins; int AsanFieldPadding; bool AsanZeroBaseShadow; - bool UbsanTrapOnError; bool AsanSharedRuntime; bool LinkCXXRuntimes; @@ -47,10 +47,12 @@ class SanitizerArgs { } bool needsUbsanRt() const; bool needsDfsanRt() const { return Sanitizers.has(SanitizerKind::DataFlow); } + bool needsSafeStackRt() const { + return Sanitizers.has(SanitizerKind::SafeStack); + } bool requiresPIE() const; bool needsUnwindTables() const; - bool needsLTO() const; bool linkCXXRuntimes() const { return LinkCXXRuntimes; } void addArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index 560df19e25ce..aba18c9916c3 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -10,6 +10,7 @@ #ifndef LLVM_CLANG_DRIVER_TOOLCHAIN_H #define LLVM_CLANG_DRIVER_TOOLCHAIN_H +#include "clang/Basic/Sanitizers.h" #include "clang/Driver/Action.h" #include "clang/Driver/Multilib.h" #include "clang/Driver/Types.h" @@ -164,7 +165,10 @@ public: } /// Choose a tool to use to handle the action \p JA. - Tool *SelectTool(const JobAction &JA) const; + /// + /// This can be overridden when a particular ToolChain needs to use + /// a C compiler other than Clang. + virtual Tool *SelectTool(const JobAction &JA) const; // Helper methods @@ -345,6 +349,9 @@ public: virtual bool AddFastMathRuntimeIfAvailable(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + + /// \brief Return sanitizers which are available in this toolchain. + virtual SanitizerMask getSupportedSanitizers() const; }; } // end namespace driver diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index 3fdee99f3e55..ad87a057a6a7 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -210,10 +210,10 @@ struct FormatStyle { enum ShortFunctionStyle { /// \brief Never merge functions into a single line. SFS_None, - /// \brief Only merge functions defined inside a class. - SFS_Inline, /// \brief Only merge empty functions. SFS_Empty, + /// \brief Only merge functions defined inside a class. Implies "empty". + SFS_Inline, /// \brief Merge all functions fitting on a single line. SFS_All, }; @@ -287,6 +287,11 @@ struct FormatStyle { bool AlwaysBreakTemplateDeclarations; /// \brief If \c true, always break before multiline string literals. + /// + /// This flag is mean to make cases where there are multiple multiline strings + /// in a file look more consistent. Thus, it will only take effect if wrapping + /// the string at that point leads to it being indented + /// \c ContinuationIndentWidth spaces from the start of the line. bool AlwaysBreakBeforeMultilineStrings; /// \brief Different ways to use tab in formatting. diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 405774b811c8..2d38352d22a8 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -56,6 +56,7 @@ class FileEntry; class FileManager; class HeaderSearch; class Preprocessor; +class PCHContainerOperations; class SourceManager; class TargetInfo; class ASTFrontendAction; @@ -422,7 +423,8 @@ private: explicit ASTUnit(bool MainFileIsAST); void CleanTemporaryFiles(); - bool Parse(std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer); + bool Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, + std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer); struct ComputedPreamble { llvm::MemoryBuffer *Buffer; @@ -442,6 +444,7 @@ private: unsigned MaxLines); std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble( + std::shared_ptr<PCHContainerOperations> PCHContainerOps, const CompilerInvocation &PreambleInvocationIn, bool AllowRebuild = true, unsigned MaxLines = 0); void RealizeTopLevelDeclsFromPreamble(); @@ -715,12 +718,16 @@ public: /// /// \param Filename - The AST file to load. /// + /// \param PCHContainerOps - The PCHContainerOperations to use for loading and + /// creating modules. /// \param Diags - The diagnostics engine to use for reporting errors; its /// lifetime is expected to extend past that of the returned ASTUnit. /// /// \returns - The initialized ASTUnit or null if the AST failed to load. static std::unique_ptr<ASTUnit> LoadFromASTFile( - const std::string &Filename, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + const std::string &Filename, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls = false, ArrayRef<RemappedFile> RemappedFiles = None, bool CaptureDiagnostics = false, bool AllowPCHWithCompilerErrors = false, @@ -735,8 +742,10 @@ private: /// /// \returns \c true if a catastrophic failure occurred (which means that the /// \c ASTUnit itself is invalid), or \c false otherwise. - bool LoadFromCompilerInvocation(bool PrecompilePreamble); - + bool LoadFromCompilerInvocation( + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + bool PrecompilePreamble); + public: /// \brief Create an ASTUnit from a source file, via a CompilerInvocation @@ -745,6 +754,9 @@ public: /// \param CI - The compiler invocation to use; it must have exactly one input /// source file. The ASTUnit takes ownership of the CompilerInvocation object. /// + /// \param PCHContainerOps - The PCHContainerOperations to use for loading and + /// creating modules. + /// /// \param Diags - The diagnostics engine to use for reporting errors; its /// lifetime is expected to extend past that of the returned ASTUnit. /// @@ -765,7 +777,9 @@ public: /// created ASTUnit was passed in \p Unit then the caller can check that. /// static ASTUnit *LoadFromCompilerInvocationAction( - CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + CompilerInvocation *CI, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, ASTFrontendAction *Action = nullptr, ASTUnit *Unit = nullptr, bool Persistent = true, StringRef ResourceFilesPath = StringRef(), bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, @@ -780,15 +794,20 @@ public: /// \param CI - The compiler invocation to use; it must have exactly one input /// source file. The ASTUnit takes ownership of the CompilerInvocation object. /// + /// \param PCHContainerOps - The PCHContainerOperations to use for loading and + /// creating modules. + /// /// \param Diags - The diagnostics engine to use for reporting errors; its /// lifetime is expected to extend past that of the returned ASTUnit. // // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we // shouldn't need to specify them at construction time. static std::unique_ptr<ASTUnit> LoadFromCompilerInvocation( - CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, - bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, - bool PrecompilePreamble = false, TranslationUnitKind TUKind = TU_Complete, + CompilerInvocation *CI, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, bool OnlyLocalDecls = false, + bool CaptureDiagnostics = false, bool PrecompilePreamble = false, + TranslationUnitKind TUKind = TU_Complete, bool CacheCodeCompletionResults = false, bool IncludeBriefCommentsInCodeCompletion = false, bool UserFilesAreVolatile = false); @@ -800,6 +819,9 @@ public: /// /// \param ArgEnd - The end of the argument vector. /// + /// \param PCHContainerOps - The PCHContainerOperations to use for loading and + /// creating modules. + /// /// \param Diags - The diagnostics engine to use for reporting errors; its /// lifetime is expected to extend past that of the returned ASTUnit. /// @@ -813,6 +835,7 @@ public: // shouldn't need to specify them at construction time. static ASTUnit *LoadFromCommandLine( const char **ArgBegin, const char **ArgEnd, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath, bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, ArrayRef<RemappedFile> RemappedFiles = None, @@ -828,8 +851,9 @@ public: /// were originally used to produce this translation unit. /// /// \returns True if a failure occurred that causes the ASTUnit not to - /// contain any translation-unit information, false otherwise. - bool Reparse(ArrayRef<RemappedFile> RemappedFiles = None); + /// contain any translation-unit information, false otherwise. + bool Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, + ArrayRef<RemappedFile> RemappedFiles = None); /// \brief Perform code completion at the given file, line, and /// column within this translation unit. @@ -852,14 +876,14 @@ public: /// FIXME: The Diag, LangOpts, SourceMgr, FileMgr, StoredDiagnostics, and /// OwnedBuffers parameters are all disgusting hacks. They will go away. void CodeComplete(StringRef File, unsigned Line, unsigned Column, - ArrayRef<RemappedFile> RemappedFiles, - bool IncludeMacros, bool IncludeCodePatterns, - bool IncludeBriefComments, + ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros, + bool IncludeCodePatterns, bool IncludeBriefComments, CodeCompleteConsumer &Consumer, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr, FileManager &FileMgr, SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics, - SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers); + SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers); /// \brief Save this translation unit to a file with the given name. /// diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index adf1c879d40e..d34cf0cad1c9 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -120,8 +120,6 @@ CODEGENOPT(SanitizeCoverageTraceCmp, 1, 0) ///< Enable cmp instruction tracing ///< in sanitizer coverage. CODEGENOPT(SanitizeCoverage8bitCounters, 1, 0) ///< Use 8-bit frequency counters ///< in sanitizer coverage. -CODEGENOPT(SanitizeUndefinedTrapOnError, 1, 0) ///< Set on - /// -fsanitize-undefined-trap-on-error CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float. CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition. diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index 0c5ce5813769..66597bd0af8e 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -197,6 +197,9 @@ public: /// continued when possible). SanitizerSet SanitizeRecover; + /// Set of sanitizer checks that trap rather than diagnose. + SanitizerSet SanitizeTrap; + public: // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 8d0d939d7811..9cd806c99b85 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ #include "clang/AST/ASTConsumer.h" +#include "clang/Frontend/PCHContainerOperations.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/CompilerInvocation.h" @@ -109,6 +110,9 @@ class CompilerInstance : public ModuleLoader { /// \brief The module dependency collector for crashdumps std::shared_ptr<ModuleDependencyCollector> ModuleDepCollector; + /// \brief The module provider. + std::shared_ptr<PCHContainerOperations> ThePCHContainerOperations; + /// \brief The dependency file generator. std::unique_ptr<DependencyFileGenerator> TheDependencyFileGenerator; @@ -172,7 +176,10 @@ class CompilerInstance : public ModuleLoader { CompilerInstance(const CompilerInstance &) = delete; void operator=(const CompilerInstance &) = delete; public: - explicit CompilerInstance(bool BuildingModule = false); + explicit CompilerInstance( + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<RawPCHContainerOperations>(), + bool BuildingModule = false); ~CompilerInstance() override; /// @name High-Level Operations @@ -492,6 +499,10 @@ public: void setModuleDepCollector( std::shared_ptr<ModuleDependencyCollector> Collector); + std::shared_ptr<PCHContainerOperations> getPCHContainerOperations() const { + return ThePCHContainerOperations; + } + /// } /// @name Code Completion /// { @@ -605,6 +616,7 @@ public: static IntrusiveRefCntPtr<ASTReader> createPCHExternalASTSource( StringRef Path, const std::string &Sysroot, bool DisablePCHValidation, bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context, + const PCHContainerOperations &PCHContainerOps, void *DeserializationListener, bool OwnDeserializationListener, bool Preamble, bool UseGlobalModuleIndex); diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index b1508287c85f..f61775f014f8 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -85,10 +85,9 @@ public: /// create the PCHGenerator instance returned by CreateASTConsumer. /// /// \returns true if an error occurred, false otherwise. - static raw_ostream *ComputeASTConsumerArguments(CompilerInstance &CI, - StringRef InFile, - std::string &Sysroot, - std::string &OutputFile); + static raw_pwrite_stream * + ComputeASTConsumerArguments(CompilerInstance &CI, StringRef InFile, + std::string &Sysroot, std::string &OutputFile); }; class GenerateModuleAction : public ASTFrontendAction { @@ -118,10 +117,10 @@ public: /// create the PCHGenerator instance returned by CreateASTConsumer. /// /// \returns true if an error occurred, false otherwise. - raw_ostream *ComputeASTConsumerArguments(CompilerInstance &CI, - StringRef InFile, - std::string &Sysroot, - std::string &OutputFile); + raw_pwrite_stream *ComputeASTConsumerArguments(CompilerInstance &CI, + StringRef InFile, + std::string &Sysroot, + std::string &OutputFile); }; class SyntaxOnlyAction : public ASTFrontendAction { diff --git a/include/clang/Frontend/PCHContainerOperations.h b/include/clang/Frontend/PCHContainerOperations.h new file mode 100644 index 000000000000..949ee63c615d --- /dev/null +++ b/include/clang/Frontend/PCHContainerOperations.h @@ -0,0 +1,76 @@ +//===--- Frontend/PCHContainerOperations.h - PCH Containers -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PCH_CONTAINER_OPERATIONS_H +#define LLVM_CLANG_PCH_CONTAINER_OPERATIONS_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/MemoryBuffer.h" +#include <memory> + +namespace llvm { +class raw_pwrite_stream; +class BitstreamReader; +} + +namespace clang { + +class ASTConsumer; +class CodeGenOptions; +class DiagnosticsEngine; +class HeaderSearchOptions; +class LangOptions; +class PreprocessorOptions; +class TargetOptions; + +struct PCHBuffer { + bool IsComplete; + llvm::SmallVector<char, 0> Data; +}; + +/// \brief This abstract interface provides operations for creating +/// and unwrapping containers for serialized ASTs (precompiled headers +/// and clang modules). +class PCHContainerOperations { +public: + virtual ~PCHContainerOperations(); + /// \brief Return an ASTConsumer that can be chained with a + /// PCHGenerator that produces a wrapper file format containing a + /// serialized AST bitstream. + virtual std::unique_ptr<ASTConsumer> CreatePCHContainerGenerator( + DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO, + const PreprocessorOptions &PPO, const TargetOptions &TO, + const LangOptions &LO, const std::string &MainFileName, + const std::string &OutputFileName, llvm::raw_pwrite_stream *OS, + std::shared_ptr<PCHBuffer> Buffer) const = 0; + + /// \brief Initialize an llvm::BitstreamReader with the serialized AST inside + /// the PCH container Buffer. + virtual void ExtractPCH(llvm::MemoryBufferRef Buffer, + llvm::BitstreamReader &StreamFile) const = 0; +}; + +/// \brief Implements a raw pass-through PCH container. +class RawPCHContainerOperations : public PCHContainerOperations { + /// \brief Return an ASTConsumer that can be chained with a + /// PCHGenerator that writes the module to a flat file. + std::unique_ptr<ASTConsumer> CreatePCHContainerGenerator( + DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO, + const PreprocessorOptions &PPO, const TargetOptions &TO, + const LangOptions &LO, const std::string &MainFileName, + const std::string &OutputFileName, llvm::raw_pwrite_stream *OS, + std::shared_ptr<PCHBuffer> Buffer) const override; + + /// \brief Initialize an llvm::BitstreamReader with Buffer. + void ExtractPCH(llvm::MemoryBufferRef Buffer, + llvm::BitstreamReader &StreamFile) const override; +}; +} + +#endif diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h index cd0ebf611201..639965343c45 100644 --- a/include/clang/Frontend/Utils.h +++ b/include/clang/Frontend/Utils.h @@ -45,6 +45,7 @@ class HeaderSearch; class HeaderSearchOptions; class IdentifierTable; class LangOptions; +class PCHContainerOperations; class Preprocessor; class PreprocessorOptions; class PreprocessorOutputOptions; @@ -61,8 +62,8 @@ void ApplyHeaderSearchOptions(HeaderSearch &HS, /// InitializePreprocessor - Initialize the preprocessor getting it and the /// environment ready to process a single file. -void InitializePreprocessor(Preprocessor &PP, - const PreprocessorOptions &PPOpts, +void InitializePreprocessor(Preprocessor &PP, const PreprocessorOptions &PPOpts, + const PCHContainerOperations &PCHContainerOps, const FrontendOptions &FEOpts); /// DoPrintPreprocessedInput - Implement -E mode. diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h index 316134c405b3..c9c32609f19b 100644 --- a/include/clang/Lex/HeaderSearchOptions.h +++ b/include/clang/Lex/HeaderSearchOptions.h @@ -98,8 +98,9 @@ public: /// Note: Only used for testing! unsigned DisableModuleHash : 1; - /// \brief Interpret module maps. This option is implied by full modules. - unsigned ModuleMaps : 1; + /// \brief Implicit module maps. This option is enabld by default when + /// modules is enabled. + unsigned ImplicitModuleMaps : 1; /// \brief Set the 'home directory' of a module map file to the current /// working directory (or the home directory of the module map file that @@ -166,7 +167,7 @@ public: public: HeaderSearchOptions(StringRef _Sysroot = "/") - : Sysroot(_Sysroot), DisableModuleHash(0), ModuleMaps(0), + : Sysroot(_Sysroot), DisableModuleHash(0), ImplicitModuleMaps(0), ModuleMapFileHomeIsCwd(0), ModuleCachePruneInterval(7*24*60*60), ModuleCachePruneAfter(31*24*60*60), diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index e41efc5d419d..0bbcfac3b81b 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -268,15 +268,10 @@ public: /// /// \param File The header file that is likely to be included. /// - /// \param RequestingModule Specifies the module the header is intended to be - /// used from. Used to disambiguate if a header is present in multiple - /// modules. - /// /// \returns The module KnownHeader, which provides the module that owns the /// given header file. The KnownHeader is default constructed to indicate /// that no module owns this header file. - KnownHeader findModuleForHeader(const FileEntry *File, - Module *RequestingModule = nullptr); + KnownHeader findModuleForHeader(const FileEntry *File); /// \brief Reports errors if a module must not include a specific file. /// diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index f6e61c0e7ad6..439a28041e2d 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -256,6 +256,10 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// \#pragma clang arc_cf_code_audited begin. SourceLocation PragmaARCCFCodeAuditedLoc; + /// \brief The source location of the currently-active + /// \#pragma clang assume_nonnull begin. + SourceLocation PragmaAssumeNonNullLoc; + /// \brief True if we hit the code-completion point. bool CodeCompletionReached; @@ -455,8 +459,9 @@ class Preprocessor : public RefCountedBase<Preprocessor> { void overrideActiveModuleMacros(Preprocessor &PP, IdentifierInfo *II) { if (auto *Info = getModuleInfo(PP, II)) { - for (auto *Active : Info->ActiveModuleMacros) - Info->OverriddenMacros.push_back(Active); + Info->OverriddenMacros.insert(Info->OverriddenMacros.end(), + Info->ActiveModuleMacros.begin(), + Info->ActiveModuleMacros.end()); Info->ActiveModuleMacros.clear(); Info->IsAmbiguous = false; } @@ -1249,6 +1254,20 @@ public: PragmaARCCFCodeAuditedLoc = Loc; } + /// \brief The location of the currently-active \#pragma clang + /// assume_nonnull begin. + /// + /// Returns an invalid location if there is no such pragma active. + SourceLocation getPragmaAssumeNonNullLoc() const { + return PragmaAssumeNonNullLoc; + } + + /// \brief Set the location of the currently-active \#pragma clang + /// assume_nonnull begin. An invalid location ends the pragma. + void setPragmaAssumeNonNullLoc(SourceLocation Loc) { + PragmaAssumeNonNullLoc = Loc; + } + /// \brief Set the directory in which the main file should be considered /// to have been found, if it is not a real file. void setMainFileDir(const DirectoryEntry *Dir) { diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index e0878093402a..7ba22b2f626c 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -94,6 +94,13 @@ public: /// "if (Tok.is(tok::l_brace)) {...}". bool is(tok::TokenKind K) const { return Kind == K; } bool isNot(tok::TokenKind K) const { return Kind != K; } + bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const { + return is(K1) || is(K2); + } + template <typename... Ts> + bool isOneOf(tok::TokenKind K1, tok::TokenKind K2, Ts... Ks) const { + return is(K1) || isOneOf(K2, Ks...); + } /// \brief Return true if this is a raw identifier (when lexing /// in raw mode) or a non-keyword identifier (when lexing in non-raw mode). diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index caba77b74c67..7042a1ef6e29 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -303,6 +303,12 @@ public: return true; } + /// Retrieve the underscored keyword (__nonnull, __nullable) that corresponds + /// to the given nullability kind. + IdentifierInfo *getNullabilityKeyword(NullabilityKind nullability) { + return Actions.getNullabilityKeyword(nullability); + } + private: //===--------------------------------------------------------------------===// // Low-Level token peeking and consumption methods. @@ -620,6 +626,16 @@ private: const char *&PrevSpec, unsigned &DiagID, bool &isInvalid); + /// Returns true if the current token is the identifier 'instancetype'. + /// + /// Should only be used in Objective-C language modes. + bool isObjCInstancetype() { + assert(getLangOpts().ObjC1); + if (!Ident_instancetype) + Ident_instancetype = PP.getIdentifierInfo("instancetype"); + return Tok.getIdentifierInfo() == Ident_instancetype; + } + /// TryKeywordIdentFallback - For compatibility with system headers using /// keywords as identifiers, attempt to convert the current token to an /// identifier and optionally disable the keyword for the remainder of the @@ -1282,6 +1298,7 @@ private: // Definitions for Objective-c context sensitive keywords recognition. enum ObjCTypeQual { objc_in=0, objc_out, objc_inout, objc_oneway, objc_bycopy, objc_byref, + objc_nonnull, objc_nullable, objc_null_unspecified, objc_NumQuals }; IdentifierInfo *ObjCTypeQuals[objc_NumQuals]; @@ -1685,7 +1702,8 @@ private: DSC_trailing, // C++11 trailing-type-specifier in a trailing return type DSC_alias_declaration, // C++11 type-specifier-seq in an alias-declaration DSC_top_level, // top-level/namespace declaration context - DSC_template_type_arg // template type argument context + DSC_template_type_arg, // template type argument context + DSC_objc_method_result, // ObjC method result context, enables 'instancetype' }; /// Is this a context in which we are parsing just a type-specifier (or @@ -1695,6 +1713,7 @@ private: case DSC_normal: case DSC_class: case DSC_top_level: + case DSC_objc_method_result: return false; case DSC_template_type_arg: @@ -2106,6 +2125,7 @@ private: void ParseBorlandTypeAttributes(ParsedAttributes &attrs); void ParseOpenCLAttributes(ParsedAttributes &attrs); void ParseOpenCLQualifiers(ParsedAttributes &Attrs); + void ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs); VersionTuple ParseVersionTuple(SourceRange &Range); void ParseAvailabilityAttribute(IdentifierInfo &Availability, diff --git a/include/clang/Rewrite/Frontend/FixItRewriter.h b/include/clang/Rewrite/Frontend/FixItRewriter.h index ad828e55ae88..3b1b31e0cdee 100644 --- a/include/clang/Rewrite/Frontend/FixItRewriter.h +++ b/include/clang/Rewrite/Frontend/FixItRewriter.h @@ -27,7 +27,7 @@ class FileEntry; class FixItOptions { public: - FixItOptions() : FixWhatYouCan(false), + FixItOptions() : InPlace(false), FixWhatYouCan(false), FixOnlyWarnings(false), Silent(false) { } virtual ~FixItOptions(); @@ -41,6 +41,10 @@ public: /// virtual std::string RewriteFilename(const std::string &Filename, int &fd) = 0; + /// True if files should be updated in place. RewriteFilename is only called + /// if this is false. + bool InPlace; + /// \brief Whether to abort fixing a file when not all errors could be fixed. bool FixWhatYouCan; diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index 58b1b9ee2436..4d18633cd338 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -81,6 +81,8 @@ public: AS_Declspec, /// __ptr16, alignas(...), etc. AS_Keyword, + /// Context-sensitive version of a keyword attribute. + AS_ContextSensitiveKeyword, /// #pragma ... AS_Pragma }; @@ -343,14 +345,20 @@ public: bool isAlignasAttribute() const { // FIXME: Use a better mechanism to determine this. - return getKind() == AT_Aligned && SyntaxUsed == AS_Keyword; + return getKind() == AT_Aligned && isKeywordAttribute(); } bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; } bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11 || isAlignasAttribute(); } - bool isKeywordAttribute() const { return SyntaxUsed == AS_Keyword; } + bool isKeywordAttribute() const { + return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword; + } + + bool isContextSensitiveKeywordAttribute() const { + return SyntaxUsed == AS_ContextSensitiveKeyword; + } bool isInvalid() const { return Invalid; } void setInvalid(bool b = true) const { Invalid = b; } diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index de39d83bded4..2ec3286ad799 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -31,6 +31,7 @@ #include "clang/Lex/Token.h" #include "clang/Sema/AttributeList.h" #include "clang/Sema/Ownership.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" @@ -785,7 +786,8 @@ public: DQ_Out = 0x4, DQ_Bycopy = 0x8, DQ_Byref = 0x10, - DQ_Oneway = 0x20 + DQ_Oneway = 0x20, + DQ_CSNullability = 0x40 }; /// PropertyAttributeKind - list of property attributes. @@ -802,17 +804,22 @@ public: DQ_PR_atomic = 0x100, DQ_PR_weak = 0x200, DQ_PR_strong = 0x400, - DQ_PR_unsafe_unretained = 0x800 + DQ_PR_unsafe_unretained = 0x800, + DQ_PR_nullability = 0x1000, + DQ_PR_null_resettable = 0x2000 }; - ObjCDeclSpec() : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr), - GetterName(nullptr), SetterName(nullptr) { } + Nullability(0), GetterName(nullptr), SetterName(nullptr) { } + ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; } void setObjCDeclQualifier(ObjCDeclQualifier DQVal) { objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); } + void clearObjCDeclQualifier(ObjCDeclQualifier DQVal) { + objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier & ~DQVal); + } ObjCPropertyAttributeKind getPropertyAttributes() const { return ObjCPropertyAttributeKind(PropertyAttributes); @@ -822,6 +829,28 @@ public: (ObjCPropertyAttributeKind)(PropertyAttributes | PRVal); } + NullabilityKind getNullability() const { + assert(((getObjCDeclQualifier() & DQ_CSNullability) || + (getPropertyAttributes() & DQ_PR_nullability)) && + "Objective-C declspec doesn't have nullability"); + return static_cast<NullabilityKind>(Nullability); + } + + SourceLocation getNullabilityLoc() const { + assert(((getObjCDeclQualifier() & DQ_CSNullability) || + (getPropertyAttributes() & DQ_PR_nullability)) && + "Objective-C declspec doesn't have nullability"); + return NullabilityLoc; + } + + void setNullability(SourceLocation loc, NullabilityKind kind) { + assert(((getObjCDeclQualifier() & DQ_CSNullability) || + (getPropertyAttributes() & DQ_PR_nullability)) && + "Set the nullability declspec or property attribute first"); + Nullability = static_cast<unsigned>(kind); + NullabilityLoc = loc; + } + const IdentifierInfo *getGetterName() const { return GetterName; } IdentifierInfo *getGetterName() { return GetterName; } void setGetterName(IdentifierInfo *name) { GetterName = name; } @@ -834,10 +863,15 @@ private: // FIXME: These two are unrelated and mutually exclusive. So perhaps // we can put them in a union to reflect their mutual exclusivity // (space saving is negligible). - ObjCDeclQualifier objcDeclQualifier : 6; + ObjCDeclQualifier objcDeclQualifier : 7; // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind - unsigned PropertyAttributes : 12; + unsigned PropertyAttributes : 14; + + unsigned Nullability : 2; + + SourceLocation NullabilityLoc; + IdentifierInfo *GetterName; // getter name or NULL if no getter IdentifierInfo *SetterName; // setter name or NULL if no setter }; @@ -1616,7 +1650,13 @@ private: bool InlineParamsUsed; /// \brief true if the declaration is preceded by \c __extension__. - bool Extension : 1; + unsigned Extension : 1; + + /// Indicates whether this is an Objective-C instance variable. + unsigned ObjCIvar : 1; + + /// Indicates whether this is an Objective-C 'weak' property. + unsigned ObjCWeakProperty : 1; /// \brief If this is the second or subsequent declarator in this declaration, /// the location of the comma before this declarator. @@ -1635,7 +1675,8 @@ public: GroupingParens(false), FunctionDefinition(FDK_Declaration), Redeclaration(false), Attrs(ds.getAttributePool().getFactory()), AsmLabel(nullptr), - InlineParamsUsed(false), Extension(false) { + InlineParamsUsed(false), Extension(false), ObjCIvar(false), + ObjCWeakProperty(false) { } ~Declarator() { @@ -1713,6 +1754,8 @@ public: Attrs.clear(); AsmLabel = nullptr; InlineParamsUsed = false; + ObjCIvar = false; + ObjCWeakProperty = false; CommaLoc = SourceLocation(); EllipsisLoc = SourceLocation(); } @@ -2121,6 +2164,12 @@ public: void setExtension(bool Val = true) { Extension = Val; } bool getExtension() const { return Extension; } + void setObjCIvar(bool Val = true) { ObjCIvar = Val; } + bool isObjCIvar() const { return ObjCIvar; } + + void setObjCWeakProperty(bool Val = true) { ObjCWeakProperty = Val; } + bool isObjCWeakProperty() const { return ObjCWeakProperty; } + void setInvalidType(bool Val = true) { InvalidType = Val; } bool isInvalidType() const { return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error; diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h index 97192b53fa44..5bfee8b0d037 100644 --- a/include/clang/Sema/Lookup.h +++ b/include/clang/Sema/Lookup.h @@ -302,14 +302,10 @@ public: if (!D->isInIdentifierNamespace(IDNS)) return nullptr; - if (isVisible(getSema(), D)) + if (isHiddenDeclarationVisible() || isVisible(getSema(), D)) return D; - if (auto *Visible = getAcceptableDeclSlow(D)) - return Visible; - - // Even if hidden declarations are visible, prefer a visible declaration. - return isHiddenDeclarationVisible() ? D : nullptr; + return getAcceptableDeclSlow(D); } private: diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 60664c5fdc99..cb75b969f116 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -210,6 +210,50 @@ namespace threadSafety { typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType*, NamedDecl*>, SourceLocation> UnexpandedParameterPack; +/// Describes whether we've seen any nullability information for the given +/// file. +struct FileNullability { + /// The first pointer declarator (of any pointer kind) in the file that does + /// not have a corresponding nullability annotation. + SourceLocation PointerLoc; + + /// Which kind of pointer declarator we saw. + uint8_t PointerKind; + + /// Whether we saw any type nullability annotations in the given file. + bool SawTypeNullability = false; +}; + +/// A mapping from file IDs to a record of whether we've seen nullability +/// information in that file. +class FileNullabilityMap { + /// A mapping from file IDs to the nullability information for each file ID. + llvm::DenseMap<FileID, FileNullability> Map; + + /// A single-element cache based on the file ID. + struct { + FileID File; + FileNullability Nullability; + } Cache; + +public: + FileNullability &operator[](FileID file) { + // Check the single-element cache. + if (file == Cache.File) + return Cache.Nullability; + + // It's not in the single-element cache; flush the cache if we have one. + if (!Cache.File.isInvalid()) { + Map[Cache.File] = Cache.Nullability; + } + + // Pull this entry into the cache. + Cache.File = file; + Cache.Nullability = Map[file]; + return Cache.Nullability; + } +}; + /// Sema - This implements semantic analysis and AST building for C. class Sema { Sema(const Sema &) = delete; @@ -341,6 +385,9 @@ public: PragmaStack<StringLiteral *> ConstSegStack; PragmaStack<StringLiteral *> CodeSegStack; + /// A mapping that describes the nullability we've seen in each header file. + FileNullabilityMap NullabilityMap; + /// Last section used with #pragma init_seg. StringLiteral *CurInitSeg; SourceLocation CurInitSegLoc; @@ -1157,6 +1204,16 @@ public: bool CheckFunctionReturnType(QualType T, SourceLocation Loc); + unsigned deduceWeakPropertyFromType(QualType T) { + if ((getLangOpts().getGC() != LangOptions::NonGC && + T.isObjCGCWeak()) || + (getLangOpts().ObjCAutoRefCount && + T.getObjCLifetime() == Qualifiers::OCL_Weak)) + return ObjCDeclSpec::DQ_PR_weak; + return 0; + } + + /// \brief Build a function type. /// /// This routine checks the function type according to C++ rules and @@ -1325,6 +1382,11 @@ public: return hasVisibleDefinition(const_cast<NamedDecl*>(D), &Hidden); } + /// Determine if the template parameter \p D has a visible default argument. + bool + hasVisibleDefaultArgument(const NamedDecl *D, + llvm::SmallVectorImpl<Module *> *Modules = nullptr); + bool RequireCompleteType(SourceLocation Loc, QualType T, TypeDiagnoser &Diagnoser); bool RequireCompleteType(SourceLocation Loc, QualType T, @@ -1727,6 +1789,22 @@ public: void createImplicitModuleImportForErrorRecovery(SourceLocation Loc, Module *Mod); + /// Kinds of missing import. Note, the values of these enumerators correspond + /// to %select values in diagnostics. + enum class MissingImportKind { + Declaration, + Definition, + DefaultArgument + }; + + /// \brief Diagnose that the specified declaration needs to be visible but + /// isn't, and suggest a module import that would resolve the problem. + void diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl, + bool NeedDefinition, bool Recover = true); + void diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl, + SourceLocation DeclLoc, ArrayRef<Module *> Modules, + MissingImportKind MIK, bool Recover); + /// \brief Retrieve a suitable printing policy. PrintingPolicy getPrintingPolicy() const { return getPrintingPolicy(Context, PP); @@ -1847,10 +1925,10 @@ public: /// struct, or union). void ActOnTagStartDefinition(Scope *S, Decl *TagDecl); + typedef void *SkippedDefinitionContext; + /// \brief Invoked when we enter a tag definition that we're skipping. - void ActOnTagStartSkippedDefinition(Scope *S, Decl *TD) { - PushDeclContext(S, cast<DeclContext>(TD)); - } + SkippedDefinitionContext ActOnTagStartSkippedDefinition(Scope *S, Decl *TD); Decl *ActOnObjCContainerStartDefinition(Decl *IDecl); @@ -1867,9 +1945,7 @@ public: void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl, SourceLocation RBraceLoc); - void ActOnTagFinishSkippedDefinition() { - PopDeclContext(); - } + void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context); void ActOnObjCContainerFinishDefinition(); @@ -2819,6 +2895,7 @@ public: unsigned ArgNum, StringRef &Str, SourceLocation *ArgLocation = nullptr); bool checkSectionName(SourceLocation LiteralLoc, StringRef Str); + void checkTargetAttr(SourceLocation LiteralLoc, StringRef Str); bool checkMSInheritanceAttrOnDefinition( CXXRecordDecl *RD, SourceRange Range, bool BestCase, MSInheritanceAttr::Spelling SemanticSpelling); @@ -2839,6 +2916,26 @@ public: /// Valid types should not have multiple attributes with different CCs. const AttributedType *getCallingConvAttributedType(QualType T) const; + /// Check whether a nullability type specifier can be added to the given + /// type. + /// + /// \param type The type to which the nullability specifier will be + /// added. On success, this type will be updated appropriately. + /// + /// \param nullability The nullability specifier to add. + /// + /// \param nullabilityLoc The location of the nullability specifier. + /// + /// \param isContextSensitive Whether this nullability specifier was + /// written as a context-sensitive keyword (in an Objective-C + /// method) or an Objective-C property attribute, rather than as an + /// underscored type specifier. + /// + /// \returns true if nullability cannot be applied, false otherwise. + bool checkNullabilityTypeSpecifier(QualType &type, NullabilityKind nullability, + SourceLocation nullabilityLoc, + bool isContextSensitive); + /// \brief Stmt attributes - this routine is the top level dispatcher. StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs, SourceRange Range); @@ -2878,6 +2975,9 @@ public: ObjCContainerDecl *CDecl, bool SynthesizeProperties); + /// Diagnose any null-resettable synthesized setters. + void diagnoseNullResettableSynthesizedSetters(ObjCImplDecl *impDecl); + /// DefaultSynthesizeProperties - This routine default synthesizes all /// properties which must be synthesized in the class's \@implementation. void DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, @@ -2914,7 +3014,8 @@ public: const unsigned Attributes, const unsigned AttributesAsWritten, bool *isOverridingProperty, - TypeSourceInfo *T, + QualType T, + TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind); /// Called by ActOnProperty and HandlePropertyInClassExtension to @@ -2930,7 +3031,8 @@ public: const bool isReadWrite, const unsigned Attributes, const unsigned AttributesAsWritten, - TypeSourceInfo *T, + QualType T, + TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind, DeclContext *lexicalDC = nullptr); @@ -7629,6 +7731,9 @@ public: /// \brief Called on well-formed '\#pragma omp taskwait'. StmtResult ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc, SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp taskgroup'. + StmtResult ActOnOpenMPTaskgroupDirective(Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); /// \brief Called on well-formed '\#pragma omp flush'. StmtResult ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, @@ -8557,9 +8662,10 @@ private: const FunctionProtoType *Proto, SourceLocation Loc); - void checkCall(NamedDecl *FDecl, ArrayRef<const Expr *> Args, - unsigned NumParams, bool IsMemberFunction, SourceLocation Loc, - SourceRange Range, VariadicCallType CallType); + void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, + ArrayRef<const Expr *> Args, bool IsMemberFunction, + SourceLocation Loc, SourceRange Range, + VariadicCallType CallType); bool CheckObjCString(Expr *Arg); @@ -8602,7 +8708,9 @@ private: llvm::APSInt &Result); bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, int High); - + bool SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, + int ArgNum, unsigned ExpectedFieldNum, + bool AllowName); public: enum FormatStringType { FST_Scanf, @@ -8731,6 +8839,13 @@ private: mutable IdentifierInfo *Ident_super; mutable IdentifierInfo *Ident___float128; + /// Nullability type specifiers. + IdentifierInfo *Ident___nonnull = nullptr; + IdentifierInfo *Ident___nullable = nullptr; + IdentifierInfo *Ident___null_unspecified = nullptr; + + IdentifierInfo *Ident_NSError = nullptr; + protected: friend class Parser; friend class InitializationSequence; @@ -8739,6 +8854,15 @@ protected: friend class ASTWriter; public: + /// Retrieve the keyword associated + IdentifierInfo *getNullabilityKeyword(NullabilityKind nullability); + + /// The struct behind the CFErrorRef pointer. + RecordDecl *CFError = nullptr; + + /// Retrieve the identifier "NSError". + IdentifierInfo *getNSErrorIdent(); + /// \brief Retrieve the parser's current scope. /// /// This routine must only be used when it is certain that semantic analysis diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index e0f01c8a3545..83185a870ab1 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -1211,8 +1211,12 @@ namespace clang { EXPR_INIT_LIST, /// \brief A DesignatedInitExpr record. EXPR_DESIGNATED_INIT, + /// \brief A DesignatedInitUpdateExpr record. + EXPR_DESIGNATED_INIT_UPDATE, /// \brief An ImplicitValueInitExpr record. EXPR_IMPLICIT_VALUE_INIT, + /// \brief An NoInitExpr record. + EXPR_NO_INIT, /// \brief A VAArgExpr record. EXPR_VA_ARG, /// \brief An AddrLabelExpr record. @@ -1392,6 +1396,7 @@ namespace clang { STMT_OMP_ATOMIC_DIRECTIVE, STMT_OMP_TARGET_DIRECTIVE, STMT_OMP_TEAMS_DIRECTIVE, + STMT_OMP_TASKGROUP_DIRECTIVE, // ARC EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index c7cc1be6e62c..429f00f852bb 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -362,6 +362,7 @@ private: SourceManager &SourceMgr; FileManager &FileMgr; + const PCHContainerOperations &PCHContainerOps; DiagnosticsEngine &Diags; /// \brief The semantic analysis object that will be processing the @@ -1237,6 +1238,9 @@ public: /// \param Context the AST context that this precompiled header will be /// loaded into. /// + /// \param PCHContainerOps the PCHContainerOperations to use for loading and + /// creating modules. + /// /// \param isysroot If non-NULL, the system include path specified by the /// user. This is only used with relocatable PCH files. If non-NULL, /// a relocatable PCH file will use the default path "/". @@ -1258,12 +1262,12 @@ public: /// /// \param UseGlobalIndex If true, the AST reader will try to load and use /// the global module index. - ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot = "", - bool DisableValidation = false, + ASTReader(Preprocessor &PP, ASTContext &Context, + const PCHContainerOperations &PCHContainerOps, + StringRef isysroot = "", bool DisableValidation = false, bool AllowASTWithCompilerErrors = false, bool AllowConfigurationMismatch = false, - bool ValidateSystemInputs = false, - bool UseGlobalIndex = true); + bool ValidateSystemInputs = false, bool UseGlobalIndex = true); ~ASTReader() override; @@ -1425,21 +1429,23 @@ public: /// \brief Retrieve the name of the original source file name directly from /// the AST file, without actually loading the AST file. - static std::string getOriginalSourceFile(const std::string &ASTFileName, - FileManager &FileMgr, - DiagnosticsEngine &Diags); + static std::string + getOriginalSourceFile(const std::string &ASTFileName, FileManager &FileMgr, + const PCHContainerOperations &PCHContainerOps, + DiagnosticsEngine &Diags); /// \brief Read the control block for the named AST file. /// /// \returns true if an error occurred, false otherwise. - static bool readASTFileControlBlock(StringRef Filename, - FileManager &FileMgr, - ASTReaderListener &Listener); + static bool + readASTFileControlBlock(StringRef Filename, FileManager &FileMgr, + const PCHContainerOperations &PCHContainerOps, + ASTReaderListener &Listener); /// \brief Determine whether the given AST file is acceptable to load into a /// translation unit with the given language and target options. - static bool isAcceptableASTFile(StringRef Filename, - FileManager &FileMgr, + static bool isAcceptableASTFile(StringRef Filename, FileManager &FileMgr, + const PCHContainerOperations &PCHContainerOps, const LangOptions &LangOpts, const TargetOptions &TargetOpts, const PreprocessorOptions &PPOpts, diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index 297ee22dfa68..decd07a00ed5 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -17,6 +17,7 @@ #include "clang/AST/ASTMutationListener.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclarationName.h" +#include "clang/Frontend/PCHContainerOperations.h" #include "clang/AST/TemplateBase.h" #include "clang/Sema/SemaConsumer.h" #include "clang/Serialization/ASTBitCodes.h" @@ -868,30 +869,28 @@ class PCHGenerator : public SemaConsumer { std::string OutputFile; clang::Module *Module; std::string isysroot; - raw_ostream *Out; Sema *SemaPtr; - SmallVector<char, 128> Buffer; + std::shared_ptr<PCHBuffer> Buffer; llvm::BitstreamWriter Stream; ASTWriter Writer; bool AllowASTWithErrors; - bool HasEmittedPCH; protected: ASTWriter &getWriter() { return Writer; } const ASTWriter &getWriter() const { return Writer; } + SmallVectorImpl<char> &getPCH() const { return Buffer->Data; } public: PCHGenerator(const Preprocessor &PP, StringRef OutputFile, - clang::Module *Module, - StringRef isysroot, raw_ostream *Out, + clang::Module *Module, StringRef isysroot, + std::shared_ptr<PCHBuffer> Buffer, bool AllowASTWithErrors = false); ~PCHGenerator() override; void InitializeSema(Sema &S) override { SemaPtr = &S; } void HandleTranslationUnit(ASTContext &Ctx) override; ASTMutationListener *GetASTMutationListener() override; ASTDeserializationListener *GetASTDeserializationListener() override; - - bool hasEmittedPCH() const { return HasEmittedPCH; } + bool hasEmittedPCH() const { return Buffer->IsComplete; } }; } // end namespace clang diff --git a/include/clang/Serialization/GlobalModuleIndex.h b/include/clang/Serialization/GlobalModuleIndex.h index 640c7bb34454..7e205106c4ee 100644 --- a/include/clang/Serialization/GlobalModuleIndex.h +++ b/include/clang/Serialization/GlobalModuleIndex.h @@ -35,6 +35,7 @@ class DirectoryEntry; class FileEntry; class FileManager; class IdentifierIterator; +class PCHContainerOperations; namespace serialization { class ModuleFile; @@ -192,10 +193,13 @@ public: /// \brief Write a global index into the given /// /// \param FileMgr The file manager to use to load module files. - /// + /// \param PCHContainerOps - The PCHContainerOperations to use for loading and + /// creating modules. /// \param Path The path to the directory containing module files, into /// which the global index will be written. - static ErrorCode writeIndex(FileManager &FileMgr, StringRef Path); + static ErrorCode writeIndex(FileManager &FileMgr, + const PCHContainerOperations &PCHContainerOps, + StringRef Path); }; } diff --git a/include/clang/Serialization/ModuleManager.h b/include/clang/Serialization/ModuleManager.h index 3de86feb66b9..ea4b57fa3ace 100644 --- a/include/clang/Serialization/ModuleManager.h +++ b/include/clang/Serialization/ModuleManager.h @@ -24,6 +24,7 @@ namespace clang { class GlobalModuleIndex; class ModuleMap; +class PCHContainerOperations; namespace serialization { @@ -49,7 +50,10 @@ class ModuleManager { /// \brief FileManager that handles translating between filenames and /// FileEntry *. FileManager &FileMgr; - + + /// \brief Knows how to unwrap module containers. + const PCHContainerOperations &PCHContainerOps; + /// \brief A lookup of in-memory (virtual file) buffers llvm::DenseMap<const FileEntry *, std::unique_ptr<llvm::MemoryBuffer>> InMemoryBuffers; @@ -112,8 +116,9 @@ public: typedef SmallVectorImpl<ModuleFile*>::const_iterator ModuleConstIterator; typedef SmallVectorImpl<ModuleFile*>::reverse_iterator ModuleReverseIterator; typedef std::pair<uint32_t, StringRef> ModuleOffset; - - explicit ModuleManager(FileManager &FileMgr); + + explicit ModuleManager(FileManager &FileMgr, + const PCHContainerOperations &PCHContainerOps); ~ModuleManager(); /// \brief Forward iterator to traverse all loaded modules. This is reverse diff --git a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h index ab92a2465c53..5850656916e3 100644 --- a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h +++ b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h @@ -69,6 +69,14 @@ enum ArgEffect { /// transfers the object to the Garbage Collector under GC. MakeCollectable, + /// The argument is a pointer to a retain-counted object; on exit, the new + /// value of the pointer is a +0 value or NULL. + UnretainedOutParameter, + + /// The argument is a pointer to a retain-counted object; on exit, the new + /// value of the pointer is a +1 value or NULL. + RetainedOutParameter, + /// The argument is treated as potentially escaping, meaning that /// even when its reference count hits 0 it should be treated as still /// possibly being alive as someone else *may* be holding onto the object. diff --git a/include/clang/Tooling/Refactoring.h b/include/clang/Tooling/Refactoring.h index e3e7f83c38c8..944fd41f85c1 100644 --- a/include/clang/Tooling/Refactoring.h +++ b/include/clang/Tooling/Refactoring.h @@ -38,7 +38,9 @@ class RefactoringTool : public ClangTool { public: /// \see ClangTool::ClangTool. RefactoringTool(const CompilationDatabase &Compilations, - ArrayRef<std::string> SourcePaths); + ArrayRef<std::string> SourcePaths, + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<RawPCHContainerOperations>()); /// \brief Returns the set of replacements to which replacements should /// be added during the run of the tool. diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h index ca187b168448..fb887e1df9e8 100644 --- a/include/clang/Tooling/Tooling.h +++ b/include/clang/Tooling/Tooling.h @@ -31,11 +31,13 @@ #define LLVM_CLANG_TOOLING_TOOLING_H #include "clang/AST/ASTConsumer.h" +#include "clang/Frontend/PCHContainerOperations.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/LLVM.h" #include "clang/Driver/Util.h" #include "clang/Frontend/FrontendAction.h" +#include "clang/Lex/ModuleLoader.h" #include "clang/Tooling/ArgumentsAdjusters.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/StringMap.h" @@ -66,9 +68,10 @@ public: virtual ~ToolAction(); /// \brief Perform an action for an invocation. - virtual bool runInvocation(clang::CompilerInvocation *Invocation, - FileManager *Files, - DiagnosticConsumer *DiagConsumer) = 0; + virtual bool + runInvocation(clang::CompilerInvocation *Invocation, FileManager *Files, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + DiagnosticConsumer *DiagConsumer) = 0; }; /// \brief Interface to generate clang::FrontendActions. @@ -83,6 +86,7 @@ public: /// \brief Invokes the compiler with a FrontendAction created by create(). bool runInvocation(clang::CompilerInvocation *Invocation, FileManager *Files, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, DiagnosticConsumer *DiagConsumer) override; /// \brief Returns a new clang::FrontendAction. @@ -139,10 +143,14 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( /// \param ToolAction The action to run over the code. /// \param Code C++ code. /// \param FileName The file name which 'Code' will be mapped as. +/// \param PCHContainerOps The PCHContainerOperations for loading and creating +/// clang modules. /// /// \return - True if 'ToolAction' was successfully executed. bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code, - const Twine &FileName = "input.cc"); + const Twine &FileName = "input.cc", + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<RawPCHContainerOperations>()); /// The first part of the pair is the filename, the second part the /// file-content. @@ -155,37 +163,48 @@ typedef std::vector<std::pair<std::string, std::string>> FileContentMappings; /// \param Code C++ code. /// \param Args Additional flags to pass on. /// \param FileName The file name which 'Code' will be mapped as. +/// \param PCHContainerOps The PCHContainerOperations for loading and creating +/// clang modules. /// /// \return - True if 'ToolAction' was successfully executed. bool runToolOnCodeWithArgs( clang::FrontendAction *ToolAction, const Twine &Code, const std::vector<std::string> &Args, const Twine &FileName = "input.cc", + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<RawPCHContainerOperations>(), const FileContentMappings &VirtualMappedFiles = FileContentMappings()); /// \brief Builds an AST for 'Code'. /// /// \param Code C++ code. /// \param FileName The file name which 'Code' will be mapped as. +/// \param PCHContainerOps The PCHContainerOperations for loading and creating +/// clang modules. /// /// \return The resulting AST or null if an error occurred. -std::unique_ptr<ASTUnit> buildASTFromCode(const Twine &Code, - const Twine &FileName = "input.cc"); +std::unique_ptr<ASTUnit> +buildASTFromCode(const Twine &Code, const Twine &FileName = "input.cc", + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<RawPCHContainerOperations>()); /// \brief Builds an AST for 'Code' with additional flags. /// /// \param Code C++ code. /// \param Args Additional flags to pass on. /// \param FileName The file name which 'Code' will be mapped as. +/// \param PCHContainerOps The PCHContainerOperations for loading and creating +/// clang modules. /// /// \return The resulting AST or null if an error occurred. -std::unique_ptr<ASTUnit> -buildASTFromCodeWithArgs(const Twine &Code, - const std::vector<std::string> &Args, - const Twine &FileName = "input.cc"); +std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs( + const Twine &Code, const std::vector<std::string> &Args, + const Twine &FileName = "input.cc", + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<RawPCHContainerOperations>()); /// \brief Utility to run a FrontendAction in a single clang invocation. class ToolInvocation { - public: +public: /// \brief Create a tool invocation. /// /// \param CommandLine The command line arguments to clang. Note that clang @@ -195,16 +214,23 @@ class ToolInvocation { /// \param FAction The action to be executed. Class takes ownership. /// \param Files The FileManager used for the execution. Class does not take /// ownership. + /// \param PCHContainerOps The PCHContainerOperations for loading and creating + /// clang modules. ToolInvocation(std::vector<std::string> CommandLine, FrontendAction *FAction, - FileManager *Files); + FileManager *Files, + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<RawPCHContainerOperations>()); /// \brief Create a tool invocation. /// /// \param CommandLine The command line arguments to clang. /// \param Action The action to be executed. /// \param Files The FileManager used for the execution. + /// \param PCHContainerOps The PCHContainerOperations for loading and creating + /// clang modules. ToolInvocation(std::vector<std::string> CommandLine, ToolAction *Action, - FileManager *Files); + FileManager *Files, + std::shared_ptr<PCHContainerOperations> PCHContainerOps); ~ToolInvocation(); @@ -229,12 +255,14 @@ class ToolInvocation { bool runInvocation(const char *BinaryName, clang::driver::Compilation *Compilation, - clang::CompilerInvocation *Invocation); + clang::CompilerInvocation *Invocation, + std::shared_ptr<PCHContainerOperations> PCHContainerOps); std::vector<std::string> CommandLine; ToolAction *Action; bool OwnsAction; FileManager *Files; + std::shared_ptr<PCHContainerOperations> PCHContainerOps; // Maps <file name> -> <file content>. llvm::StringMap<StringRef> MappedFileContents; DiagnosticConsumer *DiagConsumer; @@ -255,8 +283,12 @@ class ClangTool { /// command lines for the given source paths. /// \param SourcePaths The source files to run over. If a source files is /// not found in Compilations, it is skipped. + /// \param PCHContainerOps The PCHContainerOperations for loading and creating + /// clang modules. ClangTool(const CompilationDatabase &Compilations, - ArrayRef<std::string> SourcePaths); + ArrayRef<std::string> SourcePaths, + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<RawPCHContainerOperations>()); ~ClangTool(); @@ -297,6 +329,7 @@ class ClangTool { private: const CompilationDatabase &Compilations; std::vector<std::string> SourcePaths; + std::shared_ptr<PCHContainerOperations> PCHContainerOps; llvm::IntrusiveRefCntPtr<FileManager> Files; // Contains a list of pairs (<file name>, <file content>). |