aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2013-02-16 00:17:33 +0000
committerJohn McCall <rjmccall@apple.com>2013-02-16 00:17:33 +0000
commit5a758de93fa2a28a84eb0d918a31d9522472990c (patch)
tree2016980e67909d016f06a75e570da1751d91326a /include/clang
parenta6e0a0db0afcbdcd5b7c939869a39754332ad040 (diff)
Rework the visibility computation algorithm in preparation
for distinguishing type vs. value visibility. The changes to the visibility of explicit specializations are intentional. The change to the "ugly" test case is a consequence of a sensible implementation, and I am happy to argue that this is better behavior. Other changes may or may not be intended; it is quite difficult to divine intent from some of the code I altered. I've left behind a comment which I hope explains the philosophy behind visibility computation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175326 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/AST/Decl.h68
-rw-r--r--include/clang/AST/DeclTemplate.h46
-rw-r--r--include/clang/AST/TemplateBase.h6
3 files changed, 77 insertions, 43 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 117ec7eef3..e9643d2dc7 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -247,63 +247,45 @@ public:
bool visibilityExplicit() const { return explicit_; }
void setLinkage(Linkage L) { linkage_ = L; }
+
void mergeLinkage(Linkage L) {
setLinkage(minLinkage(linkage(), L));
}
- void mergeLinkage(LinkageInfo Other) {
- mergeLinkage(Other.linkage());
+ void mergeLinkage(LinkageInfo other) {
+ mergeLinkage(other.linkage());
}
- // Merge the visibility V giving preference to explicit ones.
- // This is used, for example, when merging the visibility of a class
- // down to one of its members. If the member has no explicit visibility,
- // the class visibility wins.
- void mergeVisibility(Visibility V, bool E = false) {
- // Never increase the visibility
- if (visibility() < V)
- return;
-
- // If we have an explicit visibility, keep it
- if (visibilityExplicit())
- return;
+ /// Merge in the visibility 'newVis'.
+ void mergeVisibility(Visibility newVis, bool newExplicit) {
+ Visibility oldVis = visibility();
- setVisibility(V, E);
- }
- // Merge the visibility V, keeping the most restrictive one.
- // This is used for cases like merging the visibility of a template
- // argument to an instantiation. If we already have a hidden class,
- // no argument should give it default visibility.
- void mergeVisibilityWithMin(Visibility V, bool E = false) {
- // Never increase the visibility
- if (visibility() < V)
+ // Never increase visibility.
+ if (oldVis < newVis)
return;
- // FIXME: this
- // If this visibility is explicit, keep it.
- if (visibilityExplicit() && !E)
+ // If the new visibility is the same as the old and the new
+ // visibility isn't explicit, we have nothing to add.
+ if (oldVis == newVis && !newExplicit)
return;
- // should be replaced with this
- // Don't lose the explicit bit for nothing
- // if (visibility() == V && visibilityExplicit())
- // return;
-
- setVisibility(V, E);
+ // Otherwise, we're either decreasing visibility or making our
+ // existing visibility explicit.
+ setVisibility(newVis, newExplicit);
}
- void mergeVisibility(LinkageInfo Other) {
- mergeVisibility(Other.visibility(), Other.visibilityExplicit());
- }
- void mergeVisibilityWithMin(LinkageInfo Other) {
- mergeVisibilityWithMin(Other.visibility(), Other.visibilityExplicit());
+ void mergeVisibility(LinkageInfo other) {
+ mergeVisibility(other.visibility(), other.visibilityExplicit());
}
- void merge(LinkageInfo Other) {
- mergeLinkage(Other);
- mergeVisibility(Other);
+ /// Merge both linkage and visibility.
+ void merge(LinkageInfo other) {
+ mergeLinkage(other);
+ mergeVisibility(other);
}
- void mergeWithMin(LinkageInfo Other) {
- mergeLinkage(Other);
- mergeVisibilityWithMin(Other);
+
+ /// Merge linkage and conditionally merge visibility.
+ void mergeMaybeWithVisibility(LinkageInfo other, bool withVis) {
+ mergeLinkage(other);
+ if (withVis) mergeVisibility(other);
}
};
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 979827a525..f50d774bf1 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -84,6 +84,13 @@ public:
unsigned size() const { return NumParams; }
+ llvm::ArrayRef<NamedDecl*> asArray() {
+ return llvm::ArrayRef<NamedDecl*>(begin(), size());
+ }
+ llvm::ArrayRef<const NamedDecl*> asArray() const {
+ return llvm::ArrayRef<const NamedDecl*>(begin(), size());
+ }
+
NamedDecl* getParam(unsigned Idx) {
assert(Idx < size() && "Template parameter index out-of-range");
return begin()[Idx];
@@ -193,6 +200,11 @@ public:
/// \brief Retrieve the template argument at a given index.
const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
+ /// \brief Produce this as an array ref.
+ llvm::ArrayRef<TemplateArgument> asArray() const {
+ return llvm::ArrayRef<TemplateArgument>(data(), size());
+ }
+
/// \brief Retrieve the number of template arguments in this
/// template argument list.
unsigned size() const { return NumArguments; }
@@ -324,6 +336,23 @@ public:
return getTemplateSpecializationKind() == TSK_ExplicitSpecialization;
}
+ /// \brief True if this declaration is an explicit specialization,
+ /// explicit instantiation declaration, or explicit instantiation
+ /// definition.
+ bool isExplicitInstantiationOrSpecialization() const {
+ switch (getTemplateSpecializationKind()) {
+ case TSK_ExplicitSpecialization:
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ return true;
+
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ return false;
+ }
+ llvm_unreachable("bad template specialization kind");
+ }
+
/// \brief Set the template specialization kind.
void setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
assert(TSK != TSK_Undeclared &&
@@ -1433,6 +1462,23 @@ public:
return getSpecializationKind() == TSK_ExplicitSpecialization;
}
+ /// \brief True if this declaration is an explicit specialization,
+ /// explicit instantiation declaration, or explicit instantiation
+ /// definition.
+ bool isExplicitInstantiationOrSpecialization() const {
+ switch (getTemplateSpecializationKind()) {
+ case TSK_ExplicitSpecialization:
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ return true;
+
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ return false;
+ }
+ llvm_unreachable("bad template specialization kind");
+ }
+
void setSpecializationKind(TemplateSpecializationKind TSK) {
SpecializationKind = TSK;
}
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 6899fdb7d9..da57293b08 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -317,6 +317,12 @@ public:
return Args.NumArgs;
}
+ /// \brief Return the array of arguments in this template argument pack.
+ llvm::ArrayRef<TemplateArgument> getPackAsArray() const {
+ assert(Kind == Pack);
+ return llvm::ArrayRef<TemplateArgument>(Args.Args, Args.NumArgs);
+ }
+
/// \brief Determines whether two template arguments are superficially the
/// same.
bool structurallyEquals(const TemplateArgument &Other) const;