diff options
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Sema/SemaLookup.cpp')
| -rw-r--r-- | gnu/llvm/tools/clang/lib/Sema/SemaLookup.cpp | 299 |
1 files changed, 203 insertions, 96 deletions
diff --git a/gnu/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/gnu/llvm/tools/clang/lib/Sema/SemaLookup.cpp index 45dc2e33da9..e2550824fb6 100644 --- a/gnu/llvm/tools/clang/lib/Sema/SemaLookup.cpp +++ b/gnu/llvm/tools/clang/lib/Sema/SemaLookup.cpp @@ -29,7 +29,6 @@ #include "clang/Lex/ModuleLoader.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" -#include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/Overload.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" @@ -280,6 +279,10 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind, IDNS = Decl::IDNS_ObjCProtocol; break; + case Sema::LookupOMPReductionName: + IDNS = Decl::IDNS_OMPReduction; + break; + case Sema::LookupAnyName: IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Using | Decl::IDNS_Namespace | Decl::IDNS_ObjCProtocol @@ -419,6 +422,18 @@ static bool isPreferredLookupResult(Sema &S, Sema::LookupNameKind Kind, } } + // VarDecl can have incomplete array types, prefer the one with more complete + // array type. + if (VarDecl *DVD = dyn_cast<VarDecl>(DUnderlying)) { + VarDecl *EVD = cast<VarDecl>(EUnderlying); + if (EVD->getType()->isIncompleteType() && + !DVD->getType()->isIncompleteType()) { + // Prefer the decl with a more complete type if visible. + return S.isVisible(DVD); + } + return false; // Avoid picking up a newer decl, just because it was newer. + } + // For most kinds of declaration, it doesn't really matter which one we pick. if (!isa<FunctionDecl>(DUnderlying) && !isa<VarDecl>(DUnderlying)) { // If the existing declaration is hidden, prefer the new one. Otherwise, @@ -432,10 +447,6 @@ static bool isPreferredLookupResult(Sema &S, Sema::LookupNameKind Kind, if (Prev == EUnderlying) return true; return false; - - // If the existing declaration is hidden, prefer the new one. Otherwise, - // keep what we've got. - return !S.isVisible(Existing); } /// Determine whether \p D can hide a tag declaration. @@ -669,24 +680,21 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) { NameKind == Sema::LookupRedeclarationWithLinkage) { IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo(); if (II) { - if (S.getLangOpts().CPlusPlus11 && S.getLangOpts().GNUMode && - II == S.getFloat128Identifier()) { - // libstdc++4.7's type_traits expects type __float128 to exist, so - // insert a dummy type to make that header build in gnu++11 mode. - R.addDecl(S.getASTContext().getFloat128StubType()); - return true; - } - if (S.getLangOpts().CPlusPlus && NameKind == Sema::LookupOrdinaryName && - II == S.getASTContext().getMakeIntegerSeqName()) { - R.addDecl(S.getASTContext().getMakeIntegerSeqDecl()); - return true; + if (S.getLangOpts().CPlusPlus && NameKind == Sema::LookupOrdinaryName) { + if (II == S.getASTContext().getMakeIntegerSeqName()) { + R.addDecl(S.getASTContext().getMakeIntegerSeqDecl()); + return true; + } else if (II == S.getASTContext().getTypePackElementName()) { + R.addDecl(S.getASTContext().getTypePackElementDecl()); + return true; + } } // If this is a builtin on this (or all) targets, create the decl. if (unsigned BuiltinID = II->getBuiltinID()) { - // In C++, we don't have any predefined library functions like - // 'malloc'. Instead, we'll just error. - if (S.getLangOpts().CPlusPlus && + // In C++ and OpenCL (spec v1.2 s6.9.f), we don't have any predefined + // library functions like 'malloc'. Instead, we'll just error. + if ((S.getLangOpts().CPlusPlus || S.getLangOpts().OpenCL) && S.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) return false; @@ -734,11 +742,11 @@ void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) { if (getLangOpts().CPlusPlus11) { // If the move constructor has not yet been declared, do so now. if (Class->needsImplicitMoveConstructor()) - DeclareImplicitMoveConstructor(Class); // might not actually do it + DeclareImplicitMoveConstructor(Class); // If the move assignment operator has not yet been declared, do so now. if (Class->needsImplicitMoveAssignment()) - DeclareImplicitMoveAssignment(Class); // might not actually do it + DeclareImplicitMoveAssignment(Class); } // If the destructor has not yet been declared, do so now. @@ -1074,32 +1082,35 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) { DeclContext *Ctx = S->getEntity(); - + bool SearchNamespaceScope = true; // Check whether the IdResolver has anything in this scope. - bool Found = false; for (; I != IEnd && S->isDeclScope(*I); ++I) { if (NamedDecl *ND = R.getAcceptableDecl(*I)) { - if (NameKind == LookupRedeclarationWithLinkage) { + if (NameKind == LookupRedeclarationWithLinkage && + !(*I)->isTemplateParameter()) { + // If it's a template parameter, we still find it, so we can diagnose + // the invalid redeclaration. + // Determine whether this (or a previous) declaration is // out-of-scope. if (!LeftStartingScope && !Initial->isDeclScope(*I)) LeftStartingScope = true; // If we found something outside of our starting scope that - // does not have linkage, skip it. If it's a template parameter, - // we still find it, so we can diagnose the invalid redeclaration. - if (LeftStartingScope && !((*I)->hasLinkage()) && - !(*I)->isTemplateParameter()) { + // does not have linkage, skip it. + if (LeftStartingScope && !((*I)->hasLinkage())) { R.setShadowed(); continue; } + } else { + // We found something in this scope, we should not look at the + // namespace scope + SearchNamespaceScope = false; } - - Found = true; R.addDecl(ND); } } - if (Found) { + if (!SearchNamespaceScope) { R.resolveKind(); if (S->isClassScope()) if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(Ctx)) @@ -1470,6 +1481,35 @@ bool Sema::hasVisibleDefaultArgument(const NamedDecl *D, Modules); } +bool Sema::hasVisibleMemberSpecialization( + const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) { + assert(isa<CXXRecordDecl>(D->getDeclContext()) && + "not a member specialization"); + for (auto *Redecl : D->redecls()) { + // If the specialization is declared at namespace scope, then it's a member + // specialization declaration. If it's lexically inside the class + // definition then it was instantiated. + // + // FIXME: This is a hack. There should be a better way to determine this. + // FIXME: What about MS-style explicit specializations declared within a + // class definition? + if (Redecl->getLexicalDeclContext()->isFileContext()) { + auto *NonConstR = const_cast<NamedDecl*>(cast<NamedDecl>(Redecl)); + + if (isVisible(NonConstR)) + return true; + + if (Modules) { + Modules->push_back(getOwningModule(NonConstR)); + const auto &Merged = Context.getModulesWithMergedDefinition(NonConstR); + Modules->insert(Modules->end(), Merged.begin(), Merged.end()); + } + } + } + + return false; +} + /// \brief Determine whether a declaration is visible to name lookup. /// /// This routine determines whether the declaration D is visible in the current @@ -1570,19 +1610,58 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) { assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case"); for (auto RD : D->redecls()) { - if (auto ND = dyn_cast<NamedDecl>(RD)) { - // FIXME: This is wrong in the case where the previous declaration is not - // visible in the same scope as D. This needs to be done much more - // carefully. - if (LookupResult::isVisible(SemaRef, ND)) - return ND; - } + // Don't bother with extra checks if we already know this one isn't visible. + if (RD == D) + continue; + + auto ND = cast<NamedDecl>(RD); + // FIXME: This is wrong in the case where the previous declaration is not + // visible in the same scope as D. This needs to be done much more + // carefully. + if (LookupResult::isVisible(SemaRef, ND)) + return ND; } return nullptr; } +bool Sema::hasVisibleDeclarationSlow(const NamedDecl *D, + llvm::SmallVectorImpl<Module *> *Modules) { + assert(!isVisible(D) && "not in slow case"); + + for (auto *Redecl : D->redecls()) { + auto *NonConstR = const_cast<NamedDecl*>(cast<NamedDecl>(Redecl)); + if (isVisible(NonConstR)) + return true; + + if (Modules) { + Modules->push_back(getOwningModule(NonConstR)); + const auto &Merged = Context.getModulesWithMergedDefinition(NonConstR); + Modules->insert(Modules->end(), Merged.begin(), Merged.end()); + } + } + + return false; +} + NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const { + if (auto *ND = dyn_cast<NamespaceDecl>(D)) { + // Namespaces are a bit of a special case: we expect there to be a lot of + // redeclarations of some namespaces, all declarations of a namespace are + // essentially interchangeable, all declarations are found by name lookup + // if any is, and namespaces are never looked up during template + // instantiation. So we benefit from caching the check in this case, and + // it is correct to do so. + auto *Key = ND->getCanonicalDecl(); + if (auto *Acceptable = getSema().VisibleNamespaceCache.lookup(Key)) + return Acceptable; + auto *Acceptable = + isVisible(getSema(), Key) ? Key : findAcceptableDecl(getSema(), Key); + if (Acceptable) + getSema().VisibleNamespaceCache.insert(std::make_pair(Key, Acceptable)); + return Acceptable; + } + return findAcceptableDecl(getSema(), D); } @@ -1986,6 +2065,10 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, BaseCallback = &LookupAnyMember; break; + case LookupOMPReductionName: + BaseCallback = &CXXRecordDecl::FindOMPReductionMember; + break; + case LookupUsingDeclName: // This lookup is for redeclarations only. @@ -2409,7 +2492,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, // FIXME: That's not correct, we may have added this class only because it // was the enclosing class of another class, and in that case we won't have // added its base classes yet. - if (!Result.Classes.insert(Class).second) + if (!Result.Classes.insert(Class)) return; // -- If T is a template-id, its associated namespaces and classes are @@ -2459,7 +2542,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, if (!BaseType) continue; CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl()); - if (Result.Classes.insert(BaseDecl).second) { + if (Result.Classes.insert(BaseDecl)) { // Find the associated namespace for this base class. DeclContext *BaseCtx = BaseDecl->getDeclContext(); CollectEnclosingNamespace(Result.Namespaces, BaseCtx); @@ -2864,42 +2947,38 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, // from an external source and invalidate lookup_result. SmallVector<NamedDecl *, 8> Candidates(R.begin(), R.end()); - for (auto *Cand : Candidates) { - if (Cand->isInvalidDecl()) + for (NamedDecl *CandDecl : Candidates) { + if (CandDecl->isInvalidDecl()) continue; - if (UsingShadowDecl *U = dyn_cast<UsingShadowDecl>(Cand)) { - // FIXME: [namespace.udecl]p15 says that we should only consider a - // using declaration here if it does not match a declaration in the - // derived class. We do not implement this correctly in other cases - // either. - Cand = U->getTargetDecl(); - - if (Cand->isInvalidDecl()) - continue; - } - - if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(Cand)) { + DeclAccessPair Cand = DeclAccessPair::make(CandDecl, AS_public); + auto CtorInfo = getConstructorInfo(Cand); + if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(Cand->getUnderlyingDecl())) { if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) - AddMethodCandidate(M, DeclAccessPair::make(M, AS_public), RD, ThisTy, - Classification, llvm::makeArrayRef(&Arg, NumArgs), - OCS, true); - else - AddOverloadCandidate(M, DeclAccessPair::make(M, AS_public), + AddMethodCandidate(M, Cand, RD, ThisTy, Classification, + llvm::makeArrayRef(&Arg, NumArgs), OCS, true); + else if (CtorInfo) + AddOverloadCandidate(CtorInfo.Constructor, CtorInfo.FoundDecl, llvm::makeArrayRef(&Arg, NumArgs), OCS, true); + else + AddOverloadCandidate(M, Cand, llvm::makeArrayRef(&Arg, NumArgs), OCS, + true); } else if (FunctionTemplateDecl *Tmpl = - dyn_cast<FunctionTemplateDecl>(Cand)) { + dyn_cast<FunctionTemplateDecl>(Cand->getUnderlyingDecl())) { if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) - AddMethodTemplateCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public), - RD, nullptr, ThisTy, Classification, - llvm::makeArrayRef(&Arg, NumArgs), - OCS, true); + AddMethodTemplateCandidate( + Tmpl, Cand, RD, nullptr, ThisTy, Classification, + llvm::makeArrayRef(&Arg, NumArgs), OCS, true); + else if (CtorInfo) + AddTemplateOverloadCandidate( + CtorInfo.ConstructorTmpl, CtorInfo.FoundDecl, nullptr, + llvm::makeArrayRef(&Arg, NumArgs), OCS, true); else - AddTemplateOverloadCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public), - nullptr, llvm::makeArrayRef(&Arg, NumArgs), - OCS, true); + AddTemplateOverloadCandidate( + Tmpl, Cand, nullptr, llvm::makeArrayRef(&Arg, NumArgs), OCS, true); } else { - assert(isa<UsingDecl>(Cand) && "illegal Kind of operator = Decl"); + assert(isa<UsingDecl>(Cand.getDecl()) && + "illegal Kind of operator = Decl"); } } @@ -3119,7 +3198,7 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, if (FoundRaw && FoundTemplate) { Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName(); for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) - NoteOverloadCandidate((*I)->getUnderlyingDecl()->getAsFunction()); + NoteOverloadCandidate(*I, (*I)->getUnderlyingDecl()->getAsFunction()); return LOLR_Error; } @@ -3984,8 +4063,8 @@ retry_lookup: void TypoCorrectionConsumer::performQualifiedLookups() { unsigned TypoLen = Typo->getName().size(); - for (auto QR : QualifiedResults) { - for (auto NSI : Namespaces) { + for (const TypoCorrection &QR : QualifiedResults) { + for (const auto &NSI : Namespaces) { DeclContext *Ctx = NSI.DeclCtx; const Type *NSType = NSI.NameSpecifier->getAsType(); @@ -4073,10 +4152,8 @@ TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet( // Build the list of identifiers that would be used for an absolute // (from the global context) NestedNameSpecifier referring to the current // context. - for (DeclContextList::reverse_iterator C = CurContextChain.rbegin(), - CEnd = CurContextChain.rend(); - C != CEnd; ++C) { - if (NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C)) + for (DeclContext *C : llvm::reverse(CurContextChain)) { + if (auto *ND = dyn_cast_or_null<NamespaceDecl>(C)) CurContextIdentifiers.push_back(ND->getIdentifier()); } @@ -4104,13 +4181,11 @@ unsigned TypoCorrectionConsumer::NamespaceSpecifierSet::buildNestedNameSpecifier( DeclContextList &DeclChain, NestedNameSpecifier *&NNS) { unsigned NumSpecifiers = 0; - for (DeclContextList::reverse_iterator C = DeclChain.rbegin(), - CEnd = DeclChain.rend(); - C != CEnd; ++C) { - if (NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C)) { + for (DeclContext *C : llvm::reverse(DeclChain)) { + if (auto *ND = dyn_cast_or_null<NamespaceDecl>(C)) { NNS = NestedNameSpecifier::Create(Context, NNS, ND); ++NumSpecifiers; - } else if (RecordDecl *RD = dyn_cast_or_null<RecordDecl>(*C)) { + } else if (auto *RD = dyn_cast_or_null<RecordDecl>(C)) { NNS = NestedNameSpecifier::Create(Context, NNS, RD->isTemplateDecl(), RD->getTypeForDecl()); ++NumSpecifiers; @@ -4127,10 +4202,9 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier( DeclContextList FullNamespaceDeclChain(NamespaceDeclChain); // Eliminate common elements from the two DeclContext chains. - for (DeclContextList::reverse_iterator C = CurContextChain.rbegin(), - CEnd = CurContextChain.rend(); - C != CEnd && !NamespaceDeclChain.empty() && - NamespaceDeclChain.back() == *C; ++C) { + for (DeclContext *C : llvm::reverse(CurContextChain)) { + if (NamespaceDeclChain.empty() || NamespaceDeclChain.back() != C) + break; NamespaceDeclChain.pop_back(); } @@ -4207,7 +4281,8 @@ static void LookupPotentialTypoResult(Sema &SemaRef, } } - if (ObjCPropertyDecl *Prop = Class->FindPropertyDeclaration(Name)) { + if (ObjCPropertyDecl *Prop = Class->FindPropertyDeclaration( + Name, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { Res.addDecl(Prop); Res.resolveKind(); return; @@ -4704,11 +4779,20 @@ TypoExpr *Sema::CorrectTypoDelayed( const ObjCObjectPointerType *OPT) { assert(CCC && "CorrectTypoDelayed requires a CorrectionCandidateCallback"); - TypoCorrection Empty; auto Consumer = makeTypoCorrectionConsumer( TypoName, LookupKind, S, SS, std::move(CCC), MemberContext, EnteringContext, OPT, Mode == CTK_ErrorRecovery); + // Give the external sema source a chance to correct the typo. + TypoCorrection ExternalTypo; + if (ExternalSource && Consumer) { + ExternalTypo = ExternalSource->CorrectTypo( + TypoName, LookupKind, S, SS, *Consumer->getCorrectionValidator(), + MemberContext, EnteringContext, OPT); + if (ExternalTypo) + Consumer->addCorrection(ExternalTypo); + } + if (!Consumer || Consumer->empty()) return nullptr; @@ -4716,7 +4800,7 @@ TypoExpr *Sema::CorrectTypoDelayed( // is not more that about a third of the length of the typo's identifier. unsigned ED = Consumer->getBestEditDistance(true); IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo(); - if (ED > 0 && Typo->getName().size() / ED < 3) + if (!ExternalTypo && ED > 0 && Typo->getName().size() / ED < 3) return nullptr; ExprEvalContexts.back().NumTypos++; @@ -4852,8 +4936,8 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction, static NamedDecl *getDefinitionToImport(NamedDecl *D) { if (VarDecl *VD = dyn_cast<VarDecl>(D)) return VD->getDefinition(); - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) - return FD->isDefined(FD) ? const_cast<FunctionDecl*>(FD) : nullptr; + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + return FD->getDefinition(); if (TagDecl *TD = dyn_cast<TagDecl>(D)) return TD->getDefinition(); if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) @@ -4866,7 +4950,7 @@ static NamedDecl *getDefinitionToImport(NamedDecl *D) { } void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl, - bool NeedDefinition, bool Recover) { + MissingImportKind MIK, bool Recover) { assert(!isVisible(Decl) && "missing import for non-hidden decl?"); // Suggest importing a module providing the definition of this entity, if @@ -4875,8 +4959,6 @@ void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl, if (!Def) Def = Decl; - // FIXME: Add a Fix-It that imports the corresponding module or includes - // the header. Module *Owner = getOwningModule(Decl); assert(Owner && "definition of hidden declaration is not in a module"); @@ -4885,12 +4967,20 @@ void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl, auto Merged = Context.getModulesWithMergedDefinition(Decl); OwningModules.insert(OwningModules.end(), Merged.begin(), Merged.end()); - diagnoseMissingImport(Loc, Decl, Decl->getLocation(), OwningModules, - NeedDefinition ? MissingImportKind::Definition - : MissingImportKind::Declaration, + diagnoseMissingImport(Loc, Decl, Decl->getLocation(), OwningModules, MIK, Recover); } +/// \brief Get a "quoted.h" or <angled.h> include path to use in a diagnostic +/// suggesting the addition of a #include of the specified file. +static std::string getIncludeStringForHeader(Preprocessor &PP, + const FileEntry *E) { + bool IsSystem; + auto Path = + PP.getHeaderSearchInfo().suggestPathToFileForDiagnostics(E, &IsSystem); + return (IsSystem ? '<' : '"') + Path + (IsSystem ? '>' : '"'); +} + void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl, SourceLocation DeclLoc, ArrayRef<Module *> Modules, @@ -4911,7 +5001,18 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl, Diag(UseLoc, diag::err_module_unimported_use_multiple) << (int)MIK << Decl << ModuleList; + } else if (const FileEntry *E = + PP.getModuleHeaderToIncludeForDiagnostics(UseLoc, DeclLoc)) { + // The right way to make the declaration visible is to include a header; + // suggest doing so. + // + // FIXME: Find a smart place to suggest inserting a #include, and add + // a FixItHint there. + Diag(UseLoc, diag::err_module_unimported_use_header) + << (int)MIK << Decl << Modules[0]->getFullModuleName() + << getIncludeStringForHeader(PP, E); } else { + // FIXME: Add a FixItHint that imports the corresponding module. Diag(UseLoc, diag::err_module_unimported_use) << (int)MIK << Decl << Modules[0]->getFullModuleName(); } @@ -4927,6 +5028,12 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl, case MissingImportKind::DefaultArgument: DiagID = diag::note_default_argument_declared_here; break; + case MissingImportKind::ExplicitSpecialization: + DiagID = diag::note_explicit_specialization_declared_here; + break; + case MissingImportKind::PartialSpecialization: + DiagID = diag::note_partial_specialization_declared_here; + break; } Diag(DeclLoc, DiagID); @@ -4962,7 +5069,7 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction, assert(Decl && "import required but no declaration to import"); diagnoseMissingImport(Correction.getCorrectionRange().getBegin(), Decl, - /*NeedDefinition*/ false, ErrorRecovery); + MissingImportKind::Declaration, ErrorRecovery); return; } |
