r175119 - merge hasCLanguageLinkage and isExternC. Keep the shorter name.

Rafael Espindola rafael.espindola at gmail.com
Wed Feb 13 17:47:04 PST 2013


Author: rafael
Date: Wed Feb 13 19:47:04 2013
New Revision: 175119

URL: http://llvm.org/viewvc/llvm-project?rev=175119&view=rev
Log:
merge hasCLanguageLinkage and isExternC. Keep the shorter name.

I added hasCLanguageLinkage while fixing some language linkage bugs some
time ago so that I wouldn't have to check all users of isExternC. It turned
out to be a much longer detour than expected, but this patch finally
merges the two again. The isExternC function now implements just the
standard notion of having C language linkage.

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaCXX/linkage2.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=175119&r1=175118&r2=175119&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Wed Feb 13 19:47:04 2013
@@ -894,14 +894,12 @@ public:
   ///  as static variables declared within a function.
   bool hasGlobalStorage() const { return !hasLocalStorage(); }
 
-  /// \brief Determines whether this variable is a variable with
-  /// external, C linkage.
-  bool isExternC() const;
-
   /// Compute the language linkage.
   LanguageLinkage getLanguageLinkage() const;
 
-  bool hasCLanguageLinkage() const {
+  /// \brief Determines whether this variable is a variable with
+  /// external, C linkage.
+  bool isExternC() const {
     return getLanguageLinkage() == CLanguageLinkage;
   }
 
@@ -1787,14 +1785,12 @@ public:
   /// This function must be an allocation or deallocation function.
   bool isReservedGlobalPlacementOperator() const;
 
-  /// \brief Determines whether this function is a function with
-  /// external, C linkage.
-  bool isExternC() const;
-
   /// Compute the language linkage.
   LanguageLinkage getLanguageLinkage() const;
 
-  bool hasCLanguageLinkage() const {
+  /// \brief Determines whether this function is a function with
+  /// external, C linkage.
+  bool isExternC() const {
     return getLanguageLinkage() == CLanguageLinkage;
   }
 

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=175119&r1=175118&r2=175119&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Wed Feb 13 19:47:04 2013
@@ -1217,20 +1217,20 @@ SourceRange VarDecl::getSourceRange() co
 
 template<typename T>
 static LanguageLinkage getLanguageLinkageTemplate(const T &D) {
-  // Language linkage is a C++ concept, but saying that everything in C has
+  // C++ [dcl.link]p1: All function types, function names with external linkage,
+  // and variable names with external linkage have a language linkage.
+  if (!isExternalLinkage(D.getLinkage()))
+    return NoLanguageLinkage;
+
+  // Language linkage is a C++ concept, but saying that everything else in C has
   // C language linkage fits the implementation nicely.
   ASTContext &Context = D.getASTContext();
   if (!Context.getLangOpts().CPlusPlus)
     return CLanguageLinkage;
 
-  // dcl.link 1: All function types, function names with external linkage, and
-  // variable names with external linkage have a language linkage.
-  if (!isExternalLinkage(D.getLinkage()))
-    return NoLanguageLinkage;
-
-  // dcl.link 4: A C language linkage is ignored in determining the language
-  // linkage of the names of class members and the function type of class member
-  // functions.
+  // C++ [dcl.link]p4: A C language linkage is ignored in determining the
+  // language linkage of the names of class members and the function type of
+  // class member functions.
   const DeclContext *DC = D.getDeclContext();
   if (DC->isRecord())
     return CXXLanguageLinkage;
@@ -1248,20 +1248,6 @@ LanguageLinkage VarDecl::getLanguageLink
   return getLanguageLinkageTemplate(*this);
 }
 
-bool VarDecl::isExternC() const {
-  if (getLinkage() != ExternalLinkage)
-    return false;
-
-  const DeclContext *DC = getDeclContext();
-  if (DC->isRecord())
-    return false;
-
-  ASTContext &Context = getASTContext();
-  if (!Context.getLangOpts().CPlusPlus)
-    return true;
-  return DC->isExternCContext();
-}
-
 VarDecl *VarDecl::getCanonicalDecl() {
   return getFirstDeclaration();
 }
@@ -1780,24 +1766,6 @@ LanguageLinkage FunctionDecl::getLanguag
   return getLanguageLinkageTemplate(*this);
 }
 
-bool FunctionDecl::isExternC() const {
-  if (getLinkage() != ExternalLinkage)
-    return false;
-
-  if (getAttr<OverloadableAttr>())
-    return false;
-
-  const DeclContext *DC = getDeclContext();
-  if (DC->isRecord())
-    return false;
-
-  ASTContext &Context = getASTContext();
-  if (!Context.getLangOpts().CPlusPlus)
-    return true;
-
-  return isMain() || DC->isExternCContext();
-}
-
 bool FunctionDecl::isGlobal() const {
   if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this))
     return Method->isStatic();
@@ -2466,7 +2434,7 @@ unsigned FunctionDecl::getMemoryFunction
     return Builtin::BIstrlen;
 
   default:
-    if (hasCLanguageLinkage()) {
+    if (isExternC()) {
       if (FnInfo->isStr("memset"))
         return Builtin::BImemset;
       else if (FnInfo->isStr("memcpy"))

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=175119&r1=175118&r2=175119&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Wed Feb 13 19:47:04 2013
@@ -366,20 +366,34 @@ bool ItaniumMangleContext::shouldMangleD
   if (D->hasAttr<AsmLabelAttr>())
     return true;
 
-  // Clang's "overloadable" attribute extension to C/C++ implies name mangling
-  // (always) as does passing a C++ member function and a function
-  // whose name is not a simple identifier.
   const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
-  if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(FD) ||
-             !FD->getDeclName().isIdentifier()))
-    return true;
+  if (FD) {
+    LanguageLinkage L = FD->getLanguageLinkage();
+    // Overloadable functions need mangling.
+    if (FD->hasAttr<OverloadableAttr>())
+      return true;
+
+    // C functions and "main" are not mangled.
+    if (FD->isMain() || L == CLanguageLinkage)
+      return false;
+
+    // C++ functions and those whose names are not a simple identifier need
+    // mangling.
+    if (!FD->getDeclName().isIdentifier() || L == CXXLanguageLinkage)
+      return true;
+  }
 
   // Otherwise, no mangling is done outside C++ mode.
   if (!getASTContext().getLangOpts().CPlusPlus)
     return false;
 
-  // Variables at global scope with non-internal linkage are not mangled
-  if (!FD) {
+  const VarDecl *VD = dyn_cast<VarDecl>(D);
+  if (VD) {
+    // C variables are not mangled.
+    if (VD->isExternC())
+      return false;
+
+    // Variables at global scope with non-internal linkage are not mangled
     const DeclContext *DC = getEffectiveDeclContext(D);
     // Check for extern variable declared locally.
     if (DC->isFunctionOrMethod() && D->hasLinkage())
@@ -389,18 +403,6 @@ bool ItaniumMangleContext::shouldMangleD
       return false;
   }
 
-  // Class members are always mangled.
-  if (getEffectiveDeclContext(D)->isRecord())
-    return true;
-
-  // C functions and "main" are not mangled.
-  if (FD)
-    return !FD->isMain() && !FD->hasCLanguageLinkage();
-
-  // C variables are not mangled.
-  if (const VarDecl *VD = dyn_cast<VarDecl>(D))
-    return !VD->hasCLanguageLinkage();
-
   return true;
 }
 

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=175119&r1=175118&r2=175119&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Feb 13 19:47:04 2013
@@ -4860,7 +4860,7 @@ void Sema::CheckShadow(Scope *S, VarDecl
 template<typename T>
 static bool mayConflictWithNonVisibleExternC(const T *ND) {
   VarDecl::StorageClass SC = ND->getStorageClass();
-  if (ND->hasCLanguageLinkage() && (SC == SC_Extern || SC == SC_PrivateExtern))
+  if (ND->isExternC() && (SC == SC_Extern || SC == SC_PrivateExtern))
     return true;
   return ND->getDeclContext()->isTranslationUnit();
 }
@@ -6581,7 +6581,7 @@ bool Sema::CheckFunctionDeclaration(Scop
     // If this function is declared as being extern "C", then check to see if 
     // the function returns a UDT (class, struct, or union type) that is not C
     // compatible, and if it does, warn the user.
-    if (NewFD->hasCLanguageLinkage()) {
+    if (NewFD->isExternC()) {
       QualType R = NewFD->getResultType();
       if (R->isIncompleteType() && !R->isVoidType())
         Diag(NewFD->getLocation(), diag::warn_return_value_udt_incomplete)

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=175119&r1=175118&r2=175119&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Feb 13 19:47:04 2013
@@ -967,7 +967,7 @@ Sema::CheckOverload(Scope *S, FunctionDe
 static bool canBeOverloaded(const FunctionDecl &D) {
   if (D.getAttr<OverloadableAttr>())
     return true;
-  if (D.hasCLanguageLinkage())
+  if (D.isExternC())
     return false;
 
   // Main cannot be overloaded (basic.start.main).

Modified: cfe/trunk/test/SemaCXX/linkage2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/linkage2.cpp?rev=175119&r1=175118&r2=175119&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/linkage2.cpp (original)
+++ cfe/trunk/test/SemaCXX/linkage2.cpp Wed Feb 13 19:47:04 2013
@@ -106,3 +106,22 @@ extern "C" {
 extern "C++" {
   extern void test8_g();
 }
+
+extern "C" {
+  void __attribute__((overloadable)) test9_f(int c); // expected-note {{previous declaration is here}}
+}
+extern "C++" {
+  void __attribute__((overloadable)) test9_f(int c); // expected-error {{declaration of 'test9_f' has a different language linkage}}
+}
+
+extern "C" {
+  void __attribute__((overloadable)) test10_f(int);
+  void __attribute__((overloadable)) test10_f(double);
+}
+
+extern "C" {
+  void test11_f() {
+    void  __attribute__((overloadable)) test11_g(int);
+    void  __attribute__((overloadable)) test11_g(double);
+  }
+}





More information about the cfe-commits mailing list