diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-06-21 14:00:56 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-06-21 14:00:56 +0000 |
commit | 2e645aa5697838f16ec570eb07c2bee7e13d0e0b (patch) | |
tree | a764184c2fc9486979b074250b013a0937ee64e5 /include/clang/AST | |
parent | 798321d8eb5630cd4a8f490a4f25e32ef195fb07 (diff) | |
download | src-2e645aa5697838f16ec570eb07c2bee7e13d0e0b.tar.gz src-2e645aa5697838f16ec570eb07c2bee7e13d0e0b.zip |
Vendor import of clang trunk r240225:vendor/clang/clang-trunk-r240225
Notes
Notes:
svn path=/vendor/clang/dist/; revision=284679
svn path=/vendor/clang/clang-trunk-r240225/; revision=284680; tag=vendor/clang/clang-trunk-r240225
Diffstat (limited to 'include/clang/AST')
-rw-r--r-- | include/clang/AST/ASTContext.h | 30 | ||||
-rw-r--r-- | include/clang/AST/CommentParser.h | 6 | ||||
-rw-r--r-- | include/clang/AST/DataRecursiveASTVisitor.h | 10 | ||||
-rw-r--r-- | include/clang/AST/DeclBase.h | 7 | ||||
-rw-r--r-- | include/clang/AST/DeclCXX.h | 2 | ||||
-rw-r--r-- | include/clang/AST/DeclObjC.h | 34 | ||||
-rw-r--r-- | include/clang/AST/DeclTemplate.h | 193 | ||||
-rw-r--r-- | include/clang/AST/EvaluatedExprVisitor.h | 71 | ||||
-rw-r--r-- | include/clang/AST/Expr.h | 78 | ||||
-rw-r--r-- | include/clang/AST/OpenMPClause.h | 4 | ||||
-rw-r--r-- | include/clang/AST/RecursiveASTVisitor.h | 5 | ||||
-rw-r--r-- | include/clang/AST/StmtOpenMP.h | 86 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 47 |
13 files changed, 445 insertions, 128 deletions
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); } |