diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-26 19:24:09 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-26 19:24:09 +0000 |
commit | f0c55418e2b09eaab37c820d3756cc1b4584d084 (patch) | |
tree | 9263bf60f263bb5a7aaa4d2c1be43e5fc4d942e0 /lib/Sema | |
parent | 583e75cce441388bc562fa225d23499261a0091e (diff) | |
download | src-f0c55418e2b09eaab37c820d3756cc1b4584d084.tar.gz src-f0c55418e2b09eaab37c820d3756cc1b4584d084.zip |
Vendor import of clang trunk r301441:vendor/clang/clang-trunk-r301441
Notes
Notes:
svn path=/vendor/clang/dist/; revision=317447
svn path=/vendor/clang/clang-trunk-r301441/; revision=317448; tag=vendor/clang/clang-trunk-r301441
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 54 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 14 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaOpenMP.cpp | 327 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 3 |
8 files changed, 270 insertions, 154 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 950f04088822..94e792c1d17d 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -1161,10 +1161,14 @@ void Sema::PushFunctionScope() { // memory for a new scope. FunctionScopes.back()->Clear(); FunctionScopes.push_back(FunctionScopes.back()); + if (LangOpts.OpenMP) + pushOpenMPFunctionRegion(); return; } FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics())); + if (LangOpts.OpenMP) + pushOpenMPFunctionRegion(); } void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) { @@ -1192,6 +1196,9 @@ void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP, FunctionScopeInfo *Scope = FunctionScopes.pop_back_val(); assert(!FunctionScopes.empty() && "mismatched push/pop!"); + if (LangOpts.OpenMP) + popOpenMPFunctionRegion(Scope); + // Issue any analysis-based warnings. if (WP && D) AnalysisWarnings.IssueWarnings(*WP, Scope, D, blkExpr); diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 45523b30ef22..044ec74679d5 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -408,7 +408,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) { } // Third argument is always an ndrange_t type. - if (Arg2->getType().getAsString() != "ndrange_t") { + if (Arg2->getType().getUnqualifiedType().getAsString() != "ndrange_t") { S.Diag(TheCall->getArg(2)->getLocStart(), diag::err_opencl_enqueue_kernel_expected_type) << "'ndrange_t'"; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index f3ffcf5d696c..f838c9a4877d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -615,7 +615,7 @@ bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) { CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext); for (const auto &Base : RD->bases()) - if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base.getType())) + if (Ty && Context.hasSameUnqualifiedType(QualType(Ty, 1), Base.getType())) return true; return S->isFunctionPrototypeScope(); } @@ -13523,7 +13523,8 @@ CreateNewDecl: // If this is an undefined enum, warn. if (TUK != TUK_Definition && !Invalid) { TagDecl *Def; - if ((getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) && + if (!EnumUnderlyingIsImplicit && + (getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) && cast<EnumDecl>(New)->isFixed()) { // C++0x: 7.2p2: opaque-enum-declaration. // Conflicts are diagnosed above. Do nothing. @@ -15687,30 +15688,41 @@ static void checkModuleImportContext(Sema &S, Module *M, } } -Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation ModuleLoc, +Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, + SourceLocation ModuleLoc, ModuleDeclKind MDK, ModuleIdPath Path) { - // 'module implementation' requires that we are not compiling a module of any - // kind. 'module' and 'module partition' require that we are compiling a - // module inteface (not a module map). - auto CMK = getLangOpts().getCompilingModule(); - if (MDK == ModuleDeclKind::Implementation - ? CMK != LangOptions::CMK_None - : CMK != LangOptions::CMK_ModuleInterface) { + // A module implementation unit requires that we are not compiling a module + // of any kind. A module interface unit requires that we are not compiling a + // module map. + switch (getLangOpts().getCompilingModule()) { + case LangOptions::CMK_None: + // It's OK to compile a module interface as a normal translation unit. + break; + + case LangOptions::CMK_ModuleInterface: + if (MDK != ModuleDeclKind::Implementation) + break; + + // We were asked to compile a module interface unit but this is a module + // implementation unit. That indicates the 'export' is missing. Diag(ModuleLoc, diag::err_module_interface_implementation_mismatch) - << (unsigned)MDK; + << FixItHint::CreateInsertion(ModuleLoc, "export "); + break; + + case LangOptions::CMK_ModuleMap: + Diag(ModuleLoc, diag::err_module_decl_in_module_map_module); return nullptr; } // FIXME: Create a ModuleDecl and return it. // FIXME: Most of this work should be done by the preprocessor rather than - // here, in case we look ahead across something where the current - // module matters (eg a #include). + // here, in order to support macro import. - // The dots in a module name in the Modules TS are a lie. Unlike Clang's - // hierarchical module map modules, the dots here are just another character - // that can appear in a module name. Flatten down to the actual module name. + // Flatten the dots in a module name. Unlike Clang's hierarchical module map + // modules, the dots here are just another character that can appear in a + // module name. std::string ModuleName; for (auto &Piece : Path) { if (!ModuleName.empty()) @@ -15735,8 +15747,8 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation ModuleLoc, case ModuleDeclKind::Module: { // FIXME: Check we're not in a submodule. - // We can't have imported a definition of this module or parsed a module - // map defining it already. + // We can't have parsed or imported a definition of this module or parsed a + // module map defining it already. if (auto *M = Map.findModule(ModuleName)) { Diag(Path[0].second, diag::err_module_redefinition) << ModuleName; if (M->DefinitionLoc.isValid()) @@ -15910,6 +15922,12 @@ Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc, ExportDecl *D = ExportDecl::Create(Context, CurContext, ExportLoc); // C++ Modules TS draft: + // An export-declaration shall appear in the purview of a module other than + // the global module. + if (ModuleScopes.empty() || !ModuleScopes.back().Module || + ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit) + Diag(ExportLoc, diag::err_export_not_in_module_interface); + // An export-declaration [...] shall not contain more than one // export keyword. // diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 027b3fe0e782..17c6975ca5e9 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -7220,6 +7220,8 @@ void Sema::DiagnoseUnguardedAvailabilityViolations(Decl *D) { Body = FD->getBody(); } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) Body = MD->getBody(); + else if (auto *BD = dyn_cast<BlockDecl>(D)) + Body = BD->getBody(); assert(Body && "Need a body here!"); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 5a56f7093777..00480f821fc6 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -171,9 +171,14 @@ DiagnoseAvailabilityOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc, if (AvailabilityResult Result = S.ShouldDiagnoseAvailabilityOfDecl(D, &Message)) { - if (Result == AR_NotYetIntroduced && S.getCurFunctionOrMethodDecl()) { - S.getEnclosingFunction()->HasPotentialAvailabilityViolations = true; - return; + if (Result == AR_NotYetIntroduced) { + if (S.getCurFunctionOrMethodDecl()) { + S.getEnclosingFunction()->HasPotentialAvailabilityViolations = true; + return; + } else if (S.getCurBlock() || S.getCurLambda()) { + S.getCurFunction()->HasPotentialAvailabilityViolations = true; + return; + } } const ObjCPropertyDecl *ObjCPDecl = nullptr; @@ -12498,6 +12503,9 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, BSI->TheDecl->setBody(cast<CompoundStmt>(Body)); + if (Body && getCurFunction()->HasPotentialAvailabilityViolations) + DiagnoseUnguardedAvailabilityViolations(BSI->TheDecl); + // Try to apply the named return value optimization. We have to check again // if we can do this, though, because blocks keep return statements around // to deduce an implicit return type. diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index e4d420f36832..ce76e14982db 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -1326,12 +1326,6 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { return !R.empty(); } -/// \brief Find the declaration that a class temploid member specialization was -/// instantiated from, or the member itself if it is an explicit specialization. -static Decl *getInstantiatedFrom(Decl *D, MemberSpecializationInfo *MSInfo) { - return MSInfo->isExplicitSpecialization() ? D : MSInfo->getInstantiatedFrom(); -} - Module *Sema::getOwningModule(Decl *Entity) { // If it's imported, grab its owning module. Module *M = Entity->getImportedOwningModule(); @@ -1413,12 +1407,11 @@ static Module *getDefiningModule(Sema &S, Decl *Entity) { if (CXXRecordDecl *Pattern = RD->getTemplateInstantiationPattern()) Entity = Pattern; } else if (EnumDecl *ED = dyn_cast<EnumDecl>(Entity)) { - if (MemberSpecializationInfo *MSInfo = ED->getMemberSpecializationInfo()) - Entity = getInstantiatedFrom(ED, MSInfo); + if (auto *Pattern = ED->getTemplateInstantiationPattern()) + Entity = Pattern; } else if (VarDecl *VD = dyn_cast<VarDecl>(Entity)) { - // FIXME: Map from variable template specializations back to the template. - if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo()) - Entity = getInstantiatedFrom(VD, MSInfo); + if (VarDecl *Pattern = VD->getTemplateInstantiationPattern()) + Entity = Pattern; } // Walk up to the containing context. That might also have been instantiated diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index d7a6d2e5885e..fb13669407fc 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -118,7 +118,9 @@ private: typedef SmallVector<SharingMapTy, 4> StackTy; /// \brief Stack of used declaration and their data-sharing attributes. - StackTy Stack; + DeclSAMapTy Threadprivates; + const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr; + SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack; /// \brief true, if check for DSA must be from parent directive, false, if /// from current directive. OpenMPClauseKind ClauseKindMode = OMPC_unknown; @@ -133,8 +135,14 @@ private: /// \brief Checks if the variable is a local for OpenMP region. bool isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter); + bool isStackEmpty() const { + return Stack.empty() || + Stack.back().second != CurrentNonCapturingFunctionScope || + Stack.back().first.empty(); + } + public: - explicit DSAStackTy(Sema &S) : Stack(1), SemaRef(S) {} + explicit DSAStackTy(Sema &S) : SemaRef(S) {} bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; } void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; } @@ -144,13 +152,38 @@ public: void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc) { - Stack.push_back(SharingMapTy(DKind, DirName, CurScope, Loc)); - Stack.back().DefaultAttrLoc = Loc; + if (Stack.empty() || + Stack.back().second != CurrentNonCapturingFunctionScope) + Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope); + Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc); + Stack.back().first.back().DefaultAttrLoc = Loc; } void pop() { - assert(Stack.size() > 1 && "Data-sharing attributes stack is empty!"); - Stack.pop_back(); + assert(!Stack.back().first.empty() && + "Data-sharing attributes stack is empty!"); + Stack.back().first.pop_back(); + } + + /// Start new OpenMP region stack in new non-capturing function. + void pushFunction() { + const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction(); + assert(!isa<CapturingScopeInfo>(CurFnScope)); + CurrentNonCapturingFunctionScope = CurFnScope; + } + /// Pop region stack for non-capturing function. + void popFunction(const FunctionScopeInfo *OldFSI) { + if (!Stack.empty() && Stack.back().second == OldFSI) { + assert(Stack.back().first.empty()); + Stack.pop_back(); + } + CurrentNonCapturingFunctionScope = nullptr; + for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) { + if (!isa<CapturingScopeInfo>(FSI)) { + CurrentNonCapturingFunctionScope = FSI; + break; + } + } } void addCriticalWithHint(OMPCriticalDirective *D, llvm::APSInt Hint) { @@ -229,31 +262,35 @@ public: /// \brief Returns currently analyzed directive. OpenMPDirectiveKind getCurrentDirective() const { - return Stack.back().Directive; + return isStackEmpty() ? OMPD_unknown : Stack.back().first.back().Directive; } /// \brief Returns parent directive. OpenMPDirectiveKind getParentDirective() const { - if (Stack.size() > 2) - return Stack[Stack.size() - 2].Directive; - return OMPD_unknown; + if (isStackEmpty() || Stack.back().first.size() == 1) + return OMPD_unknown; + return std::next(Stack.back().first.rbegin())->Directive; } /// \brief Set default data sharing attribute to none. void setDefaultDSANone(SourceLocation Loc) { - Stack.back().DefaultAttr = DSA_none; - Stack.back().DefaultAttrLoc = Loc; + assert(!isStackEmpty()); + Stack.back().first.back().DefaultAttr = DSA_none; + Stack.back().first.back().DefaultAttrLoc = Loc; } /// \brief Set default data sharing attribute to shared. void setDefaultDSAShared(SourceLocation Loc) { - Stack.back().DefaultAttr = DSA_shared; - Stack.back().DefaultAttrLoc = Loc; + assert(!isStackEmpty()); + Stack.back().first.back().DefaultAttr = DSA_shared; + Stack.back().first.back().DefaultAttrLoc = Loc; } DefaultDataSharingAttributes getDefaultDSA() const { - return Stack.back().DefaultAttr; + return isStackEmpty() ? DSA_unspecified + : Stack.back().first.back().DefaultAttr; } SourceLocation getDefaultDSALocation() const { - return Stack.back().DefaultAttrLoc; + return isStackEmpty() ? SourceLocation() + : Stack.back().first.back().DefaultAttrLoc; } /// \brief Checks if the specified variable is a threadprivate. @@ -264,52 +301,64 @@ public: /// \brief Marks current region as ordered (it has an 'ordered' clause). void setOrderedRegion(bool IsOrdered, Expr *Param) { - Stack.back().OrderedRegion.setInt(IsOrdered); - Stack.back().OrderedRegion.setPointer(Param); + assert(!isStackEmpty()); + Stack.back().first.back().OrderedRegion.setInt(IsOrdered); + Stack.back().first.back().OrderedRegion.setPointer(Param); } /// \brief Returns true, if parent region is ordered (has associated /// 'ordered' clause), false - otherwise. bool isParentOrderedRegion() const { - if (Stack.size() > 2) - return Stack[Stack.size() - 2].OrderedRegion.getInt(); - return false; + if (isStackEmpty() || Stack.back().first.size() == 1) + return false; + return std::next(Stack.back().first.rbegin())->OrderedRegion.getInt(); } /// \brief Returns optional parameter for the ordered region. Expr *getParentOrderedRegionParam() const { - if (Stack.size() > 2) - return Stack[Stack.size() - 2].OrderedRegion.getPointer(); - return nullptr; + if (isStackEmpty() || Stack.back().first.size() == 1) + return nullptr; + return std::next(Stack.back().first.rbegin())->OrderedRegion.getPointer(); } /// \brief Marks current region as nowait (it has a 'nowait' clause). void setNowaitRegion(bool IsNowait = true) { - Stack.back().NowaitRegion = IsNowait; + assert(!isStackEmpty()); + Stack.back().first.back().NowaitRegion = IsNowait; } /// \brief Returns true, if parent region is nowait (has associated /// 'nowait' clause), false - otherwise. bool isParentNowaitRegion() const { - if (Stack.size() > 2) - return Stack[Stack.size() - 2].NowaitRegion; - return false; + if (isStackEmpty() || Stack.back().first.size() == 1) + return false; + return std::next(Stack.back().first.rbegin())->NowaitRegion; } /// \brief Marks parent region as cancel region. void setParentCancelRegion(bool Cancel = true) { - if (Stack.size() > 2) - Stack[Stack.size() - 2].CancelRegion = - Stack[Stack.size() - 2].CancelRegion || Cancel; + if (!isStackEmpty() && Stack.back().first.size() > 1) { + auto &StackElemRef = *std::next(Stack.back().first.rbegin()); + StackElemRef.CancelRegion |= StackElemRef.CancelRegion || Cancel; + } } /// \brief Return true if current region has inner cancel construct. - bool isCancelRegion() const { return Stack.back().CancelRegion; } + bool isCancelRegion() const { + return isStackEmpty() ? false : Stack.back().first.back().CancelRegion; + } /// \brief Set collapse value for the region. - void setAssociatedLoops(unsigned Val) { Stack.back().AssociatedLoops = Val; } + void setAssociatedLoops(unsigned Val) { + assert(!isStackEmpty()); + Stack.back().first.back().AssociatedLoops = Val; + } /// \brief Return collapse value for region. - unsigned getAssociatedLoops() const { return Stack.back().AssociatedLoops; } + unsigned getAssociatedLoops() const { + return isStackEmpty() ? 0 : Stack.back().first.back().AssociatedLoops; + } /// \brief Marks current target region as one with closely nested teams /// region. void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) { - if (Stack.size() > 2) - Stack[Stack.size() - 2].InnerTeamsRegionLoc = TeamsRegionLoc; + if (!isStackEmpty() && Stack.back().first.size() > 1) { + std::next(Stack.back().first.rbegin())->InnerTeamsRegionLoc = + TeamsRegionLoc; + } } /// \brief Returns true, if current region has closely nested teams region. bool hasInnerTeamsRegion() const { @@ -317,14 +366,20 @@ public: } /// \brief Returns location of the nested teams region (if any). SourceLocation getInnerTeamsRegionLoc() const { - if (Stack.size() > 1) - return Stack.back().InnerTeamsRegionLoc; - return SourceLocation(); + return isStackEmpty() ? SourceLocation() + : Stack.back().first.back().InnerTeamsRegionLoc; } - Scope *getCurScope() const { return Stack.back().CurScope; } - Scope *getCurScope() { return Stack.back().CurScope; } - SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; } + Scope *getCurScope() const { + return isStackEmpty() ? nullptr : Stack.back().first.back().CurScope; + } + Scope *getCurScope() { + return isStackEmpty() ? nullptr : Stack.back().first.back().CurScope; + } + SourceLocation getConstructLoc() { + return isStackEmpty() ? SourceLocation() + : Stack.back().first.back().ConstructLoc; + } /// Do the check specified in \a Check to all component lists and return true /// if any issue is found. @@ -333,8 +388,10 @@ public: const llvm::function_ref< bool(OMPClauseMappableExprCommon::MappableExprComponentListRef, OpenMPClauseKind)> &Check) { - auto SI = Stack.rbegin(); - auto SE = Stack.rend(); + if (isStackEmpty()) + return false; + auto SI = Stack.back().first.rbegin(); + auto SE = Stack.back().first.rend(); if (SI == SE) return false; @@ -361,9 +418,9 @@ public: ValueDecl *VD, OMPClauseMappableExprCommon::MappableExprComponentListRef Components, OpenMPClauseKind WhereFoundClauseKind) { - assert(Stack.size() > 1 && + assert(!isStackEmpty() && "Not expecting to retrieve components from a empty stack!"); - auto &MEC = Stack.back().MappedExprComponents[VD]; + auto &MEC = Stack.back().first.back().MappedExprComponents[VD]; // Create new entry and append the new components there. MEC.Components.resize(MEC.Components.size() + 1); MEC.Components.back().append(Components.begin(), Components.end()); @@ -371,23 +428,25 @@ public: } unsigned getNestingLevel() const { - assert(Stack.size() > 1); - return Stack.size() - 2; + assert(!isStackEmpty()); + return Stack.back().first.size() - 1; } void addDoacrossDependClause(OMPDependClause *C, OperatorOffsetTy &OpsOffs) { - assert(Stack.size() > 2); - assert(isOpenMPWorksharingDirective(Stack[Stack.size() - 2].Directive)); - Stack[Stack.size() - 2].DoacrossDepends.insert({C, OpsOffs}); + assert(!isStackEmpty() && Stack.back().first.size() > 1); + auto &StackElem = *std::next(Stack.back().first.rbegin()); + assert(isOpenMPWorksharingDirective(StackElem.Directive)); + StackElem.DoacrossDepends.insert({C, OpsOffs}); } llvm::iterator_range<DoacrossDependMapTy::const_iterator> getDoacrossDependClauses() const { - assert(Stack.size() > 1); - if (isOpenMPWorksharingDirective(Stack[Stack.size() - 1].Directive)) { - auto &Ref = Stack[Stack.size() - 1].DoacrossDepends; + assert(!isStackEmpty()); + auto &StackElem = Stack.back().first.back(); + if (isOpenMPWorksharingDirective(StackElem.Directive)) { + auto &Ref = StackElem.DoacrossDepends; return llvm::make_range(Ref.begin(), Ref.end()); } - return llvm::make_range(Stack[0].DoacrossDepends.end(), - Stack[0].DoacrossDepends.end()); + return llvm::make_range(StackElem.DoacrossDepends.end(), + StackElem.DoacrossDepends.end()); } }; bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) { @@ -416,7 +475,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter, auto *VD = dyn_cast<VarDecl>(D); auto *FD = dyn_cast<FieldDecl>(D); DSAVarData DVar; - if (Iter == std::prev(Stack.rend())) { + if (isStackEmpty() || Iter == Stack.back().first.rend()) { // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a region but not in construct] // File-scope or namespace-scope variables referenced in called routines @@ -490,8 +549,9 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter, // bound to the current team is shared. if (isOpenMPTaskingDirective(DVar.DKind)) { DSAVarData DVarTemp; - for (StackTy::reverse_iterator I = std::next(Iter), EE = Stack.rend(); - I != EE; ++I) { + auto I = Iter, E = Stack.back().first.rend(); + do { + ++I; // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables // Referenced in a Construct, implicitly determined, p.6] // In a task construct, if no default clause is present, a variable @@ -503,9 +563,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter, DVar.CKind = OMPC_firstprivate; return DVar; } - if (isParallelOrTaskRegion(I->Directive)) - break; - } + } while (I != E && !isParallelOrTaskRegion(I->Directive)); DVar.CKind = (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared; return DVar; @@ -520,12 +578,13 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter, } Expr *DSAStackTy::addUniqueAligned(ValueDecl *D, Expr *NewDE) { - assert(Stack.size() > 1 && "Data sharing attributes stack is empty"); + assert(!isStackEmpty() && "Data sharing attributes stack is empty"); D = getCanonicalDecl(D); - auto It = Stack.back().AlignedMap.find(D); - if (It == Stack.back().AlignedMap.end()) { + auto &StackElem = Stack.back().first.back(); + auto It = StackElem.AlignedMap.find(D); + if (It == StackElem.AlignedMap.end()) { assert(NewDE && "Unexpected nullptr expr to be added into aligned map"); - Stack.back().AlignedMap[D] = NewDE; + StackElem.AlignedMap[D] = NewDE; return nullptr; } else { assert(It->second && "Unexpected nullptr expr in the aligned map"); @@ -535,35 +594,43 @@ Expr *DSAStackTy::addUniqueAligned(ValueDecl *D, Expr *NewDE) { } void DSAStackTy::addLoopControlVariable(ValueDecl *D, VarDecl *Capture) { - assert(Stack.size() > 1 && "Data-sharing attributes stack is empty"); + assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); D = getCanonicalDecl(D); - Stack.back().LCVMap.insert( - std::make_pair(D, LCDeclInfo(Stack.back().LCVMap.size() + 1, Capture))); + auto &StackElem = Stack.back().first.back(); + StackElem.LCVMap.insert( + {D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture)}); } DSAStackTy::LCDeclInfo DSAStackTy::isLoopControlVariable(ValueDecl *D) { - assert(Stack.size() > 1 && "Data-sharing attributes stack is empty"); + assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); D = getCanonicalDecl(D); - return Stack.back().LCVMap.count(D) > 0 ? Stack.back().LCVMap[D] - : LCDeclInfo(0, nullptr); + auto &StackElem = Stack.back().first.back(); + auto It = StackElem.LCVMap.find(D); + if (It != StackElem.LCVMap.end()) + return It->second; + return {0, nullptr}; } DSAStackTy::LCDeclInfo DSAStackTy::isParentLoopControlVariable(ValueDecl *D) { - assert(Stack.size() > 2 && "Data-sharing attributes stack is empty"); + assert(!isStackEmpty() && Stack.back().first.size() > 1 && + "Data-sharing attributes stack is empty"); D = getCanonicalDecl(D); - return Stack[Stack.size() - 2].LCVMap.count(D) > 0 - ? Stack[Stack.size() - 2].LCVMap[D] - : LCDeclInfo(0, nullptr); + auto &StackElem = *std::next(Stack.back().first.rbegin()); + auto It = StackElem.LCVMap.find(D); + if (It != StackElem.LCVMap.end()) + return It->second; + return {0, nullptr}; } ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) { - assert(Stack.size() > 2 && "Data-sharing attributes stack is empty"); - if (Stack[Stack.size() - 2].LCVMap.size() < I) + assert(!isStackEmpty() && Stack.back().first.size() > 1 && + "Data-sharing attributes stack is empty"); + auto &StackElem = *std::next(Stack.back().first.rbegin()); + if (StackElem.LCVMap.size() < I) return nullptr; - for (auto &Pair : Stack[Stack.size() - 2].LCVMap) { + for (auto &Pair : StackElem.LCVMap) if (Pair.second.first == I) return Pair.first; - } return nullptr; } @@ -571,13 +638,13 @@ void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A, DeclRefExpr *PrivateCopy) { D = getCanonicalDecl(D); if (A == OMPC_threadprivate) { - auto &Data = Stack[0].SharingMap[D]; + auto &Data = Threadprivates[D]; Data.Attributes = A; Data.RefExpr.setPointer(E); Data.PrivateCopy = nullptr; } else { - assert(Stack.size() > 1 && "Data-sharing attributes stack is empty"); - auto &Data = Stack.back().SharingMap[D]; + assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); + auto &Data = Stack.back().first.back().SharingMap[D]; assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) || (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) || (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) || @@ -592,7 +659,7 @@ void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A, Data.RefExpr.setPointerAndInt(E, IsLastprivate); Data.PrivateCopy = PrivateCopy; if (PrivateCopy) { - auto &Data = Stack.back().SharingMap[PrivateCopy->getDecl()]; + auto &Data = Stack.back().first.back().SharingMap[PrivateCopy->getDecl()]; Data.Attributes = A; Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate); Data.PrivateCopy = nullptr; @@ -602,19 +669,17 @@ void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A, bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) { D = D->getCanonicalDecl(); - if (Stack.size() > 2) { - reverse_iterator I = Iter, E = std::prev(Stack.rend()); + if (!isStackEmpty() && Stack.back().first.size() > 1) { + reverse_iterator I = Iter, E = Stack.back().first.rend(); Scope *TopScope = nullptr; - while (I != E && !isParallelOrTaskRegion(I->Directive)) { + while (I != E && !isParallelOrTaskRegion(I->Directive)) ++I; - } if (I == E) return false; TopScope = I->CurScope ? I->CurScope->getParent() : nullptr; Scope *CurScope = getCurScope(); - while (CurScope != TopScope && !CurScope->isDeclScope(D)) { + while (CurScope != TopScope && !CurScope->isDeclScope(D)) CurScope = CurScope->getParent(); - } return CurScope != TopScope; } return false; @@ -665,16 +730,16 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) { D->getLocation()), OMPC_threadprivate); } - if (Stack[0].SharingMap.count(D)) { - DVar.RefExpr = Stack[0].SharingMap[D].RefExpr.getPointer(); + auto TI = Threadprivates.find(D); + if (TI != Threadprivates.end()) { + DVar.RefExpr = TI->getSecond().RefExpr.getPointer(); DVar.CKind = OMPC_threadprivate; return DVar; } - if (Stack.size() == 1) { + if (isStackEmpty()) // Not in OpenMP execution region and top scope was already checked. return DVar; - } // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct, C/C++, predetermined, p.4] @@ -722,11 +787,10 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) { // Explicitly specified attributes and local variables with predetermined // attributes. - auto StartI = std::next(Stack.rbegin()); - auto EndI = std::prev(Stack.rend()); - if (FromParent && StartI != EndI) { + auto StartI = std::next(Stack.back().first.rbegin()); + auto EndI = Stack.back().first.rend(); + if (FromParent && StartI != EndI) StartI = std::next(StartI); - } auto I = std::prev(StartI); if (I->SharingMap.count(D)) { DVar.RefExpr = I->SharingMap[D].RefExpr.getPointer(); @@ -740,12 +804,15 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) { DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D, bool FromParent) { + if (isStackEmpty()) { + StackTy::reverse_iterator I; + return getDSA(I, D); + } D = getCanonicalDecl(D); - auto StartI = Stack.rbegin(); - auto EndI = std::prev(Stack.rend()); - if (FromParent && StartI != EndI) { + auto StartI = Stack.back().first.rbegin(); + auto EndI = Stack.back().first.rend(); + if (FromParent && StartI != EndI) StartI = std::next(StartI); - } return getDSA(StartI, D); } @@ -754,33 +821,40 @@ DSAStackTy::hasDSA(ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> &CPred, const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred, bool FromParent) { + if (isStackEmpty()) + return {}; D = getCanonicalDecl(D); - auto StartI = std::next(Stack.rbegin()); - auto EndI = Stack.rend(); - if (FromParent && StartI != EndI) { + auto StartI = std::next(Stack.back().first.rbegin()); + auto EndI = Stack.back().first.rend(); + if (FromParent && StartI != EndI) StartI = std::next(StartI); - } - for (auto I = StartI, EE = EndI; I != EE; ++I) { + if (StartI == EndI) + return {}; + auto I = std::prev(StartI); + do { + ++I; if (!DPred(I->Directive) && !isParallelOrTaskRegion(I->Directive)) continue; DSAVarData DVar = getDSA(I, D); if (CPred(DVar.CKind)) return DVar; - } - return DSAVarData(); + } while (I != EndI); + return {}; } DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA( ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> &CPred, const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred, bool FromParent) { + if (isStackEmpty()) + return {}; D = getCanonicalDecl(D); - auto StartI = std::next(Stack.rbegin()); - auto EndI = Stack.rend(); + auto StartI = std::next(Stack.back().first.rbegin()); + auto EndI = Stack.back().first.rend(); if (FromParent && StartI != EndI) StartI = std::next(StartI); if (StartI == EndI || !DPred(StartI->Directive)) - return DSAVarData(); + return {}; DSAVarData DVar = getDSA(StartI, D); return CPred(DVar.CKind) ? DVar : DSAVarData(); } @@ -790,9 +864,11 @@ bool DSAStackTy::hasExplicitDSA( unsigned Level, bool NotLastprivate) { if (CPred(ClauseKindMode)) return true; + if (isStackEmpty()) + return false; D = getCanonicalDecl(D); - auto StartI = std::next(Stack.begin()); - auto EndI = Stack.end(); + auto StartI = Stack.back().first.begin(); + auto EndI = Stack.back().first.end(); if (std::distance(StartI, EndI) <= (int)Level) return false; std::advance(StartI, Level); @@ -805,8 +881,10 @@ bool DSAStackTy::hasExplicitDSA( bool DSAStackTy::hasExplicitDirective( const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred, unsigned Level) { - auto StartI = std::next(Stack.begin()); - auto EndI = Stack.end(); + if (isStackEmpty()) + return false; + auto StartI = Stack.back().first.begin(); + auto EndI = Stack.back().first.end(); if (std::distance(StartI, EndI) <= (int)Level) return false; std::advance(StartI, Level); @@ -819,13 +897,12 @@ bool DSAStackTy::hasDirective( &DPred, bool FromParent) { // We look only in the enclosing region. - if (Stack.size() < 2) + if (isStackEmpty()) return false; - auto StartI = std::next(Stack.rbegin()); - auto EndI = std::prev(Stack.rend()); - if (FromParent && StartI != EndI) { + auto StartI = std::next(Stack.back().first.rbegin()); + auto EndI = Stack.back().first.rend(); + if (FromParent && StartI != EndI) StartI = std::next(StartI); - } for (auto I = StartI, EE = EndI; I != EE; ++I) { if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc)) return true; @@ -839,6 +916,14 @@ void Sema::InitDataSharingAttributesStack() { #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack) +void Sema::pushOpenMPFunctionRegion() { + DSAStack->pushFunction(); +} + +void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) { + DSAStack->popFunction(OldFSI); +} + bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) { assert(LangOpts.OpenMP && "OpenMP is not allowed"); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 693b5c088acc..f4a97f55789e 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2220,6 +2220,9 @@ public: Base = BaseResult.get(); QualType BaseType = Base->getType(); + if (isArrow && !BaseType->isPointerType()) + return ExprError(); + // FIXME: this involves duplicating earlier analysis in a lot of // cases; we should avoid this when possible. LookupResult R(getSema(), MemberNameInfo, Sema::LookupMemberName); |