Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===--- SemaInternal.h - Internal Sema Interfaces --------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file provides common API and #includes for the internal
  10. // implementation of Sema.
  11. //
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_CLANG_SEMA_SEMAINTERNAL_H
  15. #define LLVM_CLANG_SEMA_SEMAINTERNAL_H
  16.  
  17. #include "clang/AST/ASTContext.h"
  18. #include "clang/Sema/Lookup.h"
  19. #include "clang/Sema/Sema.h"
  20. #include "clang/Sema/SemaDiagnostic.h"
  21.  
  22. namespace clang {
  23.  
  24. inline PartialDiagnostic Sema::PDiag(unsigned DiagID) {
  25.   return PartialDiagnostic(DiagID, Context.getDiagAllocator());
  26. }
  27.  
  28. inline bool
  29. FTIHasSingleVoidParameter(const DeclaratorChunk::FunctionTypeInfo &FTI) {
  30.   return FTI.NumParams == 1 && !FTI.isVariadic &&
  31.          FTI.Params[0].Ident == nullptr && FTI.Params[0].Param &&
  32.          cast<ParmVarDecl>(FTI.Params[0].Param)->getType()->isVoidType();
  33. }
  34.  
  35. inline bool
  36. FTIHasNonVoidParameters(const DeclaratorChunk::FunctionTypeInfo &FTI) {
  37.   // Assume FTI is well-formed.
  38.   return FTI.NumParams && !FTIHasSingleVoidParameter(FTI);
  39. }
  40.  
  41. // Helper function to check whether D's attributes match current CUDA mode.
  42. // Decls with mismatched attributes and related diagnostics may have to be
  43. // ignored during this CUDA compilation pass.
  44. inline bool DeclAttrsMatchCUDAMode(const LangOptions &LangOpts, Decl *D) {
  45.   if (!LangOpts.CUDA || !D)
  46.     return true;
  47.   bool isDeviceSideDecl = D->hasAttr<CUDADeviceAttr>() ||
  48.                           D->hasAttr<CUDASharedAttr>() ||
  49.                           D->hasAttr<CUDAGlobalAttr>();
  50.   return isDeviceSideDecl == LangOpts.CUDAIsDevice;
  51. }
  52.  
  53. /// Return a DLL attribute from the declaration.
  54. inline InheritableAttr *getDLLAttr(Decl *D) {
  55.   assert(!(D->hasAttr<DLLImportAttr>() && D->hasAttr<DLLExportAttr>()) &&
  56.          "A declaration cannot be both dllimport and dllexport.");
  57.   if (auto *Import = D->getAttr<DLLImportAttr>())
  58.     return Import;
  59.   if (auto *Export = D->getAttr<DLLExportAttr>())
  60.     return Export;
  61.   return nullptr;
  62. }
  63.  
  64. /// Retrieve the depth and index of a template parameter.
  65. inline std::pair<unsigned, unsigned> getDepthAndIndex(NamedDecl *ND) {
  66.   if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
  67.     return std::make_pair(TTP->getDepth(), TTP->getIndex());
  68.  
  69.   if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
  70.     return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
  71.  
  72.   const auto *TTP = cast<TemplateTemplateParmDecl>(ND);
  73.   return std::make_pair(TTP->getDepth(), TTP->getIndex());
  74. }
  75.  
  76. /// Retrieve the depth and index of an unexpanded parameter pack.
  77. inline std::pair<unsigned, unsigned>
  78. getDepthAndIndex(UnexpandedParameterPack UPP) {
  79.   if (const auto *TTP = UPP.first.dyn_cast<const TemplateTypeParmType *>())
  80.     return std::make_pair(TTP->getDepth(), TTP->getIndex());
  81.  
  82.   return getDepthAndIndex(UPP.first.get<NamedDecl *>());
  83. }
  84.  
  85. class TypoCorrectionConsumer : public VisibleDeclConsumer {
  86.   typedef SmallVector<TypoCorrection, 1> TypoResultList;
  87.   typedef llvm::StringMap<TypoResultList> TypoResultsMap;
  88.   typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap;
  89.  
  90. public:
  91.   TypoCorrectionConsumer(Sema &SemaRef,
  92.                          const DeclarationNameInfo &TypoName,
  93.                          Sema::LookupNameKind LookupKind,
  94.                          Scope *S, CXXScopeSpec *SS,
  95.                          std::unique_ptr<CorrectionCandidateCallback> CCC,
  96.                          DeclContext *MemberContext,
  97.                          bool EnteringContext)
  98.       : Typo(TypoName.getName().getAsIdentifierInfo()), CurrentTCIndex(0),
  99.         SavedTCIndex(0), SemaRef(SemaRef), S(S),
  100.         SS(SS ? std::make_unique<CXXScopeSpec>(*SS) : nullptr),
  101.         CorrectionValidator(std::move(CCC)), MemberContext(MemberContext),
  102.         Result(SemaRef, TypoName, LookupKind),
  103.         Namespaces(SemaRef.Context, SemaRef.CurContext, SS),
  104.         EnteringContext(EnteringContext), SearchNamespaces(false) {
  105.     Result.suppressDiagnostics();
  106.     // Arrange for ValidatedCorrections[0] to always be an empty correction.
  107.     ValidatedCorrections.push_back(TypoCorrection());
  108.   }
  109.  
  110.   bool includeHiddenDecls() const override { return true; }
  111.  
  112.   // Methods for adding potential corrections to the consumer.
  113.   void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
  114.                  bool InBaseClass) override;
  115.   void FoundName(StringRef Name);
  116.   void addKeywordResult(StringRef Keyword);
  117.   void addCorrection(TypoCorrection Correction);
  118.  
  119.   bool empty() const {
  120.     return CorrectionResults.empty() && ValidatedCorrections.size() == 1;
  121.   }
  122.  
  123.   /// Return the list of TypoCorrections for the given identifier from
  124.   /// the set of corrections that have the closest edit distance, if any.
  125.   TypoResultList &operator[](StringRef Name) {
  126.     return CorrectionResults.begin()->second[Name];
  127.   }
  128.  
  129.   /// Return the edit distance of the corrections that have the
  130.   /// closest/best edit distance from the original typop.
  131.   unsigned getBestEditDistance(bool Normalized) {
  132.     if (CorrectionResults.empty())
  133.       return (std::numeric_limits<unsigned>::max)();
  134.  
  135.     unsigned BestED = CorrectionResults.begin()->first;
  136.     return Normalized ? TypoCorrection::NormalizeEditDistance(BestED) : BestED;
  137.   }
  138.  
  139.   /// Set-up method to add to the consumer the set of namespaces to use
  140.   /// in performing corrections to nested name specifiers. This method also
  141.   /// implicitly adds all of the known classes in the current AST context to the
  142.   /// to the consumer for correcting nested name specifiers.
  143.   void
  144.   addNamespaces(const llvm::MapVector<NamespaceDecl *, bool> &KnownNamespaces);
  145.  
  146.   /// Return the next typo correction that passes all internal filters
  147.   /// and is deemed valid by the consumer's CorrectionCandidateCallback,
  148.   /// starting with the corrections that have the closest edit distance. An
  149.   /// empty TypoCorrection is returned once no more viable corrections remain
  150.   /// in the consumer.
  151.   const TypoCorrection &getNextCorrection();
  152.  
  153.   /// Get the last correction returned by getNextCorrection().
  154.   const TypoCorrection &getCurrentCorrection() {
  155.     return CurrentTCIndex < ValidatedCorrections.size()
  156.                ? ValidatedCorrections[CurrentTCIndex]
  157.                : ValidatedCorrections[0];  // The empty correction.
  158.   }
  159.  
  160.   /// Return the next typo correction like getNextCorrection, but keep
  161.   /// the internal state pointed to the current correction (i.e. the next time
  162.   /// getNextCorrection is called, it will return the same correction returned
  163.   /// by peekNextcorrection).
  164.   const TypoCorrection &peekNextCorrection() {
  165.     auto Current = CurrentTCIndex;
  166.     const TypoCorrection &TC = getNextCorrection();
  167.     CurrentTCIndex = Current;
  168.     return TC;
  169.   }
  170.  
  171.   /// In the case of deeply invalid expressions, `getNextCorrection()` will
  172.   /// never be called since the transform never makes progress. If we don't
  173.   /// detect this we risk trying to correct typos forever.
  174.   bool hasMadeAnyCorrectionProgress() const { return CurrentTCIndex != 0; }
  175.  
  176.   /// Reset the consumer's position in the stream of viable corrections
  177.   /// (i.e. getNextCorrection() will return each of the previously returned
  178.   /// corrections in order before returning any new corrections).
  179.   void resetCorrectionStream() {
  180.     CurrentTCIndex = 0;
  181.   }
  182.  
  183.   /// Return whether the end of the stream of corrections has been
  184.   /// reached.
  185.   bool finished() {
  186.     return CorrectionResults.empty() &&
  187.            CurrentTCIndex >= ValidatedCorrections.size();
  188.   }
  189.  
  190.   /// Save the current position in the correction stream (overwriting any
  191.   /// previously saved position).
  192.   void saveCurrentPosition() {
  193.     SavedTCIndex = CurrentTCIndex;
  194.   }
  195.  
  196.   /// Restore the saved position in the correction stream.
  197.   void restoreSavedPosition() {
  198.     CurrentTCIndex = SavedTCIndex;
  199.   }
  200.  
  201.   ASTContext &getContext() const { return SemaRef.Context; }
  202.   const LookupResult &getLookupResult() const { return Result; }
  203.  
  204.   bool isAddressOfOperand() const { return CorrectionValidator->IsAddressOfOperand; }
  205.   const CXXScopeSpec *getSS() const { return SS.get(); }
  206.   Scope *getScope() const { return S; }
  207.   CorrectionCandidateCallback *getCorrectionValidator() const {
  208.     return CorrectionValidator.get();
  209.   }
  210.  
  211. private:
  212.   class NamespaceSpecifierSet {
  213.     struct SpecifierInfo {
  214.       DeclContext* DeclCtx;
  215.       NestedNameSpecifier* NameSpecifier;
  216.       unsigned EditDistance;
  217.     };
  218.  
  219.     typedef SmallVector<DeclContext*, 4> DeclContextList;
  220.     typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList;
  221.  
  222.     ASTContext &Context;
  223.     DeclContextList CurContextChain;
  224.     std::string CurNameSpecifier;
  225.     SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers;
  226.     SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers;
  227.  
  228.     std::map<unsigned, SpecifierInfoList> DistanceMap;
  229.  
  230.     /// Helper for building the list of DeclContexts between the current
  231.     /// context and the top of the translation unit
  232.     static DeclContextList buildContextChain(DeclContext *Start);
  233.  
  234.     unsigned buildNestedNameSpecifier(DeclContextList &DeclChain,
  235.                                       NestedNameSpecifier *&NNS);
  236.  
  237.    public:
  238.     NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext,
  239.                           CXXScopeSpec *CurScopeSpec);
  240.  
  241.     /// Add the DeclContext (a namespace or record) to the set, computing
  242.     /// the corresponding NestedNameSpecifier and its distance in the process.
  243.     void addNameSpecifier(DeclContext *Ctx);
  244.  
  245.     /// Provides flat iteration over specifiers, sorted by distance.
  246.     class iterator
  247.         : public llvm::iterator_facade_base<iterator, std::forward_iterator_tag,
  248.                                             SpecifierInfo> {
  249.       /// Always points to the last element in the distance map.
  250.       const std::map<unsigned, SpecifierInfoList>::iterator OuterBack;
  251.       /// Iterator on the distance map.
  252.       std::map<unsigned, SpecifierInfoList>::iterator Outer;
  253.       /// Iterator on an element in the distance map.
  254.       SpecifierInfoList::iterator Inner;
  255.  
  256.     public:
  257.       iterator(NamespaceSpecifierSet &Set, bool IsAtEnd)
  258.           : OuterBack(std::prev(Set.DistanceMap.end())),
  259.             Outer(Set.DistanceMap.begin()),
  260.             Inner(!IsAtEnd ? Outer->second.begin() : OuterBack->second.end()) {
  261.         assert(!Set.DistanceMap.empty());
  262.       }
  263.  
  264.       iterator &operator++() {
  265.         ++Inner;
  266.         if (Inner == Outer->second.end() && Outer != OuterBack) {
  267.           ++Outer;
  268.           Inner = Outer->second.begin();
  269.         }
  270.         return *this;
  271.       }
  272.  
  273.       SpecifierInfo &operator*() { return *Inner; }
  274.       bool operator==(const iterator &RHS) const { return Inner == RHS.Inner; }
  275.     };
  276.  
  277.     iterator begin() { return iterator(*this, /*IsAtEnd=*/false); }
  278.     iterator end() { return iterator(*this, /*IsAtEnd=*/true); }
  279.   };
  280.  
  281.   void addName(StringRef Name, NamedDecl *ND,
  282.                NestedNameSpecifier *NNS = nullptr, bool isKeyword = false);
  283.  
  284.   /// Find any visible decls for the given typo correction candidate.
  285.   /// If none are found, it to the set of candidates for which qualified lookups
  286.   /// will be performed to find possible nested name specifier changes.
  287.   bool resolveCorrection(TypoCorrection &Candidate);
  288.  
  289.   /// Perform qualified lookups on the queued set of typo correction
  290.   /// candidates and add the nested name specifier changes to each candidate if
  291.   /// a lookup succeeds (at which point the candidate will be returned to the
  292.   /// main pool of potential corrections).
  293.   void performQualifiedLookups();
  294.  
  295.   /// The name written that is a typo in the source.
  296.   IdentifierInfo *Typo;
  297.  
  298.   /// The results found that have the smallest edit distance
  299.   /// found (so far) with the typo name.
  300.   ///
  301.   /// The pointer value being set to the current DeclContext indicates
  302.   /// whether there is a keyword with this name.
  303.   TypoEditDistanceMap CorrectionResults;
  304.  
  305.   SmallVector<TypoCorrection, 4> ValidatedCorrections;
  306.   size_t CurrentTCIndex;
  307.   size_t SavedTCIndex;
  308.  
  309.   Sema &SemaRef;
  310.   Scope *S;
  311.   std::unique_ptr<CXXScopeSpec> SS;
  312.   std::unique_ptr<CorrectionCandidateCallback> CorrectionValidator;
  313.   DeclContext *MemberContext;
  314.   LookupResult Result;
  315.   NamespaceSpecifierSet Namespaces;
  316.   SmallVector<TypoCorrection, 2> QualifiedResults;
  317.   bool EnteringContext;
  318.   bool SearchNamespaces;
  319. };
  320.  
  321. inline Sema::TypoExprState::TypoExprState() {}
  322.  
  323. inline Sema::TypoExprState::TypoExprState(TypoExprState &&other) noexcept {
  324.   *this = std::move(other);
  325. }
  326.  
  327. inline Sema::TypoExprState &Sema::TypoExprState::
  328. operator=(Sema::TypoExprState &&other) noexcept {
  329.   Consumer = std::move(other.Consumer);
  330.   DiagHandler = std::move(other.DiagHandler);
  331.   RecoveryHandler = std::move(other.RecoveryHandler);
  332.   return *this;
  333. }
  334.  
  335. } // end namespace clang
  336.  
  337. #endif
  338.