Home | History | Annotate | Line # | Download | only in AST
      1 //===----- Linkage.h - Linkage calculation-related utilities ----*- 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 AST-internal utilities for linkage and visibility
     10 // calculation.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_CLANG_LIB_AST_LINKAGE_H
     15 #define LLVM_CLANG_LIB_AST_LINKAGE_H
     16 
     17 #include "clang/AST/ASTFwd.h"
     18 #include "clang/AST/Decl.h"
     19 #include "clang/AST/DeclCXX.h"
     20 #include "clang/AST/Type.h"
     21 #include "llvm/ADT/DenseMap.h"
     22 #include "llvm/ADT/Optional.h"
     23 #include "llvm/ADT/PointerIntPair.h"
     24 
     25 namespace clang {
     26 /// Kinds of LV computation.  The linkage side of the computation is
     27 /// always the same, but different things can change how visibility is
     28 /// computed.
     29 struct LVComputationKind {
     30   /// The kind of entity whose visibility is ultimately being computed;
     31   /// visibility computations for types and non-types follow different rules.
     32   unsigned ExplicitKind : 1;
     33   /// Whether explicit visibility attributes should be ignored. When set,
     34   /// visibility may only be restricted by the visibility of template arguments.
     35   unsigned IgnoreExplicitVisibility : 1;
     36   /// Whether all visibility should be ignored. When set, we're only interested
     37   /// in computing linkage.
     38   unsigned IgnoreAllVisibility : 1;
     39 
     40   enum { NumLVComputationKindBits = 3 };
     41 
     42   explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK)
     43       : ExplicitKind(EK), IgnoreExplicitVisibility(false),
     44         IgnoreAllVisibility(false) {}
     45 
     46   NamedDecl::ExplicitVisibilityKind getExplicitVisibilityKind() const {
     47     return static_cast<NamedDecl::ExplicitVisibilityKind>(ExplicitKind);
     48   }
     49 
     50   bool isTypeVisibility() const {
     51     return getExplicitVisibilityKind() == NamedDecl::VisibilityForType;
     52   }
     53   bool isValueVisibility() const {
     54     return getExplicitVisibilityKind() == NamedDecl::VisibilityForValue;
     55   }
     56 
     57   /// Do an LV computation when we only care about the linkage.
     58   static LVComputationKind forLinkageOnly() {
     59     LVComputationKind Result(NamedDecl::VisibilityForValue);
     60     Result.IgnoreExplicitVisibility = true;
     61     Result.IgnoreAllVisibility = true;
     62     return Result;
     63   }
     64 
     65   unsigned toBits() {
     66     unsigned Bits = 0;
     67     Bits = (Bits << 1) | ExplicitKind;
     68     Bits = (Bits << 1) | IgnoreExplicitVisibility;
     69     Bits = (Bits << 1) | IgnoreAllVisibility;
     70     return Bits;
     71   }
     72 };
     73 
     74 class LinkageComputer {
     75   // We have a cache for repeated linkage/visibility computations. This saves us
     76   // from exponential behavior in heavily templated code, such as:
     77   //
     78   // template <typename T, typename V> struct {};
     79   // using A = int;
     80   // using B = Foo<A, A>;
     81   // using C = Foo<B, B>;
     82   // using D = Foo<C, C>;
     83   //
     84   // The integer represents an LVComputationKind.
     85   using QueryType =
     86       llvm::PointerIntPair<const NamedDecl *,
     87                            LVComputationKind::NumLVComputationKindBits>;
     88   llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo;
     89 
     90   static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) {
     91     return QueryType(ND, Kind.toBits());
     92   }
     93 
     94   llvm::Optional<LinkageInfo> lookup(const NamedDecl *ND,
     95                                      LVComputationKind Kind) const {
     96     auto Iter = CachedLinkageInfo.find(makeCacheKey(ND, Kind));
     97     if (Iter == CachedLinkageInfo.end())
     98       return None;
     99     return Iter->second;
    100   }
    101 
    102   void cache(const NamedDecl *ND, LVComputationKind Kind, LinkageInfo Info) {
    103     CachedLinkageInfo[makeCacheKey(ND, Kind)] = Info;
    104   }
    105 
    106   LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
    107                                            LVComputationKind computation);
    108 
    109   LinkageInfo getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
    110                                            LVComputationKind computation);
    111 
    112   void mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn,
    113                        const FunctionTemplateSpecializationInfo *specInfo,
    114                        LVComputationKind computation);
    115 
    116   void mergeTemplateLV(LinkageInfo &LV,
    117                        const ClassTemplateSpecializationDecl *spec,
    118                        LVComputationKind computation);
    119 
    120   void mergeTemplateLV(LinkageInfo &LV,
    121                        const VarTemplateSpecializationDecl *spec,
    122                        LVComputationKind computation);
    123 
    124   LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
    125                                          LVComputationKind computation,
    126                                          bool IgnoreVarTypeLinkage);
    127 
    128   LinkageInfo getLVForClassMember(const NamedDecl *D,
    129                                   LVComputationKind computation,
    130                                   bool IgnoreVarTypeLinkage);
    131 
    132   LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl,
    133                               LVComputationKind computation);
    134 
    135   LinkageInfo getLVForLocalDecl(const NamedDecl *D,
    136                                 LVComputationKind computation);
    137 
    138   LinkageInfo getLVForType(const Type &T, LVComputationKind computation);
    139 
    140   LinkageInfo getLVForTemplateParameterList(const TemplateParameterList *Params,
    141                                             LVComputationKind computation);
    142 
    143   LinkageInfo getLVForValue(const APValue &V, LVComputationKind computation);
    144 
    145 public:
    146   LinkageInfo computeLVForDecl(const NamedDecl *D,
    147                                LVComputationKind computation,
    148                                bool IgnoreVarTypeLinkage = false);
    149 
    150   LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation);
    151 
    152   LinkageInfo computeTypeLinkageInfo(const Type *T);
    153   LinkageInfo computeTypeLinkageInfo(QualType T) {
    154     return computeTypeLinkageInfo(T.getTypePtr());
    155   }
    156 
    157   LinkageInfo getDeclLinkageAndVisibility(const NamedDecl *D);
    158 
    159   LinkageInfo getTypeLinkageAndVisibility(const Type *T);
    160   LinkageInfo getTypeLinkageAndVisibility(QualType T) {
    161     return getTypeLinkageAndVisibility(T.getTypePtr());
    162   }
    163 };
    164 } // namespace clang
    165 
    166 #endif
    167