[llvm-branch-commits] [cfe-branch] r122499 - in /cfe/branches/Apple/whitney: include/clang/AST/Decl.h include/clang/AST/DeclBase.h include/clang/AST/Redeclarable.h lib/AST/Decl.cpp lib/AST/Decl.cpp.rej lib/Serialization/ASTReaderDecl.cpp test/CodeGenCXX/visibility.cpp
Daniel Dunbar
daniel at zuster.org
Thu Dec 23 08:34:02 PST 2010
Author: ddunbar
Date: Thu Dec 23 10:34:01 2010
New Revision: 122499
URL: http://llvm.org/viewvc/llvm-project?rev=122499&view=rev
Log:
Merge r117998, r121023, r121025:
--
Author: John McCall <rjmccall at apple.com>
Date: Tue Nov 2 01:45:15 2010 +0000
Ignore attributes on classes when calculating visibility for members
with their own explicit visibility attributes. Basically we only want to
apply a single visibility attribute from any particular ancestry.
Author: Douglas Gregor <dgregor at apple.com>
Date: Mon Dec 6 18:36:25 2010 +0000
Re-implement caching for the linkage calculation of declarations.
My previous attempt at solving the compile-time problem with many
redeclarations of the same entity cached both linkage and visibility,
while this patch only tackles linkage. There are several reasons for
this difference:
- Linkage is a language concept, and is evaluated many times during
semantic analysis and codegen, while visibility is only a
code-generation concept that is evaluated only once per (unique)
declaration. Hence, we *must* optimize linkage calculations but
don't need to optimize visibility computation.
- Once we know the linkage of a declaration, subsequent
redeclarations can't change that linkage. Hence, cache
invalidation is far simpler than for visibility, where a later
redeclaration can completely change the visibility.
- We have 3 spare bits in Decl to store the linkage cache, so the
cache doesn't increase the size of declarations. With the
visibility+linkage cache, NamedDecl got larger.
Author: Douglas Gregor <dgregor at apple.com>
Date: Mon Dec 6 18:50:56 2010 +0000
Use the unused merge() function, fixing an minor, unintended change I
introduced in r121023.
*** MANUAL MERGE ***
Added:
cfe/branches/Apple/whitney/lib/AST/Decl.cpp.rej
Modified:
cfe/branches/Apple/whitney/include/clang/AST/Decl.h
cfe/branches/Apple/whitney/include/clang/AST/DeclBase.h
cfe/branches/Apple/whitney/include/clang/AST/Redeclarable.h
cfe/branches/Apple/whitney/lib/AST/Decl.cpp
cfe/branches/Apple/whitney/lib/Serialization/ASTReaderDecl.cpp
cfe/branches/Apple/whitney/test/CodeGenCXX/visibility.cpp
Modified: cfe/branches/Apple/whitney/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/include/clang/AST/Decl.h?rev=122499&r1=122498&r2=122499&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/include/clang/AST/Decl.h (original)
+++ cfe/branches/Apple/whitney/include/clang/AST/Decl.h Thu Dec 23 10:34:01 2010
@@ -264,7 +264,7 @@
};
/// \brief Determine what kind of linkage this entity has.
- Linkage getLinkage() const { return getLinkageAndVisibility().linkage(); }
+ Linkage getLinkage() const;
/// \brief Determines the visibility of this entity.
Visibility getVisibility() const { return getLinkageAndVisibility().visibility(); }
@@ -272,6 +272,10 @@
/// \brief Determines the linkage and visibility of this entity.
LinkageInfo getLinkageAndVisibility() const;
+ /// \brief Clear the linkage cache in response to a change
+ /// to the declaration.
+ void ClearLinkageCache() { HasCachedLinkage = 0; }
+
/// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for
/// the underlying named decl.
NamedDecl *getUnderlyingDecl();
@@ -625,6 +629,8 @@
bool NRVOVariable : 1;
friend class StmtIteratorBase;
+ friend class ASTDeclReader;
+
protected:
VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo, StorageClass SC,
@@ -660,10 +666,7 @@
StorageClass getStorageClassAsWritten() const {
return (StorageClass) SClassAsWritten;
}
- void setStorageClass(StorageClass SC) {
- assert(isLegalForVariable(SC));
- SClass = SC;
- }
+ void setStorageClass(StorageClass SC);
void setStorageClassAsWritten(StorageClass SC) {
assert(isLegalForVariable(SC));
SClassAsWritten = SC;
@@ -1480,10 +1483,7 @@
}
StorageClass getStorageClass() const { return StorageClass(SClass); }
- void setStorageClass(StorageClass SC) {
- assert(isLegalForFunction(SC));
- SClass = SC;
- }
+ void setStorageClass(StorageClass SC);
StorageClass getStorageClassAsWritten() const {
return StorageClass(SClassAsWritten);
@@ -2513,6 +2513,32 @@
return DB;
}
+template<typename decl_type>
+void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *PrevDecl) {
+ // Note: This routine is implemented here because we need both NamedDecl
+ // and Redeclarable to be defined.
+
+ decl_type *First;
+
+ if (PrevDecl) {
+ // Point to previous. Make sure that this is actually the most recent
+ // redeclaration, or we can build invalid chains. If the most recent
+ // redeclaration is invalid, it won't be PrevDecl, but we want it anyway.
+ RedeclLink = PreviousDeclLink(llvm::cast<decl_type>(
+ PrevDecl->getMostRecentDeclaration()));
+ First = PrevDecl->getFirstDeclaration();
+ assert(First->RedeclLink.NextIsLatest() && "Expected first");
+ } else {
+ // Make this first.
+ First = static_cast<decl_type*>(this);
+ }
+
+ // First one will point to this one as latest.
+ First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this));
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(static_cast<decl_type*>(this)))
+ ND->ClearLinkageCache();
+}
+
} // end namespace clang
#endif
Modified: cfe/branches/Apple/whitney/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/include/clang/AST/DeclBase.h?rev=122499&r1=122498&r2=122499&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/include/clang/AST/DeclBase.h (original)
+++ cfe/branches/Apple/whitney/include/clang/AST/DeclBase.h Thu Dec 23 10:34:01 2010
@@ -198,7 +198,7 @@
return DeclCtx.get<DeclContext*>();
}
- /// Loc - The location that this decl.
+ /// Loc - The location of this decl.
SourceLocation Loc;
/// DeclKind - This indicates which class this is.
@@ -231,8 +231,19 @@
unsigned ChangedAfterLoad : 1;
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
- unsigned IdentifierNamespace : 15;
+ unsigned IdentifierNamespace : 12;
+ /// \brief Whether the \c CachedLinkage field is active.
+ ///
+ /// This field is only valid for NamedDecls subclasses.
+ mutable unsigned HasCachedLinkage : 1;
+
+ /// \brief If \c HasCachedLinkage, the linkage of this declaration.
+ ///
+ /// This field is only valid for NamedDecls subclasses.
+ mutable unsigned CachedLinkage : 2;
+
+
private:
#ifndef NDEBUG
void CheckAccessDeclContext() const;
@@ -247,7 +258,9 @@
Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false),
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
- IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
+ IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
+ HasCachedLinkage(0)
+ {
if (Decl::CollectingStats()) add(DK);
}
@@ -255,7 +268,9 @@
: NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false),
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
- IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
+ IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
+ HasCachedLinkage(0)
+ {
if (Decl::CollectingStats()) add(DK);
}
Modified: cfe/branches/Apple/whitney/include/clang/AST/Redeclarable.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/include/clang/AST/Redeclarable.h?rev=122499&r1=122498&r2=122499&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/include/clang/AST/Redeclarable.h (original)
+++ cfe/branches/Apple/whitney/include/clang/AST/Redeclarable.h Thu Dec 23 10:34:01 2010
@@ -109,25 +109,7 @@
/// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
/// first and only declaration.
- void setPreviousDeclaration(decl_type *PrevDecl) {
- decl_type *First;
-
- if (PrevDecl) {
- // Point to previous. Make sure that this is actually the most recent
- // redeclaration, or we can build invalid chains. If the most recent
- // redeclaration is invalid, it won't be PrevDecl, but we want it anyway.
- RedeclLink = PreviousDeclLink(llvm::cast<decl_type>(
- PrevDecl->getMostRecentDeclaration()));
- First = PrevDecl->getFirstDeclaration();
- assert(First->RedeclLink.NextIsLatest() && "Expected first");
- } else {
- // Make this first.
- First = static_cast<decl_type*>(this);
- }
-
- // First one will point to this one as latest.
- First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this));
- }
+ void setPreviousDeclaration(decl_type *PrevDecl);
/// \brief Iterates through all the redeclarations of the same decl.
class redecl_iterator {
Modified: cfe/branches/Apple/whitney/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/AST/Decl.cpp?rev=122499&r1=122498&r2=122499&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/AST/Decl.cpp (original)
+++ cfe/branches/Apple/whitney/lib/AST/Decl.cpp Thu Dec 23 10:34:01 2010
@@ -95,6 +95,34 @@
minVisibility(L.second, R.visibility()));
}
+/// Flags controlling the computation of linkage and visibility.
+struct LVFlags {
+ bool ConsiderGlobalVisibility;
+ bool ConsiderVisibilityAttributes;
+
+ LVFlags() : ConsiderGlobalVisibility(true),
+ ConsiderVisibilityAttributes(true) {
+ }
+
+ /// \brief Returns a set of flags that is only useful for computing the
+ /// linkage, not the visibility, of a declaration.
+ static LVFlags CreateOnlyDeclLinkage() {
+ LVFlags F;
+ F.ConsiderGlobalVisibility = false;
+ F.ConsiderVisibilityAttributes = false;
+ return F;
+ }
+
+ /// Returns a set of flags, otherwise based on these, which ignores
+ /// off all sources of visibility except template arguments.
+ LVFlags onlyTemplateVisibility() const {
+ LVFlags F = *this;
+ F.ConsiderGlobalVisibility = false;
+ F.ConsiderVisibilityAttributes = false;
+ return F;
+ }
+};
+
/// \brief Get the most restrictive linkage for the types in the given
/// template parameter list.
static LVPair
@@ -118,10 +146,14 @@
return LV;
}
+/// getLVForDecl - Get the linkage and visibility for the given declaration.
+static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags F);
+
/// \brief Get the most restrictive linkage for the types and
/// declarations in the given template argument list.
static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
- unsigned NumArgs) {
+ unsigned NumArgs,
+ LVFlags &F) {
LVPair LV(ExternalLinkage, DefaultVisibility);
for (unsigned I = 0; I != NumArgs; ++I) {
@@ -140,20 +172,19 @@
// arguments, valid only in C++0x.
if (Decl *D = Args[I].getAsDecl()) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
- LV = merge(LV, ND->getLinkageAndVisibility());
- if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
- LV = merge(LV, VD->getLinkageAndVisibility());
+ LV = merge(LV, getLVForDecl(ND, F));
}
break;
case TemplateArgument::Template:
if (TemplateDecl *Template = Args[I].getAsTemplate().getAsTemplateDecl())
- LV = merge(LV, Template->getLinkageAndVisibility());
+ LV = merge(LV, getLVForDecl(Template, F));
break;
case TemplateArgument::Pack:
LV = merge(LV, getLVForTemplateArgumentList(Args[I].pack_begin(),
- Args[I].pack_size()));
+ Args[I].pack_size(),
+ F));
break;
}
}
@@ -161,23 +192,7 @@
return LV;
}
-static LVPair
-getLVForTemplateArgumentList(const TemplateArgumentList &TArgs) {
- return getLVForTemplateArgumentList(TArgs.getFlatArgumentList(),
- TArgs.flat_size());
-}
-
-/// getLVForDecl - Get the cached linkage and visibility for the given
-/// declaration.
-///
-/// \param ConsiderGlobalVisibility - Whether to honor global visibility
-/// settings. This is generally false when computing the visibility
-/// of the context of a declaration.
-static LinkageInfo getLVForDecl(const NamedDecl *D,
- bool ConsiderGlobalVisibility);
-
-static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
- bool ConsiderGlobalVisibility) {
+static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
"Not a name having namespace scope");
ASTContext &Context = D->getASTContext();
@@ -242,8 +257,11 @@
// external.
LinkageInfo LV;
- if (const VisibilityAttr *VA = GetExplicitVisibility(D)) {
- LV.setVisibility(GetVisibilityFromAttr(VA), true);
+ if (F.ConsiderVisibilityAttributes) {
+ if (const VisibilityAttr *VA = GetExplicitVisibility(D)) {
+ LV.setVisibility(GetVisibilityFromAttr(VA), true);
+ F.ConsiderGlobalVisibility = false;
+ }
}
// C++ [basic.link]p4:
@@ -299,7 +317,7 @@
// is visible, or if the prior declaration specifies no
// linkage, then the identifier has external linkage.
if (const VarDecl *PrevVar = Var->getPreviousDeclaration()) {
- LinkageInfo PrevLV = PrevVar->getLinkageAndVisibility();
+ LinkageInfo PrevLV = getLVForDecl(PrevVar, F);
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
LV.mergeVisibility(PrevLV);
}
@@ -334,7 +352,7 @@
// is visible, or if the prior declaration specifies no
// linkage, then the identifier has external linkage.
if (const FunctionDecl *PrevFunc = Function->getPreviousDeclaration()) {
- LinkageInfo PrevLV = PrevFunc->getLinkageAndVisibility();
+ LinkageInfo PrevLV = getLVForDecl(PrevFunc, F);
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
LV.mergeVisibility(PrevLV);
}
@@ -342,9 +360,12 @@
if (FunctionTemplateSpecializationInfo *SpecInfo
= Function->getTemplateSpecializationInfo()) {
- LV.merge(SpecInfo->getTemplate()->getLinkageAndVisibility());
+ LV.merge(getLVForDecl(SpecInfo->getTemplate(),
+ F.onlyTemplateVisibility()));
const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments;
- LV.merge(getLVForTemplateArgumentList(TemplateArgs));
+ LV.merge(getLVForTemplateArgumentList(TemplateArgs.getFlatArgumentList(),
+ TemplateArgs.flat_size(),
+ F));
}
// - a named class (Clause 9), or an unnamed class defined in a
@@ -362,25 +383,26 @@
// linkage of the template and template arguments.
if (const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
- // From the template. Note below the restrictions on how we
- // compute template visibility.
- LV.merge(Spec->getSpecializedTemplate()->getLinkageAndVisibility());
+ // From the template.
+ LV.merge(getLVForDecl(Spec->getSpecializedTemplate(),
+ F.onlyTemplateVisibility()));
// The arguments at which the template was instantiated.
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
- LV.merge(getLVForTemplateArgumentList(TemplateArgs));
+ LV.merge(getLVForTemplateArgumentList(TemplateArgs.getFlatArgumentList(),
+ TemplateArgs.flat_size(),
+ F));
}
// Consider -fvisibility unless the type has C linkage.
- if (ConsiderGlobalVisibility)
- ConsiderGlobalVisibility =
+ if (F.ConsiderGlobalVisibility)
+ F.ConsiderGlobalVisibility =
(Context.getLangOptions().CPlusPlus &&
!Tag->getDeclContext()->isExternCContext());
// - an enumerator belonging to an enumeration with external linkage;
} else if (isa<EnumConstantDecl>(D)) {
- LinkageInfo EnumLV =
- cast<NamedDecl>(D->getDeclContext())->getLinkageAndVisibility();
+ LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()), F);
if (!isExternalLinkage(EnumLV.linkage()))
return LinkageInfo::none();
LV.merge(EnumLV);
@@ -390,10 +412,6 @@
} else if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
LV.merge(getLVForTemplateParameterList(Template->getTemplateParameters()));
- // We do not want to consider attributes or global settings when
- // computing template visibility.
- return LV;
-
// - a namespace (7.3), unless it is declared within an unnamed
// namespace.
} else if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace()) {
@@ -416,15 +434,13 @@
// If we didn't end up with hidden visibility, consider attributes
// and -fvisibility.
- if (ConsiderGlobalVisibility && !LV.visibilityExplicit() &&
- LV.visibility() != HiddenVisibility)
+ if (F.ConsiderGlobalVisibility)
LV.mergeVisibility(Context.getLangOptions().getVisibilityMode());
return LV;
}
-static LinkageInfo getLVForClassMember(const NamedDecl *D,
- bool ConsiderGlobalVisibility) {
+static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
// Only certain class members have linkage. Note that fields don't
// really have linkage, but it's convenient to say they do for the
// purposes of calculating linkage of pointer-to-data-member
@@ -436,29 +452,35 @@
(D->getDeclName() || cast<TagDecl>(D)->getTypedefForAnonDecl()))))
return LinkageInfo::none();
- const VisibilityAttr *VA = GetExplicitVisibility(D);
- if (VA)
- ConsiderGlobalVisibility = false;
+ LinkageInfo LV;
+
+ // The flags we're going to use to compute the class's visibility.
+ LVFlags ClassF = F;
+
+ // If we have an explicit visibility attribute, merge that in.
+ if (F.ConsiderVisibilityAttributes) {
+ if (const VisibilityAttr *VA = GetExplicitVisibility(D)) {
+ LV.mergeVisibility(GetVisibilityFromAttr(VA), true);
+
+ // Ignore global visibility later, but not this attribute.
+ F.ConsiderGlobalVisibility = false;
+
+ // Ignore both global visibility and attributes when computing our
+ // parent's visibility.
+ ClassF = F.onlyTemplateVisibility();
+ }
+ }
// Class members only have linkage if their class has external
- // linkage. Consider global visibility only if we have no explicit
- // visibility attributes.
- LinkageInfo ClassLV = getLVForDecl(cast<RecordDecl>(D->getDeclContext()),
- ConsiderGlobalVisibility);
- if (!isExternalLinkage(ClassLV.linkage()))
+ // linkage.
+ LV.merge(getLVForDecl(cast<RecordDecl>(D->getDeclContext()), ClassF));
+ if (!isExternalLinkage(LV.linkage()))
return LinkageInfo::none();
// If the class already has unique-external linkage, we can't improve.
- if (ClassLV.linkage() == UniqueExternalLinkage)
+ if (LV.linkage() == UniqueExternalLinkage)
return LinkageInfo::uniqueExternal();
- // Start with the class's linkage and visibility.
- LinkageInfo LV = ClassLV;
-
- // If we have an explicit visibility attribute, merge that in.
- if (VA)
- LV.mergeVisibility(GetVisibilityFromAttr(VA), true);
-
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
TemplateSpecializationKind TSK = TSK_Undeclared;
@@ -466,7 +488,10 @@
// the template parameters and arguments.
if (FunctionTemplateSpecializationInfo *Spec
= MD->getTemplateSpecializationInfo()) {
- LV.merge(getLVForTemplateArgumentList(*Spec->TemplateArguments));
+ LV.merge(getLVForTemplateArgumentList(
+ Spec->TemplateArguments->getFlatArgumentList(),
+ Spec->TemplateArguments->flat_size(),
+ F));
LV.merge(getLVForTemplateParameterList(
Spec->getTemplate()->getTemplateParameters()));
@@ -483,7 +508,7 @@
// about whether containing classes have visibility attributes,
// and that's intentional.
if (TSK != TSK_ExplicitInstantiationDeclaration &&
- ConsiderGlobalVisibility &&
+ F.ConsiderGlobalVisibility &&
MD->getASTContext().getLangOptions().InlineVisibilityHidden) {
// InlineVisibilityHidden only applies to definitions, and
// isInlined() only gives meaningful answers on definitions
@@ -501,7 +526,10 @@
= dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
// Merge template argument/parameter information for member
// class template specializations.
- LV.merge(getLVForTemplateArgumentList(Spec->getTemplateArgs()));
+ const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+ LV.merge(getLVForTemplateArgumentList(TemplateArgs.getFlatArgumentList(),
+ TemplateArgs.flat_size(),
+ F));
LV.merge(getLVForTemplateParameterList(
Spec->getSpecializedTemplate()->getTemplateParameters()));
}
@@ -517,22 +545,40 @@
LV.mergeVisibility(TypeLV.second);
}
- ConsiderGlobalVisibility &= !LV.visibilityExplicit();
+ F.ConsiderGlobalVisibility &= !LV.visibilityExplicit();
// Apply -fvisibility if desired.
- if (ConsiderGlobalVisibility && LV.visibility() != HiddenVisibility) {
+ if (F.ConsiderGlobalVisibility && LV.visibility() != HiddenVisibility) {
LV.mergeVisibility(D->getASTContext().getLangOptions().getVisibilityMode());
}
return LV;
}
+Linkage NamedDecl::getLinkage() const {
+ if (HasCachedLinkage) {
+#ifndef NDEBUG
+ assert(CachedLinkage == getLVForDecl(this,
+ LVFlags::CreateOnlyDeclLinkage()).linkage());
+#endif
+ return Linkage(CachedLinkage);
+ }
+
+ CachedLinkage = getLVForDecl(this,
+ LVFlags::CreateOnlyDeclLinkage()).linkage();
+ HasCachedLinkage = 1;
+ return Linkage(CachedLinkage);
+}
+
LinkageInfo NamedDecl::getLinkageAndVisibility() const {
- return getLVForDecl(this, /*ConsiderGlobalSettings*/ true);
+ LinkageInfo LI = getLVForDecl(this, LVFlags());
+ assert(!HasCachedLinkage || (CachedLinkage == LI.linkage()));
+ HasCachedLinkage = 1;
+ CachedLinkage = LI.linkage();
+ return LI;
}
-static LinkageInfo getLVForDecl(const NamedDecl *D,
- bool ConsiderGlobalVisibility) {
+static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
// Objective-C: treat all Objective-C declarations as having external
// linkage.
switch (D->getKind()) {
@@ -555,7 +601,7 @@
// Handle linkage for namespace-scope names.
if (D->getDeclContext()->getRedeclContext()->isFileContext())
- return getLVForNamespaceScopeDecl(D, ConsiderGlobalVisibility);
+ return getLVForNamespaceScopeDecl(D, Flags);
// C++ [basic.link]p5:
// In addition, a member function, static data member, a named
@@ -565,7 +611,7 @@
// purposes (7.1.3), has external linkage if the name of the class
// has external linkage.
if (D->getDeclContext()->isRecord())
- return getLVForClassMember(D, ConsiderGlobalVisibility);
+ return getLVForClassMember(D, Flags);
// C++ [basic.link]p6:
// The name of a function declared in block scope and the name of
@@ -584,11 +630,13 @@
return LinkageInfo::uniqueExternal();
LinkageInfo LV;
- if (const VisibilityAttr *VA = GetExplicitVisibility(Function))
- LV.setVisibility(GetVisibilityFromAttr(VA));
-
+ if (Flags.ConsiderVisibilityAttributes) {
+ if (const VisibilityAttr *VA = GetExplicitVisibility(Function))
+ LV.setVisibility(GetVisibilityFromAttr(VA));
+ }
+
if (const FunctionDecl *Prev = Function->getPreviousDeclaration()) {
- LinkageInfo PrevLV = Prev->getLinkageAndVisibility();
+ LinkageInfo PrevLV = getLVForDecl(Prev, Flags);
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
LV.mergeVisibility(PrevLV);
}
@@ -605,11 +653,13 @@
LinkageInfo LV;
if (Var->getStorageClass() == SC_PrivateExtern)
LV.setVisibility(HiddenVisibility);
- else if (const VisibilityAttr *VA = GetExplicitVisibility(Var))
- LV.setVisibility(GetVisibilityFromAttr(VA));
-
+ else if (Flags.ConsiderVisibilityAttributes) {
+ if (const VisibilityAttr *VA = GetExplicitVisibility(Var))
+ LV.setVisibility(GetVisibilityFromAttr(VA));
+ }
+
if (const VarDecl *Prev = Var->getPreviousDeclaration()) {
- LinkageInfo PrevLV = Prev->getLinkageAndVisibility();
+ LinkageInfo PrevLV = getLVForDecl(Prev, Flags);
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
LV.mergeVisibility(PrevLV);
}
@@ -881,6 +931,14 @@
return new (C) VarDecl(Var, DC, L, Id, T, TInfo, S, SCAsWritten);
}
+void VarDecl::setStorageClass(StorageClass SC) {
+ assert(isLegalForVariable(SC));
+ if (getStorageClass() != SC)
+ ClearLinkageCache();
+
+ SClass = SC;
+}
+
SourceLocation VarDecl::getInnerLocStart() const {
SourceLocation Start = getTypeSpecStartLoc();
if (Start.isInvalid())
@@ -1284,6 +1342,14 @@
return getFirstDeclaration();
}
+void FunctionDecl::setStorageClass(StorageClass SC) {
+ assert(isLegalForFunction(SC));
+ if (getStorageClass() != SC)
+ ClearLinkageCache();
+
+ SClass = SC;
+}
+
/// \brief Returns a value indicating whether this function
/// corresponds to a builtin function.
///
@@ -1789,6 +1855,7 @@
TypedefDeclOrQualifier = TDD;
if (TypeForDecl)
TypeForDecl->ClearLinkageCache();
+ ClearLinkageCache();
}
void TagDecl::startDefinition() {
Added: cfe/branches/Apple/whitney/lib/AST/Decl.cpp.rej
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/AST/Decl.cpp.rej?rev=122499&view=auto
==============================================================================
--- cfe/branches/Apple/whitney/lib/AST/Decl.cpp.rej (added)
+++ cfe/branches/Apple/whitney/lib/AST/Decl.cpp.rej Thu Dec 23 10:34:01 2010
@@ -0,0 +1,52 @@
+***************
+*** 102,108 ****
+ F.ConsiderVisibilityAttributes = false;
+ return F;
+ }
+- };
+ } // end anonymous namespace
+
+ /// \brief Get the most restrictive linkage for the types in the given
+--- 102,108 ----
+ F.ConsiderVisibilityAttributes = false;
+ return F;
+ }
++ };
+ } // end anonymous namespace
+
+ /// \brief Get the most restrictive linkage for the types in the given
+***************
+*** 153,170 ****
+ // The decl can validly be null as the representation of nullptr
+ // arguments, valid only in C++0x.
+ if (Decl *D = Args[I].getAsDecl()) {
+- if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+- LinkageInfo LI = getLVForDecl(ND, F);
+- LV = merge(LV, LVPair(LI.linkage(), LI.visibility()));
+- }
+ }
+ break;
+
+ case TemplateArgument::Template:
+- if (TemplateDecl *Template = Args[I].getAsTemplate().getAsTemplateDecl()){
+- LinkageInfo LI = getLVForDecl(Template, F);
+- LV = merge(LV, LVPair(LI.linkage(), LI.visibility()));
+- }
+ break;
+
+ case TemplateArgument::Pack:
+--- 153,166 ----
+ // The decl can validly be null as the representation of nullptr
+ // arguments, valid only in C++0x.
+ if (Decl *D = Args[I].getAsDecl()) {
++ if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
++ LV = merge(LV, getLVForDecl(ND, F));
+ }
+ break;
+
+ case TemplateArgument::Template:
++ if (TemplateDecl *Template = Args[I].getAsTemplate().getAsTemplateDecl())
++ LV = merge(LV, getLVForDecl(Template, F));
+ break;
+
+ case TemplateArgument::Pack:
Modified: cfe/branches/Apple/whitney/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Serialization/ASTReaderDecl.cpp?rev=122499&r1=122498&r2=122499&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/branches/Apple/whitney/lib/Serialization/ASTReaderDecl.cpp Thu Dec 23 10:34:01 2010
@@ -382,7 +382,7 @@
// FunctionDecl's body is handled last at ASTDeclReader::Visit,
// after everything else is read.
- FD->setStorageClass((StorageClass)Record[Idx++]);
+ FD->SClass = (StorageClass)Record[Idx++];
FD->setStorageClassAsWritten((StorageClass)Record[Idx++]);
FD->IsInline = Record[Idx++];
FD->IsInlineSpecified = Record[Idx++];
@@ -639,7 +639,7 @@
void ASTDeclReader::VisitVarDecl(VarDecl *VD) {
VisitDeclaratorDecl(VD);
VisitRedeclarable(VD);
- VD->setStorageClass((StorageClass)Record[Idx++]);
+ VD->SClass = (StorageClass)Record[Idx++];
VD->setStorageClassAsWritten((StorageClass)Record[Idx++]);
VD->setThreadSpecified(Record[Idx++]);
VD->setCXXDirectInitializer(Record[Idx++]);
Modified: cfe/branches/Apple/whitney/test/CodeGenCXX/visibility.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/test/CodeGenCXX/visibility.cpp?rev=122499&r1=122498&r2=122499&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/test/CodeGenCXX/visibility.cpp (original)
+++ cfe/branches/Apple/whitney/test/CodeGenCXX/visibility.cpp Thu Dec 23 10:34:01 2010
@@ -255,6 +255,95 @@
}
}
+namespace Test17 {
+ struct HIDDEN A {
+ static void foo();
+ static void DEFAULT bar();
+ static void HIDDEN baz();
+
+ struct DEFAULT B {
+ static void foo();
+ static void DEFAULT bar();
+ static void HIDDEN baz();
+ };
+ };
+
+ void test() {
+ A::foo();
+ A::bar();
+ A::baz();
+ A::B::foo();
+ A::B::bar();
+ A::B::baz();
+ }
+ // CHECK: declare hidden void @_ZN6Test171A3fooEv()
+ // CHECK: declare void @_ZN6Test171A3barEv()
+ // CHECK: declare hidden void @_ZN6Test171A3bazEv()
+ // CHECK: declare void @_ZN6Test171A1B3fooEv()
+ // CHECK: declare void @_ZN6Test171A1B3barEv()
+ // CHECK: declare hidden void @_ZN6Test171A1B3bazEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test171A3fooEv()
+ // CHECK-HIDDEN: declare void @_ZN6Test171A3barEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test171A3bazEv()
+ // CHECK-HIDDEN: declare void @_ZN6Test171A1B3fooEv()
+ // CHECK-HIDDEN: declare void @_ZN6Test171A1B3barEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test171A1B3bazEv()
+}
+
+namespace Test18 {
+ template <class T> struct HIDDEN A {
+ static void foo();
+ static void DEFAULT bar();
+ static void HIDDEN baz();
+
+ struct DEFAULT B {
+ static void foo();
+ static void DEFAULT bar();
+ static void HIDDEN baz();
+ };
+ };
+ struct HIDDEN H;
+
+ void test() {
+ A<int>::foo();
+ A<int>::bar();
+ A<int>::baz();
+ A<int>::B::foo();
+ A<int>::B::bar();
+ A<int>::B::baz();
+ A<H>::foo();
+ A<H>::bar();
+ A<H>::baz();
+ A<H>::B::foo();
+ A<H>::B::bar();
+ A<H>::B::baz();
+ }
+ // CHECK: declare hidden void @_ZN6Test181AIiE3fooEv()
+ // CHECK: declare void @_ZN6Test181AIiE3barEv()
+ // CHECK: declare hidden void @_ZN6Test181AIiE3bazEv()
+ // CHECK: declare void @_ZN6Test181AIiE1B3fooEv()
+ // CHECK: declare void @_ZN6Test181AIiE1B3barEv()
+ // CHECK: declare hidden void @_ZN6Test181AIiE1B3bazEv()
+ // CHECK: declare hidden void @_ZN6Test181AINS_1HEE3fooEv()
+ // CHECK: declare hidden void @_ZN6Test181AINS_1HEE3barEv()
+ // CHECK: declare hidden void @_ZN6Test181AINS_1HEE3bazEv()
+ // CHECK: declare hidden void @_ZN6Test181AINS_1HEE1B3fooEv()
+ // CHECK: declare hidden void @_ZN6Test181AINS_1HEE1B3barEv()
+ // CHECK: declare hidden void @_ZN6Test181AINS_1HEE1B3bazEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AIiE3fooEv()
+ // CHECK-HIDDEN: declare void @_ZN6Test181AIiE3barEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AIiE3bazEv()
+ // CHECK-HIDDEN: declare void @_ZN6Test181AIiE1B3fooEv()
+ // CHECK-HIDDEN: declare void @_ZN6Test181AIiE1B3barEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AIiE1B3bazEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE3fooEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE3barEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE3bazEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE1B3fooEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE1B3barEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE1B3bazEv()
+}
+
namespace Test19 {
struct A { A(); ~A(); };
More information about the llvm-branch-commits
mailing list