forked from OSchip/llvm-project
164 lines
6.0 KiB
C++
164 lines
6.0 KiB
C++
//===----- Linkage.h - Linkage calculation-related utilities ----*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file provides AST-internal utilities for linkage and visibility
|
|
// calculation.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_LIB_AST_LINKAGE_H
|
|
#define LLVM_CLANG_LIB_AST_LINKAGE_H
|
|
|
|
#include "clang/AST/Decl.h"
|
|
#include "clang/AST/DeclCXX.h"
|
|
#include "clang/AST/Type.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/Optional.h"
|
|
#include "llvm/ADT/PointerIntPair.h"
|
|
|
|
namespace clang {
|
|
/// Kinds of LV computation. The linkage side of the computation is
|
|
/// always the same, but different things can change how visibility is
|
|
/// computed.
|
|
struct LVComputationKind {
|
|
/// The kind of entity whose visibility is ultimately being computed;
|
|
/// visibility computations for types and non-types follow different rules.
|
|
unsigned ExplicitKind : 1;
|
|
/// Whether explicit visibility attributes should be ignored. When set,
|
|
/// visibility may only be restricted by the visibility of template arguments.
|
|
unsigned IgnoreExplicitVisibility : 1;
|
|
/// Whether all visibility should be ignored. When set, we're only interested
|
|
/// in computing linkage.
|
|
unsigned IgnoreAllVisibility : 1;
|
|
|
|
enum { NumLVComputationKindBits = 3 };
|
|
|
|
explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK)
|
|
: ExplicitKind(EK), IgnoreExplicitVisibility(false),
|
|
IgnoreAllVisibility(false) {}
|
|
|
|
NamedDecl::ExplicitVisibilityKind getExplicitVisibilityKind() const {
|
|
return static_cast<NamedDecl::ExplicitVisibilityKind>(ExplicitKind);
|
|
}
|
|
|
|
bool isTypeVisibility() const {
|
|
return getExplicitVisibilityKind() == NamedDecl::VisibilityForType;
|
|
}
|
|
bool isValueVisibility() const {
|
|
return getExplicitVisibilityKind() == NamedDecl::VisibilityForValue;
|
|
}
|
|
|
|
/// Do an LV computation when we only care about the linkage.
|
|
static LVComputationKind forLinkageOnly() {
|
|
LVComputationKind Result(NamedDecl::VisibilityForValue);
|
|
Result.IgnoreExplicitVisibility = true;
|
|
Result.IgnoreAllVisibility = true;
|
|
return Result;
|
|
}
|
|
|
|
unsigned toBits() {
|
|
unsigned Bits = 0;
|
|
Bits = (Bits << 1) | ExplicitKind;
|
|
Bits = (Bits << 1) | IgnoreExplicitVisibility;
|
|
Bits = (Bits << 1) | IgnoreAllVisibility;
|
|
return Bits;
|
|
}
|
|
};
|
|
|
|
class LinkageComputer {
|
|
// We have a cache for repeated linkage/visibility computations. This saves us
|
|
// from exponential behavior in heavily templated code, such as:
|
|
//
|
|
// template <typename T, typename V> struct {};
|
|
// using A = int;
|
|
// using B = Foo<A, A>;
|
|
// using C = Foo<B, B>;
|
|
// using D = Foo<C, C>;
|
|
//
|
|
// The integer represents an LVComputationKind.
|
|
using QueryType =
|
|
llvm::PointerIntPair<const NamedDecl *,
|
|
LVComputationKind::NumLVComputationKindBits>;
|
|
llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo;
|
|
|
|
static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) {
|
|
return QueryType(ND, Kind.toBits());
|
|
}
|
|
|
|
llvm::Optional<LinkageInfo> lookup(const NamedDecl *ND,
|
|
LVComputationKind Kind) const {
|
|
auto Iter = CachedLinkageInfo.find(makeCacheKey(ND, Kind));
|
|
if (Iter == CachedLinkageInfo.end())
|
|
return None;
|
|
return Iter->second;
|
|
}
|
|
|
|
void cache(const NamedDecl *ND, LVComputationKind Kind, LinkageInfo Info) {
|
|
CachedLinkageInfo[makeCacheKey(ND, Kind)] = Info;
|
|
}
|
|
|
|
LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
|
|
LVComputationKind computation);
|
|
|
|
LinkageInfo getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
|
|
LVComputationKind computation);
|
|
|
|
void mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn,
|
|
const FunctionTemplateSpecializationInfo *specInfo,
|
|
LVComputationKind computation);
|
|
|
|
void mergeTemplateLV(LinkageInfo &LV,
|
|
const ClassTemplateSpecializationDecl *spec,
|
|
LVComputationKind computation);
|
|
|
|
void mergeTemplateLV(LinkageInfo &LV,
|
|
const VarTemplateSpecializationDecl *spec,
|
|
LVComputationKind computation);
|
|
|
|
LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
|
|
LVComputationKind computation,
|
|
bool IgnoreVarTypeLinkage);
|
|
|
|
LinkageInfo getLVForClassMember(const NamedDecl *D,
|
|
LVComputationKind computation,
|
|
bool IgnoreVarTypeLinkage);
|
|
|
|
LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl,
|
|
LVComputationKind computation);
|
|
|
|
LinkageInfo getLVForLocalDecl(const NamedDecl *D,
|
|
LVComputationKind computation);
|
|
|
|
LinkageInfo getLVForType(const Type &T, LVComputationKind computation);
|
|
|
|
LinkageInfo getLVForTemplateParameterList(const TemplateParameterList *Params,
|
|
LVComputationKind computation);
|
|
|
|
public:
|
|
LinkageInfo computeLVForDecl(const NamedDecl *D,
|
|
LVComputationKind computation,
|
|
bool IgnoreVarTypeLinkage = false);
|
|
|
|
LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation);
|
|
|
|
LinkageInfo computeTypeLinkageInfo(const Type *T);
|
|
LinkageInfo computeTypeLinkageInfo(QualType T) {
|
|
return computeTypeLinkageInfo(T.getTypePtr());
|
|
}
|
|
|
|
LinkageInfo getDeclLinkageAndVisibility(const NamedDecl *D);
|
|
|
|
LinkageInfo getTypeLinkageAndVisibility(const Type *T);
|
|
LinkageInfo getTypeLinkageAndVisibility(QualType T) {
|
|
return getTypeLinkageAndVisibility(T.getTypePtr());
|
|
}
|
|
};
|
|
} // namespace clang
|
|
|
|
#endif
|