[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