[cfe-commits] r171193 - in /cfe/trunk: include/clang/AST/Decl.h lib/AST/Decl.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaOverload.cpp test/SemaCXX/linkage2.cpp
Rafael Espindola
rafael.espindola at gmail.com
Fri Dec 28 06:21:58 PST 2012
Author: rafael
Date: Fri Dec 28 08:21:58 2012
New Revision: 171193
URL: http://llvm.org/viewvc/llvm-project?rev=171193&view=rev
Log:
Reject overloading of two static extern C functions.
This patch moves hasCLanguageLinkage to be VarDecl and FunctionDecl methods
so that they can be used from SemaOverload.cpp and then fixes the logic
in Sema::IsOverload.
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/lib/AST/Decl.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=171193&r1=171192&r2=171193&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Dec 28 08:21:58 2012
@@ -903,6 +903,12 @@
/// external, C linkage.
bool isExternC() const;
+ /// Checks if this variable has C language linkage. Note that this is not the
+ /// same as isExternC since decls with non external linkage can have C
+ /// language linkage. They can also have C language linkage when they are not
+ /// declared in an extern C context, but a previous decl is.
+ bool hasCLanguageLinkage() const;
+
/// isLocalVarDecl - Returns true for local variable declarations
/// other than parameters. Note that this includes static variables
/// inside of functions. It also includes variables inside blocks.
@@ -1790,6 +1796,12 @@
/// external, C linkage.
bool isExternC() const;
+ /// Checks if this function has C language linkage. Note that this is not the
+ /// same as isExternC since decls with non external linkage can have C
+ /// language linkage. They can also have C language linkage when they are not
+ /// declared in an extern C context, but a previous decl is.
+ bool hasCLanguageLinkage() const;
+
/// \brief Determines whether this is a global function.
bool isGlobal() const;
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=171193&r1=171192&r2=171193&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Fri Dec 28 08:21:58 2012
@@ -1177,6 +1177,32 @@
return DeclaratorDecl::getSourceRange();
}
+template<typename decl_type>
+static bool hasCLanguageLinkageTemplate(const decl_type &D) {
+ // Language linkage is a C++ concept, but saying that everything in C has
+ // C language linkage fits the implementation nicelly.
+ ASTContext &Context = D.getASTContext();
+ if (!Context.getLangOpts().CPlusPlus)
+ return true;
+
+ // 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.
+ const DeclContext *DC = D.getDeclContext();
+ if (DC->isRecord())
+ return false;
+
+ // If the first decl is in an extern "C" context, any other redeclaration
+ // will have C language linkage. If the first one is not in an extern "C"
+ // context, we would have reported an error for any other decl being in one.
+ const decl_type *First = D.getFirstDeclaration();
+ return First->getDeclContext()->isExternCContext();
+}
+
+bool VarDecl::hasCLanguageLinkage() const {
+ return hasCLanguageLinkageTemplate(*this);
+}
+
bool VarDecl::isExternC() const {
if (getLinkage() != ExternalLinkage)
return false;
@@ -1702,6 +1728,10 @@
return (proto->getArgType(1).getCanonicalType() == Context.VoidPtrTy);
}
+bool FunctionDecl::hasCLanguageLinkage() const {
+ return hasCLanguageLinkageTemplate(*this);
+}
+
bool FunctionDecl::isExternC() const {
if (getLinkage() != ExternalLinkage)
return false;
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=171193&r1=171192&r2=171193&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Dec 28 08:21:58 2012
@@ -1969,32 +1969,6 @@
return ABIDefaultCC == CC;
}
-/// Check if the given decl has C language linkage. Note that this is not
-/// the same as D.isExternC() since decls with non external linkage can have C
-/// language linkage. They can also have C language linkage when they are
-/// not declared in an extern C context, but a previous decl is.
-template<typename T>
-bool hasCLanguageLinkage(const T &D) {
- // Language linkage is a C++ concept, but saying that everything in C has
- // C language linkage fits the implementation nicelly.
- ASTContext &Context = D.getASTContext();
- if (!Context.getLangOpts().CPlusPlus)
- return true;
-
- // 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.
- const DeclContext *DC = D.getDeclContext();
- if (DC->isRecord())
- return false;
-
- // If the first decl is in an extern "C" context, any other redeclaration
- // will have C language linkage. If the first one is not in an extern "C"
- // context, we would have reported an error for any other decl being in one.
- const T *First = D.getFirstDeclaration();
- return First->getDeclContext()->isExternCContext();
-}
-
/// MergeFunctionDecl - We just parsed a function 'New' from
/// declarator D which has the same name and scope as a previous
/// declaration 'Old'. Figure out how to resolve this situation,
@@ -2255,7 +2229,7 @@
assert(OldQTypeForComparison.isCanonical());
}
- if (!hasCLanguageLinkage(*Old) && hasCLanguageLinkage(*New)) {
+ if (!Old->hasCLanguageLinkage() && New->hasCLanguageLinkage()) {
Diag(New->getLocation(), diag::err_different_language_linkage) << New;
Diag(Old->getLocation(), PrevDiag);
return true;
@@ -2645,7 +2619,7 @@
return;
}
- if (!hasCLanguageLinkage(*Old) && hasCLanguageLinkage(*New)) {
+ if (!Old->hasCLanguageLinkage() && New->hasCLanguageLinkage()) {
Diag(New->getLocation(), diag::err_different_language_linkage) << New;
Diag(Old->getLocation(), diag::note_previous_definition);
New->setInvalidDecl();
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=171193&r1=171192&r2=171193&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Dec 28 08:21:58 2012
@@ -930,11 +930,19 @@
return Ovl_Overload;
}
+static bool canBeOverloaded(const FunctionDecl &D) {
+ if (D.getAttr<OverloadableAttr>())
+ return true;
+ if (D.hasCLanguageLinkage())
+ return false;
+ return true;
+}
+
bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
bool UseUsingDeclRules) {
// If both of the functions are extern "C", then they are not
// overloads.
- if (Old->isExternC() && New->isExternC())
+ if (!canBeOverloaded(*Old) && !canBeOverloaded(*New))
return false;
FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
Modified: cfe/trunk/test/SemaCXX/linkage2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/linkage2.cpp?rev=171193&r1=171192&r2=171193&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/linkage2.cpp (original)
+++ cfe/trunk/test/SemaCXX/linkage2.cpp Fri Dec 28 08:21:58 2012
@@ -11,3 +11,10 @@
void f(); // expected-error {{declaration of 'f' has a different language linkage}}
}
}
+
+extern "C" {
+ static void test2_f() { // expected-note {{previous definition is here}}
+ }
+ static void test2_f(int x) { // expected-error {{conflicting types for 'test2_f'}}
+ }
+}
More information about the cfe-commits
mailing list