diff options
-rw-r--r-- | include/clang/AST/Decl.h | 16 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 52 | ||||
-rw-r--r-- | lib/AST/ItaniumMangle.cpp | 42 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 2 | ||||
-rw-r--r-- | test/SemaCXX/linkage2.cpp | 19 |
6 files changed, 60 insertions, 75 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 947525f691..117ec7eef3 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -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; } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 5c489273d2..433e76767c 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1217,20 +1217,20 @@ SourceRange VarDecl::getSourceRange() const { 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::getLanguageLinkage() const { 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::getLanguageLinkage() const { 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::getMemoryFunctionKind() const { return Builtin::BIstrlen; default: - if (hasCLanguageLinkage()) { + if (isExternC()) { if (FnInfo->isStr("memset")) return Builtin::BImemset; else if (FnInfo->isStr("memcpy")) diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index a7fc16aae3..e9a3b03483 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -366,20 +366,34 @@ bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) { 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::shouldMangleDeclName(const NamedDecl *D) { 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; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 9c7fb6b4b2..d2b4697ee3 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4860,7 +4860,7 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) { 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(Scope *S, FunctionDecl *NewFD, // 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) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index c2e0d6f809..9bba5f6c78 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -967,7 +967,7 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, 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). diff --git a/test/SemaCXX/linkage2.cpp b/test/SemaCXX/linkage2.cpp index d1d8d3a156..2cee581b49 100644 --- a/test/SemaCXX/linkage2.cpp +++ b/test/SemaCXX/linkage2.cpp @@ -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); + } +} |