diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-08-18 08:26:59 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-08-18 08:26:59 +0000 |
commit | 5a4cb1eb0c4e2560397c009da45d57bb1ebb6135 (patch) | |
tree | 4b0e7bd16ff6d9639594693aca2d6931a71b1dec | |
parent | 46faa67da1d7e9450e8fa363f6633e2c68e33ff1 (diff) |
Vendor import of clang release_70 branch r339999:vendor/clang/clang-release_70-r339999
Notes
Notes:
svn path=/vendor/clang/dist-release_70/; revision=338002
svn path=/vendor/clang/clang-release_70-r339999/; revision=338003; tag=vendor/clang/clang-release_70-r339999
42 files changed, 1078 insertions, 495 deletions
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index 5f446d85dc8c..06512d067e55 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -186,6 +186,12 @@ Windows Support Visual Studio's default stdafx.h setup now uses precompiled headers with clang-cl. +- The alternative entry point names + (``wmain``/``WinMain``/``wWinMain``/``DllMain``) now are properly mangled + as plain C names in C++ contexts when targeting MinGW, without having to + explicit specify ``extern "C"``. (This was already the case for MSVC + targets.) + - ... diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index a9ab687a8de9..6eb86183d936 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -2718,7 +2718,7 @@ public: /// predicate. void forEachMultiversionedFunctionVersion( const FunctionDecl *FD, - llvm::function_ref<void(const FunctionDecl *)> Pred) const; + llvm::function_ref<void(FunctionDecl *)> Pred) const; const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *RD); diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index a28609f8cdf9..419dbe52fab6 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -922,8 +922,11 @@ public: /// \endcode /// In this example directive '#pragma omp for' has 'ordered' clause with /// parameter 2. -class OMPOrderedClause : public OMPClause { +class OMPOrderedClause final + : public OMPClause, + private llvm::TrailingObjects<OMPOrderedClause, Expr *> { friend class OMPClauseReader; + friend TrailingObjects; /// Location of '('. SourceLocation LParenLoc; @@ -931,6 +934,26 @@ class OMPOrderedClause : public OMPClause { /// Number of for-loops. Stmt *NumForLoops = nullptr; + /// Real number of loops. + unsigned NumberOfLoops = 0; + + /// Build 'ordered' clause. + /// + /// \param Num Expression, possibly associated with this clause. + /// \param NumLoops Number of loops, associated with this clause. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + OMPOrderedClause(Expr *Num, unsigned NumLoops, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) + : OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc), + NumForLoops(Num), NumberOfLoops(NumLoops) {} + + /// Build an empty clause. + explicit OMPOrderedClause(unsigned NumLoops) + : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()), + NumberOfLoops(NumLoops) {} + /// Set the number of associated for-loops. void setNumForLoops(Expr *Num) { NumForLoops = Num; } @@ -938,17 +961,17 @@ public: /// Build 'ordered' clause. /// /// \param Num Expression, possibly associated with this clause. + /// \param NumLoops Number of loops, associated with this clause. /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - OMPOrderedClause(Expr *Num, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc), - NumForLoops(Num) {} + static OMPOrderedClause *Create(const ASTContext &C, Expr *Num, + unsigned NumLoops, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); /// Build an empty clause. - explicit OMPOrderedClause() - : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()) {} + static OMPOrderedClause* CreateEmpty(const ASTContext &C, unsigned NumLoops); /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } @@ -959,6 +982,17 @@ public: /// Return the number of associated for-loops. Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); } + /// Set number of iterations for the specified loop. + void setLoopNumIterations(unsigned NumLoop, Expr *NumIterations); + /// Get number of iterations for all the loops. + ArrayRef<Expr *> getLoopNumIterations() const; + + /// Set loop counter for the specified loop. + void setLoopCounter(unsigned NumLoop, Expr *Counter); + /// Get loops counter for the specified loop. + Expr *getLoopCunter(unsigned NumLoop); + const Expr *getLoopCunter(unsigned NumLoop) const; + child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); } static bool classof(const OMPClause *T) { @@ -3087,24 +3121,32 @@ class OMPDependClause final /// Colon location. SourceLocation ColonLoc; + /// Number of loops, associated with the depend clause. + unsigned NumLoops = 0; + /// Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// \param N Number of the variables in the clause. + /// \param NumLoops Number of loops that is associated with this depend + /// clause. OMPDependClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N) + SourceLocation EndLoc, unsigned N, unsigned NumLoops) : OMPVarListClause<OMPDependClause>(OMPC_depend, StartLoc, LParenLoc, - EndLoc, N) {} + EndLoc, N), NumLoops(NumLoops) {} /// Build an empty clause. /// /// \param N Number of variables. - explicit OMPDependClause(unsigned N) + /// \param NumLoops Number of loops that is associated with this depend + /// clause. + explicit OMPDependClause(unsigned N, unsigned NumLoops) : OMPVarListClause<OMPDependClause>(OMPC_depend, SourceLocation(), SourceLocation(), SourceLocation(), - N) {} + N), + NumLoops(NumLoops) {} /// Set dependency kind. void setDependencyKind(OpenMPDependClauseKind K) { DepKind = K; } @@ -3126,16 +3168,23 @@ public: /// \param DepLoc Location of the dependency type. /// \param ColonLoc Colon location. /// \param VL List of references to the variables. - static OMPDependClause * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, OpenMPDependClauseKind DepKind, - SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL); + /// \param NumLoops Number of loops that is associated with this depend + /// clause. + static OMPDependClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, + OpenMPDependClauseKind DepKind, + SourceLocation DepLoc, SourceLocation ColonLoc, + ArrayRef<Expr *> VL, unsigned NumLoops); /// Creates an empty clause with \a N variables. /// /// \param C AST context. /// \param N The number of variables. - static OMPDependClause *CreateEmpty(const ASTContext &C, unsigned N); + /// \param NumLoops Number of loops that is associated with this depend + /// clause. + static OMPDependClause *CreateEmpty(const ASTContext &C, unsigned N, + unsigned NumLoops); /// Get dependency type. OpenMPDependClauseKind getDependencyKind() const { return DepKind; } @@ -3146,15 +3195,16 @@ public: /// Get colon location. SourceLocation getColonLoc() const { return ColonLoc; } - /// Set the loop counter value for the depend clauses with 'sink|source' kind - /// of dependency. Required for codegen. - void setCounterValue(Expr *V); + /// Get number of loops associated with the clause. + unsigned getNumLoops() const { return NumLoops; } - /// Get the loop counter value. - Expr *getCounterValue(); + /// Set the loop data for the depend clauses with 'sink|source' kind of + /// dependency. + void setLoopData(unsigned NumLoop, Expr *Cnt); - /// Get the loop counter value. - const Expr *getCounterValue() const; + /// Get the loop data. + Expr *getLoopData(unsigned NumLoop); + const Expr *getLoopData(unsigned NumLoop) const; child_range children() { return child_range(reinterpret_cast<Stmt **>(varlist_begin()), diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index fea8e129d7da..1f17819dba74 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -2938,9 +2938,10 @@ def OMPDeclareSimdDecl : Attr { }]; } -def OMPDeclareTargetDecl : Attr { +def OMPDeclareTargetDecl : InheritableAttr { let Spellings = [Pragma<"omp", "declare target">]; let SemaHandler = 0; + let Subjects = SubjectList<[Function, SharedVar]>; let Documentation = [OMPDeclareTargetDocs]; let Args = [ EnumArgument<"MapType", "MapTypeTy", @@ -2953,6 +2954,15 @@ def OMPDeclareTargetDecl : Attr { if (getMapType() != MT_To) OS << ' ' << ConvertMapTypeTyToStr(getMapType()); } + static llvm::Optional<MapTypeTy> + isDeclareTargetDeclaration(const ValueDecl *VD) { + if (!VD->hasAttrs()) + return llvm::None; + if (const auto *Attr = VD->getAttr<OMPDeclareTargetDeclAttr>()) + return Attr->getMapType(); + + return llvm::None; + } }]; } diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 2156ef93c19f..c0128f56a59e 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -364,7 +364,6 @@ def NonVirtualDtor : DiagGroup<"non-virtual-dtor">; def NullPointerArithmetic : DiagGroup<"null-pointer-arithmetic">; def : DiagGroup<"effc++", [NonVirtualDtor]>; def OveralignedType : DiagGroup<"over-aligned">; -def AlignedAllocationUnavailable : DiagGroup<"aligned-allocation-unavailable">; def OldStyleCast : DiagGroup<"old-style-cast">; def : DiagGroup<"old-style-definition">; def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 586f65e9201c..dc192aafe38c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -6465,12 +6465,12 @@ def warn_overaligned_type : Warning< "type %0 requires %1 bytes of alignment and the default allocator only " "guarantees %2 bytes">, InGroup<OveralignedType>, DefaultIgnore; -def warn_aligned_allocation_unavailable :Warning< +def err_aligned_allocation_unavailable : Error< "aligned %select{allocation|deallocation}0 function of type '%1' is only " - "available on %2 %3 or newer">, InGroup<AlignedAllocationUnavailable>, DefaultError; + "available on %2 %3 or newer">; def note_silence_unligned_allocation_unavailable : Note< "if you supply your own aligned allocation functions, use " - "-Wno-aligned-allocation-unavailable to silence this diagnostic">; + "-faligned-allocation to silence this diagnostic">; def err_conditional_void_nonvoid : Error< "%select{left|right}1 operand to ? is void, but %select{right|left}1 operand " diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 2470638bec66..7da45d277490 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1488,7 +1488,7 @@ def fobjc_weak : Flag<["-"], "fobjc-weak">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Enable ARC-style weak references in Objective-C">; // Objective-C ABI options. -def fobjc_runtime_EQ : Joined<["-"], "fobjc-runtime=">, Group<f_Group>, Flags<[CC1Option]>, +def fobjc_runtime_EQ : Joined<["-"], "fobjc-runtime=">, Group<f_Group>, Flags<[CC1Option, CoreOption]>, HelpText<"Specify the target Objective-C runtime kind and version">; def fobjc_abi_version_EQ : Joined<["-"], "fobjc-abi-version=">, Group<f_Group>; def fobjc_nonfragile_abi_version_EQ : Joined<["-"], "fobjc-nonfragile-abi-version=">, Group<f_Group>; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index d50f4493788a..c085f52cae31 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -9798,20 +9798,16 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return true; // If the decl is marked as `declare target`, it should be emitted. - for (const auto *Decl : D->redecls()) { - if (!Decl->hasAttrs()) - continue; - if (const auto *Attr = Decl->getAttr<OMPDeclareTargetDeclAttr>()) - if (Attr->getMapType() != OMPDeclareTargetDeclAttr::MT_Link) - return true; - } + if (const llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) + return *Res != OMPDeclareTargetDeclAttr::MT_Link; return false; } void ASTContext::forEachMultiversionedFunctionVersion( const FunctionDecl *FD, - llvm::function_ref<void(const FunctionDecl *)> Pred) const { + llvm::function_ref<void(FunctionDecl *)> Pred) const { assert(FD->isMultiVersion() && "Only valid for multiversioned functions"); llvm::SmallDenseSet<const FunctionDecl*, 4> SeenDecls; FD = FD->getCanonicalDecl(); diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 09e22f19f87a..55485611054c 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -1091,6 +1091,10 @@ void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { printTemplateParameters(FD->getTemplateParameterList(I)); } VisitRedeclarableTemplateDecl(D); + // Declare target attribute is special one, natural spelling for the pragma + // assumes "ending" construct so print it here. + if (D->getTemplatedDecl()->hasAttr<OMPDeclareTargetDeclAttr>()) + Out << "#pragma omp end declare target\n"; // Never print "instantiations" for deduction guides (they don't really // have them). diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 5db51b5cb384..40281481f1d1 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -445,7 +445,7 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { mangleFunctionEncoding(FD, Context.shouldMangleDeclName(FD)); else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) mangleVariableEncoding(VD); - else + else if (!isa<ObjCInterfaceDecl>(D)) llvm_unreachable("Tried to mangle unexpected NamedDecl!"); } @@ -1884,13 +1884,13 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, llvm_unreachable("placeholder types shouldn't get to name mangling"); case BuiltinType::ObjCId: - mangleArtificalTagType(TTK_Struct, "objc_object"); + mangleArtificalTagType(TTK_Struct, ".objc_object"); break; case BuiltinType::ObjCClass: - mangleArtificalTagType(TTK_Struct, "objc_class"); + mangleArtificalTagType(TTK_Struct, ".objc_class"); break; case BuiltinType::ObjCSel: - mangleArtificalTagType(TTK_Struct, "objc_selector"); + mangleArtificalTagType(TTK_Struct, ".objc_selector"); break; #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ @@ -2570,9 +2570,10 @@ void MicrosoftCXXNameMangler::mangleType(const DependentAddressSpaceType *T, void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers, SourceRange) { - // ObjC interfaces have structs underlying them. + // ObjC interfaces are mangled as if they were structs with a name that is + // not a valid C/C++ identifier mangleTagTypeKind(TTK_Struct); - mangleName(T->getDecl()); + mangle(T->getDecl(), ".objc_cls_"); } void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers, @@ -2590,11 +2591,11 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers, Out << "?$"; if (T->isObjCId()) - mangleSourceName("objc_object"); + mangleSourceName(".objc_object"); else if (T->isObjCClass()) - mangleSourceName("objc_class"); + mangleSourceName(".objc_class"); else - mangleSourceName(T->getInterface()->getName()); + mangleSourceName((".objc_cls_" + T->getInterface()->getName()).str()); for (const auto &Q : T->quals()) mangleObjCProtocol(Q); diff --git a/lib/AST/OpenMPClause.cpp b/lib/AST/OpenMPClause.cpp index 50729264bfe1..0b8aa883e180 100644 --- a/lib/AST/OpenMPClause.cpp +++ b/lib/AST/OpenMPClause.cpp @@ -181,6 +181,57 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) return nullptr; } +OMPOrderedClause *OMPOrderedClause::Create(const ASTContext &C, Expr *Num, + unsigned NumLoops, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * NumLoops)); + auto *Clause = + new (Mem) OMPOrderedClause(Num, NumLoops, StartLoc, LParenLoc, EndLoc); + for (unsigned I = 0; I < NumLoops; ++I) { + Clause->setLoopNumIterations(I, nullptr); + Clause->setLoopCounter(I, nullptr); + } + return Clause; +} + +OMPOrderedClause *OMPOrderedClause::CreateEmpty(const ASTContext &C, + unsigned NumLoops) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * NumLoops)); + auto *Clause = new (Mem) OMPOrderedClause(NumLoops); + for (unsigned I = 0; I < NumLoops; ++I) { + Clause->setLoopNumIterations(I, nullptr); + Clause->setLoopCounter(I, nullptr); + } + return Clause; +} + +void OMPOrderedClause::setLoopNumIterations(unsigned NumLoop, + Expr *NumIterations) { + assert(NumLoop < NumberOfLoops && "out of loops number."); + getTrailingObjects<Expr *>()[NumLoop] = NumIterations; +} + +ArrayRef<Expr *> OMPOrderedClause::getLoopNumIterations() const { + return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumberOfLoops); +} + +void OMPOrderedClause::setLoopCounter(unsigned NumLoop, Expr *Counter) { + assert(NumLoop < NumberOfLoops && "out of loops number."); + getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop] = Counter; +} + +Expr *OMPOrderedClause::getLoopCunter(unsigned NumLoop) { + assert(NumLoop < NumberOfLoops && "out of loops number."); + return getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop]; +} + +const Expr *OMPOrderedClause::getLoopCunter(unsigned NumLoop) const { + assert(NumLoop < NumberOfLoops && "out of loops number."); + return getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop]; +} + void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) { assert(VL.size() == varlist_size() && "Number of private copies is not the same as the preallocated buffer"); @@ -653,44 +704,58 @@ OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) { return new (Mem) OMPFlushClause(N); } -OMPDependClause *OMPDependClause::Create( - const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, OpenMPDependClauseKind DepKind, - SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + 1)); - OMPDependClause *Clause = - new (Mem) OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size()); +OMPDependClause * +OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + OpenMPDependClauseKind DepKind, SourceLocation DepLoc, + SourceLocation ColonLoc, ArrayRef<Expr *> VL, + unsigned NumLoops) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + NumLoops)); + OMPDependClause *Clause = new (Mem) + OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops); Clause->setVarRefs(VL); Clause->setDependencyKind(DepKind); Clause->setDependencyLoc(DepLoc); Clause->setColonLoc(ColonLoc); - Clause->setCounterValue(nullptr); + for (unsigned I = 0 ; I < NumLoops; ++I) + Clause->setLoopData(I, nullptr); return Clause; } -OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + 1)); - return new (Mem) OMPDependClause(N); -} - -void OMPDependClause::setCounterValue(Expr *V) { - assert(getDependencyKind() == OMPC_DEPEND_sink || - getDependencyKind() == OMPC_DEPEND_source || V == nullptr); - *getVarRefs().end() = V; -} - -const Expr *OMPDependClause::getCounterValue() const { - auto *V = *getVarRefs().end(); - assert(getDependencyKind() == OMPC_DEPEND_sink || - getDependencyKind() == OMPC_DEPEND_source || V == nullptr); - return V; -} - -Expr *OMPDependClause::getCounterValue() { - auto *V = *getVarRefs().end(); - assert(getDependencyKind() == OMPC_DEPEND_sink || - getDependencyKind() == OMPC_DEPEND_source || V == nullptr); - return V; +OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N, + unsigned NumLoops) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + NumLoops)); + return new (Mem) OMPDependClause(N, NumLoops); +} + +void OMPDependClause::setLoopData(unsigned NumLoop, Expr *Cnt) { + assert((getDependencyKind() == OMPC_DEPEND_sink || + getDependencyKind() == OMPC_DEPEND_source) && + NumLoop < NumLoops && + "Expected sink or source depend + loop index must be less number of " + "loops."); + auto It = std::next(getVarRefs().end(), NumLoop); + *It = Cnt; +} + +Expr *OMPDependClause::getLoopData(unsigned NumLoop) { + assert((getDependencyKind() == OMPC_DEPEND_sink || + getDependencyKind() == OMPC_DEPEND_source) && + NumLoop < NumLoops && + "Expected sink or source depend + loop index must be less number of " + "loops."); + auto It = std::next(getVarRefs().end(), NumLoop); + return *It; +} + +const Expr *OMPDependClause::getLoopData(unsigned NumLoop) const { + assert((getDependencyKind() == OMPC_DEPEND_sink || + getDependencyKind() == OMPC_DEPEND_source) && + NumLoop < NumLoops && + "Expected sink or source depend + loop index must be less number of " + "loops."); + auto It = std::next(getVarRefs().end(), NumLoop); + return *It; } unsigned OMPClauseMappableExprCommon::getComponentsTotalNumber( diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index a2ff102e1ab4..5890b407e767 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -1829,7 +1829,7 @@ void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF, SmallString<128> Name; { llvm::raw_svector_ostream OS(Name); - const FunctionDecl *ParentSEHFn = ParentCGF.CurSEHParent; + const NamedDecl *ParentSEHFn = ParentCGF.CurSEHParent; assert(ParentSEHFn && "No CurSEHParent!"); MangleContext &Mangler = CGM.getCXXABI().getMangleContext(); if (IsFilter) @@ -1972,6 +1972,11 @@ llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() { return Builder.CreateZExt(&*AI, Int32Ty); } +void CodeGenFunction::pushSEHCleanup(CleanupKind Kind, + llvm::Function *FinallyFunc) { + EHStack.pushCleanup<PerformSEHFinally>(Kind, FinallyFunc); +} + void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) { CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true); if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) { diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 915738b8b301..622c8bfb500f 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -18,6 +18,7 @@ #include "CGCleanup.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" +#include "CGCXXABI.h" #include "clang/CodeGen/ConstantInitBuilder.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" @@ -178,6 +179,9 @@ protected: /// runtime provides some LLVM passes that can use this to do things like /// automatic IMP caching and speculative inlining. unsigned msgSendMDKind; + /// Does the current target use SEH-based exceptions? False implies + /// Itanium-style DWARF unwinding. + bool usesSEHExceptions; /// Helper to check if we are targeting a specific runtime version or later. bool isRuntime(ObjCRuntime::Kind kind, unsigned major, unsigned minor=0) { @@ -217,6 +221,7 @@ protected: llvm::Constant *value = llvm::ConstantDataArray::getString(VMContext,Str); auto *GV = new llvm::GlobalVariable(TheModule, value->getType(), true, llvm::GlobalValue::LinkOnceODRLinkage, value, name); + GV->setComdat(TheModule.getOrInsertComdat(name)); if (Private) GV->setVisibility(llvm::GlobalValue::HiddenVisibility); ConstStr = GV; @@ -510,8 +515,8 @@ protected: /// Returns a selector with the specified type encoding. An empty string is /// used to return an untyped selector (with the types field set to NULL). - virtual llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel, - const std::string &TypeEncoding); + virtual llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel, + const std::string &TypeEncoding); /// Returns the name of ivar offset variables. In the GNUstep v1 ABI, this /// contains the class and ivar names, in the v2 ABI this contains the type @@ -810,8 +815,12 @@ class CGObjCGNUstep : public CGObjCGNU { // Slot_t objc_slot_lookup_super(struct objc_super*, SEL); SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy, PtrToObjCSuperTy, SelectorTy); - // If we're in ObjC++ mode, then we want to make - if (CGM.getLangOpts().CPlusPlus) { + // If we're in ObjC++ mode, then we want to make + if (usesSEHExceptions) { + llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); + // void objc_exception_rethrow(void) + ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy); + } else if (CGM.getLangOpts().CPlusPlus) { llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); // void *__cxa_begin_catch(void *e) EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy); @@ -888,22 +897,25 @@ class CGObjCGNUstep : public CGObjCGNU { /// This is the ABI that provides a clean break with the legacy GCC ABI and /// cleans up a number of things that were added to work around 1980s linkers. class CGObjCGNUstep2 : public CGObjCGNUstep { - /// The section for selectors. - static constexpr const char *const SelSection = "__objc_selectors"; - /// The section for classes. - static constexpr const char *const ClsSection = "__objc_classes"; - /// The section for references to classes. - static constexpr const char *const ClsRefSection = "__objc_class_refs"; - /// The section for categories. - static constexpr const char *const CatSection = "__objc_cats"; - /// The section for protocols. - static constexpr const char *const ProtocolSection = "__objc_protocols"; - /// The section for protocol references. - static constexpr const char *const ProtocolRefSection = "__objc_protocol_refs"; - /// The section for class aliases - static constexpr const char *const ClassAliasSection = "__objc_class_aliases"; - /// The section for constexpr constant strings - static constexpr const char *const ConstantStringSection = "__objc_constant_string"; + enum SectionKind + { + SelectorSection = 0, + ClassSection, + ClassReferenceSection, + CategorySection, + ProtocolSection, + ProtocolReferenceSection, + ClassAliasSection, + ConstantStringSection + }; + static const char *const SectionsBaseNames[8]; + template<SectionKind K> + std::string sectionName() { + std::string name(SectionsBaseNames[K]); + if (CGM.getTriple().isOSBinFormatCOFF()) + name += "$m"; + return name; + } /// The GCC ABI superclass message lookup function. Takes a pointer to a /// structure describing the receiver and the class, and a selector as /// arguments. Returns the IMP for the corresponding method. @@ -1069,7 +1081,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { isNamed ? StringRef(StringName) : ".objc_string", Align, false, isNamed ? llvm::GlobalValue::LinkOnceODRLinkage : llvm::GlobalValue::PrivateLinkage); - ObjCStrGV->setSection(ConstantStringSection); + ObjCStrGV->setSection(sectionName<ConstantStringSection>()); if (isNamed) { ObjCStrGV->setComdat(TheModule.getOrInsertComdat(StringName)); ObjCStrGV->setVisibility(llvm::GlobalValue::HiddenVisibility); @@ -1247,9 +1259,10 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { assert(!TheModule.getGlobalVariable(RefName)); // Emit a reference symbol. auto GV = new llvm::GlobalVariable(TheModule, ProtocolPtrTy, - false, llvm::GlobalValue::ExternalLinkage, + false, llvm::GlobalValue::LinkOnceODRLinkage, llvm::ConstantExpr::getBitCast(Protocol, ProtocolPtrTy), RefName); - GV->setSection(ProtocolRefSection); + GV->setComdat(TheModule.getOrInsertComdat(RefName)); + GV->setSection(sectionName<ProtocolReferenceSection>()); GV->setAlignment(CGM.getPointerAlign().getQuantity()); Ref = GV; } @@ -1282,9 +1295,22 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { EmittedProtocol = true; + auto SymName = SymbolForProtocol(ProtocolName); + auto *OldGV = TheModule.getGlobalVariable(SymName); + // Use the protocol definition, if there is one. if (const ObjCProtocolDecl *Def = PD->getDefinition()) PD = Def; + else { + // If there is no definition, then create an external linkage symbol and + // hope that someone else fills it in for us (and fail to link if they + // don't). + assert(!OldGV); + Protocol = new llvm::GlobalVariable(TheModule, ProtocolTy, + /*isConstant*/false, + llvm::GlobalValue::ExternalLinkage, nullptr, SymName); + return Protocol; + } SmallVector<llvm::Constant*, 16> Protocols; for (const auto *PI : PD->protocols()) @@ -1301,8 +1327,6 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { EmitProtocolMethodList(PD->class_methods(), ClassMethodList, OptionalClassMethodList); - auto SymName = SymbolForProtocol(ProtocolName); - auto *OldGV = TheModule.getGlobalVariable(SymName); // The isa pointer must be set to a magic number so the runtime knows it's // the correct layout. ConstantInitBuilder builder(CGM); @@ -1326,7 +1350,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { auto *GV = ProtocolBuilder.finishAndCreateGlobal(SymName, CGM.getPointerAlign(), false, llvm::GlobalValue::ExternalLinkage); - GV->setSection(ProtocolSection); + GV->setSection(sectionName<ProtocolSection>()); GV->setComdat(TheModule.getOrInsertComdat(SymName)); if (OldGV) { OldGV->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GV, @@ -1342,8 +1366,8 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { return Val; return llvm::ConstantExpr::getBitCast(Val, Ty); } - llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel, - const std::string &TypeEncoding) override { + llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel, + const std::string &TypeEncoding) override { return GetConstantSelector(Sel, TypeEncoding); } llvm::Constant *GetTypeString(llvm::StringRef TypeEncoding) { @@ -1359,6 +1383,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { TypeEncoding); auto *GV = new llvm::GlobalVariable(TheModule, Init->getType(), true, llvm::GlobalValue::LinkOnceODRLinkage, Init, TypesVarName); + GV->setComdat(TheModule.getOrInsertComdat(TypesVarName)); GV->setVisibility(llvm::GlobalValue::HiddenVisibility); TypesGlobal = GV; } @@ -1387,12 +1412,41 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage); GV->setComdat(TheModule.getOrInsertComdat(SelVarName)); GV->setVisibility(llvm::GlobalValue::HiddenVisibility); - GV->setSection(SelSection); + GV->setSection(sectionName<SelectorSection>()); auto *SelVal = EnforceType(GV, SelectorTy); return SelVal; } + llvm::StructType *emptyStruct = nullptr; + + /// Return pointers to the start and end of a section. On ELF platforms, we + /// use the __start_ and __stop_ symbols that GNU-compatible linkers will set + /// to the start and end of section names, as long as those section names are + /// valid identifiers and the symbols are referenced but not defined. On + /// Windows, we use the fact that MSVC-compatible linkers will lexically sort + /// by subsections and place everything that we want to reference in a middle + /// subsection and then insert zero-sized symbols in subsections a and z. std::pair<llvm::Constant*,llvm::Constant*> GetSectionBounds(StringRef Section) { + if (CGM.getTriple().isOSBinFormatCOFF()) { + if (emptyStruct == nullptr) { + emptyStruct = llvm::StructType::create(VMContext, ".objc_section_sentinel"); + emptyStruct->setBody({}, /*isPacked*/true); + } + auto ZeroInit = llvm::Constant::getNullValue(emptyStruct); + auto Sym = [&](StringRef Prefix, StringRef SecSuffix) { + auto *Sym = new llvm::GlobalVariable(TheModule, emptyStruct, + /*isConstant*/false, + llvm::GlobalValue::LinkOnceODRLinkage, ZeroInit, Prefix + + Section); + Sym->setVisibility(llvm::GlobalValue::HiddenVisibility); + Sym->setSection((Section + SecSuffix).str()); + Sym->setComdat(TheModule.getOrInsertComdat((Prefix + + Section).str())); + Sym->setAlignment(1); + return Sym; + }; + return { Sym("__start_", "$a"), Sym("__stop", "$z") }; + } auto *Start = new llvm::GlobalVariable(TheModule, PtrTy, /*isConstant*/false, llvm::GlobalValue::ExternalLinkage, nullptr, StringRef("__start_") + @@ -1405,6 +1459,9 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { Stop->setVisibility(llvm::GlobalValue::HiddenVisibility); return { Start, Stop }; } + CatchTypeInfo getCatchAllTypeInfo() override { + return CGM.getCXXABI().getCatchAllTypeInfo(); + } llvm::Function *ModuleInitFunction() override { llvm::Function *LoadFunction = llvm::Function::Create( llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false), @@ -1420,19 +1477,11 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { ConstantInitBuilder builder(CGM); auto InitStructBuilder = builder.beginStruct(); InitStructBuilder.addInt(Int64Ty, 0); - auto addSection = [&](const char *section) { - auto bounds = GetSectionBounds(section); + for (auto *s : SectionsBaseNames) { + auto bounds = GetSectionBounds(s); InitStructBuilder.add(bounds.first); InitStructBuilder.add(bounds.second); }; - addSection(SelSection); - addSection(ClsSection); - addSection(ClsRefSection); - addSection(CatSection); - addSection(ProtocolSection); - addSection(ProtocolRefSection); - addSection(ClassAliasSection); - addSection(ConstantStringSection); auto *InitStruct = InitStructBuilder.finishAndCreateGlobal(".objc_init", CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage); InitStruct->setVisibility(llvm::GlobalValue::HiddenVisibility); @@ -1451,18 +1500,23 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { // Check that this hasn't been renamed. This shouldn't happen, because // this function should be called precisely once. assert(InitVar->getName() == ".objc_ctor"); - InitVar->setSection(".ctors"); + // In Windows, initialisers are sorted by the suffix. XCL is for library + // initialisers, which run before user initialisers. We are running + // Objective-C loads at the end of library load. This means +load methods + // will run before any other static constructors, but that static + // constructors can see a fully initialised Objective-C state. + if (CGM.getTriple().isOSBinFormatCOFF()) + InitVar->setSection(".CRT$XCLz"); + else + InitVar->setSection(".ctors"); InitVar->setVisibility(llvm::GlobalValue::HiddenVisibility); InitVar->setComdat(TheModule.getOrInsertComdat(".objc_ctor")); - CGM.addCompilerUsedGlobal(InitVar); + CGM.addUsedGlobal(InitVar); for (auto *C : Categories) { auto *Cat = cast<llvm::GlobalVariable>(C->stripPointerCasts()); - Cat->setSection(CatSection); + Cat->setSection(sectionName<CategorySection>()); CGM.addUsedGlobal(Cat); } - // Add a null value fore each special section so that we can always - // guarantee that the _start and _stop symbols will exist and be - // meaningful. auto createNullGlobal = [&](StringRef Name, ArrayRef<llvm::Constant*> Init, StringRef Section) { auto nullBuilder = builder.beginStruct(); @@ -1476,38 +1530,48 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { CGM.addUsedGlobal(GV); return GV; }; - createNullGlobal(".objc_null_selector", {NULLPtr, NULLPtr}, SelSection); - if (Categories.empty()) - createNullGlobal(".objc_null_category", {NULLPtr, NULLPtr, - NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr}, CatSection); - if (!EmittedClass) { - createNullGlobal(".objc_null_cls_init_ref", NULLPtr, ClsSection); - createNullGlobal(".objc_null_class_ref", { NULLPtr, NULLPtr }, - ClsRefSection); - } - if (!EmittedProtocol) - createNullGlobal(".objc_null_protocol", {NULLPtr, NULLPtr, NULLPtr, - NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, - NULLPtr}, ProtocolSection); - if (!EmittedProtocolRef) - createNullGlobal(".objc_null_protocol_ref", {NULLPtr}, ProtocolRefSection); - if (!ClassAliases.empty()) - for (auto clsAlias : ClassAliases) - createNullGlobal(std::string(".objc_class_alias") + - clsAlias.second, { MakeConstantString(clsAlias.second), - GetClassVar(clsAlias.first) }, ClassAliasSection); - else - createNullGlobal(".objc_null_class_alias", { NULLPtr, NULLPtr }, - ClassAliasSection); - if (ConstantStrings.empty()) { - auto i32Zero = llvm::ConstantInt::get(Int32Ty, 0); - createNullGlobal(".objc_null_constant_string", { NULLPtr, i32Zero, - i32Zero, i32Zero, i32Zero, NULLPtr }, ConstantStringSection); + for (auto clsAlias : ClassAliases) + createNullGlobal(std::string(".objc_class_alias") + + clsAlias.second, { MakeConstantString(clsAlias.second), + GetClassVar(clsAlias.first) }, sectionName<ClassAliasSection>()); + // On ELF platforms, add a null value for each special section so that we + // can always guarantee that the _start and _stop symbols will exist and be + // meaningful. This is not required on COFF platforms, where our start and + // stop symbols will create the section. + if (!CGM.getTriple().isOSBinFormatCOFF()) { + createNullGlobal(".objc_null_selector", {NULLPtr, NULLPtr}, + sectionName<SelectorSection>()); + if (Categories.empty()) + createNullGlobal(".objc_null_category", {NULLPtr, NULLPtr, + NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr}, + sectionName<CategorySection>()); + if (!EmittedClass) { + createNullGlobal(".objc_null_cls_init_ref", NULLPtr, + sectionName<ClassReferenceSection>()); + createNullGlobal(".objc_null_class_ref", { NULLPtr, NULLPtr }, + sectionName<ClassReferenceSection>()); + } + if (!EmittedProtocol) + createNullGlobal(".objc_null_protocol", {NULLPtr, NULLPtr, NULLPtr, + NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, + NULLPtr}, sectionName<ProtocolSection>()); + if (!EmittedProtocolRef) + createNullGlobal(".objc_null_protocol_ref", {NULLPtr}, + sectionName<ProtocolReferenceSection>()); + if (ClassAliases.empty()) + createNullGlobal(".objc_null_class_alias", { NULLPtr, NULLPtr }, + sectionName<ClassAliasSection>()); + if (ConstantStrings.empty()) { + auto i32Zero = llvm::ConstantInt::get(Int32Ty, 0); + createNullGlobal(".objc_null_constant_string", { NULLPtr, i32Zero, + i32Zero, i32Zero, i32Zero, NULLPtr }, + sectionName<ConstantStringSection>()); + } } ConstantStrings.clear(); Categories.clear(); Classes.clear(); - return nullptr;//CGObjCGNU::ModuleInitFunction(); + return nullptr; } /// In the v2 ABI, ivar offset variables use the type encoding in their name /// to trigger linker failures if the types don't match. @@ -1774,7 +1838,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { } auto *classRefSymbol = GetClassVar(className); - classRefSymbol->setSection(ClsRefSection); + classRefSymbol->setSection(sectionName<ClassReferenceSection>()); classRefSymbol->setInitializer(llvm::ConstantExpr::getBitCast(classStruct, IdTy)); @@ -1805,7 +1869,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { auto classInitRef = new llvm::GlobalVariable(TheModule, classStruct->getType(), false, llvm::GlobalValue::ExternalLinkage, classStruct, "._OBJC_INIT_CLASS_" + className); - classInitRef->setSection(ClsSection); + classInitRef->setSection(sectionName<ClassSection>()); CGM.addUsedGlobal(classInitRef); EmittedClass = true; @@ -1829,6 +1893,18 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { }; +const char *const CGObjCGNUstep2::SectionsBaseNames[8] = +{ +"__objc_selectors", +"__objc_classes", +"__objc_class_refs", +"__objc_cats", +"__objc_protocols", +"__objc_protocol_refs", +"__objc_class_aliases", +"__objc_constant_string" +}; + /// Support for the ObjFW runtime. class CGObjCObjFW: public CGObjCGNU { protected: @@ -1931,6 +2007,8 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion, ProtocolVersion(protocolClassVersion), ClassABIVersion(classABI) { msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend"); + usesSEHExceptions = + cgm.getContext().getTargetInfo().getTriple().isWindowsMSVCEnvironment(); CodeGenTypes &Types = CGM.getTypes(); IntTy = cast<llvm::IntegerType>( @@ -2121,8 +2199,8 @@ llvm::Value *CGObjCGNU::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) { return Value; } -llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel, - const std::string &TypeEncoding) { +llvm::Value *CGObjCGNU::GetTypedSelector(CodeGenFunction &CGF, Selector Sel, + const std::string &TypeEncoding) { SmallVectorImpl<TypedSelector> &Types = SelectorTable[Sel]; llvm::GlobalAlias *SelValue = nullptr; @@ -2155,13 +2233,13 @@ Address CGObjCGNU::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) { } llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel) { - return GetSelector(CGF, Sel, std::string()); + return GetTypedSelector(CGF, Sel, std::string()); } llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl *Method) { std::string SelTypes = CGM.getContext().getObjCEncodingForMethodDecl(Method); - return GetSelector(CGF, Method->getSelector(), SelTypes); + return GetTypedSelector(CGF, Method->getSelector(), SelTypes); } llvm::Constant *CGObjCGNU::GetEHType(QualType T) { @@ -2186,6 +2264,9 @@ llvm::Constant *CGObjCGNU::GetEHType(QualType T) { } llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) { + if (usesSEHExceptions) + return CGM.getCXXABI().getAddrOfRTTIDescriptor(T); + if (!CGM.getLangOpts().CPlusPlus) return CGObjCGNU::GetEHType(T); @@ -3726,6 +3807,7 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF, const ObjCAtThrowStmt &S, bool ClearInsertionPoint) { llvm::Value *ExceptionAsObject; + bool isRethrow = false; if (const Expr *ThrowExpr = S.getThrowExpr()) { llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr); @@ -3734,11 +3816,24 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF, assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && "Unexpected rethrow outside @catch block."); ExceptionAsObject = CGF.ObjCEHValueStack.back(); + isRethrow = true; + } + if (isRethrow && usesSEHExceptions) { + // For SEH, ExceptionAsObject may be undef, because the catch handler is + // not passed it for catchalls and so it is not visible to the catch + // funclet. The real thrown object will still be live on the stack at this + // point and will be rethrown. If we are explicitly rethrowing the object + // that was passed into the `@catch` block, then this code path is not + // reached and we will instead call `objc_exception_throw` with an explicit + // argument. + CGF.EmitRuntimeCallOrInvoke(ExceptionReThrowFn).setDoesNotReturn(); + } + else { + ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy); + llvm::CallSite Throw = + CGF.EmitRuntimeCallOrInvoke(ExceptionThrowFn, ExceptionAsObject); + Throw.setDoesNotReturn(); } - ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy); - llvm::CallSite Throw = - CGF.EmitRuntimeCallOrInvoke(ExceptionThrowFn, ExceptionAsObject); - Throw.setDoesNotReturn(); CGF.Builder.CreateUnreachable(); if (ClearInsertionPoint) CGF.Builder.ClearInsertionPoint(); diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp index a43885c0f9a2..64a9df2bfc0d 100644 --- a/lib/CodeGen/CGObjCRuntime.cpp +++ b/lib/CodeGen/CGObjCRuntime.cpp @@ -15,6 +15,7 @@ #include "CGObjCRuntime.h" #include "CGCleanup.h" +#include "CGCXXABI.h" #include "CGRecordLayout.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" @@ -22,6 +23,7 @@ #include "clang/AST/StmtObjC.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "llvm/IR/CallSite.h" +#include "llvm/Support/SaveAndRestore.h" using namespace clang; using namespace CodeGen; @@ -120,6 +122,8 @@ namespace { const Stmt *Body; llvm::BasicBlock *Block; llvm::Constant *TypeInfo; + /// Flags used to differentiate cleanups and catchalls in Windows SEH + unsigned Flags; }; struct CallObjCEndCatch final : EHScopeStack::Cleanup { @@ -148,13 +152,17 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, if (S.getNumCatchStmts()) Cont = CGF.getJumpDestInCurrentScope("eh.cont"); + bool useFunclets = EHPersonality::get(CGF).usesFuncletPads(); + CodeGenFunction::FinallyInfo FinallyInfo; - if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) - FinallyInfo.enter(CGF, Finally->getFinallyBody(), - beginCatchFn, endCatchFn, exceptionRethrowFn); + if (!useFunclets) + if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) + FinallyInfo.enter(CGF, Finally->getFinallyBody(), + beginCatchFn, endCatchFn, exceptionRethrowFn); SmallVector<CatchHandler, 8> Handlers; + // Enter the catch, if there is one. if (S.getNumCatchStmts()) { for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) { @@ -166,10 +174,13 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, Handler.Variable = CatchDecl; Handler.Body = CatchStmt->getCatchBody(); Handler.Block = CGF.createBasicBlock("catch"); + Handler.Flags = 0; // @catch(...) always matches. if (!CatchDecl) { - Handler.TypeInfo = nullptr; // catch-all + auto catchAll = getCatchAllTypeInfo(); + Handler.TypeInfo = catchAll.RTTI; + Handler.Flags = catchAll.Flags; // Don't consider any other catches. break; } @@ -179,9 +190,31 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size()); for (unsigned I = 0, E = Handlers.size(); I != E; ++I) - Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block); + Catch->setHandler(I, { Handlers[I].TypeInfo, Handlers[I].Flags }, Handlers[I].Block); } + if (useFunclets) + if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) { + CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true); + if (!CGF.CurSEHParent) + CGF.CurSEHParent = cast<NamedDecl>(CGF.CurFuncDecl); + // Outline the finally block. + const Stmt *FinallyBlock = Finally->getFinallyBody(); + HelperCGF.startOutlinedSEHHelper(CGF, /*isFilter*/false, FinallyBlock); + + // Emit the original filter expression, convert to i32, and return. + HelperCGF.EmitStmt(FinallyBlock); + + HelperCGF.FinishFunction(FinallyBlock->getLocEnd()); + + llvm::Function *FinallyFunc = HelperCGF.CurFn; + + + // Push a cleanup for __finally blocks. + CGF.pushSEHCleanup(NormalAndEHCleanup, FinallyFunc); + } + + // Emit the try body. CGF.EmitStmt(S.getTryBody()); @@ -197,6 +230,13 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, CatchHandler &Handler = Handlers[I]; CGF.EmitBlock(Handler.Block); + llvm::CatchPadInst *CPI = nullptr; + SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(CGF.CurrentFuncletPad); + if (useFunclets) + if ((CPI = dyn_cast_or_null<llvm::CatchPadInst>(Handler.Block->getFirstNonPHI()))) { + CGF.CurrentFuncletPad = CPI; + CPI->setOperand(2, CGF.getExceptionSlot().getPointer()); + } llvm::Value *RawExn = CGF.getExceptionFromSlot(); // Enter the catch. @@ -223,6 +263,8 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, CGF.EmitAutoVarDecl(*CatchParam); EmitInitOfCatchParam(CGF, CastExn, CatchParam); } + if (CPI) + CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI); CGF.ObjCEHValueStack.push_back(Exn); CGF.EmitStmt(Handler.Body); @@ -232,13 +274,13 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, cleanups.ForceCleanup(); CGF.EmitBranchThroughCleanup(Cont); - } + } // Go back to the try-statement fallthrough. CGF.Builder.restoreIP(SavedIP); // Pop out of the finally. - if (S.getFinallyStmt()) + if (!useFunclets && S.getFinallyStmt()) FinallyInfo.exit(CGF); if (Cont.isValid()) @@ -277,7 +319,7 @@ namespace { : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {} void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow(); + CGF.EmitNounwindRuntimeCall(SyncExitFn, SyncArg); } }; } diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index ce082a61eb5e..78d5aba4128e 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -17,6 +17,7 @@ #define LLVM_CLANG_LIB_CODEGEN_CGOBJCRUNTIME_H #include "CGBuilder.h" #include "CGCall.h" +#include "CGCleanup.h" #include "CGValue.h" #include "clang/AST/DeclObjC.h" #include "clang/Basic/IdentifierTable.h" // Selector @@ -141,6 +142,8 @@ public: /// error to Sema. virtual llvm::Constant *GetEHType(QualType T) = 0; + virtual CatchTypeInfo getCatchAllTypeInfo() { return { nullptr, 0 }; } + /// Generate a constant string object. virtual ConstantAddress GenerateConstantString(const StringLiteral *) = 0; diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index fa850155df4f..4454c719864f 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -897,25 +897,6 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, CGF.EmitBlock(DoneBB, /*IsFinished=*/true); } -static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> -isDeclareTargetDeclaration(const ValueDecl *VD) { - for (const Decl *D : VD->redecls()) { - if (!D->hasAttrs()) - continue; - if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>()) - return Attr->getMapType(); - } - if (const auto *V = dyn_cast<VarDecl>(VD)) { - if (const VarDecl *TD = V->getTemplateInstantiationPattern()) - return isDeclareTargetDeclaration(TD); - } else if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { - if (const auto *TD = FD->getTemplateInstantiationPattern()) - return isDeclareTargetDeclaration(TD); - } - - return llvm::None; -} - LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { return CGF.EmitOMPSharedLValue(E); } @@ -2417,7 +2398,7 @@ Address CGOpenMPRuntime::getAddrOfDeclareTargetLink(const VarDecl *VD) { if (CGM.getLangOpts().OpenMPSimd) return Address::invalid(); llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - isDeclareTargetDeclaration(VD); + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) { SmallString<64> PtrName; { @@ -2639,7 +2620,7 @@ bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Addr, bool PerformInit) { Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - isDeclareTargetDeclaration(VD); + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link) return false; VD = VD->getDefinition(CGM.getContext()); @@ -6945,7 +6926,7 @@ private: if (const auto *VD = dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - isDeclareTargetDeclaration(VD)) + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) if (*Res == OMPDeclareTargetDeclAttr::MT_Link) { IsLink = true; BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD); @@ -7436,7 +7417,7 @@ public: if (!VD) continue; llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - isDeclareTargetDeclaration(VD); + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); if (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) continue; StructRangeInfoTy PartialStruct; @@ -8066,7 +8047,7 @@ bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { scanForTargetRegionsFunctions(FD->getBody(), CGM.getMangledName(GD)); // Do not to emit function if it is not marked as declare target. - return !isDeclareTargetDeclaration(FD) && + return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD) && AlreadyEmittedTargetFunctions.count(FD->getCanonicalDecl()) == 0; } @@ -8093,14 +8074,15 @@ bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { // Do not to emit variable if it is not marked as declare target. llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - isDeclareTargetDeclaration(cast<VarDecl>(GD.getDecl())); + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( + cast<VarDecl>(GD.getDecl())); return !Res || *Res == OMPDeclareTargetDeclAttr::MT_Link; } void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, llvm::Constant *Addr) { if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - isDeclareTargetDeclaration(VD)) { + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; StringRef VarName; CharUnits VarSize; @@ -8173,7 +8155,7 @@ bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { const FunctionDecl *FD = D->getCanonicalDecl(); // Do not to emit function if it is marked as declare target as it was already // emitted. - if (isDeclareTargetDeclaration(D)) { + if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { if (D->hasBody() && AlreadyEmittedTargetFunctions.count(FD) == 0) { if (auto *F = dyn_cast_or_null<llvm::Function>( CGM.GetGlobalValue(CGM.getMangledName(GD)))) @@ -8782,7 +8764,8 @@ public: } // namespace void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, - const OMPLoopDirective &D) { + const OMPLoopDirective &D, + ArrayRef<Expr *> NumIterations) { if (!CGF.HaveInsertPoint()) return; @@ -8805,32 +8788,45 @@ void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, } else { RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); } + llvm::APInt Size(/*numBits=*/32, NumIterations.size()); + QualType ArrayTy = + C.getConstantArrayType(KmpDimTy, Size, ArrayType::Normal, 0); - Address DimsAddr = CGF.CreateMemTemp(KmpDimTy, "dims"); - CGF.EmitNullInitialization(DimsAddr, KmpDimTy); + Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); + CGF.EmitNullInitialization(DimsAddr, ArrayTy); enum { LowerFD = 0, UpperFD, StrideFD }; // Fill dims with data. - LValue DimsLVal = CGF.MakeAddrLValue(DimsAddr, KmpDimTy); - // dims.upper = num_iterations; - LValue UpperLVal = - CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), UpperFD)); - llvm::Value *NumIterVal = CGF.EmitScalarConversion( - CGF.EmitScalarExpr(D.getNumIterations()), D.getNumIterations()->getType(), - Int64Ty, D.getNumIterations()->getExprLoc()); - CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); - // dims.stride = 1; - LValue StrideLVal = - CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), StrideFD)); - CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), - StrideLVal); + for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { + LValue DimsLVal = + CGF.MakeAddrLValue(CGF.Builder.CreateConstArrayGEP( + DimsAddr, I, C.getTypeSizeInChars(KmpDimTy)), + KmpDimTy); + // dims.upper = num_iterations; + LValue UpperLVal = CGF.EmitLValueForField( + DimsLVal, *std::next(RD->field_begin(), UpperFD)); + llvm::Value *NumIterVal = + CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]), + D.getNumIterations()->getType(), Int64Ty, + D.getNumIterations()->getExprLoc()); + CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); + // dims.stride = 1; + LValue StrideLVal = CGF.EmitLValueForField( + DimsLVal, *std::next(RD->field_begin(), StrideFD)); + CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), + StrideLVal); + } // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, // kmp_int32 num_dims, struct kmp_dim * dims); - llvm::Value *Args[] = {emitUpdateLocation(CGF, D.getLocStart()), - getThreadID(CGF, D.getLocStart()), - llvm::ConstantInt::getSigned(CGM.Int32Ty, 1), - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - DimsAddr.getPointer(), CGM.VoidPtrTy)}; + llvm::Value *Args[] = { + emitUpdateLocation(CGF, D.getLocStart()), + getThreadID(CGF, D.getLocStart()), + llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), + CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( + CGF.Builder + .CreateConstArrayGEP(DimsAddr, 0, C.getTypeSizeInChars(KmpDimTy)) + .getPointer(), + CGM.VoidPtrTy)}; llvm::Value *RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_init); CGF.EmitRuntimeCall(RTLFn, Args); @@ -8845,16 +8841,29 @@ void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C) { QualType Int64Ty = CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); - const Expr *CounterVal = C->getCounterValue(); - assert(CounterVal); - llvm::Value *CntVal = CGF.EmitScalarConversion(CGF.EmitScalarExpr(CounterVal), - CounterVal->getType(), Int64Ty, - CounterVal->getExprLoc()); - Address CntAddr = CGF.CreateMemTemp(Int64Ty, ".cnt.addr"); - CGF.EmitStoreOfScalar(CntVal, CntAddr, /*Volatile=*/false, Int64Ty); - llvm::Value *Args[] = {emitUpdateLocation(CGF, C->getLocStart()), - getThreadID(CGF, C->getLocStart()), - CntAddr.getPointer()}; + llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); + QualType ArrayTy = CGM.getContext().getConstantArrayType( + Int64Ty, Size, ArrayType::Normal, 0); + Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); + for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { + const Expr *CounterVal = C->getLoopData(I); + assert(CounterVal); + llvm::Value *CntVal = CGF.EmitScalarConversion( + CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, + CounterVal->getExprLoc()); + CGF.EmitStoreOfScalar( + CntVal, + CGF.Builder.CreateConstArrayGEP( + CntAddr, I, CGM.getContext().getTypeSizeInChars(Int64Ty)), + /*Volatile=*/false, Int64Ty); + } + llvm::Value *Args[] = { + emitUpdateLocation(CGF, C->getLocStart()), + getThreadID(CGF, C->getLocStart()), + CGF.Builder + .CreateConstArrayGEP(CntAddr, 0, + CGM.getContext().getTypeSizeInChars(Int64Ty)) + .getPointer()}; llvm::Value *RTLFn; if (C->getDependencyKind() == OMPC_DEPEND_source) { RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); @@ -9169,7 +9178,8 @@ void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( } void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, - const OMPLoopDirective &D) { + const OMPLoopDirective &D, + ArrayRef<Expr *> NumIterations) { llvm_unreachable("Not supported in SIMD-only mode"); } diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h index 01ff0c20fd66..94731b64ebdb 100644 --- a/lib/CodeGen/CGOpenMPRuntime.h +++ b/lib/CodeGen/CGOpenMPRuntime.h @@ -1465,8 +1465,8 @@ public: /// Emit initialization for doacross loop nesting support. /// \param D Loop-based construct used in doacross nesting construct. - virtual void emitDoacrossInit(CodeGenFunction &CGF, - const OMPLoopDirective &D); + virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, + ArrayRef<Expr *> NumIterations); /// Emit code for doacross ordered directive with 'depend' clause. /// \param C 'depend' clause with 'sink|source' dependency kind. @@ -2051,8 +2051,8 @@ public: /// Emit initialization for doacross loop nesting support. /// \param D Loop-based construct used in doacross nesting construct. - void emitDoacrossInit(CodeGenFunction &CGF, - const OMPLoopDirective &D) override; + void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, + ArrayRef<Expr *> NumIterations) override; /// Emit code for doacross ordered directive with 'depend' clause. /// \param C 'depend' clause with 'sink|source' dependency kind. diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index 036b5371fe0b..2768a8eb1857 100644 --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -191,20 +191,10 @@ class CheckVarsEscapingDeclContext final bool AllEscaped = false; bool IsForCombinedParallelRegion = false; - static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> - isDeclareTargetDeclaration(const ValueDecl *VD) { - for (const Decl *D : VD->redecls()) { - if (!D->hasAttrs()) - continue; - if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>()) - return Attr->getMapType(); - } - return llvm::None; - } - void markAsEscaped(const ValueDecl *VD) { // Do not globalize declare target variables. - if (!isa<VarDecl>(VD) || isDeclareTargetDeclaration(VD)) + if (!isa<VarDecl>(VD) || + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) return; VD = cast<ValueDecl>(VD->getCanonicalDecl()); // Variables captured by value must be globalized. diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp index 0d343f84c71f..03102f04aa9c 100644 --- a/lib/CodeGen/CGStmtOpenMP.cpp +++ b/lib/CodeGen/CGStmtOpenMP.cpp @@ -1509,6 +1509,23 @@ void CodeGenFunction::EmitOMPPrivateLoopCounters( } ++I; } + // Privatize extra loop counters used in loops for ordered(n) clauses. + for (const auto *C : S.getClausesOfKind<OMPOrderedClause>()) { + if (!C->getNumForLoops()) + continue; + for (unsigned I = S.getCollapsedNumber(), + E = C->getLoopNumIterations().size(); + I < E; ++I) { + const auto *DRE = cast<DeclRefExpr>(C->getLoopCunter(I)); + const auto *VD = cast<VarDecl>(DRE->getDecl()); + // Override only those variables that are really emitted already. + if (LocalDeclMap.count(VD)) { + (void)LoopScope.addPrivate(VD, [this, DRE, VD]() { + return CreateMemTemp(DRE->getType(), VD->getName()); + }); + } + } + } } static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S, @@ -2244,7 +2261,7 @@ bool CodeGenFunction::EmitOMPWorksharingLoop( bool Ordered = false; if (const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) { if (OrderedClause->getNumForLoops()) - RT.emitDoacrossInit(*this, S); + RT.emitDoacrossInit(*this, S, OrderedClause->getLoopNumIterations()); else Ordered = true; } @@ -4943,6 +4960,20 @@ void CodeGenFunction::EmitSimpleOMPExecutableDirective( CGF.EmitVarDecl(*VD); } } + for (const auto *C : D.getClausesOfKind<OMPOrderedClause>()) { + if (!C->getNumForLoops()) + continue; + for (unsigned I = LD->getCollapsedNumber(), + E = C->getLoopNumIterations().size(); + I < E; ++I) { + if (const auto *VD = dyn_cast<OMPCapturedExprDecl>( + cast<DeclRefExpr>(C->getLoopCunter(I))->getDecl())) { + // Emit only those that were not explicitly referenced in clauses. + if (!CGF.LocalDeclMap.count(VD)) + CGF.EmitVarDecl(*VD); + } + } + } } CGF.EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt()); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index f9e284232972..878923a85bdf 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -470,7 +470,7 @@ public: /// potentially set the return value. bool SawAsmBlock = false; - const FunctionDecl *CurSEHParent = nullptr; + const NamedDecl *CurSEHParent = nullptr; /// True if the current function is an outlined SEH helper. This can be a /// finally block or filter expression. @@ -2878,6 +2878,8 @@ public: void EnterSEHTryStmt(const SEHTryStmt &S); void ExitSEHTryStmt(const SEHTryStmt &S); + void pushSEHCleanup(CleanupKind kind, + llvm::Function *FinallyFunc); void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, bool IsFilter, const Stmt *OutlinedStmt); diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 8e9c4c6aecb8..45a29a0225a4 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -4912,7 +4912,8 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args, } if ((runtime.getKind() == ObjCRuntime::GNUstep) && (runtime.getVersion() >= VersionTuple(2, 0))) - if (!getToolChain().getTriple().isOSBinFormatELF()) { + if (!getToolChain().getTriple().isOSBinFormatELF() && + !getToolChain().getTriple().isOSBinFormatCOFF()) { getToolChain().getDriver().Diag( diag::err_drv_gnustep_objc_runtime_incompatible_binary) << runtime.getVersion().getMajor(); diff --git a/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp index 9205dd52de0b..dc540688d2b1 100644 --- a/lib/Driver/ToolChains/Darwin.cpp +++ b/lib/Driver/ToolChains/Darwin.cpp @@ -2035,7 +2035,11 @@ bool Darwin::isAlignedAllocationUnavailable() const { void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind DeviceOffloadKind) const { - if (isAlignedAllocationUnavailable()) + // Pass "-faligned-alloc-unavailable" only when the user hasn't manually + // enabled or disabled aligned allocations. + if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation, + options::OPT_fno_aligned_allocation) && + isAlignedAllocationUnavailable()) CC1Args.push_back("-faligned-alloc-unavailable"); } diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index e3f4f92b9d1e..e576fc098dad 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -553,7 +553,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, Builder.defineMacro("__cpp_guaranteed_copy_elision", "201606L"); Builder.defineMacro("__cpp_nontype_template_parameter_auto", "201606L"); } - if (LangOpts.AlignedAllocation) + if (LangOpts.AlignedAllocation && !LangOpts.AlignedAllocationUnavailable) Builder.defineMacro("__cpp_aligned_new", "201606L"); if (LangOpts.RelaxedTemplateTemplateArgs) Builder.defineMacro("__cpp_template_template_args", "201611L"); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 7a8f2d3f4702..c851a81af464 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1747,9 +1747,9 @@ static void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, StringRef OSName = AvailabilityAttr::getPlatformNameSourceSpelling( S.getASTContext().getTargetInfo().getPlatformName()); - S.Diag(Loc, diag::warn_aligned_allocation_unavailable) - << IsDelete << FD.getType().getAsString() << OSName - << alignedAllocMinVersion(T.getOS()).getAsString(); + S.Diag(Loc, diag::err_aligned_allocation_unavailable) + << IsDelete << FD.getType().getAsString() << OSName + << alignedAllocMinVersion(T.getOS()).getAsString(); S.Diag(Loc, diag::note_silence_unligned_allocation_unavailable); } } diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index e1a4c420d402..6060e5b75c22 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -73,6 +73,8 @@ public: }; using OperatorOffsetTy = llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>; + using DoacrossDependMapTy = + llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>; private: struct DSAInfo { @@ -97,8 +99,6 @@ private: llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>; using CriticalsWithHintsTy = llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>; - using DoacrossDependMapTy = - llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>; struct ReductionData { using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>; SourceRange ReductionRange; @@ -137,7 +137,7 @@ private: /// first argument (Expr *) contains optional argument of the /// 'ordered' clause, the second one is true if the regions has 'ordered' /// clause, false otherwise. - llvm::PointerIntPair<const Expr *, 1, bool> OrderedRegion; + llvm::Optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion; bool NowaitRegion = false; bool CancelRegion = false; unsigned AssociatedLoops = 1; @@ -398,23 +398,42 @@ public: } /// Marks current region as ordered (it has an 'ordered' clause). - void setOrderedRegion(bool IsOrdered, const Expr *Param) { + void setOrderedRegion(bool IsOrdered, const Expr *Param, + OMPOrderedClause *Clause) { assert(!isStackEmpty()); - Stack.back().first.back().OrderedRegion.setInt(IsOrdered); - Stack.back().first.back().OrderedRegion.setPointer(Param); + if (IsOrdered) + Stack.back().first.back().OrderedRegion.emplace(Param, Clause); + else + Stack.back().first.back().OrderedRegion.reset(); + } + /// Returns true, if region is ordered (has associated 'ordered' clause), + /// false - otherwise. + bool isOrderedRegion() const { + if (isStackEmpty()) + return false; + return Stack.back().first.rbegin()->OrderedRegion.hasValue(); + } + /// Returns optional parameter for the ordered region. + std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const { + if (isStackEmpty() || + !Stack.back().first.rbegin()->OrderedRegion.hasValue()) + return std::make_pair(nullptr, nullptr); + return Stack.back().first.rbegin()->OrderedRegion.getValue(); } /// Returns true, if parent region is ordered (has associated /// 'ordered' clause), false - otherwise. bool isParentOrderedRegion() const { if (isStackEmpty() || Stack.back().first.size() == 1) return false; - return std::next(Stack.back().first.rbegin())->OrderedRegion.getInt(); + return std::next(Stack.back().first.rbegin())->OrderedRegion.hasValue(); } /// Returns optional parameter for the ordered region. - const Expr *getParentOrderedRegionParam() const { - if (isStackEmpty() || Stack.back().first.size() == 1) - return nullptr; - return std::next(Stack.back().first.rbegin())->OrderedRegion.getPointer(); + std::pair<const Expr *, OMPOrderedClause *> + getParentOrderedRegionParam() const { + if (isStackEmpty() || Stack.back().first.size() == 1 || + !std::next(Stack.back().first.rbegin())->OrderedRegion.hasValue()) + return std::make_pair(nullptr, nullptr); + return std::next(Stack.back().first.rbegin())->OrderedRegion.getValue(); } /// Marks current region as nowait (it has a 'nowait' clause). void setNowaitRegion(bool IsNowait = true) { @@ -1239,17 +1258,6 @@ void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) { DSAStack->popFunction(OldFSI); } -static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> -isDeclareTargetDeclaration(const ValueDecl *VD) { - for (const Decl *D : VD->redecls()) { - if (!D->hasAttrs()) - continue; - if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>()) - return Attr->getMapType(); - } - return llvm::None; -} - bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const { assert(LangOpts.OpenMP && "OpenMP is not allowed"); @@ -1429,7 +1437,7 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) const { // If the declaration is enclosed in a 'declare target' directive, // then it should not be captured. // - if (isDeclareTargetDeclaration(VD)) + if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) return nullptr; return VD; } @@ -1968,7 +1976,7 @@ public: // Skip internally declared static variables. llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - isDeclareTargetDeclaration(VD); + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); if (VD->hasGlobalStorage() && !CS->capturesVariable(VD) && (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)) return; @@ -3736,6 +3744,13 @@ public: Expr *buildCounterInit() const; /// Build step of the counter be used for codegen. Expr *buildCounterStep() const; + /// Build loop data with counter value for depend clauses in ordered + /// directives. + Expr * + buildOrderedLoopData(Scope *S, Expr *Counter, + llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, + SourceLocation Loc, Expr *Inc = nullptr, + OverloadedOperatorKind OOK = OO_Amp); /// Return true if any expression is dependent. bool dependent() const; @@ -3900,7 +3915,12 @@ bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) { SemaRef.Diag(S->getLocStart(), diag::ext_omp_loop_not_canonical_init) << S->getSourceRange(); - return setLCDeclAndLB(Var, nullptr, Var->getInit()); + return setLCDeclAndLB( + Var, + buildDeclRefExpr(SemaRef, Var, + Var->getType().getNonReferenceType(), + DS->getLocStart()), + Var->getInit()); } } } @@ -4262,7 +4282,8 @@ Expr *OpenMPIterationSpaceChecker::buildPreCond( /// Build reference expression to the counter be used for codegen. DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar( - llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, DSAStackTy &DSA) const { + llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, + DSAStackTy &DSA) const { auto *VD = dyn_cast<VarDecl>(LCDecl); if (!VD) { VD = SemaRef.isOpenMPCapturedDecl(LCDecl); @@ -4302,6 +4323,63 @@ Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; } /// Build step of the counter be used for codegen. Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; } +Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData( + Scope *S, Expr *Counter, + llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc, + Expr *Inc, OverloadedOperatorKind OOK) { + Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get(); + if (!Cnt) + return nullptr; + if (Inc) { + assert((OOK == OO_Plus || OOK == OO_Minus) && + "Expected only + or - operations for depend clauses."); + BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub; + Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get(); + if (!Cnt) + return nullptr; + } + ExprResult Diff; + QualType VarType = LCDecl->getType().getNonReferenceType(); + if (VarType->isIntegerType() || VarType->isPointerType() || + SemaRef.getLangOpts().CPlusPlus) { + // Upper - Lower + Expr *Upper = + TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, UB, Captures).get(); + Expr *Lower = + TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt; + if (!Upper || !Lower) + return nullptr; + + Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower); + + if (!Diff.isUsable() && VarType->getAsCXXRecordDecl()) { + // BuildBinOp already emitted error, this one is to point user to upper + // and lower bound, and to tell what is passed to 'operator-'. + SemaRef.Diag(Upper->getLocStart(), diag::err_omp_loop_diff_cxx) + << Upper->getSourceRange() << Lower->getSourceRange(); + return nullptr; + } + } + + if (!Diff.isUsable()) + return nullptr; + + // Parentheses (for dumping/debugging purposes only). + Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get()); + if (!Diff.isUsable()) + return nullptr; + + ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures); + if (!NewStep.isUsable()) + return nullptr; + // (Upper - Lower) / Step + Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get()); + if (!Diff.isUsable()) + return nullptr; + + return Diff.get(); +} + /// Iteration space of a single for loop. struct LoopIterationSpace final { /// Condition of the loop. @@ -4361,7 +4439,8 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) { static bool checkOpenMPIterationSpace( OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, - Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, + unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, + Expr *OrderedLoopCountExpr, Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA, LoopIterationSpace &ResultIterSpace, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) { @@ -4371,9 +4450,9 @@ static bool checkOpenMPIterationSpace( if (!For) { SemaRef.Diag(S->getLocStart(), diag::err_omp_not_for) << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr) - << getOpenMPDirectiveName(DKind) << NestedLoopCount + << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount; - if (NestedLoopCount > 1) { + if (TotalNestedLoopCount > 1) { if (CollapseLoopCountExpr && OrderedLoopCountExpr) SemaRef.Diag(DSA.getConstructLoc(), diag::note_omp_collapse_ordered_expr) @@ -4506,6 +4585,41 @@ static bool checkOpenMPIterationSpace( ResultIterSpace.PrivateCounterVar == nullptr || ResultIterSpace.CounterInit == nullptr || ResultIterSpace.CounterStep == nullptr); + if (!HasErrors && DSA.isOrderedRegion()) { + if (DSA.getOrderedRegionParam().second->getNumForLoops()) { + if (CurrentNestedLoopCount < + DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) { + DSA.getOrderedRegionParam().second->setLoopNumIterations( + CurrentNestedLoopCount, ResultIterSpace.NumIterations); + DSA.getOrderedRegionParam().second->setLoopCounter( + CurrentNestedLoopCount, ResultIterSpace.CounterVar); + } + } + for (auto &Pair : DSA.getDoacrossDependClauses()) { + if (CurrentNestedLoopCount >= Pair.first->getNumLoops()) { + // Erroneous case - clause has some problems. + continue; + } + if (Pair.first->getDependencyKind() == OMPC_DEPEND_sink && + Pair.second.size() <= CurrentNestedLoopCount) { + // Erroneous case - clause has some problems. + Pair.first->setLoopData(CurrentNestedLoopCount, nullptr); + continue; + } + Expr *CntValue; + if (Pair.first->getDependencyKind() == OMPC_DEPEND_source) + CntValue = ISC.buildOrderedLoopData( + DSA.getCurScope(), ResultIterSpace.CounterVar, Captures, + Pair.first->getDependencyLoc()); + else + CntValue = ISC.buildOrderedLoopData( + DSA.getCurScope(), ResultIterSpace.CounterVar, Captures, + Pair.first->getDependencyLoc(), + Pair.second[CurrentNestedLoopCount].first, + Pair.second[CurrentNestedLoopCount].second); + Pair.first->setLoopData(CurrentNestedLoopCount, CntValue); + } + } return HasErrors; } @@ -4691,6 +4805,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, if (CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) NestedLoopCount = Result.getLimitedValue(); } + unsigned OrderedLoopCount = 1; if (OrderedLoopCountExpr) { // Found 'ordered' clause - calculate collapse number. llvm::APSInt Result; @@ -4703,20 +4818,21 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, diag::note_collapse_loop_count) << CollapseLoopCountExpr->getSourceRange(); } - NestedLoopCount = Result.getLimitedValue(); + OrderedLoopCount = Result.getLimitedValue(); } } // This is helper routine for loop directives (e.g., 'for', 'simd', // 'for simd', etc.). llvm::MapVector<const Expr *, DeclRefExpr *> Captures; SmallVector<LoopIterationSpace, 4> IterSpaces; - IterSpaces.resize(NestedLoopCount); + IterSpaces.resize(std::max(OrderedLoopCount, NestedLoopCount)); Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true); for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) { - if (checkOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt, - NestedLoopCount, CollapseLoopCountExpr, - OrderedLoopCountExpr, VarsWithImplicitDSA, - IterSpaces[Cnt], Captures)) + if (checkOpenMPIterationSpace( + DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount, + std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr, + OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces[Cnt], + Captures)) return 0; // Move on to the next nested for loop, or to the loop body. // OpenMP [2.8.1, simd construct, Restrictions] @@ -4725,6 +4841,27 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // any two loops. CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers(); } + for (unsigned Cnt = NestedLoopCount; Cnt < OrderedLoopCount; ++Cnt) { + if (checkOpenMPIterationSpace( + DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount, + std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr, + OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces[Cnt], + Captures)) + return 0; + if (Cnt > 0 && IterSpaces[Cnt].CounterVar) { + // Handle initialization of captured loop iterator variables. + auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar); + if (isa<OMPCapturedExprDecl>(DRE->getDecl())) { + Captures[DRE] = DRE; + } + } + // Move on to the next nested for loop, or to the loop body. + // OpenMP [2.8.1, simd construct, Restrictions] + // All loops associated with the construct must be perfectly nested; that + // is, there must be no intervening code nor any OpenMP directive between + // any two loops. + CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers(); + } Built.clear(/* size */ NestedLoopCount); @@ -5104,7 +5241,6 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.Inits.resize(NestedLoopCount); Built.Updates.resize(NestedLoopCount); Built.Finals.resize(NestedLoopCount); - SmallVector<Expr *, 4> LoopMultipliers; { ExprResult Div; // Go from inner nested loop to outer. @@ -5174,7 +5310,6 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, HasErrors = true; break; } - LoopMultipliers.push_back(Div.get()); } if (!Update.isUsable() || !Final.isUsable()) { HasErrors = true; @@ -5222,55 +5357,6 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.DistCombinedFields.NLB = CombNextLB.get(); Built.DistCombinedFields.NUB = CombNextUB.get(); - Expr *CounterVal = SemaRef.DefaultLvalueConversion(IV.get()).get(); - // Fill data for doacross depend clauses. - for (const auto &Pair : DSA.getDoacrossDependClauses()) { - if (Pair.first->getDependencyKind() == OMPC_DEPEND_source) { - Pair.first->setCounterValue(CounterVal); - } else { - if (NestedLoopCount != Pair.second.size() || - NestedLoopCount != LoopMultipliers.size() + 1) { - // Erroneous case - clause has some problems. - Pair.first->setCounterValue(CounterVal); - continue; - } - assert(Pair.first->getDependencyKind() == OMPC_DEPEND_sink); - auto I = Pair.second.rbegin(); - auto IS = IterSpaces.rbegin(); - auto ILM = LoopMultipliers.rbegin(); - Expr *UpCounterVal = CounterVal; - Expr *Multiplier = nullptr; - for (int Cnt = NestedLoopCount - 1; Cnt >= 0; --Cnt) { - if (I->first) { - assert(IS->CounterStep); - Expr *NormalizedOffset = - SemaRef - .BuildBinOp(CurScope, I->first->getExprLoc(), BO_Div, - I->first, IS->CounterStep) - .get(); - if (Multiplier) { - NormalizedOffset = - SemaRef - .BuildBinOp(CurScope, I->first->getExprLoc(), BO_Mul, - NormalizedOffset, Multiplier) - .get(); - } - assert(I->second == OO_Plus || I->second == OO_Minus); - BinaryOperatorKind BOK = (I->second == OO_Plus) ? BO_Add : BO_Sub; - UpCounterVal = SemaRef - .BuildBinOp(CurScope, I->first->getExprLoc(), BOK, - UpCounterVal, NormalizedOffset) - .get(); - } - Multiplier = *ILM; - ++I; - ++IS; - ++ILM; - } - Pair.first->setCounterValue(UpCounterVal); - } - } - return NestedLoopCount; } @@ -5838,12 +5924,12 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses, Diag(DependFound->getLocStart(), diag::err_omp_depend_clause_thread_simd) << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind()); ErrorFound = true; - } else if (DependFound && !DSAStack->getParentOrderedRegionParam()) { + } else if (DependFound && !DSAStack->getParentOrderedRegionParam().first) { Diag(DependFound->getLocStart(), diag::err_omp_ordered_directive_without_param); ErrorFound = true; } else if (TC || Clauses.empty()) { - if (const Expr *Param = DSAStack->getParentOrderedRegionParam()) { + if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) { SourceLocation ErrLoc = TC ? TC->getLocStart() : StartLoc; Diag(ErrLoc, diag::err_omp_ordered_directive_with_param) << (TC != nullptr); @@ -8619,9 +8705,11 @@ OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc, } else { NumForLoops = nullptr; } - DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops); - return new (Context) - OMPOrderedClause(NumForLoops, StartLoc, LParenLoc, EndLoc); + auto *Clause = OMPOrderedClause::Create( + Context, NumForLoops, NumForLoops ? DSAStack->getAssociatedLoops() : 0, + StartLoc, LParenLoc, EndLoc); + DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause); + return Clause; } OMPClause *Sema::ActOnOpenMPSimpleClause( @@ -11477,8 +11565,9 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, DSAStackTy::OperatorOffsetTy OpsOffs; llvm::APSInt DepCounter(/*BitWidth=*/32); llvm::APSInt TotalDepCount(/*BitWidth=*/32); - if (DepKind == OMPC_DEPEND_sink) { - if (const Expr *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) { + if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) { + if (const Expr *OrderedCountExpr = + DSAStack->getParentOrderedRegionParam().first) { TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context); TotalDepCount.setIsUnsigned(/*Val=*/true); } @@ -11494,7 +11583,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation ELoc = RefExpr->getExprLoc(); Expr *SimpleExpr = RefExpr->IgnoreParenCasts(); if (DepKind == OMPC_DEPEND_sink) { - if (DSAStack->getParentOrderedRegionParam() && + if (DSAStack->getParentOrderedRegionParam().first && DepCounter >= TotalDepCount) { Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr); continue; @@ -11560,7 +11649,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, continue; } if (!CurContext->isDependentContext() && - DSAStack->getParentOrderedRegionParam() && + DSAStack->getParentOrderedRegionParam().first && DepCounter != DSAStack->isParentLoopControlVariable(D).first) { const ValueDecl *VD = DSAStack->getParentLoopControlVariable(DepCounter.getZExtValue()); @@ -11598,7 +11687,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink && TotalDepCount > VarList.size() && - DSAStack->getParentOrderedRegionParam() && + DSAStack->getParentOrderedRegionParam().first && DSAStack->getParentLoopControlVariable(VarList.size() + 1)) { Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration) << 1 << DSAStack->getParentLoopControlVariable(VarList.size() + 1); @@ -11608,7 +11697,8 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, return nullptr; auto *C = OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, - DepKind, DepLoc, ColonLoc, Vars); + DepKind, DepLoc, ColonLoc, Vars, + TotalDepCount.getZExtValue()); if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) && DSAStack->isParentOrderedRegion()) DSAStack->addDoacrossDependClause(C, OpsOffs); @@ -13042,6 +13132,8 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, return; } } + if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) + D = FTD->getTemplatedDecl(); if (const auto *FD = dyn_cast<FunctionDecl>(D)) { if (FD->hasAttr<OMPDeclareTargetDeclAttr>() && (FD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() == @@ -13052,16 +13144,6 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, return; } } - if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) { - if (FTD->hasAttr<OMPDeclareTargetDeclAttr>() && - (FTD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() == - OMPDeclareTargetDeclAttr::MT_Link)) { - assert(IdLoc.isValid() && "Source location is expected"); - Diag(IdLoc, diag::err_omp_function_in_link_clause); - Diag(FTD->getLocation(), diag::note_defined_here) << FTD; - return; - } - } if (!E) { // Checking declaration inside declare target region. if (!D->hasAttr<OMPDeclareTargetDeclAttr>() && diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 86492716f685..512b00b1008c 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5192,10 +5192,20 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) { bool DefinitionRequired = Function->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; - InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true, - DefinitionRequired, true); - if (Function->isDefined()) - Function->setInstantiationIsPending(false); + if (Function->isMultiVersion()) { + getASTContext().forEachMultiversionedFunctionVersion( + Function, [this, Inst, DefinitionRequired](FunctionDecl *CurFD) { + InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, CurFD, true, + DefinitionRequired, true); + if (CurFD->isDefined()) + CurFD->setInstantiationIsPending(false); + }); + } else { + InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, Function, true, + DefinitionRequired, true); + if (Function->isDefined()) + Function->setInstantiationIsPending(false); + } continue; } diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index d9d780b25b31..570b554986f8 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1856,7 +1856,7 @@ OMPClause *OMPClauseReader::readClause() { C = new (Context) OMPScheduleClause(); break; case OMPC_ordered: - C = new (Context) OMPOrderedClause(); + C = OMPOrderedClause::CreateEmpty(Context, Reader->Record.readInt()); break; case OMPC_nowait: C = new (Context) OMPNowaitClause(); @@ -1927,9 +1927,12 @@ OMPClause *OMPClauseReader::readClause() { case OMPC_flush: C = OMPFlushClause::CreateEmpty(Context, Reader->Record.readInt()); break; - case OMPC_depend: - C = OMPDependClause::CreateEmpty(Context, Reader->Record.readInt()); + case OMPC_depend: { + unsigned NumVars = Reader->Record.readInt(); + unsigned NumLoops = Reader->Record.readInt(); + C = OMPDependClause::CreateEmpty(Context, NumVars, NumLoops); break; + } case OMPC_device: C = new (Context) OMPDeviceClause(); break; @@ -2087,6 +2090,10 @@ void OMPClauseReader::VisitOMPScheduleClause(OMPScheduleClause *C) { void OMPClauseReader::VisitOMPOrderedClause(OMPOrderedClause *C) { C->setNumForLoops(Reader->Record.readSubExpr()); + for (unsigned I = 0, E = C->NumberOfLoops; I < E; ++I) + C->setLoopNumIterations(I, Reader->Record.readSubExpr()); + for (unsigned I = 0, E = C->NumberOfLoops; I < E; ++I) + C->setLoopCounter(I, Reader->Record.readSubExpr()); C->setLParenLoc(Reader->ReadSourceLocation()); } @@ -2395,10 +2402,11 @@ void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) { unsigned NumVars = C->varlist_size(); SmallVector<Expr *, 16> Vars; Vars.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) + for (unsigned I = 0; I != NumVars; ++I) Vars.push_back(Reader->Record.readSubExpr()); C->setVarRefs(Vars); - C->setCounterValue(Reader->Record.readSubExpr()); + for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) + C->setLoopData(I, Reader->Record.readSubExpr()); } void OMPClauseReader::VisitOMPDeviceClause(OMPDeviceClause *C) { diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 48c3f79a4380..09cb0ddc4d49 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1898,7 +1898,12 @@ void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) { } void OMPClauseWriter::VisitOMPOrderedClause(OMPOrderedClause *C) { + Record.push_back(C->getLoopNumIterations().size()); Record.AddStmt(C->getNumForLoops()); + for (Expr *NumIter : C->getLoopNumIterations()) + Record.AddStmt(NumIter); + for (unsigned I = 0, E = C->getLoopNumIterations().size(); I <E; ++I) + Record.AddStmt(C->getLoopCunter(I)); Record.AddSourceLocation(C->getLParenLoc()); } @@ -2102,13 +2107,15 @@ void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) { void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) { Record.push_back(C->varlist_size()); + Record.push_back(C->getNumLoops()); Record.AddSourceLocation(C->getLParenLoc()); Record.push_back(C->getDependencyKind()); Record.AddSourceLocation(C->getDependencyLoc()); Record.AddSourceLocation(C->getColonLoc()); for (auto *VE : C->varlists()) Record.AddStmt(VE); - Record.AddStmt(C->getCounterValue()); + for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) + Record.AddStmt(C->getLoopData(I)); } void OMPClauseWriter::VisitOMPDeviceClause(OMPDeviceClause *C) { diff --git a/test/CodeGenCXX/attr-target-mv-member-funcs.cpp b/test/CodeGenCXX/attr-target-mv-member-funcs.cpp index 2e5db3b705e4..622b738ad284 100644 --- a/test/CodeGenCXX/attr-target-mv-member-funcs.cpp +++ b/test/CodeGenCXX/attr-target-mv-member-funcs.cpp @@ -111,13 +111,12 @@ int templ_use() { // CHECK: call i32 @_ZN5templIiE3fooEi.ifunc // CHECK: call i32 @_ZN5templIdE3fooEi.ifunc - // CHECK: define i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.resolver() comdat // CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_sandybridge // CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_ivybridge // CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.sse4.2 // CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi -// + // CHECK: define i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.resolver() comdat // CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_sandybridge // CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_ivybridge @@ -135,3 +134,12 @@ int templ_use() { // CHECK: define linkonce_odr i32 @_ZN1S3fooEi(%struct.S* %this, i32) // CHECK: ret i32 2 +// CHECK: define linkonce_odr i32 @_ZN5templIiE3fooEi.sse4.2 +// CHECK: declare i32 @_ZN5templIiE3fooEi.arch_sandybridge +// CHECK: define linkonce_odr i32 @_ZN5templIiE3fooEi.arch_ivybridge +// CHECK: define linkonce_odr i32 @_ZN5templIiE3fooEi + +// CHECK: define linkonce_odr i32 @_ZN5templIdE3fooEi.sse4.2 +// CHECK: declare i32 @_ZN5templIdE3fooEi.arch_sandybridge +// CHECK: define linkonce_odr i32 @_ZN5templIdE3fooEi.arch_ivybridge +// CHECK: define linkonce_odr i32 @_ZN5templIdE3fooEi diff --git a/test/CodeGenObjC/gnu-init.m b/test/CodeGenObjC/gnu-init.m index beb06bbe0df4..2188165ff177 100644 --- a/test/CodeGenObjC/gnu-init.m +++ b/test/CodeGenObjC/gnu-init.m @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s -check-prefix=CHECK-NEW +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s -check-prefix=CHECK-WIN // RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-1.8 -o - %s | FileCheck %s -check-prefix=CHECK-OLD // Almost minimal Objective-C file, check that it emits calls to the correct @@ -49,9 +50,9 @@ // CHECK-NEW: @.objc_null_class_alias = linkonce_odr hidden global { i8*, i8* } zeroinitializer, section "__objc_class_aliases", comdat, align 8 // CHECK-NEW: @.objc_null_constant_string = linkonce_odr hidden global { i8*, i32, i32, i32, i32, i8* } zeroinitializer, section "__objc_constant_string", comdat, align 8 // Make sure that the null symbols are not going to be removed, even by linking. -// CHECK-NEW: @llvm.used = appending global [7 x i8*] [i8* bitcast ({ { i8*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }** @._OBJC_INIT_CLASS_X to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_selector to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_category to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_protocol to i8*), i8* bitcast ({ i8* }* @.objc_null_protocol_ref to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_class_alias to i8*), i8* bitcast ({ i8*, i32, i32, i32, i32, i8* }* @.objc_null_constant_string to i8*)], section "llvm.metadata" +// CHECK-NEW: @llvm.used = appending global [8 x i8*] [i8* bitcast ({ { i8*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }** @._OBJC_INIT_CLASS_X to i8*), i8* bitcast (void ()** @.objc_ctor to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_selector to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_category to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_protocol to i8*), i8* bitcast ({ i8* }* @.objc_null_protocol_ref to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_class_alias to i8*), i8* bitcast ({ i8*, i32, i32, i32, i32, i8* }* @.objc_null_constant_string to i8*)], section "llvm.metadata" // Make sure that the load function and the reference to it are marked as used. -// CHECK-NEW: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast (void ()* @.objcv2_load_function to i8*), i8* bitcast (void ()** @.objc_ctor to i8*)], section "llvm.metadata" +// CHECK-NEW: @llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (void ()* @.objcv2_load_function to i8*)], section "llvm.metadata" // Check that we emit the load function in a comdat and that it does the right thing. // CHECK-NEW: define linkonce_odr hidden void @.objcv2_load_function() comdat { @@ -67,3 +68,37 @@ // CHECK-OLD-NEXT: entry: // CHECK-OLD-NEXT: call void ({ i64, i64, i8*, { i64, { i8*, i8* }*, i16, i16, [4 x i8*] }* }*, ...) @__objc_exec_class({ i64, i64, i8*, { i64, { i8*, i8* }*, i16, i16, [4 x i8*] }* }* @4) + + +// Make sure all of our section boundary variables are emitted correctly. +// CHECK-WIN-DAG: @__start___objc_selectors = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_selectors$a", comdat, align 1 +// CHECK-WIN-DAG: @__stop__objc_selectors = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_selectors$z", comdat, align 1 +// CHECK-WIN-DAG: @__start___objc_classes = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_classes$a", comdat, align 1 +// CHECK-WIN-DAG: @__stop__objc_classes = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_classes$z", comdat, align 1 +// CHECK-WIN-DAG: @__start___objc_class_refs = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_class_refs$a", comdat, align 1 +// CHECK-WIN-DAG: @__stop__objc_class_refs = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_class_refs$z", comdat, align 1 +// CHECK-WIN-DAG: @__start___objc_cats = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_cats$a", comdat, align 1 +// CHECK-WIN-DAG: @__stop__objc_cats = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_cats$z", comdat, align 1 +// CHECK-WIN-DAG: @__start___objc_protocols = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_protocols$a", comdat, align 1 +// CHECK-WIN-DAG: @__stop__objc_protocols = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_protocols$z", comdat, align 1 +// CHECK-WIN-DAG: @__start___objc_protocol_refs = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_protocol_refs$a", comdat, align 1 +// CHECK-WIN-DAG: @__stop__objc_protocol_refs = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_protocol_refs$z", comdat, align 1 +// CHECK-WIN-DAG: @__start___objc_class_aliases = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_class_aliases$a", comdat, align 1 +// CHECK-WIN-DAG: @__stop__objc_class_aliases = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_class_aliases$z", comdat, align 1 +// CHECK-WIN-DAG: @__start___objc_constant_string = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_constant_string$a", comdat, align 1 +// CHECK-WIN-DAG: @__stop__objc_constant_string = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_constant_string$z", comdat, align 1 +// CHECK-WIN: @.objc_init = linkonce_odr hidden global { i64, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel* } { i64 0, %.objc_section_sentinel* @__start___objc_selectors, %.objc_section_sentinel* @__stop__objc_selectors, %.objc_section_sentinel* @__start___objc_classes, %.objc_section_sentinel* @__stop__objc_classes, %.objc_section_sentinel* @__start___objc_class_refs, %.objc_section_sentinel* @__stop__objc_class_refs, %.objc_section_sentinel* @__start___objc_cats, %.objc_section_sentinel* @__stop__objc_cats, %.objc_section_sentinel* @__start___objc_protocols, %.objc_section_sentinel* @__stop__objc_protocols, %.objc_section_sentinel* @__start___objc_protocol_refs, %.objc_section_sentinel* @__stop__objc_protocol_refs, %.objc_section_sentinel* @__start___objc_class_aliases, %.objc_section_sentinel* @__stop__objc_class_aliases, %.objc_section_sentinel* @__start___objc_constant_string, %.objc_section_sentinel* @__stop__objc_constant_string }, comdat, align 8 + +// Make sure our init variable is in the correct section for late library init. +// CHECK-WIN: @.objc_ctor = linkonce hidden constant void ()* @.objcv2_load_function, section ".CRT$XCLz", comdat + +// We shouldn't have emitted any null placeholders on Windows. +// CHECK-WIN: @llvm.used = appending global [2 x i8*] [i8* bitcast ({ { i8*, i8*, i8*, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i32, i8* }*, i8*, i8*, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i32, i8* }** @._OBJC_INIT_CLASS_X to i8*), i8* bitcast (void ()** @.objc_ctor to i8*)], section "llvm.metadata" +// CHECK-WIN: @llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (void ()* @.objcv2_load_function to i8*)], section "llvm.metadata" + +// Check our load function is in a comdat. +// CHECK-WIN: define linkonce_odr hidden void @.objcv2_load_function() comdat { + +// Make sure we have dllimport on the load function +// CHECK-WIN: declare dllimport void @__objc_load + diff --git a/test/CodeGenObjC/gnustep2-proto.m b/test/CodeGenObjC/gnustep2-proto.m index 536714f03a99..8550b0fb2d92 100644 --- a/test/CodeGenObjC/gnustep2-proto.m +++ b/test/CodeGenObjC/gnustep2-proto.m @@ -22,11 +22,11 @@ // Check that we're emitting the protocol and a correctly initialised // indirection variable. -// CHECK: @._OBJC_PROTOCOL_X = global +// CHECK: @._OBJC_PROTOCOL_X = global // CHECK-SAME: , section "__objc_protocols", comdat, align 8 -// CHECK: @._OBJC_REF_PROTOCOL_X = global +// CHECK: @._OBJC_REF_PROTOCOL_X = linkonce_odr global // CHECK-SAME: @._OBJC_PROTOCOL_X -// CHECK-SAME: , section "__objc_protocol_refs", align 8 +// CHECK-SAME: , section "__objc_protocol_refs", comdat, align 8 // Check that we load from the indirection variable on protocol references. diff --git a/test/CodeGenObjCXX/arc-marker-funclet.mm b/test/CodeGenObjCXX/arc-marker-funclet.mm index 900c2788daed..6ad0acd6878a 100644 --- a/test/CodeGenObjCXX/arc-marker-funclet.mm +++ b/test/CodeGenObjCXX/arc-marker-funclet.mm @@ -10,7 +10,7 @@ void g() { } } -// CHECK: call i8* @"?f@@YAPAUobjc_object@@XZ"() [ "funclet"(token %1) ] +// CHECK: call i8* @"?f@@YAPAU.objc_object@@XZ"() [ "funclet"(token %1) ] // CHECK-NEXT: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""() [ "funclet"(token %1) ] // The corresponding f() call was invoked from the entry basic block. diff --git a/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm b/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm index 910a7db73404..125f8821ef28 100644 --- a/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm +++ b/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm @@ -9,7 +9,7 @@ struct A { // Verify that we destruct things from left to right in the MS C++ ABI: a, b, c, d. // -// CHECK-LABEL: define dso_local void @"?test_arc_order@@YAXUA@@PAUobjc_object@@01@Z" +// CHECK-LABEL: define dso_local void @"?test_arc_order@@YAXUA@@PAU.objc_object@@01@Z" // CHECK: (<{ %struct.A, i8*, %struct.A, i8* }>* inalloca) void test_arc_order(A a, id __attribute__((ns_consumed)) b , A c, id __attribute__((ns_consumed)) d) { // CHECK: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %{{.*}}) diff --git a/test/CodeGenObjCXX/msabi-objc-extensions.mm b/test/CodeGenObjCXX/msabi-objc-extensions.mm index 2f724a985f33..d3c77dddb4d0 100644 --- a/test/CodeGenObjCXX/msabi-objc-extensions.mm +++ b/test/CodeGenObjCXX/msabi-objc-extensions.mm @@ -6,61 +6,61 @@ @class I; void f(id<P>, id, id<P>, id) {} -// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@PAUobjc_object@@01@Z" +// CHECK-LABEL: "?f@@YAXPAU?$.objc_object@U?$Protocol@UP@@@__ObjC@@@@PAU.objc_object@@01@Z" void f(id, id<P>, id<P>, id) {} -// CHECK-LABEL: "?f@@YAXPAUobjc_object@@PAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@10@Z" +// CHECK-LABEL: "?f@@YAXPAU.objc_object@@PAU?$.objc_object@U?$Protocol@UP@@@__ObjC@@@@10@Z" void f(id<P>, id<P>) {} -// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@0@Z" +// CHECK-LABEL: "?f@@YAXPAU?$.objc_object@U?$Protocol@UP@@@__ObjC@@@@0@Z" void f(id<P>) {} -// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@@Z" +// CHECK-LABEL: "?f@@YAXPAU?$.objc_object@U?$Protocol@UP@@@__ObjC@@@@@Z" void f(id<P, Q>) {} -// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z" +// CHECK-LABEL: "?f@@YAXPAU?$.objc_object@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z" void f(Class<P>) {} -// CHECK-LABEL: "?f@@YAXPAU?$objc_class@U?$Protocol@UP@@@__ObjC@@@@@Z" +// CHECK-LABEL: "?f@@YAXPAU?$.objc_class@U?$Protocol@UP@@@__ObjC@@@@@Z" void f(Class<P, Q>) {} -// CHECK-LABEL: "?f@@YAXPAU?$objc_class@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z" +// CHECK-LABEL: "?f@@YAXPAU?$.objc_class@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z" void f(I<P> *) {} -// CHECK-LABEL: "?f@@YAXPAU?$I@U?$Protocol@UP@@@__ObjC@@@@@Z" +// CHECK-LABEL: "?f@@YAXPAU?$.objc_cls_I@U?$Protocol@UP@@@__ObjC@@@@@Z" void f(I<P, Q> *) {} -// CHECK-LABEL: "?f@@YAXPAU?$I@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z" +// CHECK-LABEL: "?f@@YAXPAU?$.objc_cls_I@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z" template <typename> struct S {}; void f(S<__unsafe_unretained id>) {} -// CHECK-LABEL: "?f@@YAXU?$S@PAUobjc_object@@@@@Z" +// CHECK-LABEL: "?f@@YAXU?$S@PAU.objc_object@@@@@Z" void f(S<__autoreleasing id>) {} -// CHECK-LABEL: "?f@@YAXU?$S@U?$Autoreleasing@PAUobjc_object@@@__ObjC@@@@@Z" +// CHECK-LABEL: "?f@@YAXU?$S@U?$Autoreleasing@PAU.objc_object@@@__ObjC@@@@@Z" void f(S<__strong id>) {} -// CHECK-LABEL: "?f@@YAXU?$S@U?$Strong@PAUobjc_object@@@__ObjC@@@@@Z" +// CHECK-LABEL: "?f@@YAXU?$S@U?$Strong@PAU.objc_object@@@__ObjC@@@@@Z" void f(S<__weak id>) {} -// CHECK-LABEL: "?f@@YAXU?$S@U?$Weak@PAUobjc_object@@@__ObjC@@@@@Z" +// CHECK-LABEL: "?f@@YAXU?$S@U?$Weak@PAU.objc_object@@@__ObjC@@@@@Z" void w(__weak id) {} -// CHECK-LABEL: "?w@@YAXPAUobjc_object@@@Z" +// CHECK-LABEL: "?w@@YAXPAU.objc_object@@@Z" void s(__strong id) {} -// CHECK-LABEL: "?s@@YAXPAUobjc_object@@@Z" +// CHECK-LABEL: "?s@@YAXPAU.objc_object@@@Z" void a(__autoreleasing id) {} -// CHECK-LABEL: "?a@@YAXPAUobjc_object@@@Z" +// CHECK-LABEL: "?a@@YAXPAU.objc_object@@@Z" void u(__unsafe_unretained id) {} -// CHECK-LABEL: "?u@@YAXPAUobjc_object@@@Z" +// CHECK-LABEL: "?u@@YAXPAU.objc_object@@@Z" S<__autoreleasing id> g() { return S<__autoreleasing id>(); } -// CHECK-LABEL: "?g@@YA?AU?$S@U?$Autoreleasing@PAUobjc_object@@@__ObjC@@@@XZ" +// CHECK-LABEL: "?g@@YA?AU?$S@U?$Autoreleasing@PAU.objc_object@@@__ObjC@@@@XZ" __autoreleasing id h() { return nullptr; } -// CHECK-LABEL: "?h@@YAPAUobjc_object@@XZ" +// CHECK-LABEL: "?h@@YAPAU.objc_object@@XZ" diff --git a/test/CodeGenObjCXX/msabi-objc-types.mm b/test/CodeGenObjCXX/msabi-objc-types.mm index 192dd4c23ffa..08807bbe1a56 100644 --- a/test/CodeGenObjCXX/msabi-objc-types.mm +++ b/test/CodeGenObjCXX/msabi-objc-types.mm @@ -3,166 +3,166 @@ @class I; id kid; -// CHECK: @"?kid@@3PAUobjc_object@@A" = dso_local global +// CHECK: @"?kid@@3PAU.objc_object@@A" = dso_local global Class klass; -// CHECK: @"?klass@@3PAUobjc_class@@A" = dso_local global +// CHECK: @"?klass@@3PAU.objc_class@@A" = dso_local global I *kI; -// CHECK: @"?kI@@3PAUI@@A" = dso_local global +// CHECK: @"?kI@@3PAU.objc_cls_I@@A" = dso_local global void f(I *) {} -// CHECK-LABEL: "?f@@YAXPAUI@@@Z" +// CHECK-LABEL: "?f@@YAXPAU.objc_cls_I@@@Z" void f(const I *) {} -// CHECK-LABEL: "?f@@YAXPBUI@@@Z" +// CHECK-LABEL: "?f@@YAXPBU.objc_cls_I@@@Z" void f(I &) {} -// CHECK-LABEL: "?f@@YAXAAUI@@@Z" +// CHECK-LABEL: "?f@@YAXAAU.objc_cls_I@@@Z" void f(const I &) {} -// CHECK-LABEL: "?f@@YAXABUI@@@Z" +// CHECK-LABEL: "?f@@YAXABU.objc_cls_I@@@Z" void f(const I &&) {} -// CHECK-LABEL: "?f@@YAX$$QBUI@@@Z" +// CHECK-LABEL: "?f@@YAX$$QBU.objc_cls_I@@@Z" void g(id) {} -// CHECK-LABEL: "?g@@YAXPAUobjc_object@@@Z" +// CHECK-LABEL: "?g@@YAXPAU.objc_object@@@Z" void g(id &) {} -// CHECK-LABEL: "?g@@YAXAAPAUobjc_object@@@Z" +// CHECK-LABEL: "?g@@YAXAAPAU.objc_object@@@Z" void g(const id &) {} -// CHECK-LABEL: "?g@@YAXABQAUobjc_object@@@Z" +// CHECK-LABEL: "?g@@YAXABQAU.objc_object@@@Z" void g(id &&) {} -// CHECK-LABEL: "?g@@YAX$$QAPAUobjc_object@@@Z" +// CHECK-LABEL: "?g@@YAX$$QAPAU.objc_object@@@Z" void h(Class) {} -// CHECK-LABEL: "?h@@YAXPAUobjc_class@@@Z" +// CHECK-LABEL: "?h@@YAXPAU.objc_class@@@Z" void h(Class &) {} -// CHECK-LABEL: "?h@@YAXAAPAUobjc_class@@@Z" +// CHECK-LABEL: "?h@@YAXAAPAU.objc_class@@@Z" void h(const Class &) {} -// CHECK-LABEL: "?h@@YAXABQAUobjc_class@@@Z" +// CHECK-LABEL: "?h@@YAXABQAU.objc_class@@@Z" void h(Class &&) {} -// CHECK-LABEL: "?h@@YAX$$QAPAUobjc_class@@@Z" +// CHECK-LABEL: "?h@@YAX$$QAPAU.objc_class@@@Z" I *i() { return nullptr; } -// CHECK-LABEL: "?i@@YAPAUI@@XZ" +// CHECK-LABEL: "?i@@YAPAU.objc_cls_I@@XZ" const I *j() { return nullptr; } -// CHECK-LABEL: "?j@@YAPBUI@@XZ" +// CHECK-LABEL: "?j@@YAPBU.objc_cls_I@@XZ" I &k() { return *kI; } -// CHECK-LABEL: "?k@@YAAAUI@@XZ" +// CHECK-LABEL: "?k@@YAAAU.objc_cls_I@@XZ" const I &l() { return *kI; } -// CHECK-LABEL: "?l@@YAABUI@@XZ" +// CHECK-LABEL: "?l@@YAABU.objc_cls_I@@XZ" void m(const id) {} -// CHECK-LABEL: "?m@@YAXQAUobjc_object@@@Z" +// CHECK-LABEL: "?m@@YAXQAU.objc_object@@@Z" void m(const I *) {} -// CHECK-LABEL: "?m@@YAXPBUI@@@Z" +// CHECK-LABEL: "?m@@YAXPBU.objc_cls_I@@@Z" void n(SEL) {} -// CHECK-LABEL: "?n@@YAXPAUobjc_selector@@@Z" +// CHECK-LABEL: "?n@@YAXPAU.objc_selector@@@Z" void n(SEL *) {} -// CHECK-LABEL: "?n@@YAXPAPAUobjc_selector@@@Z" +// CHECK-LABEL: "?n@@YAXPAPAU.objc_selector@@@Z" void n(const SEL *) {} -// CHECK-LABEL: "?n@@YAXPBQAUobjc_selector@@@Z" +// CHECK-LABEL: "?n@@YAXPBQAU.objc_selector@@@Z" void n(SEL &) {} -// CHECK-LABEL: "?n@@YAXAAPAUobjc_selector@@@Z" +// CHECK-LABEL: "?n@@YAXAAPAU.objc_selector@@@Z" void n(const SEL &) {} -// CHECK-LABEL: "?n@@YAXABQAUobjc_selector@@@Z" +// CHECK-LABEL: "?n@@YAXABQAU.objc_selector@@@Z" void n(SEL &&) {} -// CHECK-LABEL: "?n@@YAX$$QAPAUobjc_selector@@@Z" +// CHECK-LABEL: "?n@@YAX$$QAPAU.objc_selector@@@Z" struct __declspec(dllexport) s { struct s &operator=(const struct s &) = delete; void m(I *) {} - // CHECK-LABEL: "?m@s@@QAAXPAUI@@@Z" + // CHECK-LABEL: "?m@s@@QAAXPAU.objc_cls_I@@@Z" void m(const I *) {} - // CHECK-LABEL: "?m@s@@QAAXPBUI@@@Z" + // CHECK-LABEL: "?m@s@@QAAXPBU.objc_cls_I@@@Z" void m(I &) {} - // CHECK-LABEL: "?m@s@@QAAXAAUI@@@Z" + // CHECK-LABEL: "?m@s@@QAAXAAU.objc_cls_I@@@Z" void m(const I &) {} - // CHECK-LABEL: "?m@s@@QAAXABUI@@@Z" + // CHECK-LABEL: "?m@s@@QAAXABU.objc_cls_I@@@Z" void m(I &&) {} - // CHECK-LABEL: "?m@s@@QAAX$$QAUI@@@Z" + // CHECK-LABEL: "?m@s@@QAAX$$QAU.objc_cls_I@@@Z" void m(const I &&) {} - // CHECK-LABEL: "?m@s@@QAAX$$QBUI@@@Z" + // CHECK-LABEL: "?m@s@@QAAX$$QBU.objc_cls_I@@@Z" void m(id) {} - // CHECK-LABEL: "?m@s@@QAAXPAUobjc_object@@@Z" + // CHECK-LABEL: "?m@s@@QAAXPAU.objc_object@@@Z" void m(id &) {} - // CHECK-LABEL: "?m@s@@QAAXAAPAUobjc_object@@@Z" + // CHECK-LABEL: "?m@s@@QAAXAAPAU.objc_object@@@Z" void m(id &&) {} - // CHECK-LABEL: "?m@s@@QAAX$$QAPAUobjc_object@@@Z" + // CHECK-LABEL: "?m@s@@QAAX$$QAPAU.objc_object@@@Z" void m(const id &) {} - // CHECK-LABEL: "?m@s@@QAAXABQAUobjc_object@@@Z" + // CHECK-LABEL: "?m@s@@QAAXABQAU.objc_object@@@Z" void m(const id &&) {} - // CHECK-LABEL: "?m@s@@QAAX$$QBQAUobjc_object@@@Z" + // CHECK-LABEL: "?m@s@@QAAX$$QBQAU.objc_object@@@Z" void m(Class *) {} - // CHECK-LABEL: "?m@s@@QAAXPAPAUobjc_class@@@Z" + // CHECK-LABEL: "?m@s@@QAAXPAPAU.objc_class@@@Z" void m(const Class *) {} - // CHECK-LABEL: "?m@s@@QAAXPBQAUobjc_class@@@Z" + // CHECK-LABEL: "?m@s@@QAAXPBQAU.objc_class@@@Z" void m(Class) {} - // CHECK-LABEL: "?m@s@@QAAXPAUobjc_class@@@Z" + // CHECK-LABEL: "?m@s@@QAAXPAU.objc_class@@@Z" void m(Class &) {} - // CHECK-LABEL: "?m@s@@QAAXAAPAUobjc_class@@@Z" + // CHECK-LABEL: "?m@s@@QAAXAAPAU.objc_class@@@Z" void m(const Class &) {} - // CHECK-LABEL: "?m@s@@QAAXABQAUobjc_class@@@Z" + // CHECK-LABEL: "?m@s@@QAAXABQAU.objc_class@@@Z" void m(Class &&) {} - // CHECK-LABEL: "?m@s@@QAAX$$QAPAUobjc_class@@@Z" + // CHECK-LABEL: "?m@s@@QAAX$$QAPAU.objc_class@@@Z" void m(const Class &&) {} - // CHECK-LABEL: "?m@s@@QAAX$$QBQAUobjc_class@@@Z" + // CHECK-LABEL: "?m@s@@QAAX$$QBQAU.objc_class@@@Z" void m(SEL) {} - // CHECK-LABEL: "?m@s@@QAAXPAUobjc_selector@@@Z" + // CHECK-LABEL: "?m@s@@QAAXPAU.objc_selector@@@Z" void m(SEL *) {} - // CHECK-LABEL: "?m@s@@QAAXPAPAUobjc_selector@@@Z" + // CHECK-LABEL: "?m@s@@QAAXPAPAU.objc_selector@@@Z" void m(const SEL *) {} - // CHECK-LABEL: "?m@s@@QAAXPBQAUobjc_selector@@@Z" + // CHECK-LABEL: "?m@s@@QAAXPBQAU.objc_selector@@@Z" void m(SEL &) {} - // CHECK-LABEL: "?m@s@@QAAXAAPAUobjc_selector@@@Z" + // CHECK-LABEL: "?m@s@@QAAXAAPAU.objc_selector@@@Z" void m(const SEL &) {} - // CHECK-LABEL: "?m@s@@QAAXABQAUobjc_selector@@@Z" + // CHECK-LABEL: "?m@s@@QAAXABQAU.objc_selector@@@Z" void m(SEL &&) {} - // CHECK-LABEL: "?m@s@@QAAX$$QAPAUobjc_selector@@@Z" + // CHECK-LABEL: "?m@s@@QAAX$$QAPAU.objc_selector@@@Z" void m(const SEL &&) {} - // CHECK-LABEL: "?m@s@@QAAX$$QBQAUobjc_selector@@@Z" + // CHECK-LABEL: "?m@s@@QAAX$$QBQAU.objc_selector@@@Z" }; template <typename T> @@ -179,14 +179,14 @@ struct t { }; template struct t<id>; -// CHECK-LABEL: "??0?$t@PAUobjc_object@@@@QAA@XZ" +// CHECK-LABEL: "??0?$t@PAU.objc_object@@@@QAA@XZ" template struct t<remove_pointer<id>::type>; -// CHECK-LABEL: "??0?$t@Uobjc_object@@@@QAA@XZ" +// CHECK-LABEL: "??0?$t@U.objc_object@@@@QAA@XZ" template struct t<SEL>; -// CHECK-LABEL: "??0?$t@PAUobjc_selector@@@@QAA@XZ" +// CHECK-LABEL: "??0?$t@PAU.objc_selector@@@@QAA@XZ" template struct t<remove_pointer<SEL>::type>; -// CHECK-LABEL: "??0?$t@Uobjc_selector@@@@QAA@XZ" +// CHECK-LABEL: "??0?$t@U.objc_selector@@@@QAA@XZ" diff --git a/test/Driver/unavailable_aligned_allocation.cpp b/test/Driver/unavailable_aligned_allocation.cpp index d5820b0665c1..508202de9f4a 100644 --- a/test/Driver/unavailable_aligned_allocation.cpp +++ b/test/Driver/unavailable_aligned_allocation.cpp @@ -51,4 +51,13 @@ // RUN: -c -### %s 2>&1 \ // RUN: | FileCheck %s -check-prefix=AVAILABLE // +// Check that passing -faligned-allocation or -fno-aligned-allocation stops the +// driver from passing -faligned-alloc-unavailable to cc1. +// +// RUN: %clang -target x86_64-apple-macosx10.12 -faligned-allocation -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=AVAILABLE +// +// RUN: %clang -target x86_64-apple-macosx10.12 -fno-aligned-allocation -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=AVAILABLE + // AVAILABLE-NOT: "-faligned-alloc-unavailable" diff --git a/test/Lexer/aligned-allocation.cpp b/test/Lexer/aligned-allocation.cpp new file mode 100644 index 000000000000..eef5d980a37b --- /dev/null +++ b/test/Lexer/aligned-allocation.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -std=c++17 -verify %s \ +// RUN: -DEXPECT_DEFINED +// +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -std=c++17 -verify %s \ +// RUN: -faligned-alloc-unavailable +// +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -std=c++17 -verify %s \ +// RUN: -faligned-allocation -faligned-alloc-unavailable + +// Test that __cpp_aligned_new is not defined when CC1 is passed +// -faligned-alloc-unavailable by the Darwin driver, even when aligned +// allocation is actually enabled. + +// expected-no-diagnostics +#ifdef EXPECT_DEFINED +# ifndef __cpp_aligned_new +# error "__cpp_aligned_new" should be defined +# endif +#else +# ifdef __cpp_aligned_new +# error "__cpp_aligned_new" should not be defined +# endif +#endif diff --git a/test/OpenMP/declare_target_ast_print.cpp b/test/OpenMP/declare_target_ast_print.cpp index bd1acc28dc6c..1ffa456b7d74 100644 --- a/test/OpenMP/declare_target_ast_print.cpp +++ b/test/OpenMP/declare_target_ast_print.cpp @@ -150,11 +150,35 @@ struct SSSTt { // CHECK: #pragma omp end declare target // CHECK: int b; +#pragma omp declare target +template <typename T> +T baz() { return T(); } +#pragma omp end declare target + +template <> +int baz() { return 1; } + +// CHECK: #pragma omp declare target +// CHECK: template <typename T> T baz() { +// CHECK: return T(); +// CHECK: } +// CHECK: #pragma omp end declare target +// CHECK: #pragma omp declare target +// CHECK: template<> float baz<float>() { +// CHECK: return float(); +// CHECK: } +// CHECK: template<> int baz<int>() { +// CHECK: return 1; +// CHECK: } +// CHECK: #pragma omp end declare target + int main (int argc, char **argv) { foo(); foo_c(); foo_cpp(); test1(); + baz<float>(); + baz<int>(); return (0); } diff --git a/test/OpenMP/ordered_doacross_codegen.c b/test/OpenMP/ordered_doacross_codegen.c index c12df2638f8f..a6cd4fe48b3f 100644 --- a/test/OpenMP/ordered_doacross_codegen.c +++ b/test/OpenMP/ordered_doacross_codegen.c @@ -19,17 +19,19 @@ void foo(); // CHECK-LABEL: @main() int main() { int i; -// CHECK: [[DIMS:%.+]] = alloca [[KMP_DIM]], +// CHECK: [[DIMS:%.+]] = alloca [1 x [[KMP_DIM]]], // CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT:%.+]]) // CHECK: icmp // CHECK-NEXT: br i1 % -// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8* +// CHECK: [[CAST:%.+]] = bitcast [1 x [[KMP_DIM]]]* [[DIMS]] to i8* // CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 24, i1 false) -// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 1 +// CHECK: [[DIM:%.+]] = getelementptr inbounds [1 x [[KMP_DIM]]], [1 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0 +// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 1 // CHECK: store i64 %{{.+}}, i64* % -// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 2 +// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 2 // CHECK: store i64 1, i64* % -// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8* +// CHECK: [[DIM:%.+]] = getelementptr inbounds [1 x [[KMP_DIM]]], [1 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0 +// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIM]] to i8* // CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 1, i8* [[CAST]]) // CHECK: call void @__kmpc_for_static_init_4( #pragma omp for ordered(1) @@ -37,18 +39,26 @@ int main() { a[i] = b[i] + 1; foo(); // CHECK: call void [[FOO:.+]]( -// CHECK: load i32, i32* [[CNT:%.+]], +// CHECK: load i32, i32* [[I:%.+]], +// CHECK-NEXT: sub nsw i32 %{{.+}}, 0 +// CHECK-NEXT: sdiv i32 %{{.+}}, 1 // CHECK-NEXT: sext i32 %{{.+}} to i64 -// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]], +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT:%.+]], i64 0, i64 0 +// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]], +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT]], i64 0, i64 0 // CHECK-NEXT: call void @__kmpc_doacross_post([[IDENT]], i32 [[GTID]], i64* [[TMP]]) #pragma omp ordered depend(source) c[i] = c[i] + 1; foo(); // CHECK: call void [[FOO]] -// CHECK: load i32, i32* [[CNT]], +// CHECK: load i32, i32* [[I]], // CHECK-NEXT: sub nsw i32 %{{.+}}, 2 +// CHECK-NEXT: sub nsw i32 %{{.+}}, 0 +// CHECK-NEXT: sdiv i32 %{{.+}}, 1 // CHECK-NEXT: sext i32 %{{.+}} to i64 -// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]], +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT:%.+]], i64 0, i64 0 +// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]], +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT]], i64 0, i64 0 // CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]]) #pragma omp ordered depend(sink : i - 2) d[i] = a[i - 2]; diff --git a/test/OpenMP/ordered_doacross_codegen.cpp b/test/OpenMP/ordered_doacross_codegen.cpp index 60b0353b711e..2f19e9c2d5ef 100644 --- a/test/OpenMP/ordered_doacross_codegen.cpp +++ b/test/OpenMP/ordered_doacross_codegen.cpp @@ -19,17 +19,19 @@ void foo(); // CHECK-LABEL: @main() int main() { int i; -// CHECK: [[DIMS:%.+]] = alloca [[KMP_DIM]], +// CHECK: [[DIMS:%.+]] = alloca [1 x [[KMP_DIM]]], // CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT:%.+]]) // CHECK: icmp // CHECK-NEXT: br i1 % -// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8* +// CHECK: [[CAST:%.+]] = bitcast [1 x [[KMP_DIM]]]* [[DIMS]] to i8* // CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 24, i1 false) -// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 1 +// CHECK: [[DIM:%.+]] = getelementptr inbounds [1 x [[KMP_DIM]]], [1 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0 +// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 1 // CHECK: store i64 %{{.+}}, i64* % -// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 2 +// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 2 // CHECK: store i64 1, i64* % -// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8* +// CHECK: [[DIM:%.+]] = getelementptr inbounds [1 x [[KMP_DIM]]], [1 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0 +// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIM]] to i8* // CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 1, i8* [[CAST]]) // CHECK: call void @__kmpc_for_static_init_4( #pragma omp for ordered(1) @@ -37,18 +39,26 @@ int main() { a[i] = b[i] + 1; foo(); // CHECK: invoke void [[FOO:.+]]( -// CHECK: load i32, i32* [[CNT:%.+]], +// CHECK: load i32, i32* [[I:%.+]], +// CHECK-NEXT: sub nsw i32 %{{.+}}, 0 +// CHECK-NEXT: sdiv i32 %{{.+}}, 1 // CHECK-NEXT: sext i32 %{{.+}} to i64 -// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]], +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT:%.+]], i64 0, i64 0 +// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]], +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT]], i64 0, i64 0 // CHECK-NEXT: call void @__kmpc_doacross_post([[IDENT]], i32 [[GTID]], i64* [[TMP]]) #pragma omp ordered depend(source) c[i] = c[i] + 1; foo(); // CHECK: invoke void [[FOO]] -// CHECK: load i32, i32* [[CNT]], +// CHECK: load i32, i32* [[I]], // CHECK-NEXT: sub nsw i32 %{{.+}}, 2 +// CHECK-NEXT: sub nsw i32 %{{.+}}, 0 +// CHECK-NEXT: sdiv i32 %{{.+}}, 1 // CHECK-NEXT: sext i32 %{{.+}} to i64 -// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]], +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT:%.+]], i64 0, i64 0 +// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]], +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT]], i64 0, i64 0 // CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]]) #pragma omp ordered depend(sink : i - 2) d[i] = a[i - 2]; @@ -75,41 +85,84 @@ struct TestStruct { T bar(T, T, T); void baz(T, T); TestStruct() { -// CHECK: [[CNT:%.+]] = alloca i64, -// CHECK: [[DIMS:%.+]] = alloca [[KMP_DIM]], +// CHECK: [[DIMS:%.+]] = alloca [2 x [[KMP_DIM]]], // CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT:%.+]]) -// CHECK: icmp -// CHECK-NEXT: br i1 % -// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8* -// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 24, i1 false) -// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 1 +// CHECK: [[CAST:%.+]] = bitcast [2 x [[KMP_DIM]]]* [[DIMS]] to i8* +// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 48, i1 false) +// CHECK: [[DIM:%.+]] = getelementptr inbounds [2 x [[KMP_DIM]]], [2 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0 +// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 1 +// CHECK: store i64 10, i64* % +// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 2 +// CHECK: store i64 1, i64* % +// CHECK: [[DIM:%.+]] = getelementptr inbounds [2 x [[KMP_DIM]]], [2 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 1 +// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 1 // CHECK: store i64 %{{.+}}, i64* % -// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 2 +// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 2 // CHECK: store i64 1, i64* % -// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8* -// CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 1, i8* [[CAST]]) -// CHECK: call void @__kmpc_for_static_init_8( +// CHECK: [[DIM:%.+]] = getelementptr inbounds [2 x [[KMP_DIM]]], [2 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0 +// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIM]] to i8* +// CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 2, i8* [[CAST]]) +// CHECK: call void @__kmpc_for_static_init_4( #pragma omp for ordered(2) for (T j = 0; j < M; j++) for (i = 0; i < n; i += 2) { a[i][j] = foo(i, j); // CHECK: invoke {{.+TestStruct.+foo}} -// CHECK: load i64, i64* [[CNT]], -// CHECK-NEXT: sub nsw i64 %{{.+}}, 1 +// CHECK: load i32*, i32** % +// CHECK: load i32, i32* % +// CHECK: load i32, i32* % +// CHECK: load i32, i32* [[J:%.+]], +// CHECK-NEXT: sub nsw i32 %{{.+}}, 0 +// CHECK-NEXT: sdiv i32 %{{.+}}, 1 +// CHECK-NEXT: sext i32 %{{.+}} to i64 +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT:%.+]], i64 0, i64 0 // CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]], +// CHECK-NEXT: [[I:%.+]] = load i32*, i32** [[I_REF:%.+]], +// CHECK-NEXT: load i32, i32* [[I]], +// CHECK-NEXT: sub nsw i32 %{{.+}}, 2 +// CHECK-NEXT: sub nsw i32 %{{.+}}, 0 +// CHECK-NEXT: sdiv i32 %{{.+}}, 2 +// CHECK-NEXT: sext i32 %{{.+}} to i64 +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 1 +// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]], +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 0 // CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]]) -// CHECK-NEXT: load i64, i64* [[CNT]], -// CHECK-NEXT: load i32, i32* % -// CHECK-NEXT: mul nsw i32 1, % +// CHECK-NEXT: load i32, i32* [[J:%.+]], +// CHECK-NEXT: sub nsw i32 %{{.+}}, 1 +// CHECK-NEXT: sub nsw i32 %{{.+}}, 0 +// CHECK-NEXT: sdiv i32 %{{.+}}, 1 // CHECK-NEXT: sext i32 %{{.+}} to i64 -// CHECK-NEXT: sub nsw i64 % +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT:%.+]], i64 0, i64 0 // CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]], +// CHECK-NEXT: [[I:%.+]] = load i32*, i32** [[I_REF]], +// CHECK-NEXT: load i32, i32* [[I]], +// CHECK-NEXT: sub nsw i32 %{{.+}}, 0 +// CHECK-NEXT: sdiv i32 %{{.+}}, 2 +// CHECK-NEXT: sext i32 %{{.+}} to i64 +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 1 +// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]], +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 0 // CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]]) #pragma omp ordered depend(sink : j, i - 2) depend(sink : j - 1, i) b[i][j] = bar(a[i][j], b[i - 1][j], b[i][j - 1]); // CHECK: invoke {{.+TestStruct.+bar}} -// CHECK: load i64, i64* [[CNT]], +// CHECK: load i32*, i32** % +// CHECK: load i32, i32* % +// CHECK: load i32, i32* % +// CHECK: load i32, i32* [[J]], +// CHECK-NEXT: sub nsw i32 %{{.+}}, 0 +// CHECK-NEXT: sdiv i32 %{{.+}}, 1 +// CHECK-NEXT: sext i32 %{{.+}} to i64 +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT:%.+]], i64 0, i64 0 // CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]], +// CHECK-NEXT: [[I:%.+]] = load i32*, i32** [[I_REF]], +// CHECK-NEXT: load i32, i32* [[I]], +// CHECK-NEXT: sub nsw i32 %{{.+}}, 0 +// CHECK-NEXT: sdiv i32 %{{.+}}, 2 +// CHECK-NEXT: sext i32 %{{.+}} to i64 +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 1 +// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]], +// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 0 // CHECK-NEXT: call void @__kmpc_doacross_post([[IDENT]], i32 [[GTID]], i64* [[TMP]]) #pragma omp ordered depend(source) baz(a[i][j], b[i][j]); diff --git a/test/OpenMP/parallel_for_simd_ast_print.cpp b/test/OpenMP/parallel_for_simd_ast_print.cpp index fd4153752af3..597e66d22e3f 100644 --- a/test/OpenMP/parallel_for_simd_ast_print.cpp +++ b/test/OpenMP/parallel_for_simd_ast_print.cpp @@ -48,7 +48,7 @@ class S8 : public S7<S1> { public: S8(int v) : S7<S1>(v){ -#pragma omp parallel for simd private(a) private(this->a) private(S7<S1>::a) +#pragma omp parallel for simd private(a) private(this->a) private(S7 <S1>::a) for (int k = 0; k < a.a; ++k) ++this->a.a; } diff --git a/test/Tooling/clang-diff-json.cpp b/test/Tooling/clang-diff-json.cpp index 20c808cb0f19..cc2bb0805e53 100644 --- a/test/Tooling/clang-diff-json.cpp +++ b/test/Tooling/clang-diff-json.cpp @@ -1,10 +1,10 @@ // RUN: clang-diff -ast-dump-json %s -- \ -// RUN: | '%python' -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \ +// RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \ // RUN: | FileCheck %s -// CHECK: "begin": 301, +// CHECK: "begin": 311, // CHECK: "type": "FieldDecl", -// CHECK: "end": 321, +// CHECK: "end": 319, // CHECK: "type": "CXXRecordDecl", class A { int x; |