diff options
Diffstat (limited to 'contrib/llvm-project/clang/include/clang/Sema/Lookup.h')
-rw-r--r-- | contrib/llvm-project/clang/include/clang/Sema/Lookup.h | 127 |
1 files changed, 97 insertions, 30 deletions
diff --git a/contrib/llvm-project/clang/include/clang/Sema/Lookup.h b/contrib/llvm-project/clang/include/clang/Sema/Lookup.h index 54fe7081b710..2f2f2607a937 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/Lookup.h +++ b/contrib/llvm-project/clang/include/clang/Sema/Lookup.h @@ -26,10 +26,10 @@ #include "clang/Basic/Specifiers.h" #include "clang/Sema/Sema.h" #include "llvm/ADT/MapVector.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Casting.h" #include <cassert> +#include <optional> #include <utility> namespace clang { @@ -117,6 +117,17 @@ public: /// @endcode AmbiguousReference, + /// Name lookup results in an ambiguity because multiple placeholder + /// variables were found in the same scope. + /// @code + /// void f() { + /// int _ = 0; + /// int _ = 0; + /// return _; // ambiguous use of placeholder variable + /// } + /// @endcode + AmbiguousReferenceToPlaceholderVariable, + /// Name lookup results in an ambiguity because an entity with a /// tag name was hidden by an entity with an ordinary name from /// a different context. @@ -148,20 +159,22 @@ public: : SemaPtr(&SemaRef), NameInfo(NameInfo), LookupKind(LookupKind), Redecl(Redecl != Sema::NotForRedeclaration), ExternalRedecl(Redecl == Sema::ForExternalRedeclaration), - Diagnose(Redecl == Sema::NotForRedeclaration) { + DiagnoseAccess(Redecl == Sema::NotForRedeclaration), + DiagnoseAmbiguous(Redecl == Sema::NotForRedeclaration) { configure(); } // TODO: consider whether this constructor should be restricted to take // as input a const IdentifierInfo* (instead of Name), // forcing other cases towards the constructor taking a DNInfo. - LookupResult(Sema &SemaRef, DeclarationName Name, - SourceLocation NameLoc, Sema::LookupNameKind LookupKind, + LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc, + Sema::LookupNameKind LookupKind, Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) : SemaPtr(&SemaRef), NameInfo(Name, NameLoc), LookupKind(LookupKind), Redecl(Redecl != Sema::NotForRedeclaration), ExternalRedecl(Redecl == Sema::ForExternalRedeclaration), - Diagnose(Redecl == Sema::NotForRedeclaration) { + DiagnoseAccess(Redecl == Sema::NotForRedeclaration), + DiagnoseAmbiguous(Redecl == Sema::NotForRedeclaration) { configure(); } @@ -192,12 +205,14 @@ public: Redecl(std::move(Other.Redecl)), ExternalRedecl(std::move(Other.ExternalRedecl)), HideTags(std::move(Other.HideTags)), - Diagnose(std::move(Other.Diagnose)), + DiagnoseAccess(std::move(Other.DiagnoseAccess)), + DiagnoseAmbiguous(std::move(Other.DiagnoseAmbiguous)), AllowHidden(std::move(Other.AllowHidden)), Shadowed(std::move(Other.Shadowed)), TemplateNameLookup(std::move(Other.TemplateNameLookup)) { Other.Paths = nullptr; - Other.Diagnose = false; + Other.DiagnoseAccess = false; + Other.DiagnoseAmbiguous = false; } LookupResult &operator=(LookupResult &&Other) { @@ -215,17 +230,22 @@ public: Redecl = std::move(Other.Redecl); ExternalRedecl = std::move(Other.ExternalRedecl); HideTags = std::move(Other.HideTags); - Diagnose = std::move(Other.Diagnose); + DiagnoseAccess = std::move(Other.DiagnoseAccess); + DiagnoseAmbiguous = std::move(Other.DiagnoseAmbiguous); AllowHidden = std::move(Other.AllowHidden); Shadowed = std::move(Other.Shadowed); TemplateNameLookup = std::move(Other.TemplateNameLookup); Other.Paths = nullptr; - Other.Diagnose = false; + Other.DiagnoseAccess = false; + Other.DiagnoseAmbiguous = false; return *this; } ~LookupResult() { - if (Diagnose) diagnose(); + if (DiagnoseAccess) + diagnoseAccess(); + if (DiagnoseAmbiguous) + diagnoseAmbiguous(); if (Paths) deletePaths(Paths); } @@ -346,30 +366,56 @@ public: /// Determine whether the given declaration is visible to the /// program. - static bool isVisible(Sema &SemaRef, NamedDecl *D) { - // If this declaration is not hidden, it's visible. - if (D->isUnconditionallyVisible()) - return true; + static bool isVisible(Sema &SemaRef, NamedDecl *D); - // During template instantiation, we can refer to hidden declarations, if - // they were visible in any module along the path of instantiation. - return isVisibleSlow(SemaRef, D); + static bool isReachable(Sema &SemaRef, NamedDecl *D); + + static bool isAcceptable(Sema &SemaRef, NamedDecl *D, + Sema::AcceptableKind Kind) { + return Kind == Sema::AcceptableKind::Visible ? isVisible(SemaRef, D) + : isReachable(SemaRef, D); } + /// Determine whether this lookup is permitted to see the declaration. + /// Note that a reachable but not visible declaration inhabiting a namespace + /// is not allowed to be seen during name lookup. + /// + /// For example: + /// ``` + /// // m.cppm + /// export module m; + /// struct reachable { int v; } + /// export auto func() { return reachable{43}; } + /// // Use.cpp + /// import m; + /// auto Use() { + /// // Not valid. We couldn't see reachable here. + /// // So isAvailableForLookup would return false when we look + /// up 'reachable' here. + /// // return reachable(43).v; + /// // Valid. The field name 'v' is allowed during name lookup. + /// // So isAvailableForLookup would return true when we look up 'v' here. + /// return func().v; + /// } + /// ``` + static bool isAvailableForLookup(Sema &SemaRef, NamedDecl *ND); + /// Retrieve the accepted (re)declaration of the given declaration, /// if there is one. NamedDecl *getAcceptableDecl(NamedDecl *D) const { if (!D->isInIdentifierNamespace(IDNS)) return nullptr; - if (isVisible(getSema(), D) || isHiddenDeclarationVisible(D)) + if (isAvailableForLookup(getSema(), D) || isHiddenDeclarationVisible(D)) return D; return getAcceptableDeclSlow(D); } private: - static bool isVisibleSlow(Sema &SemaRef, NamedDecl *D); + static bool isAcceptableSlow(Sema &SemaRef, NamedDecl *D, + Sema::AcceptableKind Kind); + static bool isReachableSlow(Sema &SemaRef, NamedDecl *D); NamedDecl *getAcceptableDeclSlow(NamedDecl *D) const; public: @@ -481,7 +527,7 @@ public: Paths = nullptr; } } else { - llvm::Optional<AmbiguityKind> SavedAK; + std::optional<AmbiguityKind> SavedAK; bool WasAmbiguous = false; if (ResultKind == Ambiguous) { SavedAK = Ambiguity; @@ -495,7 +541,7 @@ public: if (ResultKind == Ambiguous) { (void)WasAmbiguous; assert(WasAmbiguous); - Ambiguity = SavedAK.getValue(); + Ambiguity = *SavedAK; } else if (Paths) { deletePaths(Paths); Paths = nullptr; @@ -581,13 +627,20 @@ public: /// Suppress the diagnostics that would normally fire because of this /// lookup. This happens during (e.g.) redeclaration lookups. void suppressDiagnostics() { - Diagnose = false; + DiagnoseAccess = false; + DiagnoseAmbiguous = false; } - /// Determines whether this lookup is suppressing diagnostics. - bool isSuppressingDiagnostics() const { - return !Diagnose; - } + /// Suppress the diagnostics that would normally fire because of this + /// lookup due to access control violations. + void suppressAccessDiagnostics() { DiagnoseAccess = false; } + + /// Determines whether this lookup is suppressing access control diagnostics. + bool isSuppressingAccessDiagnostics() const { return !DiagnoseAccess; } + + /// Determines whether this lookup is suppressing ambiguous lookup + /// diagnostics. + bool isSuppressingAmbiguousDiagnostics() const { return !DiagnoseAmbiguous; } /// Sets a 'context' source range. void setContextRange(SourceRange SR) { @@ -631,6 +684,15 @@ public: F.CalledDone = true; } + // The move assignment operator is defined as deleted pending + // further motivation. + Filter &operator=(Filter &&) = delete; + + // The copy constrcutor and copy assignment operator is defined as deleted + // pending further motivation. + Filter(const Filter &) = delete; + Filter &operator=(const Filter &) = delete; + ~Filter() { assert(CalledDone && "LookupResult::Filter destroyed without done() call"); @@ -691,11 +753,15 @@ public: } private: - void diagnose() { + void diagnoseAccess() { + if (!isAmbiguous() && isClassLookup() && + getSema().getLangOpts().AccessControl) + getSema().CheckLookupAccess(*this); + } + + void diagnoseAmbiguous() { if (isAmbiguous()) getSema().DiagnoseAmbiguousLookup(*this); - else if (isClassLookup() && getSema().getLangOpts().AccessControl) - getSema().CheckLookupAccess(*this); } void setAmbiguous(AmbiguityKind AK) { @@ -741,7 +807,8 @@ private: /// are present bool HideTags = true; - bool Diagnose = false; + bool DiagnoseAccess = false; + bool DiagnoseAmbiguous = false; /// True if we should allow hidden declarations to be 'visible'. bool AllowHidden = false; |