summaryrefslogtreecommitdiff
path: root/lib/AST/Linkage.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/Linkage.h')
-rw-r--r--lib/AST/Linkage.h159
1 files changed, 159 insertions, 0 deletions
diff --git a/lib/AST/Linkage.h b/lib/AST/Linkage.h
new file mode 100644
index 000000000000..e6489c7ef2b3
--- /dev/null
+++ b/lib/AST/Linkage.h
@@ -0,0 +1,159 @@
+//===----- Linkage.h - Linkage calculation-related utilities ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+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;
+
+ 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 unsigned represents an LVComputationKind.
+ using QueryType = std::pair<const NamedDecl *, unsigned>;
+ llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo;
+
+ static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) {
+ return std::make_pair(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