mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-18 16:58:23 +00:00
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. llvm-svn: 171193
This commit is contained in:
parent
9e575dafad
commit
576127d90e
@ -903,6 +903,12 @@ public:
|
||||
/// 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 @@ public:
|
||||
/// 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;
|
||||
|
||||
|
@ -1177,6 +1177,32 @@ SourceRange VarDecl::getSourceRange() const {
|
||||
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 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const {
|
||||
return (proto->getArgType(1).getCanonicalType() == Context.VoidPtrTy);
|
||||
}
|
||||
|
||||
bool FunctionDecl::hasCLanguageLinkage() const {
|
||||
return hasCLanguageLinkageTemplate(*this);
|
||||
}
|
||||
|
||||
bool FunctionDecl::isExternC() const {
|
||||
if (getLinkage() != ExternalLinkage)
|
||||
return false;
|
||||
|
@ -1969,32 +1969,6 @@ static bool isABIDefaultCC(Sema &S, CallingConv CC, FunctionDecl *D) {
|
||||
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 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
|
||||
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 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
||||
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();
|
||||
|
@ -930,11 +930,19 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
|
||||
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();
|
||||
|
@ -11,3 +11,10 @@ namespace test1 {
|
||||
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'}}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user