diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/Sema.cpp | 32 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp | 3 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp | 94 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp | 259 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp | 13 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp | 242 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp | 29 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp | 3 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp | 40 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp | 52 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp | 6 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp | 54 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp | 196 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 14 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaType.cpp | 5 | 
15 files changed, 850 insertions, 192 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp index 2f493fa5fbef..ca1d27e9505f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp @@ -477,6 +477,13 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {      return true;    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { +    // If this is a function template and none of its specializations is used, +    // we should warn. +    if (FunctionTemplateDecl *Template = FD->getDescribedFunctionTemplate()) +      for (const auto *Spec : Template->specializations()) +        if (ShouldRemoveFromUnused(SemaRef, Spec)) +          return true; +      // UnusedFileScopedDecls stores the first declaration.      // The declaration may have become definition so check again.      const FunctionDecl *DeclToCheck; @@ -500,6 +507,13 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {          VD->isUsableInConstantExpressions(SemaRef->Context))        return true; +    if (VarTemplateDecl *Template = VD->getDescribedVarTemplate()) +      // If this is a variable template and none of its specializations is used, +      // we should warn. +      for (const auto *Spec : Template->specializations()) +        if (ShouldRemoveFromUnused(SemaRef, Spec)) +          return true; +      // UnusedFileScopedDecls stores the first declaration.      // The declaration may have become definition so check again.      const VarDecl *DeclToCheck = VD->getDefinition(); @@ -905,10 +919,14 @@ void Sema::ActOnEndOfTranslationUnit() {                     << /*function*/0 << DiagD->getDeclName();            }          } else { -          Diag(DiagD->getLocation(), -               isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function -                                         : diag::warn_unused_function) -                << DiagD->getDeclName(); +          if (FD->getDescribedFunctionTemplate()) +            Diag(DiagD->getLocation(), diag::warn_unused_template) +              << /*function*/0 << DiagD->getDeclName(); +          else +            Diag(DiagD->getLocation(), +                 isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function +                                           : diag::warn_unused_function) +              << DiagD->getDeclName();          }        } else {          const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition(); @@ -924,7 +942,11 @@ void Sema::ActOnEndOfTranslationUnit() {              Diag(DiagD->getLocation(), diag::warn_unused_const_variable)                  << DiagD->getDeclName();          } else { -          Diag(DiagD->getLocation(), diag::warn_unused_variable) +          if (DiagD->getDescribedVarTemplate()) +            Diag(DiagD->getLocation(), diag::warn_unused_template) +              << /*variable*/1 << DiagD->getDeclName(); +          else +            Diag(DiagD->getLocation(), diag::warn_unused_variable)                << DiagD->getDeclName();          }        } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp index 7e91709e67da..7d534263f468 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp @@ -1871,7 +1871,8 @@ static bool fixOverloadedReinterpretCastExpr(Sema &Self, QualType DestType,    // No guarantees that ResolveAndFixSingleFunctionTemplateSpecialization    // preserves Result.    Result = E; -  if (!Self.resolveAndFixAddressOfOnlyViableOverloadCandidate(Result)) +  if (!Self.resolveAndFixAddressOfOnlyViableOverloadCandidate( +          Result, /*DoFunctionPointerConversion=*/true))      return false;    return Result.isUsable();  } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp index cfac3f1dc1de..8fb2f4139236 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp @@ -3869,6 +3869,41 @@ static void AddObjCProperties(    }  } +static void AddRecordMembersCompletionResults(Sema &SemaRef, +                                              ResultBuilder &Results, Scope *S, +                                              QualType BaseType, +                                              RecordDecl *RD) { +  // Indicate that we are performing a member access, and the cv-qualifiers +  // for the base object type. +  Results.setObjectTypeQualifiers(BaseType.getQualifiers()); + +  // Access to a C/C++ class, struct, or union. +  Results.allowNestedNameSpecifiers(); +  CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext); +  SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer, +                             SemaRef.CodeCompleter->includeGlobals(), +                             /*IncludeDependentBases=*/true); + +  if (SemaRef.getLangOpts().CPlusPlus) { +    if (!Results.empty()) { +      // The "template" keyword can follow "->" or "." in the grammar. +      // However, we only want to suggest the template keyword if something +      // is dependent. +      bool IsDependent = BaseType->isDependentType(); +      if (!IsDependent) { +        for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent()) +          if (DeclContext *Ctx = DepScope->getEntity()) { +            IsDependent = Ctx->isDependentContext(); +            break; +          } +      } + +      if (IsDependent) +        Results.AddResult(CodeCompletionResult("template")); +    } +  } +} +  void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,                                             SourceLocation OpLoc, bool IsArrow,                                             bool IsBaseExprStatement) { @@ -3879,8 +3914,6 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,    if (ConvertedBase.isInvalid())      return;    Base = ConvertedBase.get(); - -  typedef CodeCompletionResult Result;    QualType BaseType = Base->getType(); @@ -3915,34 +3948,18 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,                          &ResultBuilder::IsMember);    Results.EnterNewScope();    if (const RecordType *Record = BaseType->getAs<RecordType>()) { -    // Indicate that we are performing a member access, and the cv-qualifiers -    // for the base object type. -    Results.setObjectTypeQualifiers(BaseType.getQualifiers()); -     -    // Access to a C/C++ class, struct, or union. -    Results.allowNestedNameSpecifiers(); -    CodeCompletionDeclConsumer Consumer(Results, CurContext); -    LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer, -                       CodeCompleter->includeGlobals()); - -    if (getLangOpts().CPlusPlus) { -      if (!Results.empty()) { -        // The "template" keyword can follow "->" or "." in the grammar. -        // However, we only want to suggest the template keyword if something -        // is dependent. -        bool IsDependent = BaseType->isDependentType(); -        if (!IsDependent) { -          for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent()) -            if (DeclContext *Ctx = DepScope->getEntity()) { -              IsDependent = Ctx->isDependentContext(); -              break; -            } -        } - -        if (IsDependent) -          Results.AddResult(Result("template")); -      } -    } +    AddRecordMembersCompletionResults(*this, Results, S, BaseType, +                                      Record->getDecl()); +  } else if (const auto *TST = BaseType->getAs<TemplateSpecializationType>()) { +    TemplateName TN = TST->getTemplateName(); +    if (const auto *TD = +            dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) { +      CXXRecordDecl *RD = TD->getTemplatedDecl(); +      AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD); +    } +  } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) { +    if (auto *RD = ICNT->getDecl()) +      AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD);    } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {      // Objective-C property reference.      AddedPropertiesSet AddedProperties; @@ -7811,6 +7828,23 @@ void Sema::CodeCompleteNaturalLanguage() {                              nullptr, 0);  } +void Sema::CodeCompleteAvailabilityPlatformName() { +  ResultBuilder Results(*this, CodeCompleter->getAllocator(), +                        CodeCompleter->getCodeCompletionTUInfo(), +                        CodeCompletionContext::CCC_Other); +  Results.EnterNewScope(); +  static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"}; +  for (const char *Platform : llvm::makeArrayRef(Platforms)) { +    Results.AddResult(CodeCompletionResult(Platform)); +    Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString( +        Twine(Platform) + "ApplicationExtension"))); +  } +  Results.ExitScope(); +  HandleCodeCompleteResults(this, CodeCompleter, +                            CodeCompletionContext::CCC_Other, Results.data(), +                            Results.size()); +} +  void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,                                         CodeCompletionTUInfo &CCTUInfo,                   SmallVectorImpl<CodeCompletionResult> &Results) { diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp index 2612023f59db..2e069a9defaa 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -64,22 +64,45 @@ namespace {  class TypeNameValidatorCCC : public CorrectionCandidateCallback {   public: -  TypeNameValidatorCCC(bool AllowInvalid, bool WantClass=false, -                       bool AllowTemplates=false) -      : AllowInvalidDecl(AllowInvalid), WantClassName(WantClass), -        AllowTemplates(AllowTemplates) { -    WantExpressionKeywords = false; -    WantCXXNamedCasts = false; -    WantRemainingKeywords = false; +   TypeNameValidatorCCC(bool AllowInvalid, bool WantClass = false, +                        bool AllowTemplates = false, +                        bool AllowNonTemplates = true) +       : AllowInvalidDecl(AllowInvalid), WantClassName(WantClass), +         AllowTemplates(AllowTemplates), AllowNonTemplates(AllowNonTemplates) { +     WantExpressionKeywords = false; +     WantCXXNamedCasts = false; +     WantRemainingKeywords = false;    }    bool ValidateCandidate(const TypoCorrection &candidate) override {      if (NamedDecl *ND = candidate.getCorrectionDecl()) { +      if (!AllowInvalidDecl && ND->isInvalidDecl()) +        return false; + +      if (getAsTypeTemplateDecl(ND)) +        return AllowTemplates; +        bool IsType = isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND); -      bool AllowedTemplate = AllowTemplates && getAsTypeTemplateDecl(ND); -      return (IsType || AllowedTemplate) && -             (AllowInvalidDecl || !ND->isInvalidDecl()); +      if (!IsType) +        return false; + +      if (AllowNonTemplates) +        return true; + +      // An injected-class-name of a class template (specialization) is valid +      // as a template or as a non-template. +      if (AllowTemplates) { +        auto *RD = dyn_cast<CXXRecordDecl>(ND); +        if (!RD || !RD->isInjectedClassName()) +          return false; +        RD = cast<CXXRecordDecl>(RD->getDeclContext()); +        return RD->getDescribedClassTemplate() || +               isa<ClassTemplateSpecializationDecl>(RD); +      } + +      return false;      } +      return !WantClassName && candidate.isKeyword();    } @@ -87,6 +110,7 @@ class TypeNameValidatorCCC : public CorrectionCandidateCallback {    bool AllowInvalidDecl;    bool WantClassName;    bool AllowTemplates; +  bool AllowNonTemplates;  };  } // end anonymous namespace @@ -627,7 +651,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,                                     Scope *S,                                     CXXScopeSpec *SS,                                     ParsedType &SuggestedType, -                                   bool AllowClassTemplates) { +                                   bool IsTemplateName) {    // Don't report typename errors for editor placeholders.    if (II->isEditorPlaceholder())      return; @@ -639,28 +663,41 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,    if (TypoCorrection Corrected =            CorrectTypo(DeclarationNameInfo(II, IILoc), LookupOrdinaryName, S, SS,                        llvm::make_unique<TypeNameValidatorCCC>( -                          false, false, AllowClassTemplates), +                          false, false, IsTemplateName, !IsTemplateName),                        CTK_ErrorRecovery)) { +    // FIXME: Support error recovery for the template-name case. +    bool CanRecover = !IsTemplateName;      if (Corrected.isKeyword()) {        // We corrected to a keyword. -      diagnoseTypo(Corrected, PDiag(diag::err_unknown_typename_suggest) << II); +      diagnoseTypo(Corrected, +                   PDiag(IsTemplateName ? diag::err_no_template_suggest +                                        : diag::err_unknown_typename_suggest) +                       << II);        II = Corrected.getCorrectionAsIdentifierInfo();      } else {        // We found a similarly-named type or interface; suggest that.        if (!SS || !SS->isSet()) {          diagnoseTypo(Corrected, -                     PDiag(diag::err_unknown_typename_suggest) << II); +                     PDiag(IsTemplateName ? diag::err_no_template_suggest +                                          : diag::err_unknown_typename_suggest) +                         << II, CanRecover);        } else if (DeclContext *DC = computeDeclContext(*SS, false)) {          std::string CorrectedStr(Corrected.getAsString(getLangOpts()));          bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&                                  II->getName().equals(CorrectedStr);          diagnoseTypo(Corrected, -                     PDiag(diag::err_unknown_nested_typename_suggest) -                       << II << DC << DroppedSpecifier << SS->getRange()); +                     PDiag(IsTemplateName +                               ? diag::err_no_member_template_suggest +                               : diag::err_unknown_nested_typename_suggest) +                         << II << DC << DroppedSpecifier << SS->getRange(), +                     CanRecover);        } else {          llvm_unreachable("could not have corrected a typo here");        } +      if (!CanRecover) +        return; +        CXXScopeSpec tmpSS;        if (Corrected.getCorrectionSpecifier())          tmpSS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(), @@ -675,7 +712,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,      return;    } -  if (getLangOpts().CPlusPlus) { +  if (getLangOpts().CPlusPlus && !IsTemplateName) {      // See if II is a class template that the user forgot to pass arguments to.      UnqualifiedId Name;      Name.setIdentifier(II, IILoc); @@ -700,10 +737,13 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,    // (struct, union, enum) from Parser::ParseImplicitInt here, instead?    if (!SS || (!SS->isSet() && !SS->isInvalid())) -    Diag(IILoc, diag::err_unknown_typename) << II; +    Diag(IILoc, IsTemplateName ? diag::err_no_template +                               : diag::err_unknown_typename) +        << II;    else if (DeclContext *DC = computeDeclContext(*SS, false)) -    Diag(IILoc, diag::err_typename_nested_not_found) -      << II << DC << SS->getRange(); +    Diag(IILoc, IsTemplateName ? diag::err_no_member_template +                               : diag::err_typename_nested_not_found) +        << II << DC << SS->getRange();    else if (isDependentScopeSpecifier(*SS)) {      unsigned DiagID = diag::err_typename_missing;      if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S)) @@ -1488,6 +1528,11 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {      if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)        return false; +    // A non-out-of-line declaration of a member specialization was implicitly +    // instantiated; it's the out-of-line declaration that we're interested in. +    if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization && +        FD->getMemberSpecializationInfo() && !FD->isOutOfLine()) +      return false;      if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {        if (MD->isVirtual() || IsDisallowedCopyOrAssign(MD)) @@ -1514,6 +1559,10 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {      if (VD->isStaticDataMember() &&          VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)        return false; +    if (VD->isStaticDataMember() && +        VD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization && +        VD->getMemberSpecializationInfo() && !VD->isOutOfLine()) +      return false;      if (VD->isInline() && !isMainFileLoc(*this, VD->getLocation()))        return false; @@ -1972,7 +2021,7 @@ bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {      Diag(New->getLocation(), diag::err_redefinition_variably_modified_typedef)        << Kind << NewType;      if (Old->getLocation().isValid()) -      Diag(Old->getLocation(), diag::note_previous_definition); +      notePreviousDefinition(Old->getLocation(), New->getLocation());      New->setInvalidDecl();      return true;    } @@ -1985,7 +2034,7 @@ bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {      Diag(New->getLocation(), diag::err_redefinition_different_typedef)        << Kind << NewType << OldType;      if (Old->getLocation().isValid()) -      Diag(Old->getLocation(), diag::note_previous_definition); +      notePreviousDefinition(Old->getLocation(), New->getLocation());      New->setInvalidDecl();      return true;    } @@ -2052,7 +2101,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,      NamedDecl *OldD = OldDecls.getRepresentativeDecl();      if (OldD->getLocation().isValid()) -      Diag(OldD->getLocation(), diag::note_previous_definition); +      notePreviousDefinition(OldD->getLocation(), New->getLocation());      return New->setInvalidDecl();    } @@ -2078,7 +2127,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,          New->setTypeSourceInfo(OldTD->getTypeSourceInfo());        // Make the old tag definition visible. -      makeMergedDefinitionVisible(Hidden, NewTag->getLocation()); +      makeMergedDefinitionVisible(Hidden);        // If this was an unscoped enumeration, yank all of its enumerators        // out of the scope. @@ -2144,7 +2193,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,      Diag(New->getLocation(), diag::err_redefinition)        << New->getDeclName(); -    Diag(Old->getLocation(), diag::note_previous_definition); +    notePreviousDefinition(Old->getLocation(), New->getLocation());      return New->setInvalidDecl();    } @@ -2165,7 +2214,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,    Diag(New->getLocation(), diag::ext_redefinition_of_typedef)      << New->getDeclName(); -  Diag(Old->getLocation(), diag::note_previous_definition); +  notePreviousDefinition(Old->getLocation(), New->getLocation());  }  /// DeclhasAttr - returns true if decl Declaration already has the target @@ -2452,7 +2501,10 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {                              ? diag::err_alias_after_tentative                              : diag::err_redefinition;          S.Diag(VD->getLocation(), Diag) << VD->getDeclName(); -        S.Diag(Def->getLocation(), diag::note_previous_definition); +        if (Diag == diag::err_redefinition) +          S.notePreviousDefinition(Def->getLocation(), VD->getLocation()); +        else +          S.Diag(Def->getLocation(), diag::note_previous_definition);          VD->setInvalidDecl();        }        ++I; @@ -2839,7 +2891,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,      } else {        Diag(New->getLocation(), diag::err_redefinition_different_kind)          << New->getDeclName(); -      Diag(OldD->getLocation(), diag::note_previous_definition); +      notePreviousDefinition(OldD->getLocation(), New->getLocation());        return true;      }    } @@ -2876,7 +2928,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,        !Old->hasAttr<InternalLinkageAttr>()) {      Diag(New->getLocation(), diag::err_internal_linkage_redeclaration)          << New->getDeclName(); -    Diag(Old->getLocation(), diag::note_previous_definition); +    notePreviousDefinition(Old->getLocation(), New->getLocation());      New->dropAttr<InternalLinkageAttr>();    } @@ -3604,9 +3656,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {    }    if (!Old) {      Diag(New->getLocation(), diag::err_redefinition_different_kind) -      << New->getDeclName(); -    Diag(Previous.getRepresentativeDecl()->getLocation(), -         diag::note_previous_definition); +        << New->getDeclName(); +    notePreviousDefinition(Previous.getRepresentativeDecl()->getLocation(), +                           New->getLocation());      return New->setInvalidDecl();    } @@ -3635,7 +3687,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {        Old->getStorageClass() == SC_None &&        !Old->hasAttr<WeakImportAttr>()) {      Diag(New->getLocation(), diag::warn_weak_import) << New->getDeclName(); -    Diag(Old->getLocation(), diag::note_previous_definition); +    notePreviousDefinition(Old->getLocation(), New->getLocation());      // Remove weak_import attribute on new declaration.      New->dropAttr<WeakImportAttr>();    } @@ -3644,7 +3696,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {        !Old->hasAttr<InternalLinkageAttr>()) {      Diag(New->getLocation(), diag::err_internal_linkage_redeclaration)          << New->getDeclName(); -    Diag(Old->getLocation(), diag::note_previous_definition); +    notePreviousDefinition(Old->getLocation(), New->getLocation());      New->dropAttr<InternalLinkageAttr>();    } @@ -3801,6 +3853,67 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {      New->setImplicitlyInline();  } +void Sema::notePreviousDefinition(SourceLocation Old, SourceLocation New) { +  SourceManager &SrcMgr = getSourceManager(); +  auto FNewDecLoc = SrcMgr.getDecomposedLoc(New); +  auto FOldDecLoc = SrcMgr.getDecomposedLoc(Old); +  auto *FNew = SrcMgr.getFileEntryForID(FNewDecLoc.first); +  auto *FOld = SrcMgr.getFileEntryForID(FOldDecLoc.first); +  auto &HSI = PP.getHeaderSearchInfo(); +  StringRef HdrFilename = SrcMgr.getFilename(SrcMgr.getSpellingLoc(Old)); + +  auto noteFromModuleOrInclude = [&](SourceLocation &Loc, +                                     SourceLocation &IncLoc) -> bool { +    Module *Mod = nullptr; +    // Redefinition errors with modules are common with non modular mapped +    // headers, example: a non-modular header H in module A that also gets +    // included directly in a TU. Pointing twice to the same header/definition +    // is confusing, try to get better diagnostics when modules is on. +    if (getLangOpts().Modules) { +      auto ModLoc = SrcMgr.getModuleImportLoc(Old); +      if (!ModLoc.first.isInvalid()) +        Mod = HSI.getModuleMap().inferModuleFromLocation( +            FullSourceLoc(Loc, SrcMgr)); +    } + +    if (IncLoc.isValid()) { +      if (Mod) { +        Diag(IncLoc, diag::note_redefinition_modules_same_file) +            << HdrFilename.str() << Mod->getFullModuleName(); +        if (!Mod->DefinitionLoc.isInvalid()) +          Diag(Mod->DefinitionLoc, diag::note_defined_here) +              << Mod->getFullModuleName(); +      } else { +        Diag(IncLoc, diag::note_redefinition_include_same_file) +            << HdrFilename.str(); +      } +      return true; +    } + +    return false; +  }; + +  // Is it the same file and same offset? Provide more information on why +  // this leads to a redefinition error. +  bool EmittedDiag = false; +  if (FNew == FOld && FNewDecLoc.second == FOldDecLoc.second) { +    SourceLocation OldIncLoc = SrcMgr.getIncludeLoc(FOldDecLoc.first); +    SourceLocation NewIncLoc = SrcMgr.getIncludeLoc(FNewDecLoc.first); +    EmittedDiag = noteFromModuleOrInclude(Old, OldIncLoc); +    EmittedDiag |= noteFromModuleOrInclude(New, NewIncLoc); + +    // If the header has no guards, emit a note suggesting one. +    if (FOld && !HSI.isFileMultipleIncludeGuarded(FOld)) +      Diag(Old, diag::note_use_ifdef_guards); + +    if (EmittedDiag) +      return; +  } + +  // Redefinition coming from different files or couldn't do better above. +  Diag(Old, diag::note_previous_definition); +} +  /// We've just determined that \p Old and \p New both appear to be definitions  /// of the same variable. Either diagnose or fix the problem.  bool Sema::checkVarDeclRedefinition(VarDecl *Old, VarDecl *New) { @@ -3816,12 +3929,12 @@ bool Sema::checkVarDeclRedefinition(VarDecl *Old, VarDecl *New) {      // Make the canonical definition visible.      if (auto *OldTD = Old->getDescribedVarTemplate()) -      makeMergedDefinitionVisible(OldTD, New->getLocation()); -    makeMergedDefinitionVisible(Old, New->getLocation()); +      makeMergedDefinitionVisible(OldTD); +    makeMergedDefinitionVisible(Old);      return false;    } else {      Diag(New->getLocation(), diag::err_redefinition) << New; -    Diag(Old->getLocation(), diag::note_previous_definition); +    notePreviousDefinition(Old->getLocation(), New->getLocation());      New->setInvalidDecl();      return true;    } @@ -6706,6 +6819,9 @@ NamedDecl *Sema::ActOnVariableDeclarator(      return NewTemplate;    } +  if (IsMemberSpecialization && !NewVD->isInvalidDecl()) +    CompleteMemberSpecialization(NewVD, Previous); +    return NewVD;  } @@ -8919,12 +9035,17 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,      }    } +  MarkUnusedFileScopedDecl(NewFD); +    if (getLangOpts().CPlusPlus) {      if (FunctionTemplate) {        if (NewFD->isInvalidDecl())          FunctionTemplate->setInvalidDecl();        return FunctionTemplate;      } + +    if (isMemberSpecialization && !NewFD->isInvalidDecl()) +      CompleteMemberSpecialization(NewFD, Previous);    }    if (NewFD->hasAttr<OpenCLKernelAttr>()) { @@ -8964,8 +9085,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,      }    } -  MarkUnusedFileScopedDecl(NewFD); -    // Here we have an function template explicit specialization at class scope.    // The actually specialization will be postponed to template instatiation    // time via the ClassScopeFunctionSpecializationDecl node. @@ -9182,7 +9301,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,          if (OldTemplateDecl->getTemplatedDecl()->isDeleted()) {            FunctionDecl *const OldTemplatedDecl =                OldTemplateDecl->getTemplatedDecl(); +          // FIXME: This assert will not hold in the presence of modules.            assert(OldTemplatedDecl->getCanonicalDecl() == OldTemplatedDecl); +          // FIXME: We need an update record for this AST mutation.            OldTemplatedDecl->setDeletedAsWritten(false);          }        } @@ -10273,23 +10394,36 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {    VDecl->setInit(Init);    if (VDecl->isLocalVarDecl()) { +    // Don't check the initializer if the declaration is malformed. +    if (VDecl->isInvalidDecl()) { +      // do nothing + +    // OpenCL v1.2 s6.5.3: __constant locals must be constant-initialized. +    // This is true even in OpenCL C++. +    } else if (VDecl->getType().getAddressSpace() == LangAS::opencl_constant) { +      CheckForConstantInitializer(Init, DclT); + +    // Otherwise, C++ does not restrict the initializer. +    } else if (getLangOpts().CPlusPlus) { +      // do nothing +      // C99 6.7.8p4: All the expressions in an initializer for an object that has      // static storage duration shall be constant expressions or string literals. -    // C++ does not have this restriction. -    if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl()) { +    } else if (VDecl->getStorageClass() == SC_Static) { +      CheckForConstantInitializer(Init, DclT); + +    // C89 is stricter than C99 for aggregate initializers. +    // C89 6.5.7p3: All the expressions [...] in an initializer list +    // for an object that has aggregate or union type shall be +    // constant expressions. +    } else if (!getLangOpts().C99 && VDecl->getType()->isAggregateType() && +               isa<InitListExpr>(Init)) {        const Expr *Culprit; -      if (VDecl->getStorageClass() == SC_Static) -        CheckForConstantInitializer(Init, DclT); -      // C89 is stricter than C99 for non-static aggregate types. -      // C89 6.5.7p3: All the expressions [...] in an initializer list -      // for an object that has aggregate or union type shall be -      // constant expressions. -      else if (!getLangOpts().C99 && VDecl->getType()->isAggregateType() && -               isa<InitListExpr>(Init) && -               !Init->isConstantInitializer(Context, false, &Culprit)) +      if (!Init->isConstantInitializer(Context, false, &Culprit)) {          Diag(Culprit->getExprLoc(),               diag::ext_aggregate_init_not_constant)            << Culprit->getSourceRange(); +      }      }    } else if (VDecl->isStaticDataMember() && !VDecl->isInline() &&               VDecl->getLexicalDeclContext()->isRecord()) { @@ -11023,8 +11157,7 @@ static bool hasDependentAlignment(VarDecl *VD) {  /// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform  /// any semantic actions necessary after any initializer has been attached. -void -Sema::FinalizeDeclaration(Decl *ThisDecl) { +void Sema::FinalizeDeclaration(Decl *ThisDecl) {    // Note that we are no longer parsing the initializer for this declaration.    ParsingInitForAutoVars.erase(ThisDecl); @@ -11189,9 +11322,8 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {    if (DC->getRedeclContext()->isFileContext() && VD->isExternallyVisible())      AddPushedVisibilityAttribute(VD); -  // FIXME: Warn on unused templates. -  if (VD->isFileVarDecl() && !VD->getDescribedVarTemplate() && -      !isa<VarTemplatePartialSpecializationDecl>(VD)) +  // FIXME: Warn on unused var template partial specializations. +  if (VD->isFileVarDecl() && !isa<VarTemplatePartialSpecializationDecl>(VD))      MarkUnusedFileScopedDecl(VD);    // Now we have parsed the initializer and can update the table of magic @@ -11765,9 +11897,8 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,         Definition->getNumTemplateParameterLists())) {      SkipBody->ShouldSkip = true;      if (auto *TD = Definition->getDescribedFunctionTemplate()) -      makeMergedDefinitionVisible(TD, FD->getLocation()); -    makeMergedDefinitionVisible(const_cast<FunctionDecl*>(Definition), -                                FD->getLocation()); +      makeMergedDefinitionVisible(TD); +    makeMergedDefinitionVisible(const_cast<FunctionDecl*>(Definition));      return;    } @@ -13421,7 +13552,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,                  // we already have. Make the existing definition visible and                  // use it in place of this one.                  SkipBody->ShouldSkip = true; -                makeMergedDefinitionVisible(Hidden, KWLoc); +                makeMergedDefinitionVisible(Hidden);                  return Def;                } else if (!IsExplicitSpecializationAfterInstantiation) {                  // A redeclaration in function prototype scope in C isn't @@ -13430,7 +13561,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,                    Diag(NameLoc, diag::warn_redefinition_in_param_list) << Name;                  else                    Diag(NameLoc, diag::err_redefinition) << Name; -                Diag(Def->getLocation(), diag::note_previous_definition); +                notePreviousDefinition(Def->getLocation(), +                                       NameLoc.isValid() ? NameLoc : KWLoc);                  // If this is a redefinition, recover by making this                  // struct be anonymous, which will make any later                  // references get the previous definition. @@ -13520,7 +13652,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,          // The tag name clashes with something else in the target scope,          // issue an error and recover by making this tag be anonymous.          Diag(NameLoc, diag::err_redefinition_different_kind) << Name; -        Diag(PrevDecl->getLocation(), diag::note_previous_definition); +        notePreviousDefinition(PrevDecl->getLocation(), NameLoc);          Name = nullptr;          Invalid = true;        } @@ -13753,6 +13885,9 @@ CreateNewDecl:    // record.    AddPushedVisibilityAttribute(New); +  if (isMemberSpecialization && !New->isInvalidDecl()) +    CompleteMemberSpecialization(New, Previous); +    OwnedDecl = true;    // In C++, don't return an invalid declaration. We can't recover well from    // the cases where we make the type anonymous. @@ -15221,7 +15356,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,          Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id;        else          Diag(IdLoc, diag::err_redefinition) << Id; -      Diag(PrevDecl->getLocation(), diag::note_previous_definition); +      notePreviousDefinition(PrevDecl->getLocation(), IdLoc);        return nullptr;      }    } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp index 97d273f6ddb6..3de792e4e406 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -7230,6 +7230,13 @@ public:          SemaRef.Context.getTargetInfo().getPlatformMinVersion());    } +  bool TraverseDecl(Decl *D) { +    // Avoid visiting nested functions to prevent duplicate warnings. +    if (!D || isa<FunctionDecl>(D)) +      return true; +    return Base::TraverseDecl(D); +  } +    bool TraverseStmt(Stmt *S) {      if (!S)        return true; @@ -7243,6 +7250,8 @@ public:    bool TraverseIfStmt(IfStmt *If); +  bool TraverseLambdaExpr(LambdaExpr *E) { return true; } +    bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) {      if (ObjCMethodDecl *D = Msg->getMethodDecl())        DiagnoseDeclAvailability( @@ -7346,7 +7355,9 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(      llvm::raw_string_ostream FixItOS(FixItString);      FixItOS << "if (" << (SemaRef.getLangOpts().ObjC1 ? "@available"                                                        : "__builtin_available") -            << "(" << SemaRef.getASTContext().getTargetInfo().getPlatformName() +            << "(" +            << AvailabilityAttr::getPlatformNameSourceSpelling( +                   SemaRef.getASTContext().getTargetInfo().getPlatformName())              << " " << Introduced.getAsString() << ", *)) {\n"              << Indentation << ExtraIndentation;      FixitDiag << FixItHint::CreateInsertion(IfInsertionLoc, FixItOS.str()); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp index 849e978e2d86..14efc9672061 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -5277,6 +5277,9 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,      // We aren't supposed to apply this logic if there's an '&' involved.      if (!find.HasFormOfMemberPointer) { +      if (Expr::hasAnyTypeDependentArguments(ArgExprs)) +        return new (Context) CallExpr( +            Context, Fn, ArgExprs, Context.DependentTy, VK_RValue, RParenLoc);        OverloadExpr *ovl = find.Expression;        if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(ovl))          return BuildOverloadedCallExpr( @@ -8028,6 +8031,33 @@ QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS,    return QualType();  } +// Diagnose cases where a scalar was implicitly converted to a vector and +// diagnose the underlying types. Otherwise, diagnose the error +// as invalid vector logical operands for non-C++ cases. +QualType Sema::InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS, +                                            ExprResult &RHS) { +  QualType LHSType = LHS.get()->IgnoreImpCasts()->getType(); +  QualType RHSType = RHS.get()->IgnoreImpCasts()->getType(); + +  bool LHSNatVec = LHSType->isVectorType(); +  bool RHSNatVec = RHSType->isVectorType(); + +  if (!(LHSNatVec && RHSNatVec)) { +    Expr *Vector = LHSNatVec ? LHS.get() : RHS.get(); +    Expr *NonVector = !LHSNatVec ? LHS.get() : RHS.get(); +    Diag(Loc, diag::err_typecheck_logical_vector_expr_gnu_cpp_restrict) +        << 0 << Vector->getType() << NonVector->IgnoreImpCasts()->getType() +        << Vector->getSourceRange(); +    return QualType(); +  } + +  Diag(Loc, diag::err_typecheck_logical_vector_expr_gnu_cpp_restrict) +      << 1 << LHSType << RHSType << LHS.get()->getSourceRange() +      << RHS.get()->getSourceRange(); + +  return QualType(); +} +  /// Try to convert a value of non-vector type to a vector type by converting  /// the type to the element type of the vector and then performing a splat.  /// If the language is OpenCL, we only use conversions that promote scalar @@ -8075,6 +8105,162 @@ static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar,    return false;  } +/// Test if a (constant) integer Int can be casted to another integer type +/// IntTy without losing precision. +static bool canConvertIntToOtherIntTy(Sema &S, ExprResult *Int, +                                      QualType OtherIntTy) { +  QualType IntTy = Int->get()->getType().getUnqualifiedType(); + +  // Reject cases where the value of the Int is unknown as that would +  // possibly cause truncation, but accept cases where the scalar can be +  // demoted without loss of precision. +  llvm::APSInt Result; +  bool CstInt = Int->get()->EvaluateAsInt(Result, S.Context); +  int Order = S.Context.getIntegerTypeOrder(OtherIntTy, IntTy); +  bool IntSigned = IntTy->hasSignedIntegerRepresentation(); +  bool OtherIntSigned = OtherIntTy->hasSignedIntegerRepresentation(); + +  if (CstInt) { +    // If the scalar is constant and is of a higher order and has more active +    // bits that the vector element type, reject it. +    unsigned NumBits = IntSigned +                           ? (Result.isNegative() ? Result.getMinSignedBits() +                                                  : Result.getActiveBits()) +                           : Result.getActiveBits(); +    if (Order < 0 && S.Context.getIntWidth(OtherIntTy) < NumBits) +      return true; + +    // If the signedness of the scalar type and the vector element type +    // differs and the number of bits is greater than that of the vector +    // element reject it. +    return (IntSigned != OtherIntSigned && +            NumBits > S.Context.getIntWidth(OtherIntTy)); +  } + +  // Reject cases where the value of the scalar is not constant and it's +  // order is greater than that of the vector element type. +  return (Order < 0); +} + +/// Test if a (constant) integer Int can be casted to floating point type +/// FloatTy without losing precision. +static bool canConvertIntTyToFloatTy(Sema &S, ExprResult *Int, +                                     QualType FloatTy) { +  QualType IntTy = Int->get()->getType().getUnqualifiedType(); + +  // Determine if the integer constant can be expressed as a floating point +  // number of the appropiate type. +  llvm::APSInt Result; +  bool CstInt = Int->get()->EvaluateAsInt(Result, S.Context); +  uint64_t Bits = 0; +  if (CstInt) { +    // Reject constants that would be truncated if they were converted to +    // the floating point type. Test by simple to/from conversion. +    // FIXME: Ideally the conversion to an APFloat and from an APFloat +    //        could be avoided if there was a convertFromAPInt method +    //        which could signal back if implicit truncation occurred. +    llvm::APFloat Float(S.Context.getFloatTypeSemantics(FloatTy)); +    Float.convertFromAPInt(Result, IntTy->hasSignedIntegerRepresentation(), +                           llvm::APFloat::rmTowardZero); +    llvm::APSInt ConvertBack(S.Context.getIntWidth(IntTy), +                             !IntTy->hasSignedIntegerRepresentation()); +    bool Ignored = false; +    Float.convertToInteger(ConvertBack, llvm::APFloat::rmNearestTiesToEven, +                           &Ignored); +    if (Result != ConvertBack) +      return true; +  } else { +    // Reject types that cannot be fully encoded into the mantissa of +    // the float. +    Bits = S.Context.getTypeSize(IntTy); +    unsigned FloatPrec = llvm::APFloat::semanticsPrecision( +        S.Context.getFloatTypeSemantics(FloatTy)); +    if (Bits > FloatPrec) +      return true; +  } + +  return false; +} + +/// Attempt to convert and splat Scalar into a vector whose types matches +/// Vector following GCC conversion rules. The rule is that implicit +/// conversion can occur when Scalar can be casted to match Vector's element +/// type without causing truncation of Scalar. +static bool tryGCCVectorConvertAndSplat(Sema &S, ExprResult *Scalar, +                                        ExprResult *Vector) { +  QualType ScalarTy = Scalar->get()->getType().getUnqualifiedType(); +  QualType VectorTy = Vector->get()->getType().getUnqualifiedType(); +  const VectorType *VT = VectorTy->getAs<VectorType>(); + +  assert(!isa<ExtVectorType>(VT) && +         "ExtVectorTypes should not be handled here!"); + +  QualType VectorEltTy = VT->getElementType(); + +  // Reject cases where the vector element type or the scalar element type are +  // not integral or floating point types. +  if (!VectorEltTy->isArithmeticType() || !ScalarTy->isArithmeticType()) +    return true; + +  // The conversion to apply to the scalar before splatting it, +  // if necessary. +  CastKind ScalarCast = CK_NoOp; + +  // Accept cases where the vector elements are integers and the scalar is +  // an integer. +  // FIXME: Notionally if the scalar was a floating point value with a precise +  //        integral representation, we could cast it to an appropriate integer +  //        type and then perform the rest of the checks here. GCC will perform +  //        this conversion in some cases as determined by the input language. +  //        We should accept it on a language independent basis. +  if (VectorEltTy->isIntegralType(S.Context) && +      ScalarTy->isIntegralType(S.Context) && +      S.Context.getIntegerTypeOrder(VectorEltTy, ScalarTy)) { + +    if (canConvertIntToOtherIntTy(S, Scalar, VectorEltTy)) +      return true; + +    ScalarCast = CK_IntegralCast; +  } else if (VectorEltTy->isRealFloatingType()) { +    if (ScalarTy->isRealFloatingType()) { + +      // Reject cases where the scalar type is not a constant and has a higher +      // Order than the vector element type. +      llvm::APFloat Result(0.0); +      bool CstScalar = Scalar->get()->EvaluateAsFloat(Result, S.Context); +      int Order = S.Context.getFloatingTypeOrder(VectorEltTy, ScalarTy); +      if (!CstScalar && Order < 0) +        return true; + +      // If the scalar cannot be safely casted to the vector element type, +      // reject it. +      if (CstScalar) { +        bool Truncated = false; +        Result.convert(S.Context.getFloatTypeSemantics(VectorEltTy), +                       llvm::APFloat::rmNearestTiesToEven, &Truncated); +        if (Truncated) +          return true; +      } + +      ScalarCast = CK_FloatingCast; +    } else if (ScalarTy->isIntegralType(S.Context)) { +      if (canConvertIntTyToFloatTy(S, Scalar, VectorEltTy)) +        return true; + +      ScalarCast = CK_IntegralToFloating; +    } else +      return true; +  } + +  // Adjust scalar if desired. +  if (Scalar) { +    if (ScalarCast != CK_NoOp) +      *Scalar = S.ImpCastExprToType(Scalar->get(), VectorEltTy, ScalarCast); +    *Scalar = S.ImpCastExprToType(Scalar->get(), VectorTy, CK_VectorSplat); +  } +  return false; +} +  QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,                                     SourceLocation Loc, bool IsCompAssign,                                     bool AllowBothBool, @@ -8143,19 +8329,29 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,      }    } -  // If there's an ext-vector type and a scalar, try to convert the scalar to +  // If there's a vector type and a scalar, try to convert the scalar to    // the vector element type and splat. -  // FIXME: this should also work for regular vector types as supported in GCC. -  if (!RHSVecType && isa<ExtVectorType>(LHSVecType)) { -    if (!tryVectorConvertAndSplat(*this, &RHS, RHSType, -                                  LHSVecType->getElementType(), LHSType)) -      return LHSType; +  if (!RHSVecType) { +    if (isa<ExtVectorType>(LHSVecType)) { +      if (!tryVectorConvertAndSplat(*this, &RHS, RHSType, +                                    LHSVecType->getElementType(), LHSType)) +        return LHSType; +    } else { +      if (!tryGCCVectorConvertAndSplat(*this, &RHS, &LHS)) +        return LHSType; +    }    } -  if (!LHSVecType && isa<ExtVectorType>(RHSVecType)) { -    if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? nullptr : &LHS), -                                  LHSType, RHSVecType->getElementType(), -                                  RHSType)) -      return RHSType; +  if (!LHSVecType) { +    if (isa<ExtVectorType>(RHSVecType)) { +      if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? nullptr : &LHS), +                                    LHSType, RHSVecType->getElementType(), +                                    RHSType)) +        return RHSType; +    } else { +      if (LHS.get()->getValueKind() == VK_LValue || +          !tryGCCVectorConvertAndSplat(*this, &LHS, &RHS)) +        return RHSType; +    }    }    // FIXME: The code below also handles conversion between vectors and @@ -8208,6 +8404,22 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,      return QualType();    } + +  // If there is a vector type that is not a ExtVector and a scalar, we reach +  // this point if scalar could not be converted to the vector's element type +  // without truncation. +  if ((RHSVecType && !isa<ExtVectorType>(RHSVecType)) || +      (LHSVecType && !isa<ExtVectorType>(LHSVecType))) { +    QualType Scalar = LHSVecType ? RHSType : LHSType; +    QualType Vector = LHSVecType ? LHSType : RHSType; +    unsigned ScalarOrVector = LHSVecType && RHSVecType ? 1 : 0; +    Diag(Loc, +         diag::err_typecheck_vector_not_convertable_implict_truncation) +        << ScalarOrVector << Scalar << Vector; + +    return QualType(); +  } +    // Otherwise, use the generic diagnostic.    Diag(Loc, diag::err_typecheck_vector_not_convertable)      << LHSType << RHSType @@ -9827,6 +10039,12 @@ QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,    if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion < 120 &&        vType->hasFloatingRepresentation())      return InvalidOperands(Loc, LHS, RHS); +  // FIXME: The check for C++ here is for GCC compatibility. GCC rejects the +  //        usage of the logical operators && and || with vectors in C. This +  //        check could be notionally dropped. +  if (!getLangOpts().CPlusPlus && +      !(isa<ExtVectorType>(vType->getAs<VectorType>()))) +    return InvalidLogicalVectorOperands(Loc, LHS, RHS);    return GetSignedVectorType(LHS.get()->getType());  } @@ -11770,6 +11988,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,        resultType = GetSignedVectorType(resultType);        break;      } else { +      // FIXME: GCC's vector extension permits the usage of '!' with a vector +      //        type in C++. We should allow that here too.        return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)          << resultType << Input.get()->getSourceRange());      } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp index 9b88cddbc969..8500b748a3ec 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp @@ -4720,10 +4720,24 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,      // regard to cv-qualifiers.      const RecordType *lhsRecord = LhsT->getAs<RecordType>(); -    if (!lhsRecord) return false; -      const RecordType *rhsRecord = RhsT->getAs<RecordType>(); -    if (!rhsRecord) return false; +    if (!rhsRecord || !lhsRecord) { +      const ObjCObjectType *LHSObjTy = LhsT->getAs<ObjCObjectType>(); +      const ObjCObjectType *RHSObjTy = RhsT->getAs<ObjCObjectType>(); +      if (!LHSObjTy || !RHSObjTy) +        return false; + +      ObjCInterfaceDecl *BaseInterface = LHSObjTy->getInterface(); +      ObjCInterfaceDecl *DerivedInterface = RHSObjTy->getInterface(); +      if (!BaseInterface || !DerivedInterface) +        return false; + +      if (Self.RequireCompleteType( +              KeyLoc, RhsT, diag::err_incomplete_type_used_in_type_trait_expr)) +        return false; + +      return BaseInterface->isSuperClassOf(DerivedInterface); +    }      assert(Self.Context.hasSameUnqualifiedType(LhsT, RhsT)               == (lhsRecord == rhsRecord)); @@ -5342,6 +5356,15 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,    // C++11 [expr.cond]p1    //   The first expression is contextually converted to bool. +  // +  // FIXME; GCC's vector extension permits the use of a?b:c where the type of +  //        a is that of a integer vector with the same number of elements and +  //        size as the vectors of b and c. If one of either b or c is a scalar +  //        it is implicitly converted to match the type of the vector. +  //        Otherwise the expression is ill-formed. If both b and c are scalars, +  //        then b and c are checked and converted to the type of a if possible. +  //        Unlike the OpenCL ?: operator, the expression is evaluated as +  //        (a[0] != 0 ? b[0] : c[0], .. , a[n] != 0 ? b[n] : c[n]).    if (!Cond.get()->isTypeDependent()) {      ExprResult CondRes = CheckCXXBooleanCondition(Cond.get());      if (CondRes.isInvalid()) diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp index a44e9243e3c5..28581bad1a7a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp @@ -4241,8 +4241,7 @@ void Sema::diagnoseARCUnbridgedCast(Expr *e) {      castType = cast->getTypeAsWritten();      CCK = CCK_OtherCast;    } else { -    castType = cast->getType(); -    CCK = CCK_ImplicitConversion; +    llvm_unreachable("Unexpected ImplicitCastExpr");    }    ARCConversionTypeClass castACTC = diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp index d0f530010a0d..32024cb335dc 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp @@ -1209,7 +1209,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,    } else {      assert((ElemType->isRecordType() || ElemType->isVectorType() || -            ElemType->isClkEventT()) && "Unexpected type"); +            ElemType->isOpenCLSpecificType()) && "Unexpected type");      // C99 6.7.8p13:      // @@ -8296,8 +8296,46 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity,                                                             AllowExplicit);    InitializationSequence Seq(*this, Entity, Kind, InitE, TopLevelOfInitList); +  // Prevent infinite recursion when performing parameter copy-initialization. +  const bool ShouldTrackCopy = +      Entity.isParameterKind() && Seq.isConstructorInitialization(); +  if (ShouldTrackCopy) { +    if (llvm::find(CurrentParameterCopyTypes, Entity.getType()) != +        CurrentParameterCopyTypes.end()) { +      Seq.SetOverloadFailure( +          InitializationSequence::FK_ConstructorOverloadFailed, +          OR_No_Viable_Function); + +      // Try to give a meaningful diagnostic note for the problematic +      // constructor. +      const auto LastStep = Seq.step_end() - 1; +      assert(LastStep->Kind == +             InitializationSequence::SK_ConstructorInitialization); +      const FunctionDecl *Function = LastStep->Function.Function; +      auto Candidate = +          llvm::find_if(Seq.getFailedCandidateSet(), +                        [Function](const OverloadCandidate &Candidate) -> bool { +                          return Candidate.Viable && +                                 Candidate.Function == Function && +                                 Candidate.Conversions.size() > 0; +                        }); +      if (Candidate != Seq.getFailedCandidateSet().end() && +          Function->getNumParams() > 0) { +        Candidate->Viable = false; +        Candidate->FailureKind = ovl_fail_bad_conversion; +        Candidate->Conversions[0].setBad(BadConversionSequence::no_conversion, +                                         InitE, +                                         Function->getParamDecl(0)->getType()); +      } +    } +    CurrentParameterCopyTypes.push_back(Entity.getType()); +  } +    ExprResult Result = Seq.Perform(*this, Entity, Kind, InitE); +  if (ShouldTrackCopy) +    CurrentParameterCopyTypes.pop_back(); +    return Result;  } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp index ce76e14982db..c5b579a4b2e9 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp @@ -1382,8 +1382,8 @@ Module *Sema::getOwningModule(Decl *Entity) {    return M;  } -void Sema::makeMergedDefinitionVisible(NamedDecl *ND, SourceLocation Loc) { -  if (auto *M = PP.getModuleContainingLocation(Loc)) +void Sema::makeMergedDefinitionVisible(NamedDecl *ND) { +  if (auto *M = getCurrentModule())      Context.mergeDefinitionIntoModule(ND, M);    else      // We're not building a module; just make the definition visible. @@ -1393,7 +1393,7 @@ void Sema::makeMergedDefinitionVisible(NamedDecl *ND, SourceLocation Loc) {    // visible too. They're not (necessarily) within a mergeable DeclContext.    if (auto *TD = dyn_cast<TemplateDecl>(ND))      for (auto *Param : *TD->getTemplateParameters()) -      makeMergedDefinitionVisible(Param, Loc); +      makeMergedDefinitionVisible(Param);  }  /// \brief Find the module in which the given declaration was defined. @@ -3445,7 +3445,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,                                 bool QualifiedNameLookup,                                 bool InBaseClass,                                 VisibleDeclConsumer &Consumer, -                               VisibleDeclsRecord &Visited) { +                               VisibleDeclsRecord &Visited, +                               bool IncludeDependentBases = false) {    if (!Ctx)      return; @@ -3501,7 +3502,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,      ShadowContextRAII Shadow(Visited);      for (auto I : Ctx->using_directives()) {        LookupVisibleDecls(I->getNominatedNamespace(), Result, -                         QualifiedNameLookup, InBaseClass, Consumer, Visited); +                         QualifiedNameLookup, InBaseClass, Consumer, Visited, +                         IncludeDependentBases);      }    } @@ -3513,14 +3515,28 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,      for (const auto &B : Record->bases()) {        QualType BaseType = B.getType(); -      // Don't look into dependent bases, because name lookup can't look -      // there anyway. -      if (BaseType->isDependentType()) -        continue; - -      const RecordType *Record = BaseType->getAs<RecordType>(); -      if (!Record) -        continue; +      RecordDecl *RD; +      if (BaseType->isDependentType()) { +        if (!IncludeDependentBases) { +          // Don't look into dependent bases, because name lookup can't look +          // there anyway. +          continue; +        } +        const auto *TST = BaseType->getAs<TemplateSpecializationType>(); +        if (!TST) +          continue; +        TemplateName TN = TST->getTemplateName(); +        const auto *TD = +            dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()); +        if (!TD) +          continue; +        RD = TD->getTemplatedDecl(); +      } else { +        const auto *Record = BaseType->getAs<RecordType>(); +        if (!Record) +          continue; +        RD = Record->getDecl(); +      }        // FIXME: It would be nice to be able to determine whether referencing        // a particular member would be ambiguous. For example, given @@ -3543,8 +3559,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,        // Find results in this base class (and its bases).        ShadowContextRAII Shadow(Visited); -      LookupVisibleDecls(Record->getDecl(), Result, QualifiedNameLookup, -                         true, Consumer, Visited); +      LookupVisibleDecls(RD, Result, QualifiedNameLookup, true, Consumer, +                         Visited, IncludeDependentBases);      }    } @@ -3713,7 +3729,8 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,  void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,                                VisibleDeclConsumer &Consumer, -                              bool IncludeGlobalScope) { +                              bool IncludeGlobalScope, +                              bool IncludeDependentBases) {    LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);    Result.setAllowHidden(Consumer.includeHiddenDecls());    VisibleDeclsRecord Visited; @@ -3721,7 +3738,8 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,      Visited.visitedContext(Context.getTranslationUnitDecl());    ShadowContextRAII Shadow(Visited);    ::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true, -                       /*InBaseClass=*/false, Consumer, Visited); +                       /*InBaseClass=*/false, Consumer, Visited, +                       IncludeDependentBases);  }  /// LookupOrCreateLabel - Do a name lookup of a label with the specified name. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp index 782c377e3202..51794160278c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp @@ -11210,12 +11210,12 @@ Sema::resolveAddressOfOnlyViableOverloadCandidate(Expr *E,  /// \brief Given an overloaded function, tries to turn it into a non-overloaded  /// function reference using resolveAddressOfOnlyViableOverloadCandidate. This  /// will perform access checks, diagnose the use of the resultant decl, and, if -/// necessary, perform a function-to-pointer decay. +/// requested, potentially perform a function-to-pointer decay.  ///  /// Returns false if resolveAddressOfOnlyViableOverloadCandidate fails.  /// Otherwise, returns true. This may emit diagnostics and return true.  bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate( -    ExprResult &SrcExpr) { +    ExprResult &SrcExpr, bool DoFunctionPointerConverion) {    Expr *E = SrcExpr.get();    assert(E->getType() == Context.OverloadTy && "SrcExpr must be an overload"); @@ -11230,7 +11230,7 @@ bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate(    DiagnoseUseOfDecl(Found, E->getExprLoc());    CheckAddressOfMemberAccess(E, DAP);    Expr *Fixed = FixOverloadedFunctionReference(E, DAP, Found); -  if (Fixed->getType()->isFunctionType()) +  if (DoFunctionPointerConverion && Fixed->getType()->isFunctionType())      SrcExpr = DefaultFunctionArrayConversion(Fixed, /*Diagnose=*/false);    else      SrcExpr = Fixed; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp index 5d7eada28717..33a8f9c4afa3 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp @@ -2268,9 +2268,57 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,          BoundExpr = IntegerLiteral::Create(              Context, CAT->getSize(), Context.getPointerDiffType(), RangeLoc);        else if (const VariableArrayType *VAT = -               dyn_cast<VariableArrayType>(UnqAT)) -        BoundExpr = VAT->getSizeExpr(); -      else { +               dyn_cast<VariableArrayType>(UnqAT)) { +        // For a variably modified type we can't just use the expression within +        // the array bounds, since we don't want that to be re-evaluated here. +        // Rather, we need to determine what it was when the array was first +        // created - so we resort to using sizeof(vla)/sizeof(element). +        // For e.g. +        //  void f(int b) {  +        //    int vla[b]; +        //    b = -1;   <-- This should not affect the num of iterations below +        //    for (int &c : vla) { .. } +        //  } + +        // FIXME: This results in codegen generating IR that recalculates the +        // run-time number of elements (as opposed to just using the IR Value +        // that corresponds to the run-time value of each bound that was +        // generated when the array was created.) If this proves too embarassing +        // even for unoptimized IR, consider passing a magic-value/cookie to +        // codegen that then knows to simply use that initial llvm::Value (that +        // corresponds to the bound at time of array creation) within +        // getelementptr.  But be prepared to pay the price of increasing a +        // customized form of coupling between the two components - which  could +        // be hard to maintain as the codebase evolves. + +        ExprResult SizeOfVLAExprR = ActOnUnaryExprOrTypeTraitExpr( +            EndVar->getLocation(), UETT_SizeOf, +            /*isType=*/true, +            CreateParsedType(VAT->desugar(), Context.getTrivialTypeSourceInfo( +                                                 VAT->desugar(), RangeLoc)) +                .getAsOpaquePtr(), +            EndVar->getSourceRange()); +        if (SizeOfVLAExprR.isInvalid()) +          return StmtError(); +         +        ExprResult SizeOfEachElementExprR = ActOnUnaryExprOrTypeTraitExpr( +            EndVar->getLocation(), UETT_SizeOf, +            /*isType=*/true, +            CreateParsedType(VAT->desugar(), +                             Context.getTrivialTypeSourceInfo( +                                 VAT->getElementType(), RangeLoc)) +                .getAsOpaquePtr(), +            EndVar->getSourceRange()); +        if (SizeOfEachElementExprR.isInvalid()) +          return StmtError(); + +        BoundExpr = +            ActOnBinOp(S, EndVar->getLocation(), tok::slash, +                       SizeOfVLAExprR.get(), SizeOfEachElementExprR.get()); +        if (BoundExpr.isInvalid()) +          return StmtError(); +         +      } else {          // Can't be a DependentSizedArrayType or an IncompleteArrayType since          // UnqAT is not incomplete and Range is not type-dependent.          llvm_unreachable("Unexpected array type in for-range"); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp index 61b4df40964c..a479d1027533 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp @@ -455,6 +455,85 @@ void Sema::LookupTemplateName(LookupResult &Found,    }  } +void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName, +                                              SourceLocation Less, +                                              SourceLocation Greater) { +  if (TemplateName.isInvalid()) +    return; + +  DeclarationNameInfo NameInfo; +  CXXScopeSpec SS; +  LookupNameKind LookupKind; + +  DeclContext *LookupCtx = nullptr; +  NamedDecl *Found = nullptr; + +  // Figure out what name we looked up. +  if (auto *ME = dyn_cast<MemberExpr>(TemplateName.get())) { +    NameInfo = ME->getMemberNameInfo(); +    SS.Adopt(ME->getQualifierLoc()); +    LookupKind = LookupMemberName; +    LookupCtx = ME->getBase()->getType()->getAsCXXRecordDecl(); +    Found = ME->getMemberDecl(); +  } else { +    auto *DRE = cast<DeclRefExpr>(TemplateName.get()); +    NameInfo = DRE->getNameInfo(); +    SS.Adopt(DRE->getQualifierLoc()); +    LookupKind = LookupOrdinaryName; +    Found = DRE->getFoundDecl(); +  } + +  // Try to correct the name by looking for templates and C++ named casts. +  struct TemplateCandidateFilter : CorrectionCandidateCallback { +    TemplateCandidateFilter() { +      WantTypeSpecifiers = false; +      WantExpressionKeywords = false; +      WantRemainingKeywords = false; +      WantCXXNamedCasts = true; +    }; +    bool ValidateCandidate(const TypoCorrection &Candidate) override { +      if (auto *ND = Candidate.getCorrectionDecl()) +        return isAcceptableTemplateName(ND->getASTContext(), ND, true); +      return Candidate.isKeyword(); +    } +  }; + +  DeclarationName Name = NameInfo.getName(); +  if (TypoCorrection Corrected = +          CorrectTypo(NameInfo, LookupKind, S, &SS, +                      llvm::make_unique<TemplateCandidateFilter>(), +                      CTK_ErrorRecovery, LookupCtx)) { +    auto *ND = Corrected.getFoundDecl(); +    if (ND) +      ND = isAcceptableTemplateName(Context, ND, +                                    /*AllowFunctionTemplates*/ true); +    if (ND || Corrected.isKeyword()) { +      if (LookupCtx) { +        std::string CorrectedStr(Corrected.getAsString(getLangOpts())); +        bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && +                                Name.getAsString() == CorrectedStr; +        diagnoseTypo(Corrected, +                     PDiag(diag::err_non_template_in_member_template_id_suggest) +                         << Name << LookupCtx << DroppedSpecifier +                         << SS.getRange(), false); +      } else { +        diagnoseTypo(Corrected, +                     PDiag(diag::err_non_template_in_template_id_suggest) +                         << Name, false); +      } +      if (Found) +        Diag(Found->getLocation(), +             diag::note_non_template_in_template_id_found); +      return; +    } +  } + +  Diag(NameInfo.getLoc(), diag::err_non_template_in_template_id) +    << Name << SourceRange(Less, Greater); +  if (Found) +    Diag(Found->getLocation(), diag::note_non_template_in_template_id_found); +} +  /// ActOnDependentIdExpression - Handle a dependent id-expression that  /// was just parsed.  This is only possible with an explicit scope  /// specifier naming a dependent type. @@ -1251,8 +1330,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,            auto *Tmpl = cast<CXXRecordDecl>(Hidden)->getDescribedClassTemplate();            assert(Tmpl && "original definition of a class template is not a "                           "class template?"); -          makeMergedDefinitionVisible(Hidden, KWLoc); -          makeMergedDefinitionVisible(Tmpl, KWLoc); +          makeMergedDefinitionVisible(Hidden); +          makeMergedDefinitionVisible(Tmpl);            return Def;          } @@ -7352,7 +7431,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,      NamedDecl *Hidden = nullptr;      if (Def && SkipBody && !hasVisibleDefinition(Def, &Hidden)) {        SkipBody->ShouldSkip = true; -      makeMergedDefinitionVisible(Hidden, KWLoc); +      makeMergedDefinitionVisible(Hidden);        // From here on out, treat this as just a redeclaration.        TUK = TUK_Declaration;      } else if (Def) { @@ -7825,6 +7904,9 @@ bool Sema::CheckFunctionTemplateSpecialization(      // C++11 [dcl.constexpr]p1: An explicit specialization of a constexpr      // function can differ from the template declaration with respect to      // the constexpr specifier. +    // FIXME: We need an update record for this AST mutation. +    // FIXME: What if there are multiple such prior declarations (for instance, +    // from different modules)?      Specialization->setConstexpr(FD->isConstexpr());    } @@ -7872,9 +7954,11 @@ bool Sema::CheckFunctionTemplateSpecialization(      // flag to not-deleted, so that we can inherit that information from 'FD'.      if (Specialization->isDeleted() && !SpecInfo->isExplicitSpecialization() &&          !Specialization->getCanonicalDecl()->isReferenced()) { +      // FIXME: This assert will not hold in the presence of modules.        assert(            Specialization->getCanonicalDecl() == Specialization &&            "This must be the only existing declaration of this specialization"); +      // FIXME: We need an update record for this AST mutation.        Specialization->setDeletedAsWritten(false);      }      SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization); @@ -7987,8 +8071,11 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {      return false;    } -  // If this is a friend, just bail out here before we start turning -  // things into explicit specializations. +  // A member specialization in a friend declaration isn't really declaring +  // an explicit specialization, just identifying a specific (possibly implicit) +  // specialization. Don't change the template specialization kind. +  // +  // FIXME: Is this really valid? Other compilers reject.    if (Member->getFriendObjectKind() != Decl::FOK_None) {      // Preserve instantiation information.      if (InstantiatedFrom && isa<CXXMethodDecl>(Member)) { @@ -8038,66 +8125,36 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {                                         false))      return true; -  // Note that this is an explicit instantiation of a member. -  // the original declaration to note that it is an explicit specialization -  // (if it was previously an implicit instantiation). This latter step -  // makes bookkeeping easier. -  if (isa<FunctionDecl>(Member)) { +  // Note that this member specialization is an "instantiation of" the +  // corresponding member of the original template. +  if (auto *MemberFunction = dyn_cast<FunctionDecl>(Member)) {      FunctionDecl *InstantiationFunction = cast<FunctionDecl>(Instantiation);      if (InstantiationFunction->getTemplateSpecializationKind() ==            TSK_ImplicitInstantiation) { -      InstantiationFunction->setTemplateSpecializationKind( -                                                  TSK_ExplicitSpecialization); -      InstantiationFunction->setLocation(Member->getLocation());        // Explicit specializations of member functions of class templates do not        // inherit '=delete' from the member function they are specializing.        if (InstantiationFunction->isDeleted()) { +        // FIXME: This assert will not hold in the presence of modules.          assert(InstantiationFunction->getCanonicalDecl() ==                 InstantiationFunction); +        // FIXME: We need an update record for this AST mutation.          InstantiationFunction->setDeletedAsWritten(false);        }      } -    cast<FunctionDecl>(Member)->setInstantiationOfMemberFunction( -                                        cast<CXXMethodDecl>(InstantiatedFrom), -                                                  TSK_ExplicitSpecialization); -    MarkUnusedFileScopedDecl(InstantiationFunction); -  } else if (isa<VarDecl>(Member)) { -    VarDecl *InstantiationVar = cast<VarDecl>(Instantiation); -    if (InstantiationVar->getTemplateSpecializationKind() == -          TSK_ImplicitInstantiation) { -      InstantiationVar->setTemplateSpecializationKind( -                                                  TSK_ExplicitSpecialization); -      InstantiationVar->setLocation(Member->getLocation()); -    } - -    cast<VarDecl>(Member)->setInstantiationOfStaticDataMember( +    MemberFunction->setInstantiationOfMemberFunction( +        cast<CXXMethodDecl>(InstantiatedFrom), TSK_ExplicitSpecialization); +  } else if (auto *MemberVar = dyn_cast<VarDecl>(Member)) { +    MemberVar->setInstantiationOfStaticDataMember(          cast<VarDecl>(InstantiatedFrom), TSK_ExplicitSpecialization); -    MarkUnusedFileScopedDecl(InstantiationVar); -  } else if (isa<CXXRecordDecl>(Member)) { -    CXXRecordDecl *InstantiationClass = cast<CXXRecordDecl>(Instantiation); -    if (InstantiationClass->getTemplateSpecializationKind() == -          TSK_ImplicitInstantiation) { -      InstantiationClass->setTemplateSpecializationKind( -                                                   TSK_ExplicitSpecialization); -      InstantiationClass->setLocation(Member->getLocation()); -    } - -    cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass( -                                        cast<CXXRecordDecl>(InstantiatedFrom), -                                                   TSK_ExplicitSpecialization); -  } else { -    assert(isa<EnumDecl>(Member) && "Only member enums remain"); -    EnumDecl *InstantiationEnum = cast<EnumDecl>(Instantiation); -    if (InstantiationEnum->getTemplateSpecializationKind() == -          TSK_ImplicitInstantiation) { -      InstantiationEnum->setTemplateSpecializationKind( -                                                   TSK_ExplicitSpecialization); -      InstantiationEnum->setLocation(Member->getLocation()); -    } - -    cast<EnumDecl>(Member)->setInstantiationOfMemberEnum( +  } else if (auto *MemberClass = dyn_cast<CXXRecordDecl>(Member)) { +    MemberClass->setInstantiationOfMemberClass( +        cast<CXXRecordDecl>(InstantiatedFrom), TSK_ExplicitSpecialization); +  } else if (auto *MemberEnum = dyn_cast<EnumDecl>(Member)) { +    MemberEnum->setInstantiationOfMemberEnum(          cast<EnumDecl>(InstantiatedFrom), TSK_ExplicitSpecialization); +  } else { +    llvm_unreachable("unknown member specialization kind");    }    // Save the caller the trouble of having to figure out which declaration @@ -8107,6 +8164,43 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {    return false;  } +/// Complete the explicit specialization of a member of a class template by +/// updating the instantiated member to be marked as an explicit specialization. +/// +/// \param OrigD The member declaration instantiated from the template. +/// \param Loc The location of the explicit specialization of the member. +template<typename DeclT> +static void completeMemberSpecializationImpl(Sema &S, DeclT *OrigD, +                                             SourceLocation Loc) { +  if (OrigD->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) +    return; + +  // FIXME: Inform AST mutation listeners of this AST mutation. +  // FIXME: If there are multiple in-class declarations of the member (from +  // multiple modules, or a declaration and later definition of a member type), +  // should we update all of them? +  OrigD->setTemplateSpecializationKind(TSK_ExplicitSpecialization); +  OrigD->setLocation(Loc); +} + +void Sema::CompleteMemberSpecialization(NamedDecl *Member, +                                        LookupResult &Previous) { +  NamedDecl *Instantiation = cast<NamedDecl>(Member->getCanonicalDecl()); +  if (Instantiation == Member) +    return; + +  if (auto *Function = dyn_cast<CXXMethodDecl>(Instantiation)) +    completeMemberSpecializationImpl(*this, Function, Member->getLocation()); +  else if (auto *Var = dyn_cast<VarDecl>(Instantiation)) +    completeMemberSpecializationImpl(*this, Var, Member->getLocation()); +  else if (auto *Record = dyn_cast<CXXRecordDecl>(Instantiation)) +    completeMemberSpecializationImpl(*this, Record, Member->getLocation()); +  else if (auto *Enum = dyn_cast<EnumDecl>(Instantiation)) +    completeMemberSpecializationImpl(*this, Enum, Member->getLocation()); +  else +    llvm_unreachable("unknown member specialization kind"); +} +  /// \brief Check the scope of an explicit instantiation.  ///  /// \returns true if a serious error occurs, false otherwise. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 9a71a17561c7..03df6fde6c80 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1849,6 +1849,19 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,          }        }      } + +    // Check the template parameter list against the previous declaration. The +    // goal here is to pick up default arguments added since the friend was +    // declared; we know the template parameter lists match, since otherwise +    // we would not have picked this template as the previous declaration. +    if (TemplateParams && FunctionTemplate->getPreviousDecl()) { +      SemaRef.CheckTemplateParameterList( +          TemplateParams, +          FunctionTemplate->getPreviousDecl()->getTemplateParameters(), +          Function->isThisDeclarationADefinition() +              ? Sema::TPC_FriendFunctionTemplateDefinition +              : Sema::TPC_FriendFunctionTemplate); +    }    }    if (Function->isLocalExternDecl() && !Function->getPreviousDecl()) @@ -3660,6 +3673,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,        New->setType(SemaRef.Context.getFunctionType(            NewProto->getReturnType(), NewProto->getParamTypes(), EPI));      } else { +      Sema::ContextRAII SwitchContext(SemaRef, New);        SemaRef.SubstExceptionSpec(New, Proto, TemplateArgs);      }    } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp index bcc66bbd1c0a..3992179fabae 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp @@ -2285,8 +2285,9 @@ bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) {    // Methods cannot return interface types. All ObjC objects are    // passed by reference.    if (T->isObjCObjectType()) { -    Diag(Loc, diag::err_object_cannot_be_passed_returned_by_value) << 0 << T; -    return 0; +    Diag(Loc, diag::err_object_cannot_be_passed_returned_by_value) +        << 0 << T << FixItHint::CreateInsertion(Loc, "*"); +    return true;    }    return false;  | 
