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) | |
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.  | 
