forked from OSchip/llvm-project
Implement dcl.link paragraph 5.
The language linkage of redeclarations must match. GCC was already reporting an error for this. llvm-svn: 171139
This commit is contained in:
parent
396cb795bc
commit
cffa95d73f
|
@ -3257,6 +3257,8 @@ def err_inline_declaration_block_scope : Error<
|
|||
"inline declaration of %0 not allowed in block scope">;
|
||||
def err_static_non_static : Error<
|
||||
"static declaration of %0 follows non-static declaration">;
|
||||
def err_different_language_linkage : Error<
|
||||
"declaration of %0 has a different language linkage">;
|
||||
def warn_weak_import : Warning <
|
||||
"an already-declared variable is made a weak_import declaration %0">;
|
||||
def warn_static_non_static : ExtWarn<
|
||||
|
|
|
@ -1969,6 +1969,32 @@ 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,
|
||||
|
@ -2229,6 +2255,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
|
|||
assert(OldQTypeForComparison.isCanonical());
|
||||
}
|
||||
|
||||
if (!hasCLanguageLinkage(*Old) && hasCLanguageLinkage(*New)) {
|
||||
Diag(New->getLocation(), diag::err_different_language_linkage) << New;
|
||||
Diag(Old->getLocation(), PrevDiag);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (OldQTypeForComparison == NewQType)
|
||||
return MergeCompatibleFunctionDecls(New, Old, S);
|
||||
|
||||
|
@ -2612,6 +2644,14 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
|||
New->setInvalidDecl();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasCLanguageLinkage(*Old) && hasCLanguageLinkage(*New)) {
|
||||
Diag(New->getLocation(), diag::err_different_language_linkage) << New;
|
||||
Diag(Old->getLocation(), diag::note_previous_definition);
|
||||
New->setInvalidDecl();
|
||||
return;
|
||||
}
|
||||
|
||||
// c99 6.2.2 P4.
|
||||
// For an identifier declared with the storage-class specifier extern in a
|
||||
// scope in which a prior declaration of that identifier is visible, if
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
namespace test1 {
|
||||
int x; // expected-note {{previous definition is here}}
|
||||
static int y; // expected-note {{previous definition is here}}
|
||||
void f() {} // expected-note {{previous definition is here}}
|
||||
|
||||
extern "C" {
|
||||
extern int x; // expected-error {{declaration of 'x' has a different language linkage}}
|
||||
extern int y; // expected-error {{declaration of 'y' has a different language linkage}}
|
||||
void f(); // expected-error {{declaration of 'f' has a different language linkage}}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue