diff options
Diffstat (limited to 'include')
22 files changed, 495 insertions, 59 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index ad723a3e2b8f..573ea55de1fd 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -2082,10 +2082,7 @@ public: const Attr *getUnusedResultAttr() const; /// \brief Returns true if this function or its return type has the - /// warn_unused_result attribute. If the return type has the attribute and - /// this function is a method of the return type's class, then false will be - /// returned to avoid spurious warnings on member methods such as assignment - /// operators. + /// warn_unused_result attribute. bool hasUnusedResultAttr() const { return getUnusedResultAttr() != nullptr; } /// \brief Returns the storage class as written in the source. For the diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h index 13af142ca3ab..463af06fddab 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -318,8 +318,9 @@ class OMPLoopDirective : public OMPExecutableDirective { /// \brief Offsets to the stored exprs. /// This enumeration contains offsets to all the pointers to children /// expressions stored in OMPLoopDirective. - /// The first 9 children are nesessary for all the loop directives, and - /// the next 10 are specific to the worksharing ones. + /// The first 9 children are necessary for all the loop directives, + /// the next 8 are specific to the worksharing ones, and the next 11 are + /// used for combined constructs containing two pragmas associated to loops. /// After the fixed children, three arrays of length CollapsedNum are /// allocated: loop counters, their updates and final values. /// PrevLowerBound and PrevUpperBound are used to communicate blocking @@ -344,7 +345,7 @@ class OMPLoopDirective : public OMPExecutableDirective { // specify the offset to the end (and start of the following counters/ // updates/finals arrays). DefaultEnd = 9, - // The following 12 exprs are used by worksharing and distribute loops only. + // The following 8 exprs are used by worksharing and distribute loops only. IsLastIterVariableOffset = 9, LowerBoundVariableOffset = 10, UpperBoundVariableOffset = 11, @@ -353,13 +354,22 @@ class OMPLoopDirective : public OMPExecutableDirective { NextLowerBoundOffset = 14, NextUpperBoundOffset = 15, NumIterationsOffset = 16, + // Offset to the end for worksharing loop directives. + WorksharingEnd = 17, PrevLowerBoundVariableOffset = 17, PrevUpperBoundVariableOffset = 18, DistIncOffset = 19, PrevEnsureUpperBoundOffset = 20, + CombinedLowerBoundVariableOffset = 21, + CombinedUpperBoundVariableOffset = 22, + CombinedEnsureUpperBoundOffset = 23, + CombinedInitOffset = 24, + CombinedConditionOffset = 25, + CombinedNextLowerBoundOffset = 26, + CombinedNextUpperBoundOffset = 27, // Offset to the end (and start of the following counters/updates/finals - // arrays) for worksharing loop directives. - WorksharingEnd = 21, + // arrays) for combined distribute loop directives. + CombinedDistributeEnd = 28, }; /// \brief Get the counters storage. @@ -423,11 +433,12 @@ protected: /// \brief Offset to the start of children expression arrays. static unsigned getArraysOffset(OpenMPDirectiveKind Kind) { - return (isOpenMPWorksharingDirective(Kind) || - isOpenMPTaskLoopDirective(Kind) || - isOpenMPDistributeDirective(Kind)) - ? WorksharingEnd - : DefaultEnd; + if (isOpenMPLoopBoundSharingDirective(Kind)) + return CombinedDistributeEnd; + if (isOpenMPWorksharingDirective(Kind) || isOpenMPTaskLoopDirective(Kind) || + isOpenMPDistributeDirective(Kind)) + return WorksharingEnd; + return DefaultEnd; } /// \brief Children number. @@ -515,33 +526,60 @@ protected: *std::next(child_begin(), NumIterationsOffset) = NI; } void setPrevLowerBoundVariable(Expr *PrevLB) { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); *std::next(child_begin(), PrevLowerBoundVariableOffset) = PrevLB; } void setPrevUpperBoundVariable(Expr *PrevUB) { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); *std::next(child_begin(), PrevUpperBoundVariableOffset) = PrevUB; } void setDistInc(Expr *DistInc) { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); *std::next(child_begin(), DistIncOffset) = DistInc; } void setPrevEnsureUpperBound(Expr *PrevEUB) { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); *std::next(child_begin(), PrevEnsureUpperBoundOffset) = PrevEUB; } + void setCombinedLowerBoundVariable(Expr *CombLB) { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + *std::next(child_begin(), CombinedLowerBoundVariableOffset) = CombLB; + } + void setCombinedUpperBoundVariable(Expr *CombUB) { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + *std::next(child_begin(), CombinedUpperBoundVariableOffset) = CombUB; + } + void setCombinedEnsureUpperBound(Expr *CombEUB) { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + *std::next(child_begin(), CombinedEnsureUpperBoundOffset) = CombEUB; + } + void setCombinedInit(Expr *CombInit) { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + *std::next(child_begin(), CombinedInitOffset) = CombInit; + } + void setCombinedCond(Expr *CombCond) { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + *std::next(child_begin(), CombinedConditionOffset) = CombCond; + } + void setCombinedNextLowerBound(Expr *CombNLB) { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + *std::next(child_begin(), CombinedNextLowerBoundOffset) = CombNLB; + } + void setCombinedNextUpperBound(Expr *CombNUB) { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + *std::next(child_begin(), CombinedNextUpperBoundOffset) = CombNUB; + } void setCounters(ArrayRef<Expr *> A); void setPrivateCounters(ArrayRef<Expr *> A); void setInits(ArrayRef<Expr *> A); @@ -549,6 +587,33 @@ protected: void setFinals(ArrayRef<Expr *> A); public: + /// The expressions built to support OpenMP loops in combined/composite + /// pragmas (e.g. pragma omp distribute parallel for) + struct DistCombinedHelperExprs { + /// DistributeLowerBound - used when composing 'omp distribute' with + /// 'omp for' in a same construct. + Expr *LB; + /// DistributeUpperBound - used when composing 'omp distribute' with + /// 'omp for' in a same construct. + Expr *UB; + /// DistributeEnsureUpperBound - used when composing 'omp distribute' + /// with 'omp for' in a same construct, EUB depends on DistUB + Expr *EUB; + /// Distribute loop iteration variable init used when composing 'omp + /// distribute' + /// with 'omp for' in a same construct + Expr *Init; + /// Distribute Loop condition used when composing 'omp distribute' + /// with 'omp for' in a same construct + Expr *Cond; + /// Update of LowerBound for statically sheduled omp loops for + /// outer loop in combined constructs (e.g. 'distribute parallel for') + Expr *NLB; + /// Update of UpperBound for statically sheduled omp loops for + /// outer loop in combined constructs (e.g. 'distribute parallel for') + Expr *NUB; + }; + /// \brief The expressions built for the OpenMP loop CodeGen for the /// whole collapsed loop nest. struct HelperExprs { @@ -611,6 +676,9 @@ public: /// Init statement for all captured expressions. Stmt *PreInits; + /// Expressions used when combining OpenMP loop pragmas + DistCombinedHelperExprs DistCombinedFields; + /// \brief Check if all the expressions are built (does not check the /// worksharing ones). bool builtAll() { @@ -654,6 +722,13 @@ public: Finals[i] = nullptr; } PreInits = nullptr; + DistCombinedFields.LB = nullptr; + DistCombinedFields.UB = nullptr; + DistCombinedFields.EUB = nullptr; + DistCombinedFields.Init = nullptr; + DistCombinedFields.Cond = nullptr; + DistCombinedFields.NLB = nullptr; + DistCombinedFields.NUB = nullptr; } }; @@ -757,37 +832,71 @@ public: *std::next(child_begin(), NumIterationsOffset))); } Expr *getPrevLowerBoundVariable() const { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); return const_cast<Expr *>(reinterpret_cast<const Expr *>( *std::next(child_begin(), PrevLowerBoundVariableOffset))); } Expr *getPrevUpperBoundVariable() const { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); return const_cast<Expr *>(reinterpret_cast<const Expr *>( *std::next(child_begin(), PrevUpperBoundVariableOffset))); } Expr *getDistInc() const { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); return const_cast<Expr *>(reinterpret_cast<const Expr *>( *std::next(child_begin(), DistIncOffset))); } Expr *getPrevEnsureUpperBound() const { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); return const_cast<Expr *>(reinterpret_cast<const Expr *>( *std::next(child_begin(), PrevEnsureUpperBoundOffset))); } + Expr *getCombinedLowerBoundVariable() const { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), CombinedLowerBoundVariableOffset))); + } + Expr *getCombinedUpperBoundVariable() const { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), CombinedUpperBoundVariableOffset))); + } + Expr *getCombinedEnsureUpperBound() const { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), CombinedEnsureUpperBoundOffset))); + } + Expr *getCombinedInit() const { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), CombinedInitOffset))); + } + Expr *getCombinedCond() const { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), CombinedConditionOffset))); + } + Expr *getCombinedNextLowerBound() const { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), CombinedNextLowerBoundOffset))); + } + Expr *getCombinedNextUpperBound() const { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), CombinedNextUpperBoundOffset))); + } const Stmt *getBody() const { // This relies on the loop form is already checked by Sema. Stmt *Body = getAssociatedStmt()->IgnoreContainers(true); diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 525f848a9fab..ad95f6f8effa 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1544,7 +1544,11 @@ class DependentSizedArrayTypeLoc : public InheritingConcreteTypeLoc<ArrayTypeLoc, DependentSizedArrayTypeLoc, DependentSizedArrayType> { - +public: + void initializeLocal(ASTContext &Context, SourceLocation Loc) { + ArrayTypeLoc::initializeLocal(Context, Loc); + setSizeExpr(getTypePtr()->getSizeExpr()); + } }; class VariableArrayTypeLoc : diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index c5d2c7fc618b..44893fbd036c 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -248,6 +248,8 @@ def COnly : LangOpt<"CPlusPlus", 1>; def CPlusPlus : LangOpt<"CPlusPlus">; def OpenCL : LangOpt<"OpenCL">; def RenderScript : LangOpt<"RenderScript">; +def ObjC : LangOpt<"ObjC1">; +def BlocksSupported : LangOpt<"Blocks">; // Defines targets for target-specific attributes. The list of strings should // specify architectures for which the target applies, based off the ArchType @@ -270,6 +272,112 @@ def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb"]> { let CXXABIs = ["Microsoft"]; } +// Attribute subject match rules that are used for #pragma clang attribute. +// +// A instance of AttrSubjectMatcherRule represents an individual match rule. +// An individual match rule can correspond to a number of different attribute +// subjects, e.g. "record" matching rule corresponds to the Record and +// CXXRecord attribute subjects. +// +// Match rules are used in the subject list of the #pragma clang attribute. +// Match rules can have sub-match rules that are instances of +// AttrSubjectMatcherSubRule. A sub-match rule can correspond to a number +// of different attribute subjects, and it can have a negated spelling as well. +// For example, "variable(unless(is_parameter))" matching rule corresponds to +// the NonParmVar attribute subject. +class AttrSubjectMatcherSubRule<string name, list<AttrSubject> subjects, + bit negated = 0> { + string Name = name; + list<AttrSubject> Subjects = subjects; + bit Negated = negated; + // Lists language options, one of which is required to be true for the + // attribute to be applicable. If empty, the language options are taken + // from the parent matcher rule. + list<LangOpt> LangOpts = []; +} +class AttrSubjectMatcherRule<string name, list<AttrSubject> subjects, + list<AttrSubjectMatcherSubRule> subrules = []> { + string Name = name; + list<AttrSubject> Subjects = subjects; + list<AttrSubjectMatcherSubRule> Constraints = subrules; + // Lists language options, one of which is required to be true for the + // attribute to be applicable. If empty, no language options are required. + list<LangOpt> LangOpts = []; +} + +// function(is_member) +def SubRuleForCXXMethod : AttrSubjectMatcherSubRule<"is_member", [CXXMethod]> { + let LangOpts = [CPlusPlus]; +} +def SubjectMatcherForFunction : AttrSubjectMatcherRule<"function", [Function], [ + SubRuleForCXXMethod +]>; +// hasType is abstract, it should be used with one of the sub-rules. +def SubjectMatcherForType : AttrSubjectMatcherRule<"hasType", [], [ + AttrSubjectMatcherSubRule<"functionType", [FunctionLike]> + + // FIXME: There's a matcher ambiguity with objc methods and blocks since + // functionType excludes them but functionProtoType includes them. + // AttrSubjectMatcherSubRule<"functionProtoType", [HasFunctionProto]> +]>; +def SubjectMatcherForTypedef : AttrSubjectMatcherRule<"type_alias", + [TypedefName]>; +def SubjectMatcherForRecord : AttrSubjectMatcherRule<"record", [Record, + CXXRecord], [ + // unless(is_union) + AttrSubjectMatcherSubRule<"is_union", [Struct], 1> +]>; +def SubjectMatcherForEnum : AttrSubjectMatcherRule<"enum", [Enum]>; +def SubjectMatcherForEnumConstant : AttrSubjectMatcherRule<"enum_constant", + [EnumConstant]>; +def SubjectMatcherForVar : AttrSubjectMatcherRule<"variable", [Var], [ + AttrSubjectMatcherSubRule<"is_thread_local", [TLSVar]>, + AttrSubjectMatcherSubRule<"is_global", [GlobalVar]>, + AttrSubjectMatcherSubRule<"is_parameter", [ParmVar]>, + // unless(is_parameter) + AttrSubjectMatcherSubRule<"is_parameter", [NonParmVar], 1> +]>; +def SubjectMatcherForField : AttrSubjectMatcherRule<"field", [Field]>; +def SubjectMatcherForNamespace : AttrSubjectMatcherRule<"namespace", + [Namespace]> { + let LangOpts = [CPlusPlus]; +} +def SubjectMatcherForObjCInterface : AttrSubjectMatcherRule<"objc_interface", + [ObjCInterface]> { + let LangOpts = [ObjC]; +} +def SubjectMatcherForObjCProtocol : AttrSubjectMatcherRule<"objc_protocol", + [ObjCProtocol]> { + let LangOpts = [ObjC]; +} +def SubjectMatcherForObjCCategory : AttrSubjectMatcherRule<"objc_category", + [ObjCCategory]> { + let LangOpts = [ObjC]; +} +def SubjectMatcherForObjCMethod : AttrSubjectMatcherRule<"objc_method", + [ObjCMethod], [ + AttrSubjectMatcherSubRule<"is_instance", [ObjCInstanceMethod]> +]> { + let LangOpts = [ObjC]; +} +def SubjectMatcherForObjCProperty : AttrSubjectMatcherRule<"objc_property", + [ObjCProperty]> { + let LangOpts = [ObjC]; +} +def SubjectMatcherForBlock : AttrSubjectMatcherRule<"block", [Block]> { + let LangOpts = [BlocksSupported]; +} + +// Aggregate attribute subject match rules are abstract match rules that can't +// be used directly in #pragma clang attribute. Instead, users have to use +// subject match rules that correspond to attribute subjects that derive from +// the specified subject. +class AttrSubjectMatcherAggregateRule<AttrSubject subject> { + AttrSubject Subject = subject; +} + +def SubjectMatcherForNamed : AttrSubjectMatcherAggregateRule<Named>; + class Attr { // The various ways in which an attribute can be spelled in source list<Spelling> Spellings; @@ -305,6 +413,14 @@ class Attr { // Set to true if this attribute meaningful when applied to or inherited // in a class template definition. bit MeaningfulToClassTemplateDefinition = 0; + // Set to true if this attribute can be used with '#pragma clang attribute'. + // By default, when this value is false, an attribute is supported by the + // '#pragma clang attribute' only when: + // - It has documentation. + // - It has a subject list whose subjects can be represented using subject + // match rules. + // - It has GNU/CXX11 spelling and doesn't require delayed parsing. + bit ForcePragmaAttributeSupport = 0; // Lists language options, one of which is required to be true for the // attribute to be applicable. If empty, no language options are required. list<LangOpt> LangOpts = []; @@ -478,6 +594,9 @@ def AnalyzerNoReturn : InheritableAttr { def Annotate : InheritableParamAttr { let Spellings = [GNU<"annotate">]; let Args = [StringArgument<"Annotation">]; + // Ensure that the annotate attribute can be used with + // '#pragma clang attribute' even though it has no subject list. + let ForcePragmaAttributeSupport = 1; let Documentation = [Undocumented]; } @@ -536,7 +655,7 @@ def Availability : InheritableAttr { } }]; let HasCustomParsing = 1; let DuplicatesAllowedWhileMerging = 1; -// let Subjects = SubjectList<[Named]>; + let Subjects = SubjectList<[Named]>; let Documentation = [AvailabilityDocs]; } @@ -547,7 +666,7 @@ def ExternalSourceSymbol : InheritableAttr { StringArgument<"definedIn", 1>, BoolArgument<"generatedDeclaration", 1>]; let HasCustomParsing = 1; -// let Subjects = SubjectList<[Named]>; + let Subjects = SubjectList<[Named]>; let Documentation = [ExternalSourceSymbolDocs]; } @@ -2242,9 +2361,8 @@ def DLLImport : InheritableAttr, TargetSpecificAttr<TargetWindows> { let Documentation = [DLLImportDocs]; } -def SelectAny : InheritableAttr { - let Spellings = [Declspec<"selectany">]; - let LangOpts = [MicrosoftExt]; +def SelectAny : InheritableAttr, TargetSpecificAttr<TargetWindows> { + let Spellings = [Declspec<"selectany">, GCC<"selectany">]; let Documentation = [Undocumented]; } diff --git a/include/clang/Basic/AttrSubjectMatchRules.h b/include/clang/Basic/AttrSubjectMatchRules.h new file mode 100644 index 000000000000..4c88adf57f17 --- /dev/null +++ b/include/clang/Basic/AttrSubjectMatchRules.h @@ -0,0 +1,32 @@ +//===-- AttrSubjectMatchRules.h - Attribute subject match rules -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_ATTR_SUBJECT_MATCH_RULES_H +#define LLVM_CLANG_BASIC_ATTR_SUBJECT_MATCH_RULES_H + +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMap.h" + +namespace clang { +namespace attr { + +/// \brief A list of all the recognized kinds of attributes. +enum SubjectMatchRule { +#define ATTR_MATCH_RULE(X, Spelling, IsAbstract) X, +#include "clang/Basic/AttrSubMatchRulesList.inc" +}; + +const char *getSubjectMatchRuleSpelling(SubjectMatchRule Rule); + +using ParsedSubjectMatchRuleSet = llvm::DenseMap<int, SourceRange>; + +} // end namespace attr +} // end namespace clang + +#endif diff --git a/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt index e4929b5b52b9..3e0fb8728c48 100644 --- a/include/clang/Basic/CMakeLists.txt +++ b/include/clang/Basic/CMakeLists.txt @@ -28,6 +28,11 @@ clang_tablegen(AttrList.inc -gen-clang-attr-list SOURCE Attr.td TARGET ClangAttrList) +clang_tablegen(AttrSubMatchRulesList.inc -gen-clang-attr-subject-match-rule-list + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ + SOURCE Attr.td + TARGET ClangAttrSubjectMatchRuleList) + clang_tablegen(AttrHasAttributeImpl.inc -gen-clang-attr-has-attribute-impl -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ SOURCE Attr.td diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 9f5f9888a819..4cde1c81fd4d 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -36,7 +36,9 @@ def GNUCompoundLiteralInitializer : DiagGroup<"gnu-compound-literal-initializer" def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion">; def BitFieldEnumConversion : DiagGroup<"bitfield-enum-conversion">; def BitFieldWidth : DiagGroup<"bitfield-width">; -def Coroutine : DiagGroup<"coroutine">; +def CoroutineMissingUnhandledException : + DiagGroup<"coroutine-missing-unhandled-exception">; +def Coroutine : DiagGroup<"coroutine", [CoroutineMissingUnhandledException]>; def ConstantConversion : DiagGroup<"constant-conversion", [ BitFieldConstantConversion ] >; def LiteralConversion : DiagGroup<"literal-conversion">; @@ -459,7 +461,9 @@ def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes, def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">; def UnknownPragmas : DiagGroup<"unknown-pragmas">; def IgnoredPragmas : DiagGroup<"ignored-pragmas", [IgnoredPragmaIntrinsic]>; -def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas]>; +def PragmaClangAttribute : DiagGroup<"pragma-clang-attribute">; +def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas, + PragmaClangAttribute]>; def UnknownWarningOption : DiagGroup<"unknown-warning-option">; def NSobjectAttribute : DiagGroup<"NSObject-attribute">; def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 7f7022b49e3d..cf33d5fba3d7 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -242,6 +242,7 @@ def warn_bad_character_encoding : ExtWarn< "illegal character encoding in character literal">, InGroup<InvalidSourceEncoding>; def err_lexing_string : Error<"failure when lexing a string">; +def err_placeholder_in_source : Error<"editor placeholder in source file">; //===----------------------------------------------------------------------===// @@ -594,8 +595,6 @@ def err_mmap_expected_mmap_file : Error<"expected a module map file name">; def err_mmap_module_redefinition : Error< "redefinition of module '%0'">; def note_mmap_prev_definition : Note<"previously defined here">; -def err_mmap_umbrella_dir_not_found : Error< - "umbrella directory '%0' not found">; def err_mmap_umbrella_clash : Error< "umbrella for module '%0' already covers this directory">; def err_mmap_module_id : Error< @@ -656,6 +655,9 @@ def note_implicit_top_level_module_import_here : Note< def warn_uncovered_module_header : Warning< "umbrella header for module '%0' does not include header '%1'">, InGroup<IncompleteUmbrella>; +def warn_mmap_umbrella_dir_not_found : Warning< + "umbrella directory '%0' not found">, + InGroup<IncompleteUmbrella>; def err_expected_id_building_module : Error< "expected a module name in '__building_module' expression">; def warn_use_of_private_header_outside_module : Warning< diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index aebf8a9f3574..d95e43c10c55 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -979,6 +979,43 @@ def err_pragma_optimize_invalid_argument : Error< "expected 'on' or 'off'">; def err_pragma_optimize_extra_argument : Error< "unexpected extra argument '%0' to '#pragma clang optimize'">; +// - #pragma clang attribute +def err_pragma_attribute_expected_push_pop : Error< + "expected 'push' or 'pop' after '#pragma clang attribute'">; +def err_pragma_attribute_invalid_argument : Error< + "unexpected argument '%0' to '#pragma clang attribute'; " + "expected 'push' or 'pop'">; +def err_pragma_attribute_expected_attribute : Error< + "expected an attribute after '('">; +def err_pragma_attribute_expected_attribute_name : Error< + "expected identifier that represents an attribute name">; +def err_pragma_attribute_extra_tokens_after_attribute : Error< + "extra tokens after attribute in a '#pragma clang attribute push'">; +def err_pragma_attribute_unsupported_attribute : Error< + "attribute %0 is not supported by '#pragma clang attribute'">; +def err_pragma_attribute_multiple_attributes : Error< + "more than one attribute specified in '#pragma clang attribute push'">; +def err_pragma_attribute_expected_attribute_syntax : Error< + "expected an attribute that is specified using the GNU, C++11 or '__declspec'" + " syntax">; +def note_pragma_attribute_use_attribute_kw : Note<"use the GNU '__attribute__' " + "syntax">; +def err_pragma_attribute_invalid_subject_set_specifier : Error< + "expected attribute subject set specifier 'apply_to'">; +def err_pragma_attribute_expected_subject_identifier : Error< + "expected an identifier that corresponds to an attribute subject rule">; +def err_pragma_attribute_unknown_subject_rule : Error< + "unknown attribute subject rule '%0'">; +def err_pragma_attribute_expected_subject_sub_identifier : Error< + "expected an identifier that corresponds to an attribute subject matcher " + "sub-rule; '%0' matcher %select{does not support sub-rules|supports the " + "following sub-rules: %2|}1">; +def err_pragma_attribute_unknown_subject_sub_rule : Error< + "%select{invalid use of|unknown}2 attribute subject matcher sub-rule '%0'; " + "'%1' matcher %select{does not support sub-rules|supports the following " + "sub-rules: %3}2">; +def err_pragma_attribute_duplicate_subject : Error< + "duplicate attribute subject matcher '%0'">; def err_opencl_unroll_hint_on_non_loop : Error< "OpenCL only supports 'opencl_unroll_hint' attribute on for, while, and do statements">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 9b2cfe495ce2..6cb872cc27c5 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -750,6 +750,25 @@ def err_pragma_loop_compatibility : Error< def err_pragma_loop_precedes_nonloop : Error< "expected a for, while, or do-while loop to follow '%0'">; +def err_pragma_attribute_matcher_subrule_contradicts_rule : Error< + "redundant attribute subject matcher sub-rule '%0'; '%1' already matches " + "those declarations">; +def err_pragma_attribute_matcher_negated_subrule_contradicts_subrule : Error< + "negated attribute subject matcher sub-rule '%0' contradicts sub-rule '%1'">; +def err_pragma_attribute_invalid_matchers : Error< + "attribute %0 can't be applied to %1">; +def err_pragma_attribute_stack_mismatch : Error< + "'#pragma clang attribute pop' with no matching '#pragma clang attribute push'">; +def warn_pragma_attribute_unused : Warning< + "unused attribute %0 in '#pragma clang attribute push' region">, + InGroup<PragmaClangAttribute>; +def note_pragma_attribute_region_ends_here : Note< + "'#pragma clang attribute push' regions ends here">; +def err_pragma_attribute_no_pop_eof : Error<"unterminated " + "'#pragma clang attribute push' at end of file">; +def note_pragma_attribute_applied_decl_here : Note< + "when applied to this declaration">; + /// Objective-C parser diagnostics def err_duplicate_class_def : Error< "duplicate interface definition for class %0">; @@ -4981,6 +5000,8 @@ def note_protected_by_if_available : Note< "jump enters controlled statement of if available">; def note_protected_by_vla : Note< "jump bypasses initialization of variable length array">; +def note_protected_by_objc_fast_enumeration : Note< + "jump enters Objective-C fast enumeration loop">; def note_protected_by_objc_try : Note< "jump bypasses initialization of @try block">; def note_protected_by_objc_catch : Note< @@ -8854,6 +8875,11 @@ def err_coroutine_invalid_func_context : Error< def err_implied_coroutine_type_not_found : Error< "%0 type was not found; include <experimental/coroutine> before defining " "a coroutine">; +def err_implicit_coroutine_std_nothrow_type_not_found : Error< + "std::nothrow was not found; include <new> before defining a coroutine which " + "uses get_return_object_on_allocation_failure()">; +def err_malformed_std_nothrow : Error< + "std::nothrow must be a valid variable declaration">; def err_malformed_std_coroutine_handle : Error< "std::experimental::coroutine_handle must be a class template">; def err_coroutine_handle_missing_member : Error< @@ -8873,16 +8899,21 @@ def err_coroutine_promise_return_ill_formed : Error< "%0 declares both 'return_value' and 'return_void'">; def note_coroutine_promise_implicit_await_transform_required_here : Note< "call to 'await_transform' implicitly required by 'co_await' here">; -def note_coroutine_promise_call_implicitly_required : Note< +def note_coroutine_promise_suspend_implicitly_required : Note< "call to '%select{initial_suspend|final_suspend}0' implicitly " "required by the %select{initial suspend point|final suspend point}0">; def err_coroutine_promise_unhandled_exception_required : Error< "%0 is required to declare the member 'unhandled_exception()'">; def warn_coroutine_promise_unhandled_exception_required_with_exceptions : Warning< "%0 is required to declare the member 'unhandled_exception()' when exceptions are enabled">, - InGroup<Coroutine>; + InGroup<CoroutineMissingUnhandledException>; def err_coroutine_promise_get_return_object_on_allocation_failure : Error< "%0: 'get_return_object_on_allocation_failure()' must be a static member function">; +def err_coroutine_promise_new_requires_nothrow : Error< + "%0 is required to have a non-throwing noexcept specification when the promise " + "type declares 'get_return_object_on_allocation_failure()'">; +def note_coroutine_promise_call_implicitly_required : Note< + "call to %0 implicitly required by coroutine function here">; } let CategoryName = "Documentation Issue" in { diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index a5fd14104d3c..9b1ba4a98e6f 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -355,6 +355,19 @@ public: RecomputeNeedsHandleIdentifier(); } + /// Return true if this identifier is an editor placeholder. + /// + /// Editor placeholders are produced by the code-completion engine and are + /// represented as characters between '<#' and '#>' in the source code. An + /// example of auto-completed call with a placeholder parameter is shown + /// below: + /// \code + /// function(<#int x#>); + /// \endcode + bool isEditorPlaceholder() const { + return getName().startswith("<#") && getName().endswith("#>"); + } + /// \brief Provide less than operator for lexicographical sorting. bool operator<(const IdentifierInfo &RHS) const { return getName() < RHS.getName(); diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index c8e197299754..6ae34a89fe28 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -266,6 +266,8 @@ LANGOPT(SanitizeAddressFieldPadding, 2, 0, "controls how aggressive is ASan " LANGOPT(XRayInstrument, 1, 0, "controls whether to do XRay instrumentation") +LANGOPT(AllowEditorPlaceholders, 1, 0, "allow editor placeholders in source") + #undef LANGOPT #undef COMPATIBLE_LANGOPT #undef BENIGN_LANGOPT diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 48e0c33f0e86..968b203a3827 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -790,6 +790,9 @@ ANNOTATION(pragma_loop_hint) ANNOTATION(pragma_fp) +// Annotation for the attribute pragma directives - #pragma clang attribute ... +ANNOTATION(pragma_attribute) + // Annotations for module import translated from #include etc. ANNOTATION(module_include) ANNOTATION(module_begin) diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td index 9b6ab3a5ef2b..61902653e210 100644 --- a/include/clang/Driver/CLCompatOptions.td +++ b/include/clang/Driver/CLCompatOptions.td @@ -172,6 +172,12 @@ def _SLASH_Zc_trigraphs : CLFlag<"Zc:trigraphs">, HelpText<"Enable trigraphs">, Alias<ftrigraphs>; def _SLASH_Zc_trigraphs_off : CLFlag<"Zc:trigraphs-">, HelpText<"Disable trigraphs (default)">, Alias<fno_trigraphs>; +def _SLASH_Zc_twoPhase : CLFlag<"Zc:twoPhase">, + HelpText<"Enable two-phase name lookup in templates">, + Alias<fno_delayed_template_parsing>; +def _SLASH_Zc_twoPhase_ : CLFlag<"Zc:twoPhase-">, + HelpText<"Disable two-phase name lookup in templates">, + Alias<fdelayed_template_parsing>; def _SLASH_Z7 : CLFlag<"Z7">, HelpText<"Enable CodeView debug information in object files">; def _SLASH_Zd : CLFlag<"Zd">, diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 36b24a02b2fe..1272a36ecc70 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1487,6 +1487,12 @@ def fstrict_return : Flag<["-"], "fstrict-return">, Group<f_Group>, def fno_strict_return : Flag<["-"], "fno-strict-return">, Group<f_Group>, Flags<[CC1Option]>; +def fallow_editor_placeholders : Flag<["-"], "fallow-editor-placeholders">, + Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Treat editor placeholders as valid source code">; +def fno_allow_editor_placeholders : Flag<["-"], + "fno-allow-editor-placeholders">, Group<f_Group>; + def fdebug_types_section: Flag <["-"], "fdebug-types-section">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Place debug types in their own section (ELF Only)">; def fno_debug_types_section: Flag<["-"], "fno-debug-types-section">, Group<f_Group>, @@ -1646,6 +1652,8 @@ def march_EQ : Joined<["-"], "march=">, Group<m_Group>; def masm_EQ : Joined<["-"], "masm=">, Group<m_Group>, Flags<[DriverOption]>; def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>; def mimplicit_it_EQ : Joined<["-"], "mimplicit-it=">, Group<m_Group>; +def mdefault_build_attributes : Joined<["-"], "mdefault-build-attributes">, Group<m_Group>; +def mno_default_build_attributes : Joined<["-"], "mno-default-build-attributes">, Group<m_Group>; def mconstant_cfstrings : Flag<["-"], "mconstant-cfstrings">, Group<clang_ignored_m_Group>; def mconsole : Joined<["-"], "mconsole">, Group<m_Group>, Flags<[DriverOption]>; def mwindows : Joined<["-"], "mwindows">, Group<m_Group>, Flags<[DriverOption]>; @@ -1653,6 +1661,7 @@ def mdll : Joined<["-"], "mdll">, Group<m_Group>, Flags<[DriverOption]>; def municode : Joined<["-"], "municode">, Group<m_Group>, Flags<[DriverOption]>; def mthreads : Joined<["-"], "mthreads">, Group<m_Group>, Flags<[DriverOption]>; def mcpu_EQ : Joined<["-"], "mcpu=">, Group<m_Group>; +def mmcu_EQ : Joined<["-"], "mmcu=">, Group<m_Group>; def mdynamic_no_pic : Joined<["-"], "mdynamic-no-pic">, Group<m_Group>; def mfix_and_continue : Flag<["-"], "mfix-and-continue">, Group<clang_ignored_m_Group>; def mieee_fp : Flag<["-"], "mieee-fp">, Group<clang_ignored_m_Group>; diff --git a/include/clang/Index/IndexSymbol.h b/include/clang/Index/IndexSymbol.h index 217d6b1fb1cc..bc34938fb405 100644 --- a/include/clang/Index/IndexSymbol.h +++ b/include/clang/Index/IndexSymbol.h @@ -106,8 +106,9 @@ enum class SymbolRole : uint32_t { RelationAccessorOf = 1 << 15, RelationContainedBy = 1 << 16, RelationIBTypeOf = 1 << 17, + RelationSpecializationOf = 1 << 18, }; -static const unsigned SymbolRoleBitNum = 18; +static const unsigned SymbolRoleBitNum = 19; typedef unsigned SymbolRoleSet; /// Represents a relation to another symbol for a symbol occurrence. diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index 830c25a2e4d2..6ac6316d1248 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -638,6 +638,8 @@ private: bool IsStartOfConflictMarker(const char *CurPtr); bool HandleEndOfConflictMarker(const char *CurPtr); + bool lexEditorPlaceholder(Token &Result, const char *CurPtr); + bool isCodeCompletionPoint(const char *CurPtr) const; void cutOffLexing() { BufferPtr = BufferEnd; } diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index 4393e205ffaf..02a1fef70f2b 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -84,6 +84,7 @@ public: StringifiedInMacro = 0x100, // This string or character literal is formed by // macro stringizing or charizing operator. CommaAfterElided = 0x200, // The comma following this token was elided (MS). + IsEditorPlaceholder = 0x400, // This identifier is a placeholder. }; tok::TokenKind getKind() const { return Kind; } @@ -298,6 +299,13 @@ public: /// Returns true if the comma after this token was elided. bool commaAfterElided() const { return getFlag(CommaAfterElided); } + + /// Returns true if this token is an editor placeholder. + /// + /// Editor placeholders are produced by the code-completion engine and are + /// represented as characters between '<#' and '#>' in the source code. The + /// lexer uses identifier tokens to represent placeholders. + bool isEditorPlaceholder() const { return getFlag(IsEditorPlaceholder); } }; /// \brief Information about the conditional stack (\#if directives) diff --git a/include/clang/Parse/CMakeLists.txt b/include/clang/Parse/CMakeLists.txt index ec75f7b96b14..2cc7e54b3b01 100644 --- a/include/clang/Parse/CMakeLists.txt +++ b/include/clang/Parse/CMakeLists.txt @@ -2,3 +2,9 @@ clang_tablegen(AttrParserStringSwitches.inc -gen-clang-attr-parser-string-switch -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ SOURCE ../Basic/Attr.td TARGET ClangAttrParserStringSwitches) + +clang_tablegen(AttrSubMatchRulesParserStringSwitches.inc + -gen-clang-attr-subject-match-rules-parser-string-switches + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ + SOURCE ../Basic/Attr.td + TARGET ClangAttrSubMatchRulesParserStringSwitches) diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 5f4e5fb4b215..8d0935dec1b6 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -184,6 +184,7 @@ class Parser : public CodeCompletionHandler { std::unique_ptr<PragmaHandler> UnrollHintHandler; std::unique_ptr<PragmaHandler> NoUnrollHintHandler; std::unique_ptr<PragmaHandler> FPHandler; + std::unique_ptr<PragmaHandler> AttributePragmaHandler; std::unique_ptr<CommentHandler> CommentSemaHandler; @@ -565,6 +566,12 @@ private: /// #pragma clang loop and #pragma unroll. bool HandlePragmaLoopHint(LoopHint &Hint); + bool ParsePragmaAttributeSubjectMatchRuleSet( + attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, + SourceLocation &AnyLoc, SourceLocation &LastMatchRuleEndLoc); + + void HandlePragmaAttribute(); + /// GetLookAheadToken - This peeks ahead N tokens and returns that token /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1) /// returns the token after Tok, etc. diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index 7c1678086c2f..f3b042c9ce79 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_SEMA_ATTRIBUTELIST_H #define LLVM_CLANG_SEMA_ATTRIBUTELIST_H +#include "clang/Basic/AttrSubjectMatchRules.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/VersionTuple.h" @@ -509,9 +510,14 @@ public: unsigned getMaxArgs() const; bool hasVariadicArg() const; bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const; + bool appliesToDecl(const Decl *D, attr::SubjectMatchRule MatchRule) const; + void getMatchRules(const LangOptions &LangOpts, + SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> + &MatchRules) const; bool diagnoseLangOpts(class Sema &S) const; bool existsInTarget(const TargetInfo &Target) const; bool isKnownToGCC() const; + bool isSupportedByPragmaAttribute() const; /// \brief If the parsed attribute has a semantic equivalent, and it would /// have a semantic Spelling enumeration (due to having semantically-distinct @@ -774,6 +780,8 @@ public: void clear() { list = nullptr; pool.clear(); } AttributeList *getList() const { return list; } + void clearListOnly() { list = nullptr; } + /// Returns a reference to the attribute list. Try not to introduce /// dependencies on this method, it may not be long-lived. AttributeList *&getListRef() { return list; } diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 5a3cdfb77c9c..bd68842c9f73 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -437,6 +437,20 @@ public: /// VisContext - Manages the stack for \#pragma GCC visibility. void *VisContext; // Really a "PragmaVisStack*" + /// \brief This represents the stack of attributes that were pushed by + /// \#pragma clang attribute. + struct PragmaAttributeEntry { + SourceLocation Loc; + AttributeList *Attribute; + SmallVector<attr::SubjectMatchRule, 4> MatchRules; + bool IsUsed; + }; + SmallVector<PragmaAttributeEntry, 2> PragmaAttributeStack; + + /// \brief The declaration that is currently receiving an attribute from the + /// #pragma attribute stack. + const Decl *PragmaAttributeCurrentTargetDecl; + /// \brief This represents the last location of a "#pragma clang optimize off" /// directive if such a directive has not been closed by an "on" yet. If /// optimizations are currently "on", this is set to an invalid location. @@ -7206,9 +7220,13 @@ public: PrintInstantiationStack(); LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size(); } + if (PragmaAttributeCurrentTargetDecl) + PrintPragmaAttributeInstantiationPoint(); } void PrintInstantiationStack(); + void PrintPragmaAttributeInstantiationPoint(); + /// \brief Determines whether we are currently in a context where /// template argument substitution failures are not considered /// errors. @@ -8152,6 +8170,20 @@ public: /// the appropriate attribute. void AddCFAuditedAttribute(Decl *D); + /// \brief Called on well-formed '\#pragma clang attribute push'. + void ActOnPragmaAttributePush(AttributeList &Attribute, + SourceLocation PragmaLoc, + attr::ParsedSubjectMatchRuleSet Rules); + + /// \brief Called on well-formed '\#pragma clang attribute pop'. + void ActOnPragmaAttributePop(SourceLocation PragmaLoc); + + /// \brief Adds the attributes that have been specified using the + /// '\#pragma clang attribute push' directives to the given declaration. + void AddPragmaAttributes(Scope *S, Decl *D); + + void DiagnoseUnterminatedPragmaAttribute(); + /// \brief Called on well formed \#pragma clang optimize. void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc); |