diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp | 371 |
1 files changed, 211 insertions, 160 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp index bcbecd545398..29038ab9fe1c 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp @@ -907,6 +907,24 @@ bool Sema::LookupBuiltin(LookupResult &R) { return false; } +/// Looks up the declaration of "struct objc_super" and +/// saves it for later use in building builtin declaration of +/// objc_msgSendSuper and objc_msgSendSuper_stret. +static void LookupPredefedObjCSuperType(Sema &Sema, Scope *S) { + ASTContext &Context = Sema.Context; + LookupResult Result(Sema, &Context.Idents.get("objc_super"), SourceLocation(), + Sema::LookupTagName); + Sema.LookupName(Result, S); + if (Result.getResultKind() == LookupResult::Found) + if (const TagDecl *TD = Result.getAsSingle<TagDecl>()) + Context.setObjCSuperType(Context.getTagDeclType(TD)); +} + +void Sema::LookupNecessaryTypesForBuiltin(Scope *S, unsigned ID) { + if (ID == Builtin::BIobjc_msgSendSuper) + LookupPredefedObjCSuperType(*this, S); +} + /// Determine whether we can declare a special member function within /// the class at this point. static bool CanDeclareSpecialMemberFunction(const CXXRecordDecl *Class) { @@ -2067,47 +2085,6 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, return Found; } -/// Callback that looks for any member of a class with the given name. -static bool LookupAnyMember(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, DeclarationName Name) { - RecordDecl *BaseRecord = Specifier->getType()->castAs<RecordType>()->getDecl(); - - Path.Decls = BaseRecord->lookup(Name); - return !Path.Decls.empty(); -} - -/// Determine whether the given set of member declarations contains only -/// static members, nested types, and enumerators. -template<typename InputIterator> -static bool HasOnlyStaticMembers(InputIterator First, InputIterator Last) { - Decl *D = (*First)->getUnderlyingDecl(); - if (isa<VarDecl>(D) || isa<TypeDecl>(D) || isa<EnumConstantDecl>(D)) - return true; - - if (isa<CXXMethodDecl>(D)) { - // Determine whether all of the methods are static. - bool AllMethodsAreStatic = true; - for(; First != Last; ++First) { - D = (*First)->getUnderlyingDecl(); - - if (!isa<CXXMethodDecl>(D)) { - assert(isa<TagDecl>(D) && "Non-function must be a tag decl"); - break; - } - - if (!cast<CXXMethodDecl>(D)->isStatic()) { - AllMethodsAreStatic = false; - break; - } - } - - if (AllMethodsAreStatic) - return true; - } - - return false; -} - /// Perform qualified name lookup into a given context. /// /// Qualified name lookup (C++ [basic.lookup.qual]) is used to find @@ -2185,6 +2162,13 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, if (!LookupRec || !LookupRec->getDefinition()) return false; + // We're done for lookups that can never succeed for C++ classes. + if (R.getLookupKind() == LookupOperatorName || + R.getLookupKind() == LookupNamespaceName || + R.getLookupKind() == LookupObjCProtocolName || + R.getLookupKind() == LookupLabel) + return false; + // If we're performing qualified name lookup into a dependent class, // then we are actually looking into a current instantiation. If we have any // dependent base classes, then we either have to delay lookup until @@ -2197,59 +2181,27 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, } // Perform lookup into our base classes. - CXXBasePaths Paths; - Paths.setOrigin(LookupRec); - - // Look for this member in our base classes - bool (*BaseCallback)(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, - DeclarationName Name) = nullptr; - switch (R.getLookupKind()) { - case LookupObjCImplicitSelfParam: - case LookupOrdinaryName: - case LookupMemberName: - case LookupRedeclarationWithLinkage: - case LookupLocalFriendName: - case LookupDestructorName: - BaseCallback = &CXXRecordDecl::FindOrdinaryMember; - break; - - case LookupTagName: - BaseCallback = &CXXRecordDecl::FindTagMember; - break; - - case LookupAnyName: - BaseCallback = &LookupAnyMember; - break; - - case LookupOMPReductionName: - BaseCallback = &CXXRecordDecl::FindOMPReductionMember; - break; - - case LookupOMPMapperName: - BaseCallback = &CXXRecordDecl::FindOMPMapperMember; - break; - - case LookupUsingDeclName: - // This lookup is for redeclarations only. - - case LookupOperatorName: - case LookupNamespaceName: - case LookupObjCProtocolName: - case LookupLabel: - // These lookups will never find a member in a C++ class (or base class). - return false; - - case LookupNestedNameSpecifierName: - BaseCallback = &CXXRecordDecl::FindNestedNameSpecifierMember; - break; - } DeclarationName Name = R.getLookupName(); - if (!LookupRec->lookupInBases( - [=](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { - return BaseCallback(Specifier, Path, Name); - }, - Paths)) + unsigned IDNS = R.getIdentifierNamespace(); + + // Look for this member in our base classes. + auto BaseCallback = [Name, IDNS](const CXXBaseSpecifier *Specifier, + CXXBasePath &Path) -> bool { + CXXRecordDecl *BaseRecord = Specifier->getType()->getAsCXXRecordDecl(); + // Drop leading non-matching lookup results from the declaration list so + // we don't need to consider them again below. + for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); + Path.Decls = Path.Decls.slice(1)) { + if (Path.Decls.front()->isInIdentifierNamespace(IDNS)) + return true; + } + return false; + }; + + CXXBasePaths Paths; + Paths.setOrigin(LookupRec); + if (!LookupRec->lookupInBases(BaseCallback, Paths)) return false; R.setNamingClass(LookupRec); @@ -2264,6 +2216,85 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, int SubobjectNumber = 0; AccessSpecifier SubobjectAccess = AS_none; + // Check whether the given lookup result contains only static members. + auto HasOnlyStaticMembers = [&](DeclContextLookupResult Result) { + for (NamedDecl *ND : Result) + if (ND->isInIdentifierNamespace(IDNS) && ND->isCXXInstanceMember()) + return false; + return true; + }; + + bool TemplateNameLookup = R.isTemplateNameLookup(); + + // Determine whether two sets of members contain the same members, as + // required by C++ [class.member.lookup]p6. + auto HasSameDeclarations = [&](DeclContextLookupResult A, + DeclContextLookupResult B) { + using Iterator = DeclContextLookupResult::iterator; + using Result = const void *; + + auto Next = [&](Iterator &It, Iterator End) -> Result { + while (It != End) { + NamedDecl *ND = *It++; + if (!ND->isInIdentifierNamespace(IDNS)) + continue; + + // C++ [temp.local]p3: + // A lookup that finds an injected-class-name (10.2) can result in + // an ambiguity in certain cases (for example, if it is found in + // more than one base class). If all of the injected-class-names + // that are found refer to specializations of the same class + // template, and if the name is used as a template-name, the + // reference refers to the class template itself and not a + // specialization thereof, and is not ambiguous. + if (TemplateNameLookup) + if (auto *TD = getAsTemplateNameDecl(ND)) + ND = TD; + + // C++ [class.member.lookup]p3: + // type declarations (including injected-class-names) are replaced by + // the types they designate + if (const TypeDecl *TD = dyn_cast<TypeDecl>(ND->getUnderlyingDecl())) { + QualType T = Context.getTypeDeclType(TD); + return T.getCanonicalType().getAsOpaquePtr(); + } + + return ND->getUnderlyingDecl()->getCanonicalDecl(); + } + return nullptr; + }; + + // We'll often find the declarations are in the same order. Handle this + // case (and the special case of only one declaration) efficiently. + Iterator AIt = A.begin(), BIt = B.begin(), AEnd = A.end(), BEnd = B.end(); + while (true) { + Result AResult = Next(AIt, AEnd); + Result BResult = Next(BIt, BEnd); + if (!AResult && !BResult) + return true; + if (!AResult || !BResult) + return false; + if (AResult != BResult) { + // Found a mismatch; carefully check both lists, accounting for the + // possibility of declarations appearing more than once. + llvm::SmallDenseMap<Result, bool, 32> AResults; + for (; AResult; AResult = Next(AIt, AEnd)) + AResults.insert({AResult, /*FoundInB*/false}); + unsigned Found = 0; + for (; BResult; BResult = Next(BIt, BEnd)) { + auto It = AResults.find(BResult); + if (It == AResults.end()) + return false; + if (!It->second) { + It->second = true; + ++Found; + } + } + return AResults.size() == Found; + } + } + }; + for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end(); Path != PathEnd; ++Path) { const CXXBasePathElement &PathElement = Path->back(); @@ -2280,51 +2311,25 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, continue; } - if (SubobjectType - != Context.getCanonicalType(PathElement.Base->getType())) { + if (SubobjectType != + Context.getCanonicalType(PathElement.Base->getType())) { // We found members of the given name in two subobjects of // different types. If the declaration sets aren't the same, this // lookup is ambiguous. - if (HasOnlyStaticMembers(Path->Decls.begin(), Path->Decls.end())) { - CXXBasePaths::paths_iterator FirstPath = Paths.begin(); - DeclContext::lookup_iterator FirstD = FirstPath->Decls.begin(); - DeclContext::lookup_iterator CurrentD = Path->Decls.begin(); - - // Get the decl that we should use for deduplicating this lookup. - auto GetRepresentativeDecl = [&](NamedDecl *D) -> Decl * { - // C++ [temp.local]p3: - // A lookup that finds an injected-class-name (10.2) can result in - // an ambiguity in certain cases (for example, if it is found in - // more than one base class). If all of the injected-class-names - // that are found refer to specializations of the same class - // template, and if the name is used as a template-name, the - // reference refers to the class template itself and not a - // specialization thereof, and is not ambiguous. - if (R.isTemplateNameLookup()) - if (auto *TD = getAsTemplateNameDecl(D)) - D = TD; - return D->getUnderlyingDecl()->getCanonicalDecl(); - }; - - while (FirstD != FirstPath->Decls.end() && - CurrentD != Path->Decls.end()) { - if (GetRepresentativeDecl(*FirstD) != - GetRepresentativeDecl(*CurrentD)) - break; - - ++FirstD; - ++CurrentD; - } - - if (FirstD == FirstPath->Decls.end() && - CurrentD == Path->Decls.end()) - continue; - } + // + // FIXME: The language rule says that this applies irrespective of + // whether the sets contain only static members. + if (HasOnlyStaticMembers(Path->Decls) && + HasSameDeclarations(Paths.begin()->Decls, Path->Decls)) + continue; R.setAmbiguousBaseSubobjectTypes(Paths); return true; } + // FIXME: This language rule no longer exists. Checking for ambiguous base + // subobjects should be done as part of formation of a class member access + // expression (when converting the object parameter to the member's type). if (SubobjectNumber != PathElement.SubobjectNumber) { // We have a different subobject of the same type. @@ -2332,7 +2337,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // A static member, a nested type or an enumerator defined in // a base class T can unambiguously be found even if an object // has more than one base class subobject of type T. - if (HasOnlyStaticMembers(Path->Decls.begin(), Path->Decls.end())) + if (HasOnlyStaticMembers(Path->Decls)) continue; // We have found a nonstatic member name in multiple, distinct @@ -2347,7 +2352,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, for (auto *D : Paths.front().Decls) { AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess, D->getAccess()); - R.addDecl(D, AS); + if (NamedDecl *ND = R.getAcceptableDecl(D)) + R.addDecl(ND, AS); } R.resolveKind(); return true; @@ -2503,13 +2509,23 @@ void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { << Name << LookupRange; CXXBasePaths *Paths = Result.getBasePaths(); - std::set<Decl *> DeclsPrinted; + std::set<const NamedDecl *> DeclsPrinted; for (CXXBasePaths::paths_iterator Path = Paths->begin(), PathEnd = Paths->end(); Path != PathEnd; ++Path) { - Decl *D = Path->Decls.front(); - if (DeclsPrinted.insert(D).second) - Diag(D->getLocation(), diag::note_ambiguous_member_found); + const NamedDecl *D = Path->Decls.front(); + if (!D->isInIdentifierNamespace(Result.getIdentifierNamespace())) + continue; + if (DeclsPrinted.insert(D).second) { + if (const auto *TD = dyn_cast<TypedefNameDecl>(D->getUnderlyingDecl())) + Diag(D->getLocation(), diag::note_ambiguous_member_type_found) + << TD->getUnderlyingType(); + else if (const auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl())) + Diag(D->getLocation(), diag::note_ambiguous_member_type_found) + << Context.getTypeDeclType(TD); + else + Diag(D->getLocation(), diag::note_ambiguous_member_found); + } } break; } @@ -2980,7 +2996,6 @@ ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II, } void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, - QualType T1, QualType T2, UnresolvedSetImpl &Functions) { // C++ [over.match.oper]p3: // -- The set of non-member candidates is the result of the @@ -3318,9 +3333,9 @@ CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { /// and filter the results to the appropriate set for the given argument types. Sema::LiteralOperatorLookupResult Sema::LookupLiteralOperator(Scope *S, LookupResult &R, - ArrayRef<QualType> ArgTys, - bool AllowRaw, bool AllowTemplate, - bool AllowStringTemplate, bool DiagnoseMissing) { + ArrayRef<QualType> ArgTys, bool AllowRaw, + bool AllowTemplate, bool AllowStringTemplatePack, + bool DiagnoseMissing, StringLiteral *StringLit) { LookupName(R, S); assert(R.getResultKind() != LookupResult::Ambiguous && "literal operator lookup can't be ambiguous"); @@ -3328,10 +3343,11 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, // Filter the lookup results appropriately. LookupResult::Filter F = R.makeFilter(); + bool AllowCooked = true; bool FoundRaw = false; bool FoundTemplate = false; - bool FoundStringTemplate = false; - bool FoundExactMatch = false; + bool FoundStringTemplatePack = false; + bool FoundCooked = false; while (F.hasNext()) { Decl *D = F.next(); @@ -3346,19 +3362,19 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, bool IsRaw = false; bool IsTemplate = false; - bool IsStringTemplate = false; - bool IsExactMatch = false; + bool IsStringTemplatePack = false; + bool IsCooked = false; if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (FD->getNumParams() == 1 && FD->getParamDecl(0)->getType()->getAs<PointerType>()) IsRaw = true; else if (FD->getNumParams() == ArgTys.size()) { - IsExactMatch = true; + IsCooked = true; for (unsigned ArgIdx = 0; ArgIdx != ArgTys.size(); ++ArgIdx) { QualType ParamTy = FD->getParamDecl(ArgIdx)->getType(); if (!Context.hasSameUnqualifiedType(ArgTys[ArgIdx], ParamTy)) { - IsExactMatch = false; + IsCooked = false; break; } } @@ -3366,29 +3382,59 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, } if (FunctionTemplateDecl *FD = dyn_cast<FunctionTemplateDecl>(D)) { TemplateParameterList *Params = FD->getTemplateParameters(); - if (Params->size() == 1) + if (Params->size() == 1) { IsTemplate = true; - else - IsStringTemplate = true; + if (!Params->getParam(0)->isTemplateParameterPack() && !StringLit) { + // Implied but not stated: user-defined integer and floating literals + // only ever use numeric literal operator templates, not templates + // taking a parameter of class type. + F.erase(); + continue; + } + + // A string literal template is only considered if the string literal + // is a well-formed template argument for the template parameter. + if (StringLit) { + SFINAETrap Trap(*this); + SmallVector<TemplateArgument, 1> Checked; + TemplateArgumentLoc Arg(TemplateArgument(StringLit), StringLit); + if (CheckTemplateArgument(Params->getParam(0), Arg, FD, + R.getNameLoc(), R.getNameLoc(), 0, + Checked) || + Trap.hasErrorOccurred()) + IsTemplate = false; + } + } else { + IsStringTemplatePack = true; + } } - if (IsExactMatch) { - FoundExactMatch = true; + if (AllowTemplate && StringLit && IsTemplate) { + FoundTemplate = true; AllowRaw = false; - AllowTemplate = false; - AllowStringTemplate = false; - if (FoundRaw || FoundTemplate || FoundStringTemplate) { + AllowCooked = false; + AllowStringTemplatePack = false; + if (FoundRaw || FoundCooked || FoundStringTemplatePack) { + F.restart(); + FoundRaw = FoundCooked = FoundStringTemplatePack = false; + } + } else if (AllowCooked && IsCooked) { + FoundCooked = true; + AllowRaw = false; + AllowTemplate = StringLit; + AllowStringTemplatePack = false; + if (FoundRaw || FoundTemplate || FoundStringTemplatePack) { // Go through again and remove the raw and template decls we've // already found. F.restart(); - FoundRaw = FoundTemplate = FoundStringTemplate = false; + FoundRaw = FoundTemplate = FoundStringTemplatePack = false; } } else if (AllowRaw && IsRaw) { FoundRaw = true; } else if (AllowTemplate && IsTemplate) { FoundTemplate = true; - } else if (AllowStringTemplate && IsStringTemplate) { - FoundStringTemplate = true; + } else if (AllowStringTemplatePack && IsStringTemplatePack) { + FoundStringTemplatePack = true; } else { F.erase(); } @@ -3396,10 +3442,15 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, F.done(); + // Per C++20 [lex.ext]p5, we prefer the template form over the non-template + // form for string literal operator templates. + if (StringLit && FoundTemplate) + return LOLR_Template; + // C++11 [lex.ext]p3, p4: If S contains a literal operator with a matching // parameter type, that is used in preference to a raw literal operator // or literal operator template. - if (FoundExactMatch) + if (FoundCooked) return LOLR_Cooked; // C++11 [lex.ext]p3, p4: S shall contain a raw literal operator or a literal @@ -3417,15 +3468,15 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, if (FoundTemplate) return LOLR_Template; - if (FoundStringTemplate) - return LOLR_StringTemplate; + if (FoundStringTemplatePack) + return LOLR_StringTemplatePack; // Didn't find anything we could use. if (DiagnoseMissing) { Diag(R.getNameLoc(), diag::err_ovl_no_viable_literal_operator) << R.getLookupName() << (int)ArgTys.size() << ArgTys[0] << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRaw - << (AllowTemplate || AllowStringTemplate); + << (AllowTemplate || AllowStringTemplatePack); return LOLR_Error; } |