[cfe-commits] r117147 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ lib/AST/ lib/CodeGen/ lib/Frontend/ lib/Serialization/ test/CodeGenCXX/ test/Index/

John McCall rjmccall at apple.com
Fri Oct 22 14:05:15 PDT 2010


Author: rjmccall
Date: Fri Oct 22 16:05:15 2010
New Revision: 117147

URL: http://llvm.org/viewvc/llvm-project?rev=117147&view=rev
Log:
Substantially revise how clang computes the visibility of a declaration to
more closely parallel the computation of linkage.  This gets us to a state
much closer to what gcc emits, modulo bugs, which will undoubtedly arise in
abundance.


Added:
    cfe/trunk/include/clang/Basic/Visibility.h
Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Basic/LangOptions.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CGObjCMac.cpp
    cfe/trunk/lib/CodeGen/CGRTTI.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/test/CodeGenCXX/member-pointer-type-convert.cpp
    cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp
    cfe/trunk/test/CodeGenCXX/visibility.cpp
    cfe/trunk/test/Index/index-templates.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Oct 22 16:05:15 2010
@@ -197,7 +197,13 @@
   bool isCXXInstanceMember() const;
 
   /// \brief Determine what kind of linkage this entity has.
-  Linkage getLinkage() const;
+  Linkage getLinkage() const { return getLinkageAndVisibility().first; }
+
+  /// \brief Determines the visibility of this entity.
+  Visibility getVisibility() const { return getLinkageAndVisibility().second; }
+
+  /// \brief Determines the linkage and visibility of this entity.
+  std::pair<Linkage,Visibility> getLinkageAndVisibility() const;
 
   /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for
   /// the underlying named decl.

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Fri Oct 22 16:05:15 2010
@@ -18,6 +18,7 @@
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/Linkage.h"
 #include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/Visibility.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/TemplateName.h"
 #include "llvm/Support/Casting.h"
@@ -800,9 +801,10 @@
     /// \brief Whether this type is a variably-modified type (C99 6.7.5).
     unsigned VariablyModified : 1;
   
-    /// \brief Whether the linkage of this type along with the presence of any
-    /// local or unnamed types is already known.
-    mutable unsigned LinkageKnown : 1;
+    /// \brief Nonzero if the cache (i.e. the bitfields here starting
+    /// with 'Cache') is valid.  If so, then this is a
+    /// LangOptions::VisibilityMode+1.
+    mutable unsigned CacheValidAndVisibility : 2;
   
     /// \brief Linkage of this type.
     mutable unsigned CachedLinkage : 2;
@@ -813,7 +815,21 @@
     /// \brief FromAST - Whether this type comes from an AST file.
     mutable unsigned FromAST : 1;
 
-    unsigned SpareBit : 1;
+    bool isCacheValid() const {
+      return (CacheValidAndVisibility != 0);
+    }
+    Visibility getVisibility() const {
+      assert(isCacheValid() && "getting linkage from invalid cache");
+      return static_cast<Visibility>(CacheValidAndVisibility-1);
+    }
+    Linkage getLinkage() const {
+      assert(isCacheValid() && "getting linkage from invalid cache");
+      return static_cast<Linkage>(CachedLinkage);
+    }
+    bool hasLocalOrUnnamedType() const {
+      assert(isCacheValid() && "getting linkage from invalid cache");
+      return CachedLocalOrUnnamed;
+    }
   };
   enum { NumTypeBits = 16 };
 
@@ -938,10 +954,35 @@
     TypeBits.FromAST = V;
   }
 
+  void ensureCachedProperties() const;
+
 protected:
-  /// \brief Compute the linkage of this type along with the presence of
-  /// any local or unnamed types.
-  virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
+  /// \brief Compute the cached properties of this type.
+  class CachedProperties {
+    char linkage;
+    char visibility;
+    bool local;
+
+  public:
+    CachedProperties(Linkage linkage, Visibility visibility, bool local)
+      : linkage(linkage), visibility(visibility), local(local) {}
+
+    Linkage getLinkage() const { return (Linkage) linkage; }
+    Visibility getVisibility() const { return (Visibility) visibility; }
+    bool hasLocalOrUnnamedType() const { return local; }
+
+    friend CachedProperties merge(CachedProperties L, CachedProperties R) {
+      return CachedProperties(minLinkage(L.getLinkage(), R.getLinkage()),
+                         minVisibility(L.getVisibility(), R.getVisibility()),
+                      L.hasLocalOrUnnamedType() | R.hasLocalOrUnnamedType());
+    }
+  };
+
+  virtual CachedProperties getCachedProperties() const;
+  static CachedProperties getCachedProperties(QualType T) {
+    return getCachedProperties(T.getTypePtr());
+  }
+  static CachedProperties getCachedProperties(const Type *T);
 
   // silence VC++ warning C4355: 'this' : used in base member initializer list
   Type *this_() { return this; }
@@ -950,7 +991,7 @@
     TypeBits.TC = tc;
     TypeBits.Dependent = Dependent;
     TypeBits.VariablyModified = VariablyModified;
-    TypeBits.LinkageKnown = false;
+    TypeBits.CacheValidAndVisibility = 0;
     TypeBits.CachedLocalOrUnnamed = false;
     TypeBits.CachedLinkage = NoLinkage;
     TypeBits.FromAST = false;
@@ -1191,6 +1232,12 @@
 
   /// \brief Determine the linkage of this type.
   Linkage getLinkage() const;
+
+  /// \brief Determine the visibility of this type.
+  Visibility getVisibility() const;
+
+  /// \brief Determine the linkage and visibility of this type.
+  std::pair<Linkage,Visibility> getLinkageAndVisibility() const;
   
   /// \brief Note that the linkage is no longer known.
   void ClearLinkageCache();
@@ -1278,7 +1325,7 @@
   };
 
 protected:
-  virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
+  virtual CachedProperties getCachedProperties() const;
   
 public:
   BuiltinType(Kind K)
@@ -1334,7 +1381,7 @@
   friend class ASTContext;  // ASTContext creates these.
 
 protected:
-  virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
+  virtual CachedProperties getCachedProperties() const;
   
 public:
   QualType getElementType() const { return ElementType; }
@@ -1366,7 +1413,7 @@
   friend class ASTContext;  // ASTContext creates these.
 
 protected:
-  virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
+  virtual CachedProperties getCachedProperties() const;
   
 public:
 
@@ -1400,7 +1447,7 @@
   friend class ASTContext;  // ASTContext creates these.
   
 protected:
-  virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
+  virtual CachedProperties getCachedProperties() const;
   
 public:
 
@@ -1437,7 +1484,7 @@
     ReferenceTypeBits.InnerRef = Referencee->isReferenceType();
   }
   
-  virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
+  virtual CachedProperties getCachedProperties() const;
   
 public:
   bool isSpelledAsLValue() const { return ReferenceTypeBits.SpelledAsLValue; }
@@ -1521,7 +1568,7 @@
   friend class ASTContext; // ASTContext creates these.
   
 protected:
-  virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
+  virtual CachedProperties getCachedProperties() const;
   
 public:
   QualType getPointeeType() const { return PointeeType; }
@@ -1590,7 +1637,7 @@
 
   friend class ASTContext;  // ASTContext creates these.
 
-  virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
+  virtual CachedProperties getCachedProperties() const;
   
 public:
   QualType getElementType() const { return ElementType; }
@@ -1893,7 +1940,7 @@
   }
   friend class ASTContext;  // ASTContext creates these.
   
-  virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
+  virtual CachedProperties getCachedProperties() const;
   
 public:
 
@@ -2123,7 +2170,7 @@
   friend class ASTContext;  // ASTContext creates these.
   
 protected:
-  virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
+  virtual CachedProperties getCachedProperties() const;
   
 public:
   // No additional state past what FunctionType provides.
@@ -2179,7 +2226,7 @@
   friend class ASTContext;  // ASTContext creates these.
 
 protected:
-  virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
+  virtual CachedProperties getCachedProperties() const;
   
 public:
   unsigned getNumArgs() const { return NumArgs; }
@@ -2421,7 +2468,7 @@
 protected:
   TagType(TypeClass TC, const TagDecl *D, QualType can);
 
-  virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
+  virtual CachedProperties getCachedProperties() const;
   
 public:
   TagDecl *getDecl() const;
@@ -3084,7 +3131,7 @@
   }
 
 protected:
-  std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const; // key function
+  CachedProperties getCachedProperties() const; // key function
   
 public:
   /// getBaseType - Gets the base type of this object type.  This is
@@ -3192,6 +3239,10 @@
     : ObjCObjectType(Nonce_ObjCInterface),
       Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
   friend class ASTContext;  // ASTContext creates these.
+
+protected:
+  virtual CachedProperties getCachedProperties() const;
+  
 public:
   /// getDecl - Get the declaration of this interface.
   ObjCInterfaceDecl *getDecl() const { return Decl; }
@@ -3242,7 +3293,7 @@
   friend class ASTContext;  // ASTContext creates these.
 
 protected:
-  virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
+  virtual CachedProperties getCachedProperties() const;
   
 public:
   /// getPointeeType - Gets the type pointed to by this ObjC pointer.

Modified: cfe/trunk/include/clang/Basic/LangOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.h?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/LangOptions.h (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.h Fri Oct 22 16:05:15 2010
@@ -15,6 +15,7 @@
 #define LLVM_CLANG_LANGOPTIONS_H
 
 #include <string>
+#include "clang/Basic/Visibility.h"
 
 namespace clang {
 
@@ -131,11 +132,6 @@
 
   enum GCMode { NonGC, GCOnly, HybridGC };
   enum StackProtectorMode { SSPOff, SSPOn, SSPReq };
-  enum VisibilityMode {
-    Default,
-    Protected,
-    Hidden
-  };
 
   enum SignedOverflowBehaviorTy {
     SOB_Undefined,  // Default C standard behavior.
@@ -161,7 +157,7 @@
     HeinousExtensions = 0;
     AltiVec = OpenCL = StackProtector = 0;
 
-    SymbolVisibility = (unsigned) Default;
+    SymbolVisibility = (unsigned) DefaultVisibility;
 
     ThreadsafeStatics = 1;
     POSIXThreads = 0;
@@ -208,10 +204,10 @@
     StackProtector = static_cast<unsigned>(m);
   }
 
-  VisibilityMode getVisibilityMode() const {
-    return (VisibilityMode) SymbolVisibility;
+  Visibility getVisibilityMode() const {
+    return (Visibility) SymbolVisibility;
   }
-  void setVisibilityMode(VisibilityMode v) { SymbolVisibility = (unsigned) v; }
+  void setVisibilityMode(Visibility v) { SymbolVisibility = (unsigned) v; }
 
   SignedOverflowBehaviorTy getSignedOverflowBehavior() const {
     return (SignedOverflowBehaviorTy)SignedOverflowBehavior;

Added: cfe/trunk/include/clang/Basic/Visibility.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Visibility.h?rev=117147&view=auto
==============================================================================
--- cfe/trunk/include/clang/Basic/Visibility.h (added)
+++ cfe/trunk/include/clang/Basic/Visibility.h Fri Oct 22 16:05:15 2010
@@ -0,0 +1,48 @@
+//===--- Visibility.h - Visibility enumeration and 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 defines the Visibility enumeration and various utility
+// functions.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_VISIBILITY_H
+#define LLVM_CLANG_BASIC_VISIBILITY_H
+
+namespace clang {
+
+/// \link Describes the different kinds of visibility that a
+/// declaration may have.  Visibility determines how a declaration
+/// interacts with the dynamic linker.  It may also affect whether the
+/// symbol can be found by runtime symbol lookup APIs.
+///
+/// Visibility is not described in any language standard and
+/// (nonetheless) sometimes has odd behavior.  Not all platforms
+/// support all visibility kinds.
+enum Visibility {
+  /// Objects with "hidden" visibility are not seen by the dynamic
+  /// linker.
+  HiddenVisibility,
+
+  /// Objects with "protected" visibility are seen by the dynamic
+  /// linker but always dynamically resolve to an object within this
+  /// shared object.
+  ProtectedVisibility,
+
+  /// Objects with "default" visibility are seen by the dynamic linker
+  /// and act like normal objects.
+  DefaultVisibility
+};
+
+inline Visibility minVisibility(Visibility L, Visibility R) {
+  return L < R ? L : R;
+}
+
+}
+
+#endif // LLVM_CLANG_BASIC_VISIBILITY_H

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Fri Oct 22 16:05:15 2010
@@ -32,35 +32,53 @@
 // NamedDecl Implementation
 //===----------------------------------------------------------------------===//
 
+static Visibility GetVisibilityFromAttr(const VisibilityAttr *A) {
+  switch (A->getVisibility()) {
+  case VisibilityAttr::Default:
+    return DefaultVisibility;
+  case VisibilityAttr::Hidden:
+    return HiddenVisibility;
+  case VisibilityAttr::Protected:
+    return ProtectedVisibility;
+  }
+  return DefaultVisibility;
+}
+
+typedef std::pair<Linkage,Visibility> LVPair;
+static LVPair merge(LVPair L, LVPair R) {
+  return LVPair(minLinkage(L.first, R.first),
+                minVisibility(L.second, R.second));
+}
+
 /// \brief Get the most restrictive linkage for the types in the given
 /// template parameter list.
-static Linkage 
-getLinkageForTemplateParameterList(const TemplateParameterList *Params) {
-  Linkage L = ExternalLinkage;
+static LVPair 
+getLVForTemplateParameterList(const TemplateParameterList *Params) {
+  LVPair LV(ExternalLinkage, DefaultVisibility);
   for (TemplateParameterList::const_iterator P = Params->begin(),
                                           PEnd = Params->end();
        P != PEnd; ++P) {
     if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P))
       if (!NTTP->getType()->isDependentType()) {
-        L = minLinkage(L, NTTP->getType()->getLinkage());
+        LV = merge(LV, NTTP->getType()->getLinkageAndVisibility());
         continue;
       }
 
     if (TemplateTemplateParmDecl *TTP
                                    = dyn_cast<TemplateTemplateParmDecl>(*P)) {
-      L = minLinkage(L, 
-            getLinkageForTemplateParameterList(TTP->getTemplateParameters()));
+      LV =
+        merge(LV, getLVForTemplateParameterList(TTP->getTemplateParameters()));
     }
   }
 
-  return L;
+  return LV;
 }
 
 /// \brief Get the most restrictive linkage for the types and
 /// declarations in the given template argument list.
-static Linkage getLinkageForTemplateArgumentList(const TemplateArgument *Args,
-                                                 unsigned NumArgs) {
-  Linkage L = ExternalLinkage;
+static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
+                                           unsigned NumArgs) {
+  LVPair LV(ExternalLinkage, DefaultVisibility);
 
   for (unsigned I = 0; I != NumArgs; ++I) {
     switch (Args[I].getKind()) {
@@ -70,40 +88,41 @@
       break;
       
     case TemplateArgument::Type:
-      L = minLinkage(L, Args[I].getAsType()->getLinkage());
+      LV = merge(LV, Args[I].getAsType()->getLinkageAndVisibility());
       break;
 
     case TemplateArgument::Declaration:
-      if (NamedDecl *ND = dyn_cast<NamedDecl>(Args[I].getAsDecl()))
-        L = minLinkage(L, ND->getLinkage());
-      if (ValueDecl *VD = dyn_cast<ValueDecl>(Args[I].getAsDecl()))
-        L = minLinkage(L, VD->getType()->getLinkage());
+      // 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, ND->getLinkageAndVisibility());
+        if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
+          LV = merge(LV, VD->getType()->getLinkageAndVisibility());
+      }
       break;
 
     case TemplateArgument::Template:
-      if (TemplateDecl *Template
-                                = Args[I].getAsTemplate().getAsTemplateDecl())
-        L = minLinkage(L, Template->getLinkage());
+      if (TemplateDecl *Template = Args[I].getAsTemplate().getAsTemplateDecl())
+        LV = merge(LV, Template->getLinkageAndVisibility());
       break;
 
     case TemplateArgument::Pack:
-      L = minLinkage(L, 
-                     getLinkageForTemplateArgumentList(Args[I].pack_begin(),
-                                                       Args[I].pack_size()));
+      LV = merge(LV, getLVForTemplateArgumentList(Args[I].pack_begin(),
+                                                  Args[I].pack_size()));
       break;
     }
   }
 
-  return L;
+  return LV;
 }
 
-static Linkage
-getLinkageForTemplateArgumentList(const TemplateArgumentList &TArgs) {
-  return getLinkageForTemplateArgumentList(TArgs.getFlatArgumentList(), 
-                                           TArgs.flat_size());
+static LVPair getLVForTemplateArgumentList(const TemplateArgumentList &TArgs) {
+  return getLVForTemplateArgumentList(TArgs.getFlatArgumentList(), 
+                                      TArgs.flat_size());
 }
 
-static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
+static LVPair getLVForNamespaceScopeDecl(const NamedDecl *D) {
   assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
          "Not a name having namespace scope");
   ASTContext &Context = D->getASTContext();
@@ -117,7 +136,7 @@
   if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
     // Explicitly declared static.
     if (Var->getStorageClass() == SC_Static)
-      return InternalLinkage;
+      return LVPair(InternalLinkage, DefaultVisibility);
 
     // - an object or reference that is explicitly declared const
     //   and neither explicitly declared extern nor previously
@@ -135,7 +154,7 @@
           FoundExtern = true;
       
       if (!FoundExtern)
-        return InternalLinkage;
+        return LVPair(InternalLinkage, DefaultVisibility);
     }
   } else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) {
     // C++ [temp]p4:
@@ -150,23 +169,63 @@
 
     // Explicitly declared static.
     if (Function->getStorageClass() == SC_Static)
-      return InternalLinkage;
+      return LVPair(InternalLinkage, DefaultVisibility);
   } else if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) {
     //   - a data member of an anonymous union.
     if (cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion())
-      return InternalLinkage;
+      return LVPair(InternalLinkage, DefaultVisibility);
   }
 
+  if (D->isInAnonymousNamespace())
+    return LVPair(UniqueExternalLinkage, DefaultVisibility);
+
+  // Set up the defaults.
+
+  // C99 6.2.2p5:
+  //   If the declaration of an identifier for an object has file
+  //   scope and no storage-class specifier, its linkage is
+  //   external.
+  LVPair LV(ExternalLinkage, DefaultVisibility);
+
+  // We ignore -fvisibility on non-definitions and explicit
+  // instantiation declarations.
+  bool ConsiderDashFVisibility = true;
+
   // C++ [basic.link]p4:
-  
+
   //   A name having namespace scope has external linkage if it is the
   //   name of
   //
   //     - an object or reference, unless it has internal linkage; or
   if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
+    // Modify the variable's LV by the LV of its type unless this is
+    // C or extern "C".  This follows from [basic.link]p9:
+    //   A type without linkage shall not be used as the type of a
+    //   variable or function with external linkage unless
+    //    - the entity has C language linkage, or
+    //    - the entity is declared within an unnamed namespace, or
+    //    - the entity is not used or is defined in the same
+    //      translation unit.
+    // and [basic.link]p10:
+    //   ...the types specified by all declarations referring to a
+    //   given variable or function shall be identical...
+    // C does not have an equivalent rule.
+    //
+    // Note that we don't want to make the variable non-external
+    // because of this, but unique-external linkage suits us.
+    if (Context.getLangOptions().CPlusPlus && !Var->isExternC()) {
+      LVPair TypeLV = Var->getType()->getLinkageAndVisibility();
+      if (TypeLV.first != ExternalLinkage)
+        return LVPair(UniqueExternalLinkage, DefaultVisibility);
+      LV.second = minVisibility(LV.second, TypeLV.second);
+    }
+
     if (!Context.getLangOptions().CPlusPlus &&
         (Var->getStorageClass() == SC_Extern ||
          Var->getStorageClass() == SC_PrivateExtern)) {
+      if (Var->getStorageClass() == SC_PrivateExtern)
+        LV.second = HiddenVisibility;
+
       // C99 6.2.2p4:
       //   For an identifier declared with the storage-class specifier
       //   extern in a scope in which a prior declaration of that
@@ -177,23 +236,23 @@
       //   is visible, or if the prior declaration specifies no
       //   linkage, then the identifier has external linkage.
       if (const VarDecl *PrevVar = Var->getPreviousDeclaration()) {
-        if (Linkage L = PrevVar->getLinkage())
-          return L;
+        LVPair PrevLV = PrevVar->getLinkageAndVisibility();
+        if (PrevLV.first) LV.first = PrevLV.first;
+        LV.second = minVisibility(LV.second, PrevLV.second);
       }
     }
 
-    // C99 6.2.2p5:
-    //   If the declaration of an identifier for an object has file
-    //   scope and no storage-class specifier, its linkage is
-    //   external.
-    if (Var->isInAnonymousNamespace())
-      return UniqueExternalLinkage;
-
-    return ExternalLinkage;
-  }
-
   //     - a function, unless it has internal linkage; or
-  if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+  } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+    // Modify the function's LV by the LV of its type unless this is
+    // C or extern "C".  See the comment above about variables.
+    if (Context.getLangOptions().CPlusPlus && !Function->isExternC()) {
+      LVPair TypeLV = Function->getType()->getLinkageAndVisibility();
+      if (TypeLV.first != ExternalLinkage)
+        return LVPair(UniqueExternalLinkage, DefaultVisibility);
+      LV.second = minVisibility(LV.second, TypeLV.second);
+    }
+
     // C99 6.2.2p5:
     //   If the declaration of an identifier for a function has no
     //   storage-class specifier, its linkage is determined exactly
@@ -213,24 +272,25 @@
       //   is visible, or if the prior declaration specifies no
       //   linkage, then the identifier has external linkage.
       if (const FunctionDecl *PrevFunc = Function->getPreviousDeclaration()) {
-        if (Linkage L = PrevFunc->getLinkage())
-          return L;
+        LVPair PrevLV = PrevFunc->getLinkageAndVisibility();
+        if (PrevLV.first) LV.first = PrevLV.first;
+        LV.second = minVisibility(LV.second, PrevLV.second);
       }
     }
 
-    if (Function->isInAnonymousNamespace())
-      return UniqueExternalLinkage;
-
     if (FunctionTemplateSpecializationInfo *SpecInfo
                                = Function->getTemplateSpecializationInfo()) {
-      Linkage L = SpecInfo->getTemplate()->getLinkage();
+      LV = merge(LV, SpecInfo->getTemplate()->getLinkageAndVisibility());
       const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments;
-      L = minLinkage(L, getLinkageForTemplateArgumentList(TemplateArgs));
-      return L;
+      LV = merge(LV, getLVForTemplateArgumentList(TemplateArgs));
+
+      if (SpecInfo->getTemplateSpecializationKind()
+            == TSK_ExplicitInstantiationDeclaration)
+        ConsiderDashFVisibility = false;
     }
 
-    return ExternalLinkage;
-  }
+    if (ConsiderDashFVisibility)
+      ConsiderDashFVisibility = Function->hasBody();
 
   //     - a named class (Clause 9), or an unnamed class defined in a
   //       typedef declaration in which the class has the typedef name
@@ -238,116 +298,180 @@
   //     - a named enumeration (7.2), or an unnamed enumeration
   //       defined in a typedef declaration in which the enumeration
   //       has the typedef name for linkage purposes (7.1.3); or
-  if (const TagDecl *Tag = dyn_cast<TagDecl>(D))
-    if (Tag->getDeclName() || Tag->getTypedefForAnonDecl()) {
-      if (Tag->isInAnonymousNamespace())
-        return UniqueExternalLinkage;
-
-      // If this is a class template specialization, consider the
-      // linkage of the template and template arguments.
-      if (const ClassTemplateSpecializationDecl *Spec
-            = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
-        const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
-        Linkage L = getLinkageForTemplateArgumentList(TemplateArgs);
-        return minLinkage(L, Spec->getSpecializedTemplate()->getLinkage());
-      }
+  } else if (const TagDecl *Tag = dyn_cast<TagDecl>(D)) {
+    // Unnamed tags have no linkage.
+    if (!Tag->getDeclName() && !Tag->getTypedefForAnonDecl())
+      return LVPair(NoLinkage, DefaultVisibility);
+
+    // If this is a class template specialization, consider the
+    // 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(LV, Spec->getSpecializedTemplate()->getLinkageAndVisibility());
 
-      return ExternalLinkage;
+      // The arguments at which the template was instantiated.
+      const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+      LV = merge(LV, getLVForTemplateArgumentList(TemplateArgs));
+
+      if (Spec->getTemplateSpecializationKind()
+            == TSK_ExplicitInstantiationDeclaration)
+        ConsiderDashFVisibility = false;
     }
 
+    if (ConsiderDashFVisibility)
+      ConsiderDashFVisibility = Tag->isDefinition();
+
   //     - an enumerator belonging to an enumeration with external linkage;
-  if (isa<EnumConstantDecl>(D)) {
-    Linkage L = cast<NamedDecl>(D->getDeclContext())->getLinkage();
-    if (isExternalLinkage(L))
-      return L;
-  }
+  } else if (isa<EnumConstantDecl>(D)) {
+    LVPair EnumLV =
+      cast<NamedDecl>(D->getDeclContext())->getLinkageAndVisibility();
+    if (!isExternalLinkage(EnumLV.first))
+      return LVPair(NoLinkage, DefaultVisibility);
+    LV = merge(LV, EnumLV);
 
   //     - a template, unless it is a function template that has
   //       internal linkage (Clause 14);
-  if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
-    if (D->isInAnonymousNamespace())
-      return UniqueExternalLinkage;
-
-    return getLinkageForTemplateParameterList(
-                                         Template->getTemplateParameters());
-  }
+  } else if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
+    LV = merge(LV, 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.
-  if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace())
-    return ExternalLinkage;
+  } else if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace()) {
+    return LV;
 
-  return NoLinkage;
+  // By extension, we assign external linkage to Objective-C
+  // interfaces.
+  } else if (isa<ObjCInterfaceDecl>(D)) {
+    // fallout
+
+  // Everything not covered here has no linkage.
+  } else {
+    return LVPair(NoLinkage, DefaultVisibility);
+  }
+
+  // If we ended up with non-external linkage, visibility should
+  // always be default.
+  if (LV.first != ExternalLinkage)
+    return LVPair(LV.first, DefaultVisibility);
+
+  // If we didn't end up with hidden visibility, consider attributes
+  // and -fvisibility.
+  if (LV.second != HiddenVisibility) {
+    Visibility StandardV;
+
+    // If we have an explicit visibility attribute, merge that in.
+    const VisibilityAttr *VA = D->getAttr<VisibilityAttr>();
+    if (VA)
+      StandardV = GetVisibilityFromAttr(VA);
+    else if (ConsiderDashFVisibility)
+      StandardV = Context.getLangOptions().getVisibilityMode();
+    else
+      StandardV = DefaultVisibility; // no-op
+
+    LV.second = minVisibility(LV.second, StandardV);  
+  }
+
+  return LV;
 }
 
-static Linkage getLinkageForClassMember(const NamedDecl *D) {
+static LVPair getLVForClassMember(const NamedDecl *D) {
+  // 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
+  // template arguments.
   if (!(isa<CXXMethodDecl>(D) ||
         isa<VarDecl>(D) ||
+        isa<FieldDecl>(D) ||
         (isa<TagDecl>(D) &&
          (D->getDeclName() || cast<TagDecl>(D)->getTypedefForAnonDecl()))))
-    return NoLinkage;
+    return LVPair(NoLinkage, DefaultVisibility);
 
   // Class members only have linkage if their class has external linkage.
-  Linkage L = cast<RecordDecl>(D->getDeclContext())->getLinkage();
-  if (!isExternalLinkage(L)) return NoLinkage;
+  LVPair ClassLV =
+    cast<RecordDecl>(D->getDeclContext())->getLinkageAndVisibility();
+  if (!isExternalLinkage(ClassLV.first))
+    return LVPair(NoLinkage, DefaultVisibility);
 
   // If the class already has unique-external linkage, we can't improve.
-  if (L == UniqueExternalLinkage) return UniqueExternalLinkage;
+  if (ClassLV.first == UniqueExternalLinkage)
+    return LVPair(UniqueExternalLinkage, DefaultVisibility);
+
+  // Start with the class's linkage and visibility.
+  LVPair LV = ClassLV;
+
+  // If we have an explicit visibility attribute, merge that in.
+  const VisibilityAttr *VA = D->getAttr<VisibilityAttr>();
+  if (VA) LV.second = minVisibility(LV.second, GetVisibilityFromAttr(VA));
+
+  // If it's a value declaration, apply the LV from its type.
+  // See the comment about namespace-scope variable decls above.
+  if (isa<ValueDecl>(D)) {
+    LVPair TypeLV = cast<ValueDecl>(D)->getType()->getLinkageAndVisibility();
+    if (TypeLV.first != ExternalLinkage)
+      LV.first = minLinkage(LV.first, UniqueExternalLinkage);
+    LV.second = minVisibility(LV.second, TypeLV.second);
+  }
 
-  // If this is a method template specialization, use the linkage for
-  // the template parameters and arguments.
   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
-    if (FunctionTemplateSpecializationInfo *SpecInfo
+    // If this is a method template specialization, use the linkage for
+    // the template parameters and arguments.
+    if (FunctionTemplateSpecializationInfo *Spec
            = MD->getTemplateSpecializationInfo()) {
-      Linkage ArgLinkage =
-        getLinkageForTemplateArgumentList(*SpecInfo->TemplateArguments);
-      Linkage ParamLinkage =
-        getLinkageForTemplateParameterList(
-                           SpecInfo->getTemplate()->getTemplateParameters());
-      return minLinkage(ArgLinkage, ParamLinkage);
+      LV = merge(LV, getLVForTemplateArgumentList(*Spec->TemplateArguments));
+      LV = merge(LV, getLVForTemplateParameterList(
+                              Spec->getTemplate()->getTemplateParameters()));
     }
 
+    // If -fvisibility-inlines-hidden was provided, then inline C++
+    // member functions get "hidden" visibility if they don't have an
+    // explicit visibility attribute.
+    if (!VA && MD->isInlined() && LV.second > HiddenVisibility &&
+        D->getASTContext().getLangOptions().InlineVisibilityHidden)
+      LV.second = HiddenVisibility;
+
   // Similarly for member class template specializations.
   } else if (const ClassTemplateSpecializationDecl *Spec
                = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
-    Linkage ArgLinkage =
-      getLinkageForTemplateArgumentList(Spec->getTemplateArgs());
-    Linkage ParamLinkage =
-      getLinkageForTemplateParameterList(
-                    Spec->getSpecializedTemplate()->getTemplateParameters());
-    return minLinkage(ArgLinkage, ParamLinkage);
+    LV = merge(LV, getLVForTemplateArgumentList(Spec->getTemplateArgs()));
+    LV = merge(LV, getLVForTemplateParameterList(
+                    Spec->getSpecializedTemplate()->getTemplateParameters()));
   }
 
-  return ExternalLinkage;
+  return LV;
 }
 
-Linkage NamedDecl::getLinkage() const {
+LVPair NamedDecl::getLinkageAndVisibility() const {
 
   // Objective-C: treat all Objective-C declarations as having external
   // linkage.
   switch (getKind()) {
     default:
       break;
+    case Decl::TemplateTemplateParm: // count these as external
+    case Decl::NonTypeTemplateParm:
     case Decl::ObjCAtDefsField:
     case Decl::ObjCCategory:
     case Decl::ObjCCategoryImpl:
-    case Decl::ObjCClass:
     case Decl::ObjCCompatibleAlias:
     case Decl::ObjCForwardProtocol:
     case Decl::ObjCImplementation:
-    case Decl::ObjCInterface:
-    case Decl::ObjCIvar:
     case Decl::ObjCMethod:
     case Decl::ObjCProperty:
     case Decl::ObjCPropertyImpl:
     case Decl::ObjCProtocol:
-      return ExternalLinkage;
+      return LVPair(ExternalLinkage, DefaultVisibility);
   }
 
   // Handle linkage for namespace-scope names.
   if (getDeclContext()->getRedeclContext()->isFileContext())
-    if (Linkage L = getLinkageForNamespaceScopeDecl(this))
-      return L;
+    return getLVForNamespaceScopeDecl(this);
   
   // C++ [basic.link]p5:
   //   In addition, a member function, static data member, a named
@@ -357,7 +481,7 @@
   //   purposes (7.1.3), has external linkage if the name of the class
   //   has external linkage.
   if (getDeclContext()->isRecord())
-    return getLinkageForClassMember(this);
+    return getLVForClassMember(this);
 
   // C++ [basic.link]p6:
   //   The name of a function declared in block scope and the name of
@@ -372,34 +496,48 @@
   //   external linkage.
   if (getLexicalDeclContext()->isFunctionOrMethod()) {
     if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this)) {
-      if (Function->getPreviousDeclaration())
-        if (Linkage L = Function->getPreviousDeclaration()->getLinkage())
-          return L;
-
       if (Function->isInAnonymousNamespace())
-        return UniqueExternalLinkage;
+        return LVPair(UniqueExternalLinkage, DefaultVisibility);
+
+      LVPair LV(ExternalLinkage, DefaultVisibility);
+      if (const VisibilityAttr *VA = Function->getAttr<VisibilityAttr>())
+        LV.second = GetVisibilityFromAttr(VA);
+
+      if (const FunctionDecl *Prev = Function->getPreviousDeclaration()) {
+        LVPair PrevLV = Prev->getLinkageAndVisibility();
+        if (PrevLV.first) LV.first = PrevLV.first;
+        LV.second = minVisibility(LV.second, PrevLV.second);
+      }
 
-      return ExternalLinkage;
+      return LV;
     }
 
     if (const VarDecl *Var = dyn_cast<VarDecl>(this))
       if (Var->getStorageClass() == SC_Extern ||
           Var->getStorageClass() == SC_PrivateExtern) {
-        if (Var->getPreviousDeclaration())
-          if (Linkage L = Var->getPreviousDeclaration()->getLinkage())
-            return L;
-
         if (Var->isInAnonymousNamespace())
-          return UniqueExternalLinkage;
+          return LVPair(UniqueExternalLinkage, DefaultVisibility);
+
+        LVPair LV(ExternalLinkage, DefaultVisibility);
+        if (Var->getStorageClass() == SC_PrivateExtern)
+          LV.second = HiddenVisibility;
+        else if (const VisibilityAttr *VA = Var->getAttr<VisibilityAttr>())
+          LV.second = GetVisibilityFromAttr(VA);
+
+        if (const VarDecl *Prev = Var->getPreviousDeclaration()) {
+          LVPair PrevLV = Prev->getLinkageAndVisibility();
+          if (PrevLV.first) LV.first = PrevLV.first;
+          LV.second = minVisibility(LV.second, PrevLV.second);
+        }
 
-        return ExternalLinkage;
+        return LV;
       }
   }
 
   // C++ [basic.link]p6:
   //   Names not covered by these rules have no linkage.
-  return NoLinkage;
-  }
+  return LVPair(NoLinkage, DefaultVisibility);
+}
 
 std::string NamedDecl::getQualifiedNameAsString() const {
   return getQualifiedNameAsString(getASTContext().getLangOptions());

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Fri Oct 22 16:05:15 2010
@@ -1268,129 +1268,154 @@
   Profile(ID, getBaseType(), qual_begin(), getNumProtocols());
 }
 
+void Type::ensureCachedProperties() const {
+  if (!TypeBits.isCacheValid()) {
+    CachedProperties Result = getCachedProperties();
+    TypeBits.CacheValidAndVisibility = Result.getVisibility() + 1U;
+    assert(TypeBits.isCacheValid() &&
+           TypeBits.getVisibility() == Result.getVisibility());
+    TypeBits.CachedLinkage = Result.getLinkage();
+    TypeBits.CachedLocalOrUnnamed = Result.hasLocalOrUnnamedType();
+  }  
+}
+
 /// \brief Determine the linkage of this type.
 Linkage Type::getLinkage() const {
   if (this != CanonicalType.getTypePtr())
     return CanonicalType->getLinkage();
-  
-  if (!TypeBits.LinkageKnown) {
-    std::pair<Linkage, bool> Result = getLinkageUnnamedLocalImpl();
-    TypeBits.CachedLinkage = Result.first;
-    TypeBits.CachedLocalOrUnnamed = Result.second;
-    TypeBits.LinkageKnown = true;
-  }
-  
-  return static_cast<clang::Linkage>(TypeBits.CachedLinkage);
+
+  ensureCachedProperties();
+  return TypeBits.getLinkage();
+}
+
+/// \brief Determine the linkage of this type.
+Visibility Type::getVisibility() const {
+  if (this != CanonicalType.getTypePtr())
+    return CanonicalType->getVisibility();
+
+  ensureCachedProperties();
+  return TypeBits.getVisibility();
 }
 
 bool Type::hasUnnamedOrLocalType() const {
   if (this != CanonicalType.getTypePtr())
     return CanonicalType->hasUnnamedOrLocalType();
-  
-  if (!TypeBits.LinkageKnown) {
-    std::pair<Linkage, bool> Result = getLinkageUnnamedLocalImpl();
-    TypeBits.CachedLinkage = Result.first;
-    TypeBits.CachedLocalOrUnnamed = Result.second;
-    TypeBits.LinkageKnown = true;
-  }
-  
-  return TypeBits.CachedLocalOrUnnamed;
+
+  ensureCachedProperties();
+  return TypeBits.hasLocalOrUnnamedType();
 }
 
-std::pair<Linkage, bool> Type::getLinkageUnnamedLocalImpl() const { 
-  // C++ [basic.link]p8:
-  //   Names not covered by these rules have no linkage.
-  return std::make_pair(NoLinkage, false);
+std::pair<Linkage,Visibility> Type::getLinkageAndVisibility() const {
+  if (this != CanonicalType.getTypePtr())
+    return CanonicalType->getLinkageAndVisibility();
+
+  ensureCachedProperties();
+  return std::make_pair(TypeBits.getLinkage(), TypeBits.getVisibility());
+}
+
+
+Type::CachedProperties Type::getCachedProperties(const Type *T) {
+  T = T->CanonicalType.getTypePtr();
+  T->ensureCachedProperties();
+  return CachedProperties(T->TypeBits.getLinkage(),
+                          T->TypeBits.getVisibility(),
+                          T->TypeBits.hasLocalOrUnnamedType());
 }
 
 void Type::ClearLinkageCache() {
   if (this != CanonicalType.getTypePtr())
     CanonicalType->ClearLinkageCache();
   else
-    TypeBits.LinkageKnown = false;
+    TypeBits.CacheValidAndVisibility = 0;
 }
 
-std::pair<Linkage, bool> BuiltinType::getLinkageUnnamedLocalImpl() const {
+Type::CachedProperties Type::getCachedProperties() const { 
+  // Treat dependent types as external.
+  if (isDependentType())
+    return CachedProperties(ExternalLinkage, DefaultVisibility, false);
+
+  // C++ [basic.link]p8:
+  //   Names not covered by these rules have no linkage.
+  return CachedProperties(NoLinkage, DefaultVisibility, false);
+}
+
+Type::CachedProperties BuiltinType::getCachedProperties() const {
   // C++ [basic.link]p8:
   //   A type is said to have linkage if and only if:
   //     - it is a fundamental type (3.9.1); or
-  return std::make_pair(ExternalLinkage, false);
+  return CachedProperties(ExternalLinkage, DefaultVisibility, false);
 }
 
-std::pair<Linkage, bool> TagType::getLinkageUnnamedLocalImpl() const {
+Type::CachedProperties TagType::getCachedProperties() const {
   // C++ [basic.link]p8:
   //     - it is a class or enumeration type that is named (or has a name for
   //       linkage purposes (7.1.3)) and the name has linkage; or
   //     -  it is a specialization of a class template (14); or
-  return std::make_pair(getDecl()->getLinkage(),
-                        getDecl()->getDeclContext()->isFunctionOrMethod() ||
+
+  std::pair<Linkage,Visibility> LV = getDecl()->getLinkageAndVisibility();
+  bool IsLocalOrUnnamed =
+    getDecl()->getDeclContext()->isFunctionOrMethod() ||
                         (!getDecl()->getIdentifier() &&
-                         !getDecl()->getTypedefForAnonDecl()));
+                         !getDecl()->getTypedefForAnonDecl());
+  return CachedProperties(LV.first, LV.second, IsLocalOrUnnamed);
 }
 
 // C++ [basic.link]p8:
 //   - it is a compound type (3.9.2) other than a class or enumeration, 
 //     compounded exclusively from types that have linkage; or
-std::pair<Linkage, bool> ComplexType::getLinkageUnnamedLocalImpl() const {
-  return std::make_pair(ElementType->getLinkage(), 
-                        ElementType->hasUnnamedOrLocalType());
+Type::CachedProperties ComplexType::getCachedProperties() const {
+  return Type::getCachedProperties(ElementType);
 }
 
-std::pair<Linkage, bool> PointerType::getLinkageUnnamedLocalImpl() const {
-  return std::make_pair(PointeeType->getLinkage(), 
-                        PointeeType->hasUnnamedOrLocalType());
+Type::CachedProperties PointerType::getCachedProperties() const {
+  return Type::getCachedProperties(PointeeType);
 }
 
-std::pair<Linkage, bool> BlockPointerType::getLinkageUnnamedLocalImpl() const {
-  return std::make_pair(PointeeType->getLinkage(),
-                        PointeeType->hasUnnamedOrLocalType());
+Type::CachedProperties BlockPointerType::getCachedProperties() const {
+  return Type::getCachedProperties(PointeeType);
 }
 
-std::pair<Linkage, bool> ReferenceType::getLinkageUnnamedLocalImpl() const {
-  return std::make_pair(PointeeType->getLinkage(),
-                        PointeeType->hasUnnamedOrLocalType());
+Type::CachedProperties ReferenceType::getCachedProperties() const {
+  return Type::getCachedProperties(PointeeType);
 }
 
-std::pair<Linkage, bool> MemberPointerType::getLinkageUnnamedLocalImpl() const {
-  return std::make_pair(minLinkage(Class->getLinkage(),
-                                   PointeeType->getLinkage()),
-                        Class->hasUnnamedOrLocalType() ||
-                        PointeeType->hasUnnamedOrLocalType());
+Type::CachedProperties MemberPointerType::getCachedProperties() const {
+  return merge(Type::getCachedProperties(Class),
+               Type::getCachedProperties(PointeeType));
 }
 
-std::pair<Linkage, bool> ArrayType::getLinkageUnnamedLocalImpl() const {
-  return std::make_pair(ElementType->getLinkage(), 
-                        ElementType->hasUnnamedOrLocalType());
+Type::CachedProperties ArrayType::getCachedProperties() const {
+  return Type::getCachedProperties(ElementType);
 }
 
-std::pair<Linkage, bool> VectorType::getLinkageUnnamedLocalImpl() const {
-  return std::make_pair(ElementType->getLinkage(),
-                        ElementType->hasUnnamedOrLocalType());
+Type::CachedProperties VectorType::getCachedProperties() const {
+  return Type::getCachedProperties(ElementType);
 }
 
-std::pair<Linkage, bool> 
-FunctionNoProtoType::getLinkageUnnamedLocalImpl() const {
-  return std::make_pair(getResultType()->getLinkage(),
-                        getResultType()->hasUnnamedOrLocalType());
+Type::CachedProperties FunctionNoProtoType::getCachedProperties() const {
+  return Type::getCachedProperties(getResultType());
 }
 
-std::pair<Linkage, bool> FunctionProtoType::getLinkageUnnamedLocalImpl() const {
-  Linkage L = getResultType()->getLinkage();
-  bool UnnamedOrLocal = getResultType()->hasUnnamedOrLocalType();
+Type::CachedProperties FunctionProtoType::getCachedProperties() const {
+  CachedProperties Cached = Type::getCachedProperties(getResultType());
   for (arg_type_iterator A = arg_type_begin(), AEnd = arg_type_end();
        A != AEnd; ++A) {
-    L = minLinkage(L, (*A)->getLinkage());
-    UnnamedOrLocal = UnnamedOrLocal || (*A)->hasUnnamedOrLocalType();
+    Cached = merge(Cached, Type::getCachedProperties(*A));
   }
-  
-  return std::make_pair(L, UnnamedOrLocal);
+  return Cached;
+}
+
+Type::CachedProperties ObjCInterfaceType::getCachedProperties() const {
+  std::pair<Linkage,Visibility> LV = getDecl()->getLinkageAndVisibility();
+  return CachedProperties(LV.first, LV.second, false);
 }
 
-std::pair<Linkage, bool> ObjCObjectType::getLinkageUnnamedLocalImpl() const {
-  return std::make_pair(ExternalLinkage, false);
+Type::CachedProperties ObjCObjectType::getCachedProperties() const {
+  if (const ObjCInterfaceType *T = getBaseType()->getAs<ObjCInterfaceType>())
+    return Type::getCachedProperties(T);
+  return CachedProperties(ExternalLinkage, DefaultVisibility, false);
 }
 
-std::pair<Linkage, bool> 
-ObjCObjectPointerType::getLinkageUnnamedLocalImpl() const {
-  return std::make_pair(ExternalLinkage, false);
+Type::CachedProperties ObjCObjectPointerType::getCachedProperties() const {
+  return Type::getCachedProperties(PointeeType);
 }

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Fri Oct 22 16:05:15 2010
@@ -180,7 +180,7 @@
   }
 
   // Finally, set up the alias with its proper name and attributes.
-  SetCommonAttributes(AliasDecl.getDecl(), Alias);
+  SetCommonAttributes(cast<NamedDecl>(AliasDecl.getDecl()), Alias);
 
   return false;
 }

Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Fri Oct 22 16:05:15 2010
@@ -2197,7 +2197,7 @@
     CGM.getContext().getASTObjCImplementationLayout(ID).getSize() / 8;
 
   // FIXME: Set CXX-structors flag.
-  if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
+  if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
     Flags |= eClassFlags_Hidden;
 
   std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
@@ -2282,7 +2282,7 @@
   unsigned Flags = eClassFlags_Meta;
   unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
 
-  if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
+  if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
     Flags |= eClassFlags_Hidden;
 
   std::vector<llvm::Constant*> Values(12);
@@ -4968,7 +4968,7 @@
   llvm::GlobalVariable *SuperClassGV, *IsAGV;
 
   bool classIsHidden =
-    CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden;
+    ID->getClassInterface()->getVisibility() == HiddenVisibility;
   if (classIsHidden)
     flags |= OBJC2_CLS_HIDDEN;
   if (ID->getNumIvarInitializers())
@@ -5263,7 +5263,7 @@
   // well (i.e., in ObjCIvarOffsetVariable).
   if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
       Ivar->getAccessControl() == ObjCIvarDecl::Package ||
-      CGM.getDeclVisibilityMode(ID) == LangOptions::Hidden)
+      ID->getVisibility() == HiddenVisibility)
     IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
   else
     IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
@@ -6237,7 +6237,7 @@
                                       ID->getIdentifier()->getName()));
   }
 
-  if (CGM.getLangOptions().getVisibilityMode() == LangOptions::Hidden)
+  if (CGM.getLangOptions().getVisibilityMode() == HiddenVisibility)
     Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
   Entry->setAlignment(CGM.getTargetData().getABITypeAlignment(
       ObjCTypes.EHTypeTy));

Modified: cfe/trunk/lib/CodeGen/CGRTTI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRTTI.cpp?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRTTI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRTTI.cpp Fri Oct 22 16:05:15 2010
@@ -113,7 +113,7 @@
     }
     if (const RecordType *RT = Ty->getAs<RecordType>())
       if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
-        return CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden;
+        return RD->getVisibility() == HiddenVisibility;
     return false;
   }
   

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Fri Oct 22 16:05:15 2010
@@ -164,81 +164,23 @@
   getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg;
 }
 
-LangOptions::VisibilityMode
-CodeGenModule::getDeclVisibilityMode(const Decl *D) const {
-  if (const VarDecl *VD = dyn_cast<VarDecl>(D))
-    if (VD->getStorageClass() == SC_PrivateExtern)
-      return LangOptions::Hidden;
-
-  if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) {
-    switch (attr->getVisibility()) {
-    default: assert(0 && "Unknown visibility!");
-    case VisibilityAttr::Default:
-      return LangOptions::Default;
-    case VisibilityAttr::Hidden:
-      return LangOptions::Hidden;
-    case VisibilityAttr::Protected:
-      return LangOptions::Protected;
-    }
-  }
-  
-  if (getLangOptions().CPlusPlus) {
-    // Entities subject to an explicit instantiation declaration get default
-    // visibility.
-    if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
-      if (Function->getTemplateSpecializationKind()
-                                        == TSK_ExplicitInstantiationDeclaration)
-        return LangOptions::Default;
-    } else if (const ClassTemplateSpecializationDecl *ClassSpec
-                              = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
-      if (ClassSpec->getSpecializationKind()
-                                        == TSK_ExplicitInstantiationDeclaration)
-        return LangOptions::Default;
-    } else if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
-      if (Record->getTemplateSpecializationKind()
-                                        == TSK_ExplicitInstantiationDeclaration)
-        return LangOptions::Default;
-    } else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
-      if (Var->isStaticDataMember() &&
-          (Var->getTemplateSpecializationKind()
-                                      == TSK_ExplicitInstantiationDeclaration))
-        return LangOptions::Default;
-    }
-
-    // If -fvisibility-inlines-hidden was provided, then inline C++ member
-    // functions get "hidden" visibility by default.
-    if (getLangOptions().InlineVisibilityHidden)
-      if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
-        if (Method->isInlined())
-          return LangOptions::Hidden;
-  }
-           
-  // If this decl is contained in a class, it should have the same visibility
-  // as the parent class.
-  if (const DeclContext *DC = D->getDeclContext()) 
-    if (DC->isRecord())
-      return getDeclVisibilityMode(cast<Decl>(DC));
-
-  return getLangOptions().getVisibilityMode();
-}
-
 void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
-                                        const Decl *D) const {
+                                        const NamedDecl *D) const {
   // Internal definitions always have default visibility.
   if (GV->hasLocalLinkage()) {
     GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
     return;
   }
 
-  switch (getDeclVisibilityMode(D)) {
-  default: assert(0 && "Unknown visibility!");
-  case LangOptions::Default:
+  switch (D->getVisibility()) {
+  case DefaultVisibility:
     return GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
-  case LangOptions::Hidden:
+  case HiddenVisibility:
     return GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
-  case LangOptions::Protected:
+  case ProtectedVisibility:
     return GV->setVisibility(llvm::GlobalValue::ProtectedVisibility);
   }
+  llvm_unreachable("unknown visibility!");
 }
 
 /// Set the symbol visibility of type information (vtable and RTTI)
@@ -498,7 +440,10 @@
 
 void CodeGenModule::SetCommonAttributes(const Decl *D,
                                         llvm::GlobalValue *GV) {
-  setGlobalVisibility(GV, D);
+  if (isa<NamedDecl>(D))
+    setGlobalVisibility(GV, cast<NamedDecl>(D));
+  else
+    GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
 
   if (D->hasAttr<UsedAttr>())
     AddUsedGlobal(GV);

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Fri Oct 22 16:05:15 2010
@@ -257,12 +257,9 @@
   static void DecorateInstruction(llvm::Instruction *Inst,
                                   llvm::MDNode *TBAAInfo);
 
-  /// getDeclVisibilityMode - Compute the visibility of the decl \arg D.
-  LangOptions::VisibilityMode getDeclVisibilityMode(const Decl *D) const;
-
   /// setGlobalVisibility - Set the visibility for the given LLVM
   /// GlobalValue.
-  void setGlobalVisibility(llvm::GlobalValue *GV, const Decl *D) const;
+  void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const;
 
   /// setTypeVisibility - Set the visibility for the given global
   /// value which holds information about a type.

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Fri Oct 22 16:05:15 2010
@@ -624,12 +624,12 @@
       Res.push_back("-fobjc-gc-only");
     }
   }
-  if (Opts.getVisibilityMode() != LangOptions::Default) {
+  if (Opts.getVisibilityMode() != DefaultVisibility) {
     Res.push_back("-fvisibility");
-    if (Opts.getVisibilityMode() == LangOptions::Hidden) {
+    if (Opts.getVisibilityMode() == HiddenVisibility) {
       Res.push_back("hidden");
     } else {
-      assert(Opts.getVisibilityMode() == LangOptions::Protected &&
+      assert(Opts.getVisibilityMode() == ProtectedVisibility &&
              "Invalid visibility!");
       Res.push_back("protected");
     }
@@ -1304,11 +1304,11 @@
 
   llvm::StringRef Vis = Args.getLastArgValue(OPT_fvisibility, "default");
   if (Vis == "default")
-    Opts.setVisibilityMode(LangOptions::Default);
+    Opts.setVisibilityMode(DefaultVisibility);
   else if (Vis == "hidden")
-    Opts.setVisibilityMode(LangOptions::Hidden);
+    Opts.setVisibilityMode(HiddenVisibility);
   else if (Vis == "protected")
-    Opts.setVisibilityMode(LangOptions::Protected);
+    Opts.setVisibilityMode(ProtectedVisibility);
   else
     Diags.Report(diag::err_drv_invalid_value)
       << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis;

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Fri Oct 22 16:05:15 2010
@@ -2526,7 +2526,7 @@
     PARSE_LANGOPT(CharIsSigned);
     PARSE_LANGOPT(ShortWChar);
     LangOpts.setGCMode((LangOptions::GCMode)Record[Idx++]);
-    LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx++]);
+    LangOpts.setVisibilityMode((Visibility)Record[Idx++]);
     LangOpts.setStackProtectorMode((LangOptions::StackProtectorMode)
                                    Record[Idx++]);
     PARSE_LANGOPT(InstantiationDepth);

Modified: cfe/trunk/test/CodeGenCXX/member-pointer-type-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/member-pointer-type-convert.cpp?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/member-pointer-type-convert.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/member-pointer-type-convert.cpp Fri Oct 22 16:05:15 2010
@@ -6,5 +6,6 @@
   const char *name;
   param_t par;
 } *ptr;
+void test_ptr() { (void) ptr; } // forced use
 
 // CHECK: type { i8*, {{i..}} }

Modified: cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp Fri Oct 22 16:05:15 2010
@@ -18,23 +18,26 @@
   // CHECK: @_ZN8ZeroInit1bE = global i64 -1,
   int A::* b = 0;
 
-  // CHECK: @_ZN8ZeroInit2saE = global %struct.anon { i64 -1 }
+  // CHECK: @_ZN8ZeroInit2saE = internal global %struct.anon { i64 -1 }
   struct {
     int A::*a;
   } sa;
+  void test_sa() { (void) sa; } // force emission
   
-  // CHECK: @_ZN8ZeroInit3ssaE = 
+  // CHECK: @_ZN8ZeroInit3ssaE = internal
   // CHECK: [2 x i64] [i64 -1, i64 -1]
   struct {
     int A::*aa[2];
   } ssa[2];
+  void test_ssa() { (void) ssa; }
   
-  // CHECK: @_ZN8ZeroInit2ssE = global %1 { %struct.anon { i64 -1 } }
+  // CHECK: @_ZN8ZeroInit2ssE = internal global %1 { %struct.anon { i64 -1 } }
   struct {
     struct {
       int A::*pa;
     } s;
   } ss;
+  void test_ss() { (void) ss; }
   
   struct A {
     int A::*a;

Modified: cfe/trunk/test/CodeGenCXX/visibility.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/visibility.cpp?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/visibility.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/visibility.cpp Fri Oct 22 16:05:15 2010
@@ -1,11 +1,15 @@
 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fvisibility hidden -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-HIDDEN
 
 #define HIDDEN __attribute__((visibility("hidden")))
 #define PROTECTED __attribute__((visibility("protected")))
 #define DEFAULT __attribute__((visibility("default")))
 
 // CHECK: @_ZN5Test425VariableInHiddenNamespaceE = hidden global i32 10
+// CHECK: @_ZN5Test71aE = hidden global
+// CHECK: @_ZN5Test71bE = global
 // CHECK: @_ZTVN5Test63fooE = weak_odr hidden constant 
+
 namespace Test1 {
   // CHECK: define hidden void @_ZN5Test11fEv
   void HIDDEN f() { }
@@ -82,3 +86,32 @@
 
   barc::barc() {}
 }
+
+namespace Test7 {
+  class HIDDEN A {};
+  A a; // top of file
+
+  template <A&> struct Aref {
+    static void foo() {}
+  };
+
+  class B : public A {};
+  B b; // top of file
+
+  // CHECK: define linkonce_odr hidden void @_ZN5Test74ArefILZNS_1aEEE3fooEv()
+  void test() {
+    Aref<a>::foo();
+  }
+}
+
+namespace Test8 {
+  void foo();
+  void bar() {}
+  // CHECK-HIDDEN: define hidden void @_ZN5Test83barEv()
+  // CHECK-HIDDEN: declare void @_ZN5Test83fooEv()
+
+  void test() {
+    foo();
+    bar();
+  }
+}

Modified: cfe/trunk/test/Index/index-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/index-templates.cpp?rev=117147&r1=117146&r2=117147&view=diff
==============================================================================
--- cfe/trunk/test/Index/index-templates.cpp (original)
+++ cfe/trunk/test/Index/index-templates.cpp Fri Oct 22 16:05:15 2010
@@ -192,7 +192,7 @@
 // CHECK-USRS: index-templates.cpp c:index-templates.cpp at 210 Extent=[8:19 - 8:20]
 // CHECK-USRS: index-templates.cpp c:index-templates.cpp at 222 Extent=[8:31 - 8:36]
 // CHECK-USRS: index-templates.cpp c:@CT>2#T#T at vector@F at clear# Extent=[10:8 - 10:15]
-// CHECK-USRS: index-templates.cpp c:index-templates.cpp at 280@CP>1#T at vector>#*t0.0#>@CT>1#T at allocator1S0_ Extent=[13:1 - 14:21]
+// CHECK-USRS: index-templates.cpp c:@CP>1#T at vector>#*t0.0#>@CT>1#T at allocator1S0_ Extent=[13:1 - 14:21]
 // CHECK-USRS: index-templates.cpp c:index-templates.cpp at 298 Extent=[13:19 - 13:20]
 // CHECK-USRS: index-templates.cpp c:@S at Z1 Extent=[16:1 - 16:14]
 // CHECK-USRS: index-templates.cpp c:@C at vector>#$@S at Z1#$@C at allocator>#S0_ Extent=[18:1 - 18:22]





More information about the cfe-commits mailing list