]> granicus.if.org Git - clang/commitdiff
When a function or variable somehow depends on a type or declaration
authorDouglas Gregor <dgregor@apple.com>
Wed, 3 Feb 2010 09:33:45 +0000 (09:33 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 3 Feb 2010 09:33:45 +0000 (09:33 +0000)
that is in an anonymous namespace, give that function or variable
internal linkage.

This change models an oddity of the C++ standard, where names declared
in an anonymous namespace have external linkage but, because anonymous
namespace are really "uniquely-named" namespaces, the names cannot be
referenced from other translation units. That means that they have
external linkage for semantic analysis, but the only sensible
implementation for code generation is to give them internal
linkage. We now model this notion via the UniqueExternalLinkage
linkage type. There are several changes here:

  - Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage
    when the declaration is in an anonymous namespace.
  - Added Type::getLinkage() to determine the linkage of a type, which
    is defined as the minimum linkage of the types (when we're dealing
    with a compound type that is not a struct/class/union).
  - Extended NamedDecl::getLinkage() to consider the linkage of the
    template arguments and template parameters of function template
    specializations and class template specializations.
  - Taught code generation to rely on NamedDecl::getLinkage() when
    determining the linkage of variables and functions, also
    considering the linkage of the types of those variables and
    functions (C++ only). Map UniqueExternalLinkage to internal
    linkage, taking out the explicit checks for
    isInAnonymousNamespace().

This fixes much of PR5792, which, as discovered by Anders Carlsson, is
actually the reason behind the pass-manager assertion that causes the
majority of clang-on-clang regression test failures. With this fix,
Clang-built-Clang+LLVM passes 88% of its regression tests (up from
67%). The specific numbers are:

LLVM:
  Expected Passes    : 4006
  Expected Failures  : 32
  Unsupported Tests  : 40
  Unexpected Failures: 736

Clang:
  Expected Passes    : 1903
  Expected Failures  : 14
  Unexpected Failures: 75

Overall:
  Expected Passes    : 5909
  Expected Failures  : 46
  Unsupported Tests  : 40
  Unexpected Failures: 811

Still to do:
  - Improve testing
  - Check whether we should allow the presence of types with
  InternalLinkage (in addition to UniqueExternalLinkage) given
  variables/functions internal linkage in C++, as mentioned in
  PR5792.
  - Determine how expensive the getLinkage() calls are in practice;
  consider caching the result in NamedDecl.
  - Assess the feasibility of Chris's idea in comment #1 of PR5792.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95216 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
include/clang/AST/Type.h
include/clang/Basic/Linkage.h [new file with mode: 0644]
include/clang/Basic/Specifiers.h
lib/AST/Decl.cpp
lib/AST/Type.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/Mangle.cpp
lib/Sema/SemaTemplate.cpp
test/CodeGenCXX/internal-linkage.cpp [new file with mode: 0644]
test/SemaTemplate/instantiate-decl-init.cpp

index dd83443c65f3fd6b3b03d4b862e33a7e7bb31b33..8166316fccc38afdff2b1ec1e0a100f2a2ce08d8 100644 (file)
@@ -19,6 +19,7 @@
 #include "clang/AST/Redeclarable.h"
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/ExternalASTSource.h"
+#include "clang/Basic/Linkage.h"
 
 namespace clang {
 class CXXTemporary;
@@ -195,23 +196,6 @@ public:
     return DC->isRecord();
   }
 
-  /// \brief Describes the different kinds of linkage 
-  /// (C++ [basic.link], C99 6.2.2) that an entity may have.
-  enum Linkage {
-    /// \brief No linkage, which means that the entity is unique and
-    /// can only be referred to from within its scope.
-    NoLinkage = 0,
-
-    /// \brief Internal linkage, which indicates that the entity can
-    /// be referred to from within the translation unit (but not other
-    /// translation units).
-    InternalLinkage,
-
-    /// \brief External linkage, which indicates that the entity can
-    /// be referred to from other translation units.
-    ExternalLinkage
-  };
-
   /// \brief Determine what kind of linkage this entity has.
   Linkage getLinkage() const;
 
index b7b60df5acb4eb064a6f9f4dacea274a5d910637..f53fd921067e7997f053b7d9ea0465fec37c4db3 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/Linkage.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/TemplateName.h"
 #include "llvm/Support/Casting.h"
@@ -974,6 +975,9 @@ public:
 
   const char *getTypeClassName() const;
 
+  /// \brief Determine the linkage of this type.
+  virtual Linkage getLinkage() const;
+
   QualType getCanonicalTypeInternal() const { return CanonicalType; }
   void dump() const;
   static bool classof(const Type *) { return true; }
@@ -1062,6 +1066,8 @@ public:
     return TypeKind >= Float && TypeKind <= LongDouble;
   }
 
+  virtual Linkage getLinkage() const;
+
   static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
   static bool classof(const BuiltinType *) { return true; }
 };
@@ -1089,6 +1095,8 @@ public:
     ID.AddPointer(Element.getAsOpaquePtr());
   }
 
+  virtual Linkage getLinkage() const;
+
   static bool classof(const Type *T) { return T->getTypeClass() == Complex; }
   static bool classof(const ComplexType *) { return true; }
 };
@@ -1116,6 +1124,8 @@ public:
     ID.AddPointer(Pointee.getAsOpaquePtr());
   }
 
+  virtual Linkage getLinkage() const;
+
   static bool classof(const Type *T) { return T->getTypeClass() == Pointer; }
   static bool classof(const PointerType *) { return true; }
 };
@@ -1146,6 +1156,8 @@ public:
       ID.AddPointer(Pointee.getAsOpaquePtr());
   }
 
+  virtual Linkage getLinkage() const;
+
   static bool classof(const Type *T) {
     return T->getTypeClass() == BlockPointer;
   }
@@ -1203,6 +1215,8 @@ public:
     ID.AddBoolean(SpelledAsLValue);
   }
 
+  virtual Linkage getLinkage() const;
+
   static bool classof(const Type *T) {
     return T->getTypeClass() == LValueReference ||
            T->getTypeClass() == RValueReference;
@@ -1277,6 +1291,8 @@ public:
     ID.AddPointer(Class);
   }
 
+  virtual Linkage getLinkage() const;
+
   static bool classof(const Type *T) {
     return T->getTypeClass() == MemberPointer;
   }
@@ -1328,6 +1344,8 @@ public:
   }
   unsigned getIndexTypeCVRQualifiers() const { return IndexTypeQuals; }
 
+  virtual Linkage getLinkage() const;
+
   static bool classof(const Type *T) {
     return T->getTypeClass() == ConstantArray ||
            T->getTypeClass() == VariableArray ||
@@ -1611,6 +1629,9 @@ public:
     ID.AddInteger(NumElements);
     ID.AddInteger(TypeClass);
   }
+
+  virtual Linkage getLinkage() const;
+
   static bool classof(const Type *T) {
     return T->getTypeClass() == Vector || T->getTypeClass() == ExtVector;
   }
@@ -1753,6 +1774,8 @@ public:
     ID.AddPointer(ResultType.getAsOpaquePtr());
   }
 
+  virtual Linkage getLinkage() const;
+
   static bool classof(const Type *T) {
     return T->getTypeClass() == FunctionNoProto;
   }
@@ -1856,6 +1879,8 @@ public:
   bool isSugared() const { return false; }
   QualType desugar() const { return QualType(this, 0); }
 
+  virtual Linkage getLinkage() const;
+
   static bool classof(const Type *T) {
     return T->getTypeClass() == FunctionProto;
   }
@@ -2058,6 +2083,8 @@ public:
   bool isBeingDefined() const { return decl.getInt(); }
   void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); }
 
+  virtual Linkage getLinkage() const;
+
   static bool classof(const Type *T) {
     return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
   }
@@ -2548,6 +2575,8 @@ public:
                       const ObjCInterfaceDecl *Decl,
                       ObjCProtocolDecl **protocols, unsigned NumProtocols);
 
+  virtual Linkage getLinkage() const;
+
   static bool classof(const Type *T) {
     return T->getTypeClass() == ObjCInterface;
   }
@@ -2628,6 +2657,8 @@ public:
   bool isSugared() const { return false; }
   QualType desugar() const { return QualType(this, 0); }
 
+  virtual Linkage getLinkage() const;
+
   void Profile(llvm::FoldingSetNodeID &ID);
   static void Profile(llvm::FoldingSetNodeID &ID, QualType T,
                       ObjCProtocolDecl **protocols, unsigned NumProtocols);
diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h
new file mode 100644 (file)
index 0000000..de0de34
--- /dev/null
@@ -0,0 +1,57 @@
+//===--- Linkage.h - Linkage 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 Linkage enumeration and various utility
+// functions.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_LINKAGE_H
+#define LLVM_CLANG_BASIC_LINKAGE_H
+
+namespace clang {
+
+/// \brief Describes the different kinds of linkage 
+/// (C++ [basic.link], C99 6.2.2) that an entity may have.
+enum Linkage {
+  /// \brief No linkage, which means that the entity is unique and
+  /// can only be referred to from within its scope.
+  NoLinkage = 0,
+
+  /// \brief Internal linkage, which indicates that the entity can
+  /// be referred to from within the translation unit (but not other
+  /// translation units).
+  InternalLinkage,
+
+  /// \brief External linkage within a unique namespace. From the
+  /// langauge perspective, these entities have external
+  /// linkage. However, since they reside in an anonymous namespace,
+  /// their names are unique to this translation unit, which is
+  /// equivalent to having internal linkage from the code-generation
+  /// point of view.
+  UniqueExternalLinkage,
+
+  /// \brief External linkage, which indicates that the entity can
+  /// be referred to from other translation units.
+  ExternalLinkage
+};
+
+/// \brief Determine whether the given linkage is semantically
+/// external.
+inline bool isExternalLinkage(Linkage L) {
+  return L == UniqueExternalLinkage || L == ExternalLinkage;
+}
+
+/// \brief Compute the minimum linkage given two linages.
+static inline Linkage minLinkage(Linkage L1, Linkage L2) {
+  return L1 < L2? L1 : L2;
+}
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_LINKAGE_H
index 4cace86dd18d5c6589ccb929baa05ce89a36508b..9e54762add7db5d799342e23b07402b658018102 100644 (file)
@@ -77,6 +77,7 @@ namespace clang {
     AS_private,
     AS_none
   };
-}
+
+} // end namespace clang
 
 #endif // LLVM_CLANG_BASIC_SPECIFIERS_H
index a2cf73849d51efe75d92184655a9c264b1733804..c3e976a080a06713bc1b0d21b2087061e4bf69dc 100644 (file)
@@ -47,7 +47,72 @@ TypeLoc TypeSourceInfo::getTypeLoc() const {
 // NamedDecl Implementation
 //===----------------------------------------------------------------------===//
 
-static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
+/// \brief Get the most restrictive linkage for the types in the given
+/// template parameter list.
+static Linkage 
+getLinkageForTemplateParameterList(const TemplateParameterList *Params) {
+  Linkage L = ExternalLinkage;
+  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());
+        continue;
+      }
+
+    if (TemplateTemplateParmDecl *TTP
+                                   = dyn_cast<TemplateTemplateParmDecl>(*P)) {
+      L = minLinkage(L, 
+            getLinkageForTemplateParameterList(TTP->getTemplateParameters()));
+    }
+  }
+
+  return L;
+}
+
+/// \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;
+
+  for (unsigned I = 0; I != NumArgs; ++I) {
+    switch (Args[I].getKind()) {
+    case TemplateArgument::Null:
+    case TemplateArgument::Integral:
+    case TemplateArgument::Expression:
+      break;
+      
+    case TemplateArgument::Type:
+      L = minLinkage(L, Args[I].getAsType()->getLinkage());
+      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());
+      break;
+
+    case TemplateArgument::Template:
+      if (TemplateDecl *Template
+                                = Args[I].getAsTemplate().getAsTemplateDecl())
+        L = minLinkage(L, Template->getLinkage());
+      break;
+
+    case TemplateArgument::Pack:
+      L = minLinkage(L, 
+                     getLinkageForTemplateArgumentList(Args[I].pack_begin(),
+                                                       Args[I].pack_size()));
+      break;
+    }
+  }
+
+  return L;
+}
+
+static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
   assert(D->getDeclContext()->getLookupContext()->isFileContext() &&
          "Not a name having namespace scope");
   ASTContext &Context = D->getASTContext();
@@ -61,7 +126,7 @@ static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
   if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
     // Explicitly declared static.
     if (Var->getStorageClass() == VarDecl::Static)
-      return NamedDecl::InternalLinkage;
+      return InternalLinkage;
 
     // - an object or reference that is explicitly declared const
     //   and neither explicitly declared extern nor previously
@@ -75,13 +140,16 @@ static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
       for (const VarDecl *PrevVar = Var->getPreviousDeclaration();
            PrevVar && !FoundExtern; 
            PrevVar = PrevVar->getPreviousDeclaration())
-        if (PrevVar->getLinkage() == NamedDecl::ExternalLinkage)
+        if (isExternalLinkage(PrevVar->getLinkage()))
           FoundExtern = true;
       
       if (!FoundExtern)
-        return NamedDecl::InternalLinkage;
+        return InternalLinkage;
     }
   } else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) {
+    // C++ [temp]p4:
+    //   A non-member function template can have internal linkage; any
+    //   other template name shall have external linkage.
     const FunctionDecl *Function = 0;
     if (const FunctionTemplateDecl *FunTmpl
                                         = dyn_cast<FunctionTemplateDecl>(D))
@@ -91,11 +159,11 @@ static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
 
     // Explicitly declared static.
     if (Function->getStorageClass() == FunctionDecl::Static)
-      return NamedDecl::InternalLinkage;
+      return InternalLinkage;
   } else if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) {
     //   - a data member of an anonymous union.
     if (cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion())
-      return NamedDecl::InternalLinkage;
+      return InternalLinkage;
   }
 
   // C++ [basic.link]p4:
@@ -118,7 +186,7 @@ static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
       //   is visible, or if the prior declaration specifies no
       //   linkage, then the identifier has external linkage.
       if (const VarDecl *PrevVar = Var->getPreviousDeclaration()) {
-        if (NamedDecl::Linkage L = PrevVar->getLinkage())
+        if (Linkage L = PrevVar->getLinkage())
           return L;
       }
     }
@@ -127,7 +195,10 @@ static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
     //   If the declaration of an identifier for an object has file
     //   scope and no storage-class specifier, its linkage is
     //   external.
-    return NamedDecl::ExternalLinkage;
+    if (Var->isInAnonymousNamespace())
+      return UniqueExternalLinkage;
+
+    return ExternalLinkage;
   }
 
   //     - a function, unless it has internal linkage; or
@@ -151,12 +222,26 @@ static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
       //   is visible, or if the prior declaration specifies no
       //   linkage, then the identifier has external linkage.
       if (const FunctionDecl *PrevFunc = Function->getPreviousDeclaration()) {
-        if (NamedDecl::Linkage L = PrevFunc->getLinkage())
+        if (Linkage L = PrevFunc->getLinkage())
           return L;
       }
     }
 
-    return NamedDecl::ExternalLinkage;
+    if (Function->isInAnonymousNamespace())
+      return UniqueExternalLinkage;
+
+    if (FunctionTemplateSpecializationInfo *SpecInfo
+                               = Function->getTemplateSpecializationInfo()) {
+      Linkage L = SpecInfo->getTemplate()->getLinkage();
+      const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments;
+      L = minLinkage(L, 
+                     getLinkageForTemplateArgumentList(
+                                          TemplateArgs.getFlatArgumentList(), 
+                                          TemplateArgs.flat_size()));
+      return L;
+    }
+
+    return ExternalLinkage;
   }
 
   //     - a named class (Clause 9), or an unnamed class defined in a
@@ -166,29 +251,50 @@ static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
   //       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())
-      return NamedDecl::ExternalLinkage;
+    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.getFlatArgumentList(),
+                                                 TemplateArgs.flat_size());
+        return minLinkage(L, Spec->getSpecializedTemplate()->getLinkage());
+      }
+
+      return ExternalLinkage;
+    }
 
   //     - an enumerator belonging to an enumeration with external linkage;
-  if (isa<EnumConstantDecl>(D))
-    if (cast<NamedDecl>(D->getDeclContext())->getLinkage() 
-                                                 == NamedDecl::ExternalLinkage)
-      return NamedDecl::ExternalLinkage;
+  if (isa<EnumConstantDecl>(D)) {
+    Linkage L = cast<NamedDecl>(D->getDeclContext())->getLinkage();
+    if (isExternalLinkage(L))
+      return L;
+  }
 
   //     - a template, unless it is a function template that has
   //       internal linkage (Clause 14);
-  if (isa<TemplateDecl>(D))
-    return NamedDecl::ExternalLinkage;
+  if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
+    if (D->isInAnonymousNamespace())
+      return UniqueExternalLinkage;
+
+    return getLinkageForTemplateParameterList(
+                                         Template->getTemplateParameters());
+  }
 
   //     - a namespace (7.3), unless it is declared within an unnamed
   //       namespace.
   if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace())
-    return NamedDecl::ExternalLinkage;
+    return ExternalLinkage;
 
-  return NamedDecl::NoLinkage;
+  return NoLinkage;
 }
 
-NamedDecl::Linkage NamedDecl::getLinkage() const {
+Linkage NamedDecl::getLinkage() const {
   // Handle linkage for namespace-scope names.
   if (getDeclContext()->getLookupContext()->isFileContext())
     if (Linkage L = getLinkageForNamespaceScopeDecl(this))
@@ -204,9 +310,11 @@ NamedDecl::Linkage NamedDecl::getLinkage() const {
   if (getDeclContext()->isRecord() &&
       (isa<CXXMethodDecl>(this) || isa<VarDecl>(this) ||
        (isa<TagDecl>(this) &&
-        (getDeclName() || cast<TagDecl>(this)->getTypedefForAnonDecl()))) &&
-      cast<RecordDecl>(getDeclContext())->getLinkage() == ExternalLinkage)
-    return ExternalLinkage;
+        (getDeclName() || cast<TagDecl>(this)->getTypedefForAnonDecl())))) {
+    Linkage L = cast<RecordDecl>(getDeclContext())->getLinkage();
+    if (isExternalLinkage(L))
+      return L;
+  }
 
   // C++ [basic.link]p6:
   //   The name of a function declared in block scope and the name of
@@ -225,6 +333,9 @@ NamedDecl::Linkage NamedDecl::getLinkage() const {
         if (Linkage L = Function->getPreviousDeclaration()->getLinkage())
           return L;
 
+      if (Function->isInAnonymousNamespace())
+        return UniqueExternalLinkage;
+
       return ExternalLinkage;
     }
 
@@ -235,6 +346,9 @@ NamedDecl::Linkage NamedDecl::getLinkage() const {
           if (Linkage L = Var->getPreviousDeclaration()->getLinkage())
             return L;
 
+        if (Var->isInAnonymousNamespace())
+          return UniqueExternalLinkage;
+
         return ExternalLinkage;
       }
   }
@@ -242,7 +356,7 @@ NamedDecl::Linkage NamedDecl::getLinkage() const {
   // C++ [basic.link]p6:
   //   Names not covered by these rules have no linkage.
   return NoLinkage;
-}
+  }
 
 std::string NamedDecl::getQualifiedNameAsString() const {
   return getQualifiedNameAsString(getASTContext().getLangOptions());
index 504ffc5e4e95f8ec4db65e2324a12f73164888ff..b3010d5e7b5aec348f4d1314e78be6bf5331307b 100644 (file)
@@ -1049,3 +1049,79 @@ void ObjCInterfaceType::Profile(llvm::FoldingSetNodeID &ID) {
   else
     Profile(ID, getDecl(), 0, 0);
 }
+
+Linkage Type::getLinkage() const { 
+  // C++ [basic.link]p8:
+  //   Names not covered by these rules have no linkage.
+  if (this != CanonicalType.getTypePtr())
+    return CanonicalType->getLinkage();
+
+  return NoLinkage; 
+}
+
+Linkage BuiltinType::getLinkage() 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 ExternalLinkage;
+}
+
+Linkage TagType::getLinkage() 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 getDecl()->getLinkage();
+}
+
+// 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
+Linkage ComplexType::getLinkage() const {
+  return ElementType->getLinkage();
+}
+
+Linkage PointerType::getLinkage() const {
+  return PointeeType->getLinkage();
+}
+
+Linkage BlockPointerType::getLinkage() const {
+  return PointeeType->getLinkage();
+}
+
+Linkage ReferenceType::getLinkage() const {
+  return PointeeType->getLinkage();
+}
+
+Linkage MemberPointerType::getLinkage() const {
+  return minLinkage(Class->getLinkage(), PointeeType->getLinkage());
+}
+
+Linkage ArrayType::getLinkage() const {
+  return ElementType->getLinkage();
+}
+
+Linkage VectorType::getLinkage() const {
+  return ElementType->getLinkage();
+}
+
+Linkage FunctionNoProtoType::getLinkage() const {
+  return getResultType()->getLinkage();
+}
+
+Linkage FunctionProtoType::getLinkage() const {
+  Linkage L = getResultType()->getLinkage();
+  for (arg_type_iterator A = arg_type_begin(), AEnd = arg_type_end();
+       A != AEnd; ++A)
+    L = minLinkage(L, (*A)->getLinkage());
+
+  return L;
+}
+
+Linkage ObjCInterfaceType::getLinkage() const {
+  return ExternalLinkage;
+}
+
+Linkage ObjCObjectPointerType::getLinkage() const {
+  return ExternalLinkage;
+}
index 28a808bd835f1bd0dfc7b086b3fb83e070e6d666..c3f5443c47bd7ad8c84678b32f84d698ac568998 100644 (file)
@@ -255,34 +255,40 @@ void CodeGenModule::EmitAnnotations() {
 static CodeGenModule::GVALinkage
 GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
                       const LangOptions &Features) {
-  // Everything located semantically within an anonymous namespace is
-  // always internal.
-  if (FD->isInAnonymousNamespace())
-    return CodeGenModule::GVA_Internal;
+  CodeGenModule::GVALinkage External = CodeGenModule::GVA_StrongExternal;
 
-  // "static" functions get internal linkage.
-  if (FD->getStorageClass() == FunctionDecl::Static && !isa<CXXMethodDecl>(FD))
-    return CodeGenModule::GVA_Internal;
+  Linkage L = FD->getLinkage();
+  if (L == ExternalLinkage && Context.getLangOptions().CPlusPlus &&
+      FD->getType()->getLinkage() == UniqueExternalLinkage)
+    L = UniqueExternalLinkage;
   
-  // The kind of external linkage this function will have, if it is not
-  // inline or static.
-  CodeGenModule::GVALinkage External = CodeGenModule::GVA_StrongExternal;
-  if (Context.getLangOptions().CPlusPlus) {
-    TemplateSpecializationKind TSK = FD->getTemplateSpecializationKind();
+  switch (L) {
+  case NoLinkage:
+  case InternalLinkage:
+  case UniqueExternalLinkage:
+    return CodeGenModule::GVA_Internal;
     
-    if (TSK == TSK_ExplicitInstantiationDefinition) {
-      // If a function has been explicitly instantiated, then it should
-      // always have strong external linkage.
+  case ExternalLinkage:
+    switch (FD->getTemplateSpecializationKind()) {
+    case TSK_Undeclared:
+    case TSK_ExplicitSpecialization:
+      External = CodeGenModule::GVA_StrongExternal;
+      break;
+
+    case TSK_ExplicitInstantiationDefinition:
+      // FIXME: explicit instantiation definitions should use weak linkage
       return CodeGenModule::GVA_StrongExternal;
-    } 
-    
-    if (TSK == TSK_ImplicitInstantiation)
+
+    case TSK_ExplicitInstantiationDeclaration:
+    case TSK_ImplicitInstantiation:
       External = CodeGenModule::GVA_TemplateInstantiation;
+      break;
+    }
   }
 
   if (!FD->isInlined())
     return External;
-
+    
   if (!Features.CPlusPlus || FD->hasAttr<GNUInlineAttr>()) {
     // GNU or C99 inline semantics. Determine whether this symbol should be
     // externally visible.
@@ -581,13 +587,24 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
       
   // Static data may be deferred, but out-of-line static data members
   // cannot be.
-  if (VD->getLinkage() == VarDecl::InternalLinkage ||
-      VD->isInAnonymousNamespace()) {
+  Linkage L = VD->getLinkage();
+  if (L == ExternalLinkage && getContext().getLangOptions().CPlusPlus &&
+      VD->getType()->getLinkage() == UniqueExternalLinkage)
+    L = UniqueExternalLinkage;
+
+  switch (L) {
+  case NoLinkage:
+  case InternalLinkage:
+  case UniqueExternalLinkage:
     // Initializer has side effects?
     if (VD->getInit() && VD->getInit()->HasSideEffects(Context))
       return false;
     return !(VD->isStaticDataMember() && VD->isOutOfLine());
+
+  case ExternalLinkage:
+    break;
   }
+
   return false;
 }
 
@@ -941,16 +958,30 @@ CodeGenModule::getVtableLinkage(const CXXRecordDecl *RD) {
 
 static CodeGenModule::GVALinkage
 GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) {
-  // Everything located semantically within an anonymous namespace is
-  // always internal.
-  if (VD->isInAnonymousNamespace())
+  // If this is a static data member, compute the kind of template
+  // specialization. Otherwise, this variable is not part of a
+  // template.
+  TemplateSpecializationKind TSK = TSK_Undeclared;
+  if (VD->isStaticDataMember())
+    TSK = VD->getTemplateSpecializationKind();
+
+  Linkage L = VD->getLinkage();
+  if (L == ExternalLinkage && Context.getLangOptions().CPlusPlus &&
+      VD->getType()->getLinkage() == UniqueExternalLinkage)
+    L = UniqueExternalLinkage;
+
+  switch (L) {
+  case NoLinkage:
+  case InternalLinkage:
+  case UniqueExternalLinkage:
     return CodeGenModule::GVA_Internal;
 
-  // Handle linkage for static data members.
-  if (VD->isStaticDataMember()) {
-    switch (VD->getTemplateSpecializationKind()) {
+  case ExternalLinkage:
+    switch (TSK) {
     case TSK_Undeclared:
     case TSK_ExplicitSpecialization:
+
+      // FIXME: ExplicitInstantiationDefinition should be weak!
     case TSK_ExplicitInstantiationDefinition:
       return CodeGenModule::GVA_StrongExternal;
       
@@ -959,13 +990,10 @@ GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) {
       // Fall through to treat this like any other instantiation.
         
     case TSK_ImplicitInstantiation:
-      return CodeGenModule::GVA_TemplateInstantiation;
+      return CodeGenModule::GVA_TemplateInstantiation;      
     }
   }
 
-  if (VD->getLinkage() == VarDecl::InternalLinkage)
-    return CodeGenModule::GVA_Internal;
-
   return CodeGenModule::GVA_StrongExternal;
 }
 
index 4f84edd908bf5e47eea7d2d85f1591e986003f54..6326625bae2b2befc90fe60a54d2096e6ffa0ba8 100644 (file)
@@ -178,8 +178,7 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
     if (isa<FunctionDecl>(DC) && D->hasLinkage())
       while (!DC->isNamespace() && !DC->isTranslationUnit())
         DC = DC->getParent();
-    if (DC->isTranslationUnit() &&
-        D->getLinkage() != NamedDecl::InternalLinkage)
+    if (DC->isTranslationUnit() && D->getLinkage() != InternalLinkage)
       return false;
   }
 
@@ -420,7 +419,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
       // We must avoid conflicts between internally- and externally-
       // linked names in the same TU. This naming convention is the
       // same as that followed by GCC, though it shouldn't actually matter.
-      if (ND->getLinkage() == NamedDecl::InternalLinkage &&
+      if (ND->getLinkage() == InternalLinkage &&
           ND->getDeclContext()->isFileContext())
         Out << 'L';
 
index 44b0d83b466cd863e1c8136cc3c0d4abf6e5000c..13cf78339141291598a2c365159d33e02e0611da 100644 (file)
@@ -2336,7 +2336,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
 
   // Functions must have external linkage.
   if (FunctionDecl *Func = dyn_cast<FunctionDecl>(DRE->getDecl())) {
-    if (Func->getLinkage() != NamedDecl::ExternalLinkage) {
+    if (!isExternalLinkage(Func->getLinkage())) {
       Diag(Arg->getSourceRange().getBegin(),
            diag::err_template_arg_function_not_extern)
         << Func << Arg->getSourceRange();
@@ -2351,7 +2351,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
   }
 
   if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
-    if (Var->getLinkage() != NamedDecl::ExternalLinkage) {
+    if (!isExternalLinkage(Var->getLinkage())) {
       Diag(Arg->getSourceRange().getBegin(),
            diag::err_template_arg_object_not_extern)
         << Var << Arg->getSourceRange();
diff --git a/test/CodeGenCXX/internal-linkage.cpp b/test/CodeGenCXX/internal-linkage.cpp
new file mode 100644 (file)
index 0000000..1ae0f08
--- /dev/null
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+
+struct Global { };
+template<typename T> struct X { };
+
+
+namespace {
+  struct Anon { };
+
+  // CHECK: @_ZN12_GLOBAL__N_15anon0E = internal global
+  Global anon0;
+}
+
+// CHECK: @anon1 = internal global
+Anon anon1;
+
+// CHECK: @anon2 = internal global
+X<Anon> anon2;
+
index b0c2aa8afa911e743c1996b91fd1038ac9f53297..69c7721b5186b34120f8cec0d000f751ea1b48cd 100644 (file)
@@ -20,3 +20,17 @@ void fn(T t, const arg& arg) {
 void test() {
   fn(1, arg());
 }
+
+struct X0 { };
+
+struct X1 {
+  explicit X1(const X0 &x0 = X0());
+};
+
+template<typename T>
+void f0() {
+  X1 x1;
+}
+
+template void f0<int>();
+template void f0<float>();