diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-07-01 13:24:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-07-01 13:24:05 +0000 |
commit | cf1b401909b5e54edfd80656b1a18eaa31f9f6f1 (patch) | |
tree | edb0ffff2a43d84ba9b4c862b394cfeeebb36ddc /lib/Sema | |
parent | ef915aab0ac566c55bfb0d7a9f6635bb5d94d4af (diff) | |
download | src-test2-cf1b401909b5e54edfd80656b1a18eaa31f9f6f1.tar.gz src-test2-cf1b401909b5e54edfd80656b1a18eaa31f9f6f1.zip |
Notes
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/AnalysisBasedWarnings.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 25 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 182 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 46 | ||||
-rw-r--r-- | lib/Sema/SemaOpenMP.cpp | 29 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 15 |
9 files changed, 268 insertions, 51 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 934e13e72d05..fd2d07957c2b 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -305,10 +305,14 @@ static bool isThrowCaught(const CXXThrowExpr *Throw, CaughtType = CaughtType->castAs<ReferenceType>() ->getPointeeType() ->getUnqualifiedDesugaredType(); + if (ThrowType->isPointerType() && CaughtType->isPointerType()) { + ThrowType = ThrowType->getPointeeType()->getUnqualifiedDesugaredType(); + CaughtType = CaughtType->getPointeeType()->getUnqualifiedDesugaredType(); + } if (CaughtType == ThrowType) return true; const CXXRecordDecl *CaughtAsRecordType = - CaughtType->getPointeeCXXRecordDecl(); + CaughtType->getAsCXXRecordDecl(); const CXXRecordDecl *ThrowTypeAsRecordType = ThrowType->getAsCXXRecordDecl(); if (CaughtAsRecordType && ThrowTypeAsRecordType) return ThrowTypeAsRecordType->isDerivedFrom(CaughtAsRecordType); diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 007a5e483e6c..34f5e26be810 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -1688,7 +1688,8 @@ bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) { QT, OpenCLTypeExtMap); } -bool Sema::checkOpenCLDisabledDecl(const Decl &D, const Expr &E) { - return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), "", +bool Sema::checkOpenCLDisabledDecl(const NamedDecl &D, const Expr &E) { + IdentifierInfo *FnName = D.getIdentifier(); + return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), FnName, OpenCLDeclExtMap, 1, D.getSourceRange()); } diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index b794628db738..845c4bf61b7a 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -6000,6 +6000,7 @@ shouldNotPrintDirectly(const ASTContext &Context, while (const TypedefType *UserTy = TyTy->getAs<TypedefType>()) { StringRef Name = UserTy->getDecl()->getName(); QualType CastTy = llvm::StringSwitch<QualType>(Name) + .Case("CFIndex", Context.LongTy) .Case("NSInteger", Context.LongTy) .Case("NSUInteger", Context.UnsignedLongTy) .Case("SInt32", Context.IntTy) @@ -9935,6 +9936,28 @@ void Sema::CheckBoolLikeConversion(Expr *E, SourceLocation CC) { ::CheckBoolLikeConversion(*this, E, CC); } +/// Diagnose when expression is an integer constant expression and its evaluation +/// results in integer overflow +void Sema::CheckForIntOverflow (Expr *E) { + // Use a work list to deal with nested struct initializers. + SmallVector<Expr *, 2> Exprs(1, E); + + do { + Expr *E = Exprs.pop_back_val(); + + if (isa<BinaryOperator>(E->IgnoreParenCasts())) { + E->IgnoreParenCasts()->EvaluateForOverflow(Context); + continue; + } + + if (auto InitList = dyn_cast<InitListExpr>(E)) + Exprs.append(InitList->inits().begin(), InitList->inits().end()); + + if (isa<ObjCBoxedExpr>(E)) + E->IgnoreParenCasts()->EvaluateForOverflow(Context); + } while (!Exprs.empty()); +} + namespace { /// \brief Visitor for expressions which looks for unsequenced operations on the /// same object. @@ -10436,7 +10459,7 @@ void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc, if (!E->isInstantiationDependent()) CheckUnsequencedOperations(E); if (!IsConstexpr && !E->isValueDependent()) - E->EvaluateForOverflow(Context); + CheckForIntOverflow(E); DiagnoseMisalignedMembers(); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index e340456bc6da..ef8a408f90de 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1327,15 +1327,17 @@ void Sema::ActOnExitFunctionContext() { /// overloaded function declaration or has the "overloadable" /// attribute. static bool AllowOverloadingOfFunction(LookupResult &Previous, - ASTContext &Context) { + ASTContext &Context, + const FunctionDecl *New) { if (Context.getLangOpts().CPlusPlus) return true; if (Previous.getResultKind() == LookupResult::FoundOverloaded) return true; - return (Previous.getResultKind() == LookupResult::Found - && Previous.getFoundDecl()->hasAttr<OverloadableAttr>()); + return Previous.getResultKind() == LookupResult::Found && + (Previous.getFoundDecl()->hasAttr<OverloadableAttr>() || + New->hasAttr<OverloadableAttr>()); } /// Add this decl to the scope shadowed decl chains. @@ -2933,6 +2935,41 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, New->dropAttr<InternalLinkageAttr>(); } + if (!getLangOpts().CPlusPlus) { + bool OldOvl = Old->hasAttr<OverloadableAttr>(); + if (OldOvl != New->hasAttr<OverloadableAttr>() && !Old->isImplicit()) { + Diag(New->getLocation(), diag::err_attribute_overloadable_mismatch) + << New << OldOvl; + + // Try our best to find a decl that actually has the overloadable + // attribute for the note. In most cases (e.g. programs with only one + // broken declaration/definition), this won't matter. + // + // FIXME: We could do this if we juggled some extra state in + // OverloadableAttr, rather than just removing it. + const Decl *DiagOld = Old; + if (OldOvl) { + auto OldIter = llvm::find_if(Old->redecls(), [](const Decl *D) { + const auto *A = D->getAttr<OverloadableAttr>(); + return A && !A->isImplicit(); + }); + // If we've implicitly added *all* of the overloadable attrs to this + // chain, emitting a "previous redecl" note is pointless. + DiagOld = OldIter == Old->redecls_end() ? nullptr : *OldIter; + } + + if (DiagOld) + Diag(DiagOld->getLocation(), + diag::note_attribute_overloadable_prev_overload) + << OldOvl; + + if (OldOvl) + New->addAttr(OverloadableAttr::CreateImplicit(Context)); + else + New->dropAttr<OverloadableAttr>(); + } + } + // If a function is first declared with a calling convention, but is later // declared or defined without one, all following decls assume the calling // convention of the first. @@ -9179,6 +9216,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, bool Redeclaration = false; NamedDecl *OldDecl = nullptr; + bool MayNeedOverloadableChecks = false; // Merge or overload the declaration with an existing declaration of // the same name, if appropriate. @@ -9187,13 +9225,14 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // a declaration that requires merging. If it's an overload, // there's no more work to do here; we'll just add the new // function to the scope. - if (!AllowOverloadingOfFunction(Previous, Context)) { + if (!AllowOverloadingOfFunction(Previous, Context, NewFD)) { NamedDecl *Candidate = Previous.getRepresentativeDecl(); if (shouldLinkPossiblyHiddenDecl(Candidate, NewFD)) { Redeclaration = true; OldDecl = Candidate; } } else { + MayNeedOverloadableChecks = true; switch (CheckOverload(S, NewFD, Previous, OldDecl, /*NewIsUsingDecl*/ false)) { case Ovl_Match: @@ -9208,18 +9247,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, Redeclaration = false; break; } - - if (!getLangOpts().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) { - // If a function name is overloadable in C, then every function - // with that name must be marked "overloadable". - Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing) - << Redeclaration << NewFD; - NamedDecl *OverloadedDecl = - Redeclaration ? OldDecl : Previous.getRepresentativeDecl(); - Diag(OverloadedDecl->getLocation(), - diag::note_attribute_overloadable_prev_overload); - NewFD->addAttr(OverloadableAttr::CreateImplicit(Context)); - } } } @@ -9234,15 +9261,10 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, MergeTypeWithPrevious = false; // ... except in the presence of __attribute__((overloadable)). - if (OldDecl->hasAttr<OverloadableAttr>()) { - if (!getLangOpts().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) { - Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing) - << Redeclaration << NewFD; - Diag(Previous.getFoundDecl()->getLocation(), - diag::note_attribute_overloadable_prev_overload); - NewFD->addAttr(OverloadableAttr::CreateImplicit(Context)); - } + if (OldDecl->hasAttr<OverloadableAttr>() || + NewFD->hasAttr<OverloadableAttr>()) { if (IsOverload(NewFD, cast<FunctionDecl>(OldDecl), false)) { + MayNeedOverloadableChecks = true; Redeclaration = false; OldDecl = nullptr; } @@ -9337,6 +9359,29 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, NewFD->setAccess(OldDecl->getAccess()); } } + } else if (!getLangOpts().CPlusPlus && MayNeedOverloadableChecks && + !NewFD->getAttr<OverloadableAttr>()) { + assert((Previous.empty() || + llvm::any_of(Previous, + [](const NamedDecl *ND) { + return ND->hasAttr<OverloadableAttr>(); + })) && + "Non-redecls shouldn't happen without overloadable present"); + + auto OtherUnmarkedIter = llvm::find_if(Previous, [](const NamedDecl *ND) { + const auto *FD = dyn_cast<FunctionDecl>(ND); + return FD && !FD->hasAttr<OverloadableAttr>(); + }); + + if (OtherUnmarkedIter != Previous.end()) { + Diag(NewFD->getLocation(), + diag::err_attribute_overloadable_multiple_unmarked_overloads); + Diag((*OtherUnmarkedIter)->getLocation(), + diag::note_attribute_overloadable_prev_overload) + << false; + + NewFD->addAttr(OverloadableAttr::CreateImplicit(Context)); + } } // Semantic checking for this function declaration (in isolation). @@ -11100,9 +11145,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { bool IsGlobal = GlobalStorage && !var->isStaticLocal(); QualType baseType = Context.getBaseElementType(type); - if (!var->getDeclContext()->isDependentContext() && - Init && !Init->isValueDependent()) { - + if (Init && !Init->isValueDependent()) { if (var->isConstexpr()) { SmallVector<PartialDiagnosticAt, 8> Notes; if (!var->evaluateValue(Notes) || !var->isInitICE()) { @@ -11932,7 +11975,7 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD, if (canRedefineFunction(Definition, getLangOpts())) return; - // Don't emit an error when this is redifinition of a typo-corrected + // Don't emit an error when this is redefinition of a typo-corrected // definition. if (TypoCorrectedFunctionDefinitions.count(Definition)) return; @@ -13190,6 +13233,55 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, if (TUK == TUK_Friend || TUK == TUK_Reference) Redecl = NotForRedeclaration; + /// Create a new tag decl in C/ObjC. Since the ODR-like semantics for ObjC/C + /// implemented asks for structural equivalence checking, the returned decl + /// here is passed back to the parser, allowing the tag body to be parsed. + auto createTagFromNewDecl = [&]() -> TagDecl * { + assert(!getLangOpts().CPlusPlus && "not meant for C++ usage"); + // If there is an identifier, use the location of the identifier as the + // location of the decl, otherwise use the location of the struct/union + // keyword. + SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc; + TagDecl *New = nullptr; + + if (Kind == TTK_Enum) { + New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, nullptr, + ScopedEnum, ScopedEnumUsesClassTag, + !EnumUnderlying.isNull()); + // If this is an undefined enum, bail. + if (TUK != TUK_Definition && !Invalid) + return nullptr; + if (EnumUnderlying) { + EnumDecl *ED = cast<EnumDecl>(New); + if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo *>()) + ED->setIntegerTypeSourceInfo(TI); + else + ED->setIntegerType(QualType(EnumUnderlying.get<const Type *>(), 0)); + ED->setPromotionType(ED->getIntegerType()); + } + } else { // struct/union + New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, + nullptr); + } + + if (RecordDecl *RD = dyn_cast<RecordDecl>(New)) { + // Add alignment attributes if necessary; these attributes are checked + // when the ASTContext lays out the structure. + // + // It is important for implementing the correct semantics that this + // happen here (in ActOnTag). The #pragma pack stack is + // maintained as a result of parser callbacks which can occur at + // many points during the parsing of a struct declaration (because + // the #pragma tokens are effectively skipped over during the + // parsing of the struct). + if (TUK == TUK_Definition) { + AddAlignmentAttributesForRecord(RD); + AddMsStructLayoutForRecord(RD); + } + } + return New; + }; + LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl); if (Name && SS.isNotEmpty()) { // We have a nested-name tag ('struct foo::bar'). @@ -13595,16 +13687,28 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, TSK_ExplicitSpecialization; } + // Note that clang allows ODR-like semantics for ObjC/C, i.e., do + // not keep more that one definition around (merge them). However, + // ensure the decl passes the structural compatibility check in + // C11 6.2.7/1 (or 6.1.2.6/1 in C89). NamedDecl *Hidden = nullptr; - if (SkipBody && getLangOpts().CPlusPlus && - !hasVisibleDefinition(Def, &Hidden)) { + if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) { // There is a definition of this tag, but it is not visible. We // explicitly make use of C++'s one definition rule here, and // assume that this definition is identical to the hidden one // we already have. Make the existing definition visible and // use it in place of this one. - SkipBody->ShouldSkip = true; - makeMergedDefinitionVisible(Hidden); + if (!getLangOpts().CPlusPlus) { + // Postpone making the old definition visible until after we + // complete parsing the new one and do the structural + // comparison. + SkipBody->CheckSameAsPrevious = true; + SkipBody->New = createTagFromNewDecl(); + SkipBody->Previous = Hidden; + } else { + SkipBody->ShouldSkip = true; + makeMergedDefinitionVisible(Hidden); + } return Def; } else if (!IsExplicitSpecializationAfterInstantiation) { // A redeclaration in function prototype scope in C isn't @@ -13832,7 +13936,7 @@ CreateNewDecl: // the ASTContext lays out the structure. // // It is important for implementing the correct semantics that this - // happen here (in act on tag decl). The #pragma pack stack is + // happen here (in ActOnTag). The #pragma pack stack is // maintained as a result of parser callbacks which can occur at // many points during the parsing of a struct declaration (because // the #pragma tokens are effectively skipped over during the @@ -13968,6 +14072,16 @@ void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) { AddPushedVisibilityAttribute(Tag); } +bool Sema::ActOnDuplicateDefinition(DeclSpec &DS, Decl *Prev, + SkipBodyInfo &SkipBody) { + if (!hasStructuralCompatLayout(Prev, SkipBody.New)) + return false; + + // Make the previous decl visible. + makeMergedDefinitionVisible(SkipBody.Previous); + return true; +} + Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) { assert(isa<ObjCContainerDecl>(IDecl) && "ActOnObjCContainerStartDefinition - Not ObjCContainerDecl"); @@ -15389,7 +15503,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, // different from T: // - every enumerator of every member of class T that is an unscoped // enumerated type - if (!TheEnumDecl->isScoped()) + if (getLangOpts().CPlusPlus && !TheEnumDecl->isScoped()) DiagnoseClassNameShadow(TheEnumDecl->getDeclContext(), DeclarationNameInfo(Id, IdLoc)); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index e8503427536d..1929bc539188 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -6571,7 +6571,7 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, } } -// Helper for delayed proccessing TransparentUnion attribute. +// Helper for delayed processing TransparentUnion attribute. void Sema::ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList) { for (const AttributeList *Attr = AttrList; Attr; Attr = Attr->getNext()) if (Attr->getKind() == AttributeList::AT_TransparentUnion) { diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 453ece9d9c4d..e9070881afe4 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3778,6 +3778,15 @@ Sema::BuildMemInitializer(Decl *ConstructorD, if (BaseType.isNull()) return true; + TInfo = Context.CreateTypeSourceInfo(BaseType); + DependentNameTypeLoc TL = + TInfo->getTypeLoc().castAs<DependentNameTypeLoc>(); + if (!TL.isNull()) { + TL.setNameLoc(IdLoc); + TL.setElaboratedKeywordLoc(SourceLocation()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + } + R.clear(); R.setLookupName(MemberOrBase); } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 710ead30790f..a9cf3ec7990b 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1646,6 +1646,27 @@ static bool isLegalArrayNewInitializer(CXXNewExpr::InitializationStyle Style, return false; } +// Emit a diagnostic if an aligned allocation/deallocation function that is not +// implemented in the standard library is selected. +static void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, + SourceLocation Loc, bool IsDelete, + Sema &S) { + if (!S.getLangOpts().AlignedAllocationUnavailable) + return; + + // Return if there is a definition. + if (FD.isDefined()) + return; + + bool IsAligned = false; + if (FD.isReplaceableGlobalAllocationFunction(&IsAligned) && IsAligned) { + S.Diag(Loc, diag::warn_aligned_allocation_unavailable) + << IsDelete << FD.getType().getAsString() + << S.getASTContext().getTargetInfo().getTriple().str(); + S.Diag(Loc, diag::note_silence_unligned_allocation_unavailable); + } +} + ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, SourceLocation PlacementLParen, @@ -2023,11 +2044,13 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, if (DiagnoseUseOfDecl(OperatorNew, StartLoc)) return ExprError(); MarkFunctionReferenced(StartLoc, OperatorNew); + diagnoseUnavailableAlignedAllocation(*OperatorNew, StartLoc, false, *this); } if (OperatorDelete) { if (DiagnoseUseOfDecl(OperatorDelete, StartLoc)) return ExprError(); MarkFunctionReferenced(StartLoc, OperatorDelete); + diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true, *this); } // C++0x [expr.new]p17: @@ -3243,6 +3266,9 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, PDiag(diag::err_access_dtor) << PointeeElem); } } + + diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true, + *this); } CXXDeleteExpr *Result = new (Context) CXXDeleteExpr( @@ -4093,15 +4119,9 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, case UTT_IsStandardLayout: case UTT_IsPOD: case UTT_IsLiteral: - ArgTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0); - LLVM_FALLTHROUGH; - - // C++1z [meta.unary.prop]: - // T shall be a complete type, cv void, or an array of unknown bound. - case UTT_IsDestructible: - case UTT_IsNothrowDestructible: - case UTT_IsTriviallyDestructible: - // Per the GCC type traits documentation, the same constraints apply to these. + // Per the GCC type traits documentation, T shall be a complete type, cv void, + // or an array of unknown bound. But GCC actually imposes the same constraints + // as above. case UTT_HasNothrowAssign: case UTT_HasNothrowMoveAssign: case UTT_HasNothrowConstructor: @@ -4113,6 +4133,14 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, case UTT_HasTrivialCopy: case UTT_HasTrivialDestructor: case UTT_HasVirtualDestructor: + ArgTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0); + LLVM_FALLTHROUGH; + + // C++1z [meta.unary.prop]: + // T shall be a complete type, cv void, or an array of unknown bound. + case UTT_IsDestructible: + case UTT_IsNothrowDestructible: + case UTT_IsTriviallyDestructible: if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType()) return true; diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 2b7733d2adbd..49da0e499771 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -412,6 +412,30 @@ public: return false; } + /// Do the check specified in \a Check to all component lists at a given level + /// and return true if any issue is found. + bool checkMappableExprComponentListsForDeclAtLevel( + ValueDecl *VD, unsigned Level, + const llvm::function_ref< + bool(OMPClauseMappableExprCommon::MappableExprComponentListRef, + OpenMPClauseKind)> &Check) { + 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); + + auto MI = StartI->MappedExprComponents.find(VD); + if (MI != StartI->MappedExprComponents.end()) + for (auto &L : MI->second.Components) + if (Check(L, MI->second.Kind)) + return true; + return false; + } + /// Create a new mappable expression component list associated with a given /// declaration and initialize it with the provided list of components. void addMappableExpressionComponents( @@ -994,9 +1018,8 @@ bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) { bool IsVariableUsedInMapClause = false; bool IsVariableAssociatedWithSection = false; - DSAStack->checkMappableExprComponentListsForDecl( - D, /*CurrentRegionOnly=*/true, - [&](OMPClauseMappableExprCommon::MappableExprComponentListRef + DSAStack->checkMappableExprComponentListsForDeclAtLevel( + D, Level, [&](OMPClauseMappableExprCommon::MappableExprComponentListRef MapExprComponents, OpenMPClauseKind WhereFoundClauseKind) { // Only the map clause information influences how a variable is diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 8c8402e75e37..b19dcb2a5099 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -15,6 +15,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" +#include "clang/AST/ASTStructuralEquivalence.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" @@ -7111,6 +7112,20 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, return false; } +bool Sema::hasStructuralCompatLayout(Decl *D, Decl *Suggested) { + llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls; + if (!Suggested) + return false; + + // FIXME: Add a specific mode for C11 6.2.7/1 in StructuralEquivalenceContext + // and isolate from other C++ specific checks. + StructuralEquivalenceContext Ctx( + D->getASTContext(), Suggested->getASTContext(), NonEquivalentDecls, + false /*StrictTypeSpelling*/, true /*Complain*/, + true /*ErrorOnTagTypeMismatch*/); + return Ctx.IsStructurallyEquivalent(D, Suggested); +} + /// \brief Determine whether there is any declaration of \p D that was ever a /// definition (perhaps before module merging) and is currently visible. /// \param D The definition of the entity. |